From efb6d0825b3ac0b8a9427b61c2bac195829ffd68 Mon Sep 17 00:00:00 2001 From: Aakansha Doshi Date: Sat, 20 Mar 2021 21:57:58 +0530 Subject: [PATCH] feat: Add label for name field and use input when editable in export dialog (#3286) * feat: Add label for name field and use input when editable in export dialog * fix * review fix * dnt allow to edit file name when view mode * Update src/components/ProjectName.tsx Co-authored-by: David Luzar Co-authored-by: David Luzar --- src/actions/actionExport.tsx | 4 +- src/components/App.tsx | 3 +- src/components/ExportDialog.scss | 7 +++ src/components/ProjectName.tsx | 69 ++++++++++++---------------- src/locales/en.json | 2 +- src/tests/excalidrawPackage.test.tsx | 9 ++-- 6 files changed, 46 insertions(+), 48 deletions(-) diff --git a/src/actions/actionExport.tsx b/src/actions/actionExport.tsx index d49faf8c..e08d1dff 100644 --- a/src/actions/actionExport.tsx +++ b/src/actions/actionExport.tsx @@ -23,7 +23,9 @@ export const actionChangeProjectName = register({ label={t("labels.fileTitle")} value={appState.name || "Unnamed"} onChange={(name: string) => updateData(name)} - isNameEditable={typeof appProps.name === "undefined"} + isNameEditable={ + typeof appProps.name === "undefined" && !appState.viewModeEnabled + } /> ), }); diff --git a/src/components/App.tsx b/src/components/App.tsx index f7c09c2f..46acaf63 100644 --- a/src/components/App.tsx +++ b/src/components/App.tsx @@ -525,8 +525,7 @@ class App extends React.Component { let zenModeEnabled = actionResult?.appState?.zenModeEnabled || false; let gridSize = actionResult?.appState?.gridSize || null; let theme = actionResult?.appState?.theme || "light"; - let name = actionResult?.appState?.name || this.state.name; - + let name = actionResult?.appState?.name ?? this.state.name; if (typeof this.props.viewModeEnabled !== "undefined") { viewModeEnabled = this.props.viewModeEnabled; } diff --git a/src/components/ExportDialog.scss b/src/components/ExportDialog.scss index 7621c8b5..b02aa530 100644 --- a/src/components/ExportDialog.scss +++ b/src/components/ExportDialog.scss @@ -31,12 +31,16 @@ .ExportDialog__name { grid-column: project-name; margin: auto; + display: flex; + align-items: center; .TextInput { height: calc(1rem - 3px); width: 200px; overflow: hidden; text-align: center; + margin-left: 8px; + text-overflow: ellipsis; &--readonly { background: none; @@ -44,6 +48,9 @@ &:hover { background: none; } + width: auto; + max-width: 200px; + padding-left: 2px; } } } diff --git a/src/components/ProjectName.tsx b/src/components/ProjectName.tsx index d474e7a3..a7d723ef 100644 --- a/src/components/ProjectName.tsx +++ b/src/components/ProjectName.tsx @@ -1,7 +1,6 @@ import "./TextInput.scss"; import React, { Component } from "react"; -import { selectNode, removeSelection } from "../utils"; type Props = { value: string; @@ -10,17 +9,18 @@ type Props = { isNameEditable: boolean; }; -export class ProjectName extends Component { - private handleFocus = (event: React.FocusEvent) => { - selectNode(event.currentTarget); +type State = { + fileName: string; +}; +export class ProjectName extends Component { + state = { + fileName: this.props.value, }; - - private handleBlur = (event: React.FocusEvent) => { - const value = event.currentTarget.innerText.trim(); + private handleBlur = (event: any) => { + const value = event.target.value; if (value !== this.props.value) { this.props.onChange(value); } - removeSelection(); }; private handleKeyDown = (event: React.KeyboardEvent) => { @@ -32,39 +32,30 @@ export class ProjectName extends Component { event.currentTarget.blur(); } }; - private makeEditable = (editable: HTMLSpanElement | null) => { - if (!editable) { - return; - } - try { - editable.contentEditable = "plaintext-only"; - } catch { - editable.contentEditable = "true"; - } - }; public render() { - return this.props.isNameEditable ? ( - - {this.props.value} - - ) : ( - - {this.props.value} - + return ( + <> + + {this.props.isNameEditable ? ( + + this.setState({ fileName: event.target.value }) + } + /> + ) : ( + + {this.props.value} + + )} + ); } } diff --git a/src/locales/en.json b/src/locales/en.json index d1bb9456..a82b3fb0 100644 --- a/src/locales/en.json +++ b/src/locales/en.json @@ -61,7 +61,7 @@ "architect": "Architect", "artist": "Artist", "cartoonist": "Cartoonist", - "fileTitle": "File title", + "fileTitle": "File name", "colorPicker": "Color picker", "canvasBackground": "Canvas background", "drawingCanvas": "Drawing canvas", diff --git a/src/tests/excalidrawPackage.test.tsx b/src/tests/excalidrawPackage.test.tsx index ac951f93..a64b73f3 100644 --- a/src/tests/excalidrawPackage.test.tsx +++ b/src/tests/excalidrawPackage.test.tsx @@ -111,11 +111,11 @@ describe("", () => { const { container } = await render(); fireEvent.click(queryByTestId(container, "export-button")!); - const textInput = document.querySelector( + const textInput: HTMLInputElement | null = document.querySelector( ".ExportDialog__name .TextInput", ); - expect(textInput?.textContent).toContain(`${t("labels.untitled")}`); - expect(textInput?.hasAttribute("data-type")).toBe(true); + expect(textInput?.value).toContain(`${t("labels.untitled")}`); + expect(textInput?.nodeName).toBe("INPUT"); }); it('should set the name and not allow editing when the name prop is present"', async () => { @@ -127,8 +127,7 @@ describe("", () => { ".ExportDialog__name .TextInput--readonly", ); expect(textInput?.textContent).toEqual(name); - - expect(textInput?.hasAttribute("data-type")).toBe(false); + expect(textInput?.nodeName).toBe("SPAN"); }); }); });