From d9502c7516bc2d4ae467c6ea8a2e4816b0885f37 Mon Sep 17 00:00:00 2001 From: muhamedsalih-tw <104364298+muhamedsalih-tw@users.noreply.github.com> Date: Thu, 17 Nov 2022 05:45:39 +0530 Subject: Transfrom workspace components to ts (#775) --- .../workspaces/components/CreateWorkspaceForm.js | 97 -------- .../workspaces/components/CreateWorkspaceForm.tsx | 97 ++++++++ .../workspaces/components/EditWorkspaceForm.js | 240 -------------------- .../workspaces/components/EditWorkspaceForm.tsx | 247 +++++++++++++++++++++ .../workspaces/components/WorkspaceDrawer.tsx | 7 +- .../workspaces/components/WorkspaceDrawerItem.js | 153 ------------- .../workspaces/components/WorkspaceDrawerItem.tsx | 153 +++++++++++++ .../workspaces/components/WorkspaceItem.tsx | 28 +-- .../components/WorkspaceServiceListItem.tsx | 5 +- .../workspaces/components/WorkspacesDashboard.js | 201 ----------------- .../workspaces/components/WorkspacesDashboard.tsx | 191 ++++++++++++++++ .../workspaces/containers/WorkspacesScreen.tsx | 13 +- 12 files changed, 720 insertions(+), 712 deletions(-) delete mode 100644 src/features/workspaces/components/CreateWorkspaceForm.js create mode 100644 src/features/workspaces/components/CreateWorkspaceForm.tsx delete mode 100644 src/features/workspaces/components/EditWorkspaceForm.js create mode 100644 src/features/workspaces/components/EditWorkspaceForm.tsx delete mode 100644 src/features/workspaces/components/WorkspaceDrawerItem.js create mode 100644 src/features/workspaces/components/WorkspaceDrawerItem.tsx delete mode 100644 src/features/workspaces/components/WorkspacesDashboard.js create mode 100644 src/features/workspaces/components/WorkspacesDashboard.tsx (limited to 'src/features/workspaces') diff --git a/src/features/workspaces/components/CreateWorkspaceForm.js b/src/features/workspaces/components/CreateWorkspaceForm.js deleted file mode 100644 index fac84bed0..000000000 --- a/src/features/workspaces/components/CreateWorkspaceForm.js +++ /dev/null @@ -1,97 +0,0 @@ -import { Component } from 'react'; -import PropTypes from 'prop-types'; -import { observer } from 'mobx-react'; -import { defineMessages, injectIntl } from 'react-intl'; -import injectSheet from 'react-jss'; - -import Input from '../../../components/ui/input/index'; -import Button from '../../../components/ui/button'; -import Form from '../../../lib/Form'; -import { required } from '../../../helpers/validation-helpers'; -import { workspaceStore } from '../index'; - -const messages = defineMessages({ - submitButton: { - id: 'settings.workspace.add.form.submitButton', - defaultMessage: 'Create workspace', - }, - name: { - id: 'settings.workspace.add.form.name', - defaultMessage: 'Name', - }, -}); - -const styles = { - form: { - display: 'flex', - }, - input: { - flexGrow: 1, - marginRight: '10px', - }, - submitButton: { - height: 'inherit', - }, -}; - -class CreateWorkspaceForm extends Component { - static propTypes = { - classes: PropTypes.object.isRequired, - isSubmitting: PropTypes.bool.isRequired, - onSubmit: PropTypes.func.isRequired, - }; - - form = (() => { - const { intl } = this.props; - return new Form({ - fields: { - name: { - label: intl.formatMessage(messages.name), - placeholder: intl.formatMessage(messages.name), - value: '', - validators: [required], - }, - }, - }); - })(); - - submitForm() { - const { form } = this; - form.submit({ - onSuccess: async f => { - const { onSubmit } = this.props; - const values = f.values(); - onSubmit(values); - }, - }); - } - - render() { - const { intl } = this.props; - const { classes, isSubmitting } = this.props; - const { form } = this; - return ( -
- -
- ); - } -} - -export default injectIntl( - injectSheet(styles, { injectTheme: true })(observer(CreateWorkspaceForm)), -); diff --git a/src/features/workspaces/components/CreateWorkspaceForm.tsx b/src/features/workspaces/components/CreateWorkspaceForm.tsx new file mode 100644 index 000000000..eafe9f36a --- /dev/null +++ b/src/features/workspaces/components/CreateWorkspaceForm.tsx @@ -0,0 +1,97 @@ +import { Component, ReactElement } from 'react'; +import { observer } from 'mobx-react'; +import { defineMessages, injectIntl, WrappedComponentProps } from 'react-intl'; +import withStyles, { WithStylesProps } from 'react-jss'; +import Input from '../../../components/ui/input/index'; +import Button from '../../../components/ui/button'; +import Form from '../../../lib/Form'; +import { required } from '../../../helpers/validation-helpers'; +import { workspaceStore } from '../index'; + +const messages = defineMessages({ + submitButton: { + id: 'settings.workspace.add.form.submitButton', + defaultMessage: 'Create workspace', + }, + name: { + id: 'settings.workspace.add.form.name', + defaultMessage: 'Name', + }, +}); + +const styles = { + form: { + display: 'flex', + }, + input: { + flexGrow: 1, + marginRight: '10px', + }, + submitButton: { + height: 'inherit', + }, +}; + +interface IProps extends WithStylesProps, WrappedComponentProps { + isSubmitting: boolean; + onSubmit: (...args: any[]) => void; +} + +@observer +class CreateWorkspaceForm extends Component { + form: Form; + + constructor(props: IProps) { + super(props); + + this.form = new Form({ + fields: { + name: { + label: this.props.intl.formatMessage(messages.name), + placeholder: this.props.intl.formatMessage(messages.name), + value: '', + validators: [required], + }, + }, + }); + } + + submitForm(): void { + this.form.submit({ + onSuccess: async form => { + const { onSubmit } = this.props; + const values = form.values(); + onSubmit(values); + }, + }); + } + + render(): ReactElement { + const { classes, isSubmitting, intl } = this.props; + const { form } = this; + + return ( +
+ +
+ ); + } +} + +export default injectIntl( + withStyles(styles, { injectTheme: true })(CreateWorkspaceForm), +); diff --git a/src/features/workspaces/components/EditWorkspaceForm.js b/src/features/workspaces/components/EditWorkspaceForm.js deleted file mode 100644 index ff4e71260..000000000 --- a/src/features/workspaces/components/EditWorkspaceForm.js +++ /dev/null @@ -1,240 +0,0 @@ -import { Component } from 'react'; -import PropTypes from 'prop-types'; -import { observer } from 'mobx-react'; -import { defineMessages, injectIntl } from 'react-intl'; -import { Link } from 'react-router-dom'; -import injectSheet from 'react-jss'; -import Infobox from '../../../components/ui/infobox/index'; -import Input from '../../../components/ui/input/index'; -import Button from '../../../components/ui/button'; -import Workspace from '../models/Workspace'; -import Service from '../../../models/Service'; -import Form from '../../../lib/Form'; -import { required } from '../../../helpers/validation-helpers'; -import WorkspaceServiceListItem from './WorkspaceServiceListItem'; -import Request from '../../../stores/lib/Request'; -import { KEEP_WS_LOADED_USID } from '../../../config'; -import Toggle from '../../../components/ui/toggle'; -import { H2 } from '../../../components/ui/headline'; - -const messages = defineMessages({ - buttonDelete: { - id: 'settings.workspace.form.buttonDelete', - defaultMessage: 'Delete workspace', - }, - buttonSave: { - id: 'settings.workspace.form.buttonSave', - defaultMessage: 'Save workspace', - }, - name: { - id: 'settings.workspace.form.name', - defaultMessage: 'Name', - }, - yourWorkspaces: { - id: 'settings.workspace.form.yourWorkspaces', - defaultMessage: 'Your workspaces', - }, - keepLoaded: { - id: 'settings.workspace.form.keepLoaded', - defaultMessage: 'Keep this workspace loaded*', - }, - keepLoadedInfo: { - id: 'settings.workspace.form.keepLoadedInfo', - defaultMessage: - '*This option will be overwritten by the global "Keep all workspaces loaded" option.', - }, - servicesInWorkspaceHeadline: { - id: 'settings.workspace.form.servicesInWorkspaceHeadline', - defaultMessage: 'Services in this Workspace', - }, - noServicesAdded: { - id: 'settings.services.noServicesAdded', - defaultMessage: 'Start by adding a service.', - }, - discoverServices: { - id: 'settings.services.discoverServices', - defaultMessage: 'Discover services', - }, -}); - -const styles = { - nameInput: { - height: 'auto', - }, - serviceList: { - height: 'auto', - }, - keepLoadedInfo: { - marginBottom: '2rem !important', - }, -}; - -class EditWorkspaceForm extends Component { - static propTypes = { - classes: PropTypes.object.isRequired, - onDelete: PropTypes.func.isRequired, - onSave: PropTypes.func.isRequired, - services: PropTypes.arrayOf(PropTypes.instanceOf(Service)).isRequired, - workspace: PropTypes.instanceOf(Workspace).isRequired, - updateWorkspaceRequest: PropTypes.instanceOf(Request).isRequired, - deleteWorkspaceRequest: PropTypes.instanceOf(Request).isRequired, - }; - - form = this.prepareWorkspaceForm(this.props.workspace); - - // eslint-disable-next-line react/no-deprecated - componentWillReceiveProps(nextProps) { - const { workspace } = this.props; - if (workspace.id !== nextProps.workspace.id) { - this.form = this.prepareWorkspaceForm(nextProps.workspace); - } - } - - prepareWorkspaceForm(workspace) { - const { intl, updateWorkspaceRequest } = this.props; - updateWorkspaceRequest.reset(); - return new Form({ - fields: { - name: { - label: intl.formatMessage(messages.name), - placeholder: intl.formatMessage(messages.name), - value: workspace.name, - validators: [required], - }, - keepLoaded: { - label: intl.formatMessage(messages.keepLoaded), - value: workspace.services.includes(KEEP_WS_LOADED_USID), - default: false, - }, - services: { - value: [...workspace.services], - }, - }, - }); - } - - save(form) { - this.props.updateWorkspaceRequest.reset(); - form.submit({ - onSuccess: async f => { - const { onSave } = this.props; - const values = f.values(); - onSave(values); - }, - onError: async () => {}, - }); - } - - delete() { - const { onDelete } = this.props; - onDelete(); - } - - toggleService(service) { - const servicesField = this.form.$('services'); - const serviceIds = servicesField.value; - if (serviceIds.includes(service.id)) { - serviceIds.splice(serviceIds.indexOf(service.id), 1); - } else { - serviceIds.push(service.id); - } - servicesField.set(serviceIds); - } - - render() { - const { intl } = this.props; - const { - classes, - workspace, - services, - deleteWorkspaceRequest, - updateWorkspaceRequest, - } = this.props; - const { form } = this; - const workspaceServices = form.$('services').value; - const isDeleting = deleteWorkspaceRequest.isExecuting; - const isSaving = updateWorkspaceRequest.isExecuting; - return ( -
-
- - - {intl.formatMessage(messages.yourWorkspaces)} - - - - {workspace.name} -
-
- {updateWorkspaceRequest.error && ( - - Error while saving workspace - - )} -
- - -

- {intl.formatMessage(messages.keepLoadedInfo)} -

-
-

{intl.formatMessage(messages.servicesInWorkspaceHeadline)}

-
- {services.length === 0 ? ( -
- {/* ===== Empty state ===== */} -

- - - - {intl.formatMessage(messages.noServicesAdded)} -

- - {intl.formatMessage(messages.discoverServices)} - -
- ) : ( - <> - {services.map(s => ( - this.toggleService(s)} - /> - ))} - - )} -
-
-
- {/* ===== Delete Button ===== */} -
-
- ); - } -} - -export default injectIntl( - injectSheet(styles, { injectTheme: true })(observer(EditWorkspaceForm)), -); diff --git a/src/features/workspaces/components/EditWorkspaceForm.tsx b/src/features/workspaces/components/EditWorkspaceForm.tsx new file mode 100644 index 000000000..a860ac2e8 --- /dev/null +++ b/src/features/workspaces/components/EditWorkspaceForm.tsx @@ -0,0 +1,247 @@ +import { Component, ReactElement } from 'react'; +import { observer } from 'mobx-react'; +import { defineMessages, injectIntl, WrappedComponentProps } from 'react-intl'; +import { Link } from 'react-router-dom'; +import withStyles, { WithStylesProps } from 'react-jss'; +import Infobox from '../../../components/ui/infobox/index'; +import Input from '../../../components/ui/input'; +import Button from '../../../components/ui/button'; +import Workspace from '../models/Workspace'; +import Service from '../../../models/Service'; +import Form from '../../../lib/Form'; +import { required } from '../../../helpers/validation-helpers'; +import WorkspaceServiceListItem from './WorkspaceServiceListItem'; +import Request from '../../../stores/lib/Request'; +import { KEEP_WS_LOADED_USID } from '../../../config'; +import Toggle from '../../../components/ui/toggle'; +import { H2 } from '../../../components/ui/headline'; + +const messages = defineMessages({ + buttonDelete: { + id: 'settings.workspace.form.buttonDelete', + defaultMessage: 'Delete workspace', + }, + buttonSave: { + id: 'settings.workspace.form.buttonSave', + defaultMessage: 'Save workspace', + }, + name: { + id: 'settings.workspace.form.name', + defaultMessage: 'Name', + }, + yourWorkspaces: { + id: 'settings.workspace.form.yourWorkspaces', + defaultMessage: 'Your workspaces', + }, + keepLoaded: { + id: 'settings.workspace.form.keepLoaded', + defaultMessage: 'Keep this workspace loaded*', + }, + keepLoadedInfo: { + id: 'settings.workspace.form.keepLoadedInfo', + defaultMessage: + '*This option will be overwritten by the global "Keep all workspaces loaded" option.', + }, + servicesInWorkspaceHeadline: { + id: 'settings.workspace.form.servicesInWorkspaceHeadline', + defaultMessage: 'Services in this Workspace', + }, + noServicesAdded: { + id: 'settings.services.noServicesAdded', + defaultMessage: 'Start by adding a service.', + }, + discoverServices: { + id: 'settings.services.discoverServices', + defaultMessage: 'Discover services', + }, +}); + +const styles = { + nameInput: { + height: 'auto', + }, + serviceList: { + height: 'auto', + }, + keepLoadedInfo: { + marginBottom: '2rem !important', + }, +}; + +interface IProps extends WithStylesProps, WrappedComponentProps { + onDelete: () => void; + onSave: (...args: any[]) => void; + services: Service[]; + workspace: Workspace; + updateWorkspaceRequest: Request; + deleteWorkspaceRequest: Request; +} + +@observer +class EditWorkspaceForm extends Component { + form: Form; + + constructor(props: IProps) { + super(props); + + this.form = this.prepareWorkspaceForm(this.props.workspace); + } + + UNSAFE_componentWillReceiveProps(nextProps): void { + const { workspace } = this.props; + if (workspace.id !== nextProps.workspace.id) { + this.form = this.prepareWorkspaceForm(nextProps.workspace); + } + } + + prepareWorkspaceForm(workspace: Workspace): Form { + const { intl, updateWorkspaceRequest } = this.props; + updateWorkspaceRequest.reset(); + + return new Form({ + fields: { + name: { + label: intl.formatMessage(messages.name), + placeholder: intl.formatMessage(messages.name), + value: workspace.name, + validators: [required], + }, + keepLoaded: { + label: intl.formatMessage(messages.keepLoaded), + value: workspace.services.includes(KEEP_WS_LOADED_USID), + default: false, + type: 'checkbox', + }, + services: { + value: [...workspace.services], + }, + }, + }); + } + + save(form): void { + this.props.updateWorkspaceRequest.reset(); + form.submit({ + onSuccess: async f => { + const { onSave } = this.props; + const values = f.values(); + onSave(values); + }, + onError: async () => {}, + }); + } + + delete(): void { + const { onDelete } = this.props; + onDelete(); + } + + toggleService(service: Service): void { + const servicesField = this.form.$('services'); + const serviceIds = servicesField.value; + if (serviceIds.includes(service.id)) { + serviceIds.splice(serviceIds.indexOf(service.id), 1); + } else { + serviceIds.push(service.id); + } + servicesField.set(serviceIds); + } + + render(): ReactElement { + const { + classes, + workspace, + services, + deleteWorkspaceRequest, + updateWorkspaceRequest, + intl, + } = this.props; + const { form } = this; + const workspaceServices = form.$('services').value; + const isDeleting = deleteWorkspaceRequest.isExecuting; + const isSaving = updateWorkspaceRequest.isExecuting; + + return ( +
+
+ + + {intl.formatMessage(messages.yourWorkspaces)} + + + + {workspace.name} +
+
+ {updateWorkspaceRequest.error && ( + + Error while saving workspace + + )} +
+ + +

+ {intl.formatMessage(messages.keepLoadedInfo)} +

+
+

{intl.formatMessage(messages.servicesInWorkspaceHeadline)}

+
+ {services.length === 0 ? ( +
+ {/* ===== Empty state ===== */} +

+ + + + {intl.formatMessage(messages.noServicesAdded)} +

+ + {intl.formatMessage(messages.discoverServices)} + +
+ ) : ( + <> + {services.map(service => ( + this.toggleService(service)} + /> + ))} + + )} +
+
+
+ {/* ===== Delete Button ===== */} +
+
+ ); + } +} + +export default injectIntl( + withStyles(styles, { injectTheme: true })(EditWorkspaceForm), +); diff --git a/src/features/workspaces/components/WorkspaceDrawer.tsx b/src/features/workspaces/components/WorkspaceDrawer.tsx index bdbebdb0a..61284d81a 100644 --- a/src/features/workspaces/components/WorkspaceDrawer.tsx +++ b/src/features/workspaces/components/WorkspaceDrawer.tsx @@ -11,7 +11,6 @@ import WorkspaceDrawerItem from './WorkspaceDrawerItem'; import workspaceActions from '../actions'; import { workspaceStore } from '../index'; import { getUserWorkspacesRequest } from '../api'; -import Service from '../../../models/Service'; import Workspace from '../models/Workspace'; const messages = defineMessages({ @@ -90,7 +89,7 @@ const styles = theme => ({ }); interface IProps extends WithStylesProps, WrappedComponentProps { - getServicesForWorkspace: (workspace: Workspace | null) => Service[]; + getServicesForWorkspace: (workspace: Workspace | null) => string[]; } @observer @@ -150,7 +149,9 @@ class WorkspaceDrawer extends Component { name={workspace.name} isActive={actualWorkspace === workspace} onClick={() => { - if (actualWorkspace === workspace) return; + if (actualWorkspace === workspace) { + return; + } workspaceActions.activate({ workspace }); workspaceActions.toggleWorkspaceDrawer(); }} diff --git a/src/features/workspaces/components/WorkspaceDrawerItem.js b/src/features/workspaces/components/WorkspaceDrawerItem.js deleted file mode 100644 index 22c0a39d9..000000000 --- a/src/features/workspaces/components/WorkspaceDrawerItem.js +++ /dev/null @@ -1,153 +0,0 @@ -import { Menu } from '@electron/remote'; -import { Component } from 'react'; -import PropTypes from 'prop-types'; -import { observer } from 'mobx-react'; -import injectSheet from 'react-jss'; -import classnames from 'classnames'; -import { defineMessages, injectIntl } from 'react-intl'; -import { altKey, cmdOrCtrlShortcutKey } from '../../../environment'; - -const messages = defineMessages({ - noServicesAddedYet: { - id: 'workspaceDrawer.item.noServicesAddedYet', - defaultMessage: 'No services added yet', - }, - contextMenuEdit: { - id: 'workspaceDrawer.item.contextMenuEdit', - defaultMessage: 'edit', - }, -}); - -let itemTransition = 'none'; - -if (window && window.matchMedia('(prefers-reduced-motion: no-preference)')) { - itemTransition = 'background-color 300ms ease-out'; -} - -const styles = theme => ({ - item: { - height: '67px', - padding: `15px ${theme.workspaces.drawer.padding}px`, - borderBottom: `1px solid ${theme.workspaces.drawer.listItem.border}`, - transition: itemTransition, - '&:first-child': { - borderTop: `1px solid ${theme.workspaces.drawer.listItem.border}`, - }, - '&:hover': { - backgroundColor: theme.workspaces.drawer.listItem.hoverBackground, - }, - }, - isActiveItem: { - backgroundColor: theme.workspaces.drawer.listItem.activeBackground, - '&:hover': { - backgroundColor: theme.workspaces.drawer.listItem.activeBackground, - }, - }, - name: { - marginTop: '4px', - color: theme.workspaces.drawer.listItem.name.color, - }, - activeName: { - color: theme.workspaces.drawer.listItem.name.activeColor, - }, - services: { - display: 'block', - fontSize: '11px', - marginTop: '5px', - color: theme.workspaces.drawer.listItem.services.color, - whiteSpace: 'nowrap', - textOverflow: 'ellipsis', - overflow: 'hidden', - lineHeight: '15px', - }, - activeServices: { - color: theme.workspaces.drawer.listItem.services.active, - }, -}); - -class WorkspaceDrawerItem extends Component { - static propTypes = { - classes: PropTypes.object.isRequired, - isActive: PropTypes.bool.isRequired, - name: PropTypes.string.isRequired, - onClick: PropTypes.func.isRequired, - services: PropTypes.arrayOf(PropTypes.string).isRequired, - onContextMenuEditClick: PropTypes.func, - shortcutIndex: PropTypes.number.isRequired, - }; - - static defaultProps = { - onContextMenuEditClick: null, - }; - - render() { - const { - classes, - isActive, - name, - onClick, - onContextMenuEditClick, - services, - shortcutIndex, - } = this.props; - - const { intl } = this.props; - - const contextMenuTemplate = [ - { - label: name, - enabled: false, - }, - { - type: 'separator', - }, - { - label: intl.formatMessage(messages.contextMenuEdit), - click: onContextMenuEditClick, - }, - ]; - - const contextMenu = Menu.buildFromTemplate(contextMenuTemplate); - - return ( -
onContextMenuEditClick && contextMenu.popup()} - data-tip={`${ - shortcutIndex <= 9 - ? `(${cmdOrCtrlShortcutKey(false)}+${altKey( - false, - )}+${shortcutIndex})` - : '' - }`} - > - - {name} - - - {services.length > 0 - ? services.join(', ') - : intl.formatMessage(messages.noServicesAddedYet)} - -
- ); - } -} - -export default injectIntl( - injectSheet(styles, { injectTheme: true })(observer(WorkspaceDrawerItem)), -); diff --git a/src/features/workspaces/components/WorkspaceDrawerItem.tsx b/src/features/workspaces/components/WorkspaceDrawerItem.tsx new file mode 100644 index 000000000..0ad56d1ae --- /dev/null +++ b/src/features/workspaces/components/WorkspaceDrawerItem.tsx @@ -0,0 +1,153 @@ +import { Component, MouseEventHandler, ReactElement } from 'react'; +import { observer } from 'mobx-react'; +import withStyles, { WithStylesProps } from 'react-jss'; +import classnames from 'classnames'; +import { defineMessages, injectIntl, WrappedComponentProps } from 'react-intl'; +import { noop } from 'lodash'; +import { Menu } from '@electron/remote'; +import { MenuItemConstructorOptions } from 'electron'; +import { altKey, cmdOrCtrlShortcutKey } from '../../../environment'; + +const messages = defineMessages({ + noServicesAddedYet: { + id: 'workspaceDrawer.item.noServicesAddedYet', + defaultMessage: 'No services added yet', + }, + contextMenuEdit: { + id: 'workspaceDrawer.item.contextMenuEdit', + defaultMessage: 'edit', + }, +}); + +const itemTransition = + window && window.matchMedia('(prefers-reduced-motion: no-preference)') + ? 'background-color 300ms ease-out' + : 'none'; + +const styles = theme => ({ + item: { + height: '67px', + padding: `15px ${theme.workspaces.drawer.padding}px`, + borderBottom: `1px solid ${theme.workspaces.drawer.listItem.border}`, + transition: itemTransition, + '&:first-child': { + borderTop: `1px solid ${theme.workspaces.drawer.listItem.border}`, + }, + '&:hover': { + backgroundColor: theme.workspaces.drawer.listItem.hoverBackground, + }, + }, + isActiveItem: { + backgroundColor: theme.workspaces.drawer.listItem.activeBackground, + '&:hover': { + backgroundColor: theme.workspaces.drawer.listItem.activeBackground, + }, + }, + name: { + marginTop: '4px', + color: theme.workspaces.drawer.listItem.name.color, + }, + activeName: { + color: theme.workspaces.drawer.listItem.name.activeColor, + }, + services: { + display: 'block', + fontSize: '11px', + marginTop: '5px', + color: theme.workspaces.drawer.listItem.services.color, + whiteSpace: 'nowrap', + textOverflow: 'ellipsis', + overflow: 'hidden', + lineHeight: '15px', + }, + activeServices: { + color: theme.workspaces.drawer.listItem.services.active, + }, +}); + +interface IProps extends WithStylesProps, WrappedComponentProps { + isActive: boolean; + name: string; + onClick: MouseEventHandler; + services: string[]; + onContextMenuEditClick?: () => void | null; + shortcutIndex: number; +} + +@observer +class WorkspaceDrawerItem extends Component { + render(): ReactElement { + const { + classes, + isActive, + name, + onClick, + onContextMenuEditClick = null, + services, + shortcutIndex, + intl, + } = this.props; + + const contextMenuTemplate: MenuItemConstructorOptions[] = [ + { + label: name, + enabled: false, + }, + { + type: 'separator', + }, + { + label: intl.formatMessage(messages.contextMenuEdit), + click: onContextMenuEditClick || noop, + }, + ]; + + const contextMenu = Menu.buildFromTemplate(contextMenuTemplate); + + return ( +
{ + if (onContextMenuEditClick) { + contextMenu.popup(); + } + }} + onKeyDown={noop} + data-tip={`${ + shortcutIndex <= 9 + ? `(${cmdOrCtrlShortcutKey(false)}+${altKey( + false, + )}+${shortcutIndex})` + : '' + }`} + > + + {name} + + + {services.length > 0 + ? services.join(', ') + : intl.formatMessage(messages.noServicesAddedYet)} + +
+ ); + } +} + +export default injectIntl( + withStyles(styles, { injectTheme: true })(WorkspaceDrawerItem), +); diff --git a/src/features/workspaces/components/WorkspaceItem.tsx b/src/features/workspaces/components/WorkspaceItem.tsx index eb33a0376..b097a8298 100644 --- a/src/features/workspaces/components/WorkspaceItem.tsx +++ b/src/features/workspaces/components/WorkspaceItem.tsx @@ -1,6 +1,8 @@ -import { Component } from 'react'; +/* eslint-disable jsx-a11y/no-noninteractive-element-interactions */ // TODO - [TS DEBT] Need to check and remove it +import { Component, ReactElement } from 'react'; import { observer } from 'mobx-react'; -import injectSheet from 'react-jss'; +import withStyles, { WithStylesProps } from 'react-jss'; +import { noop } from 'lodash'; import Workspace from '../models/Workspace'; const styles = theme => ({ @@ -14,24 +16,24 @@ const styles = theme => ({ columnName: {}, }); -type Props = { - classes: any; - workspace: typeof Workspace; - onItemClick: (workspace) => void; -}; +interface IProps extends WithStylesProps { + workspace: Workspace; + onItemClick: (workspace: Workspace) => void; +} -class WorkspaceItem extends Component { - render() { +@observer +class WorkspaceItem extends Component { + render(): ReactElement { const { classes, workspace, onItemClick } = this.props; return ( - onItemClick(workspace)}>{workspace.name} + onItemClick(workspace)} onKeyDown={noop}> + {workspace.name} + ); } } -export default injectSheet(styles, { injectTheme: true })( - observer(WorkspaceItem), -); +export default withStyles(styles, { injectTheme: true })(WorkspaceItem); diff --git a/src/features/workspaces/components/WorkspaceServiceListItem.tsx b/src/features/workspaces/components/WorkspaceServiceListItem.tsx index e708d5cdf..9034be37c 100644 --- a/src/features/workspaces/components/WorkspaceServiceListItem.tsx +++ b/src/features/workspaces/components/WorkspaceServiceListItem.tsx @@ -2,6 +2,7 @@ import { Component, ReactElement } from 'react'; import { observer } from 'mobx-react'; import withStyles, { WithStylesProps } from 'react-jss'; import classnames from 'classnames'; +import { noop } from 'lodash'; import Toggle from '../../../components/ui/toggle'; import ServiceIcon from '../../../components/ui/ServiceIcon'; import Service from '../../../models/Service'; @@ -39,9 +40,9 @@ interface IProps extends WithStylesProps { class WorkspaceServiceListItem extends Component { render(): ReactElement { const { classes, isInWorkspace, onToggle, service } = this.props; - return ( -
+ // onclick in below div used to fix bug raised under toggle duplicate component removal +
-
-

{intl.formatMessage(messages.headline)}

-
-
- {/* ===== Workspace updated info ===== */} - {updateWorkspaceRequest.wasExecuted && updateWorkspaceRequest.result && ( - - - {intl.formatMessage(messages.updatedInfo)} - - - )} - - {/* ===== Workspace deleted info ===== */} - {deleteWorkspaceRequest.wasExecuted && deleteWorkspaceRequest.result && ( - - - {intl.formatMessage(messages.deletedInfo)} - - - )} - - {/* ===== Create workspace form ===== */} -
- -
- {getUserWorkspacesRequest.isExecuting ? ( - - ) : ( - <> - {/* ===== Workspace could not be loaded error ===== */} - {getUserWorkspacesRequest.error ? ( - - {intl.formatMessage(messages.workspacesRequestFailed)} - - ) : ( - <> - {workspaces.length === 0 ? ( -
- {/* ===== Workspaces empty state ===== */} -

- - - - {intl.formatMessage(messages.noServicesAdded)} -

-
- ) : ( - - {/* ===== Workspaces list ===== */} - - {workspaces.map(workspace => ( - onWorkspaceClick(w)} - /> - ))} - -
- )} - - )} - - )} -
-
- ); - } -} - -export default injectIntl( - inject('stores')( - injectSheet(styles, { injectTheme: true })(observer(WorkspacesDashboard)), - ), -); - -WorkspacesDashboard.propTypes = { - stores: PropTypes.shape({ - ui: PropTypes.instanceOf(UIStore).isRequired, - }).isRequired, -}; diff --git a/src/features/workspaces/components/WorkspacesDashboard.tsx b/src/features/workspaces/components/WorkspacesDashboard.tsx new file mode 100644 index 000000000..60fc7a0ce --- /dev/null +++ b/src/features/workspaces/components/WorkspacesDashboard.tsx @@ -0,0 +1,191 @@ +/* eslint-disable react/jsx-no-useless-fragment */ +import { Component, ReactElement } from 'react'; +import { observer } from 'mobx-react'; +import { defineMessages, injectIntl, WrappedComponentProps } from 'react-intl'; +import withStyles, { WithStylesProps } from 'react-jss'; +import Infobox from '../../../components/ui/infobox/index'; +import Loader from '../../../components/ui/Loader'; +import WorkspaceItem from './WorkspaceItem'; +import CreateWorkspaceForm from './CreateWorkspaceForm'; +import Request from '../../../stores/lib/Request'; +import Appear from '../../../components/ui/effects/Appear'; +import { H1 } from '../../../components/ui/headline'; +import Workspace from '../models/Workspace'; + +const messages = defineMessages({ + headline: { + id: 'settings.workspaces.headline', + defaultMessage: 'Your workspaces', + }, + noServicesAdded: { + id: 'settings.workspaces.noWorkspacesAdded', + defaultMessage: "You haven't created any workspaces yet.", + }, + workspacesRequestFailed: { + id: 'settings.workspaces.workspacesRequestFailed', + defaultMessage: 'Could not load your workspaces', + }, + tryReloadWorkspaces: { + id: 'settings.workspaces.tryReloadWorkspaces', + defaultMessage: 'Try again', + }, + updatedInfo: { + id: 'settings.workspaces.updatedInfo', + defaultMessage: 'Your changes have been saved', + }, + deletedInfo: { + id: 'settings.workspaces.deletedInfo', + defaultMessage: 'Workspace has been deleted', + }, + workspaceFeatureInfo: { + id: 'settings.workspaces.workspaceFeatureInfo', + defaultMessage: + 'Ferdium Workspaces let you focus on what’s important right now. Set up different sets of services and easily switch between them at any time. You decide which services you need when and where, so we can help you stay on top of your game - or easily switch off from work whenever you want.', + }, + workspaceFeatureHeadline: { + id: 'settings.workspaces.workspaceFeatureHeadline', + defaultMessage: 'Less is More: Introducing Ferdium Workspaces', + }, +}); + +const styles = { + table: { + width: '100%', + '& td': { + padding: '10px', + }, + }, + createForm: { + height: 'auto', + }, + appear: { + height: 'auto', + }, + teaserImage: { + width: 250, + margin: [-8, 0, 0, 20], + alignSelf: 'center', + }, +}; + +interface IProps extends WithStylesProps, WrappedComponentProps { + getUserWorkspacesRequest: Request; + createWorkspaceRequest: Request; + deleteWorkspaceRequest: Request; + updateWorkspaceRequest: Request; + onCreateWorkspaceSubmit: (workspace: Workspace) => void; + onWorkspaceClick: (workspace: Workspace) => void; + workspaces: Workspace[]; +} + +@observer +class WorkspacesDashboard extends Component { + render(): ReactElement { + const { + classes, + getUserWorkspacesRequest, + createWorkspaceRequest, + deleteWorkspaceRequest, + updateWorkspaceRequest, + onCreateWorkspaceSubmit, + onWorkspaceClick, + workspaces, + } = this.props; + + const { intl } = this.props; + + return ( +
+
+

{intl.formatMessage(messages.headline)}

+
+
+ {/* ===== Workspace updated info ===== */} + {updateWorkspaceRequest.wasExecuted && updateWorkspaceRequest.result && ( + + + {intl.formatMessage(messages.updatedInfo)} + + + )} + + {/* ===== Workspace deleted info ===== */} + {deleteWorkspaceRequest.wasExecuted && deleteWorkspaceRequest.result && ( + + + {intl.formatMessage(messages.deletedInfo)} + + + )} + + {/* ===== Create workspace form ===== */} +
+ +
+ {getUserWorkspacesRequest.isExecuting ? ( + + ) : ( + <> + {/* ===== Workspace could not be loaded error ===== */} + {getUserWorkspacesRequest.error ? ( + + {intl.formatMessage(messages.workspacesRequestFailed)} + + ) : ( + <> + {workspaces.length === 0 ? ( +
+ {/* ===== Workspaces empty state ===== */} +

+ + + + {intl.formatMessage(messages.noServicesAdded)} +

+
+ ) : ( + + {/* ===== Workspaces list ===== */} + + {workspaces.map(workspace => ( + onWorkspaceClick(w)} + /> + ))} + +
+ )} + + )} + + )} +
+
+ ); + } +} + +export default injectIntl( + withStyles(styles, { injectTheme: true })(WorkspacesDashboard), +); diff --git a/src/features/workspaces/containers/WorkspacesScreen.tsx b/src/features/workspaces/containers/WorkspacesScreen.tsx index d43dc5efa..39f19935f 100644 --- a/src/features/workspaces/containers/WorkspacesScreen.tsx +++ b/src/features/workspaces/containers/WorkspacesScreen.tsx @@ -10,8 +10,13 @@ import { getUserWorkspacesRequest, updateWorkspaceRequest, } from '../api'; +import Workspace from '../models/Workspace'; -class WorkspacesScreen extends Component { +interface IProps extends StoresProps {} + +@inject('stores', 'actions') +@observer +class WorkspacesScreen extends Component { render() { const { actions } = this.props; return ( @@ -23,11 +28,13 @@ class WorkspacesScreen extends Component { deleteWorkspaceRequest={deleteWorkspaceRequest} updateWorkspaceRequest={updateWorkspaceRequest} onCreateWorkspaceSubmit={data => actions.workspaces.create(data)} - onWorkspaceClick={w => actions.workspaces.edit({ workspace: w })} + onWorkspaceClick={(workspace: Workspace) => + actions.workspaces.edit({ workspace }) + } /> ); } } -export default inject('stores', 'actions')(observer(WorkspacesScreen)); +export default WorkspacesScreen; -- cgit v1.2.3-70-g09d2