diff --git a/client/resources/original_messages.json b/client/resources/original_messages.json index 014bedab41..421edccf0a 100644 --- a/client/resources/original_messages.json +++ b/client/resources/original_messages.json @@ -607,4 +607,4 @@ "description": "Affirmative answer to a form question.", "message": "Yes" } -} \ No newline at end of file +} diff --git a/client/src/www/TODO.spec.ts b/client/src/www/TODO.spec.ts index 79c10169fc..70654b393b 100644 --- a/client/src/www/TODO.spec.ts +++ b/client/src/www/TODO.spec.ts @@ -36,7 +36,6 @@ import * as errorReporter from './shared/error_reporter'; import * as addServerView from './ui_components/add-server-view'; import * as appRoot from './ui_components/app-root.js'; import * as privacyView from './ui_components/privacy-view'; -import * as serverRenameDialog from './ui_components/server-rename-dialog'; import * as userCommsDialog from './ui_components/user-comms-dialog'; import * as aboutView from './views/about_view'; import * as languageView from './views/language_view'; @@ -54,7 +53,6 @@ describe('TODOs', () => { expect(languageView).toBeDefined(); expect(platform).toBeDefined(); expect(privacyView).toBeDefined(); - expect(serverRenameDialog).toBeDefined(); expect(server).toBeDefined(); expect(updater).toBeDefined(); expect(urlInterceptor).toBeDefined(); diff --git a/client/src/www/app/app.ts b/client/src/www/app/app.ts index c39f1a25dd..2c781924f9 100644 --- a/client/src/www/app/app.ts +++ b/client/src/www/app/app.ts @@ -165,10 +165,6 @@ export class App { 'AutoConnectDialogDismissed', this.autoConnectDialogDismissed.bind(this) ); - this.rootEl.addEventListener( - 'ShowServerRename', - this.rootEl.showServerRename.bind(this.rootEl) - ); this.rootEl.addEventListener( 'PrivacyTermsAcked', this.ackPrivacyTerms.bind(this) diff --git a/client/src/www/messages/en.json b/client/src/www/messages/en.json index 313dc47094..f3e657f33d 100644 --- a/client/src/www/messages/en.json +++ b/client/src/www/messages/en.json @@ -114,4 +114,4 @@ "update-downloaded": "An updated version of Outline has been downloaded. It will be installed when you restart Outline.", "version": "Version {appVersion}", "yes": "Yes" -} \ No newline at end of file +} diff --git a/client/src/www/ui_components/app-root.js b/client/src/www/ui_components/app-root.js index 992c60813d..018af55782 100644 --- a/client/src/www/ui_components/app-root.js +++ b/client/src/www/ui_components/app-root.js @@ -53,7 +53,6 @@ import '../views/licenses_view'; // eslint-disable-next-line n/no-missing-import import '../views/servers_view'; -import './server-rename-dialog.js'; import './user-comms-dialog.js'; import {AppLocalizeBehavior} from '@polymer/app-localize-behavior/app-localize-behavior.js'; @@ -546,12 +545,6 @@ export class AppRoot extends mixinBehaviors( https://github.com/PolymerElements/paper-dialog/issues/152 and https://github.com/PolymerElements/app-layout/issues/295 Once those are fixed we can consider moving this into server-card.html --> - - - mwc-textfield { - margin-top: 0; - } - - -

[[localize('server-rename')]]

- -
- [[localize('cancel')]] - [[localize('save')]] -
-
- `, - - is: 'server-rename-dialog', - - properties: { - // Need to declare localize function passed in from parent, or else - // localize() calls within the template won't be updated. - localize: Function, - rootPath: String, - __serverName: String, - __serverId: String, - }, - - open: function (serverName, serverId) { - // Store the initial serverName so we can know if it changed, and - // store the serverId so we can emit the rename request event. - this.__serverName = serverName; - this.__serverId = serverId; - this.$.serverNameInput.value = serverName; - this.$.renameDialog.open(); - // Focus on serverNameInput, only after the dialog has been displayed. - afterNextRender(this, () => { - this.$.serverNameInput.focus(); - }); - }, - - _saveRename: function () { - const newName = this.$.serverNameInput.value; - if (newName !== this.__serverName) { - this.fire('RenameRequested', {serverId: this.__serverId, newName: newName}); - } - }, -}); diff --git a/client/src/www/views/servers_view/server_list_item/index.ts b/client/src/www/views/servers_view/server_list_item/index.ts index 8d70bf6580..e439b9a726 100644 --- a/client/src/www/views/servers_view/server_list_item/index.ts +++ b/client/src/www/views/servers_view/server_list_item/index.ts @@ -22,7 +22,7 @@ export enum ServerListItemEvent { CONNECT = 'ConnectPressed', DISCONNECT = 'DisconnectPressed', FORGET = 'ForgetPressed', - RENAME = 'ShowServerRename', + RENAME = 'RenameRequested', } /** @@ -46,4 +46,5 @@ export interface ServerListItemElement { localize: Localizer; menu: Ref; menuButton: Ref; + isRenameDialogOpen: boolean; } diff --git a/client/src/www/views/servers_view/server_list_item/server_card/index.ts b/client/src/www/views/servers_view/server_list_item/server_card/index.ts index d7e342bdb8..cc4bc99963 100644 --- a/client/src/www/views/servers_view/server_list_item/server_card/index.ts +++ b/client/src/www/views/servers_view/server_list_item/server_card/index.ts @@ -15,10 +15,11 @@ import type {Menu} from '@material/web/menu/menu'; import {Localizer} from '@outline/infrastructure/i18n'; import {css, html, LitElement} from 'lit'; -import {customElement, property} from 'lit/decorators.js'; +import {customElement, property, state} from 'lit/decorators.js'; import {createRef, Ref, ref} from 'lit/directives/ref.js'; import '../../server_connection_indicator'; +import './server_rename_dialog'; import {ServerListItem, ServerListItemElement, ServerListItemEvent} from '..'; import {ServerConnectionState} from '../../server_connection_indicator'; @@ -154,14 +155,18 @@ const getSharedComponents = (element: ServerListItemElement & LitElement) => { }; const dispatchers = { - beginRename: () => + beginRename: () => (element.isRenameDialogOpen = true), + submitRename: (event: CustomEvent) => { + element.isRenameDialogOpen = false; + element.dispatchEvent( new CustomEvent(ServerListItemEvent.RENAME, { - detail: {serverId: server.id, name: server.name}, + detail: {serverId: event.detail.id, newName: event.detail.name}, bubbles: true, composed: true, }) - ), + ); + }, forget: () => element.dispatchEvent( new CustomEvent(ServerListItemEvent.FORGET, { @@ -213,7 +218,7 @@ const getSharedComponents = (element: ServerListItemElement & LitElement) => { `, menu: html` - + ${localize('server-rename')} @@ -243,6 +248,14 @@ const getSharedComponents = (element: ServerListItemElement & LitElement) => { `, + renameDialog: html` (element.isRenameDialogOpen = false)} + @submit=${dispatchers.submitRename} + >`, }, }; }; @@ -255,6 +268,8 @@ export class ServerRowCard extends LitElement implements ServerListItemElement { @property() server: ServerListItem; @property() localize: Localizer; + @state() isRenameDialogOpen = false; + menu: Ref = createRef(); menuButton: Ref = createRef(); @@ -299,7 +314,7 @@ export class ServerRowCard extends LitElement implements ServerListItemElement { ${elements.menuButton} ${elements.footer} - ${elements.menu} + ${elements.menu} ${elements.renameDialog} `; } } @@ -315,6 +330,8 @@ export class ServerHeroCard @property() server: ServerListItem; @property() localize: Localizer; + @state() isRenameDialogOpen = false; + menu: Ref = createRef(); menuButton: Ref = createRef(); @@ -401,7 +418,7 @@ export class ServerHeroCard ${elements.footer} - ${elements.menu} + ${elements.menu} ${elements.renameDialog} `; } } diff --git a/client/src/www/views/servers_view/server_list_item/server_card/server_rename_dialog/index.ts b/client/src/www/views/servers_view/server_list_item/server_card/server_rename_dialog/index.ts new file mode 100644 index 0000000000..3334cc6c75 --- /dev/null +++ b/client/src/www/views/servers_view/server_list_item/server_card/server_rename_dialog/index.ts @@ -0,0 +1,85 @@ +/* + Copyright 2024 The Outline Authors + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + http://www.apache.org/licenses/LICENSE-2.0 + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +import type {MdFilledTextField} from '@material/web/all.js'; + +import {LitElement, html, css} from 'lit'; +import {customElement, property, state, query} from 'lit/decorators.js'; +import '@material/web/all.js'; + +@customElement('server-rename-dialog') +export class ServerRenameDialog extends LitElement { + @property({type: Boolean}) open: boolean = false; + @property({type: Function}) localize!: (key: string) => string; + @property({type: String}) serverId!: string; + @property({type: String}) serverName!: string; + + @state() internalServerName: string | null = null; + + @query('md-filled-text-field') textField: MdFilledTextField; + + static styles = css` + :host { + --md-sys-color-primary: var(--outline-primary); + --md-sys-shape-corner-extra-large: 2px; + --md-sys-shape-corner-full: 2px; + } + + fieldset { + border: none; + text-transform: uppercase; + } + `; + + render() { + if (this.internalServerName === null) { + this.internalServerName = this.serverName; + } + + return html` + +
${this.localize('server-rename')}
+ { + this.internalServerName = (e.target as HTMLInputElement).value; + }} + > +
+ ${this.localize('cancel')} + ${this.localize('save')} +
+
+ `; + } + + private handleClose() { + this.dispatchEvent(new CustomEvent('cancel')); + } + + private handleRename() { + this.dispatchEvent( + new CustomEvent('submit', { + detail: {id: this.serverId, name: this.internalServerName}, + }) + ); + } +} diff --git a/client/src/www/views/servers_view/server_list_item/server_card/server_rename_dialog/stories.ts b/client/src/www/views/servers_view/server_list_item/server_card/server_rename_dialog/stories.ts new file mode 100644 index 0000000000..8405e6a583 --- /dev/null +++ b/client/src/www/views/servers_view/server_list_item/server_card/server_rename_dialog/stories.ts @@ -0,0 +1,38 @@ +/* + Copyright 2024 The Outline Authors + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + http://www.apache.org/licenses/LICENSE-2.0 + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +import {html} from 'lit'; + +import './index'; +import {ServerRenameDialog} from './index'; +import {localize} from '../../../../../testing/localize'; + +export default { + title: 'Client/Servers View/Server List Item/Server Rename Dialog', + args: { + open: true, + serverId: 'my-server-id', + serverName: 'My Server', + }, +}; + +export const Example = ({open, serverId, serverName}: ServerRenameDialog) => { + return html` + + `; +}; diff --git a/client/src/www/views/servers_view/server_list_item/server_card/stories.ts b/client/src/www/views/servers_view/server_list_item/server_card/stories.ts index ec34aea793..ef9187d143 100644 --- a/client/src/www/views/servers_view/server_list_item/server_card/stories.ts +++ b/client/src/www/views/servers_view/server_list_item/server_card/stories.ts @@ -39,16 +39,17 @@ export default { }, }; -export const ServerRowCard = ({server}: ServerListItemElement) => - html` -
- -
- `; - -export const ServerHeroCard = ({server}: ServerListItemElement) => - html` -
- -
- `; +export const ServerRowCard = ({server}: ServerListItemElement) => html` +
+ +
+`; + +export const ServerHeroCard = ({server}: ServerListItemElement) => html` +
+ +
+`;