From d4101a48b3eee8b1fb177831aa02a4b4fbec2588 Mon Sep 17 00:00:00 2001 From: Markus Hatvan Date: Sat, 18 Sep 2021 11:15:25 +0200 Subject: chore: convert various files from JS to TS (#1959) --- src/features/appearance/index.js | 259 ---------------------------- src/features/appearance/index.ts | 250 +++++++++++++++++++++++++++ src/features/basicAuth/Form.js | 17 -- src/features/basicAuth/Form.ts | 17 ++ src/features/basicAuth/mainIpcHandler.js | 9 - src/features/basicAuth/mainIpcHandler.ts | 11 ++ src/features/basicAuth/store.js | 30 ---- src/features/basicAuth/store.ts | 30 ++++ src/features/basicAuth/styles.js | 12 -- src/features/basicAuth/styles.ts | 12 ++ src/features/communityRecipes/index.js | 7 - src/features/communityRecipes/index.ts | 7 + src/features/utils/ActionBinding.js | 29 ---- src/features/utils/ActionBinding.ts | 29 ++++ src/features/workspaces/actions.js | 27 --- src/features/workspaces/actions.ts | 30 ++++ src/features/workspaces/api.js | 66 ------- src/features/workspaces/api.ts | 86 +++++++++ src/features/workspaces/constants.js | 4 - src/features/workspaces/constants.ts | 4 + src/features/workspaces/index.js | 30 ---- src/features/workspaces/index.ts | 28 +++ src/features/workspaces/models/Workspace.js | 37 ---- src/features/workspaces/models/Workspace.ts | 39 +++++ 24 files changed, 543 insertions(+), 527 deletions(-) delete mode 100644 src/features/appearance/index.js create mode 100644 src/features/appearance/index.ts delete mode 100644 src/features/basicAuth/Form.js create mode 100644 src/features/basicAuth/Form.ts delete mode 100644 src/features/basicAuth/mainIpcHandler.js create mode 100644 src/features/basicAuth/mainIpcHandler.ts delete mode 100644 src/features/basicAuth/store.js create mode 100644 src/features/basicAuth/store.ts delete mode 100644 src/features/basicAuth/styles.js create mode 100644 src/features/basicAuth/styles.ts delete mode 100644 src/features/communityRecipes/index.js create mode 100644 src/features/communityRecipes/index.ts delete mode 100644 src/features/utils/ActionBinding.js create mode 100644 src/features/utils/ActionBinding.ts delete mode 100644 src/features/workspaces/actions.js create mode 100644 src/features/workspaces/actions.ts delete mode 100644 src/features/workspaces/api.js create mode 100644 src/features/workspaces/api.ts delete mode 100644 src/features/workspaces/constants.js create mode 100644 src/features/workspaces/constants.ts delete mode 100644 src/features/workspaces/index.js create mode 100644 src/features/workspaces/index.ts delete mode 100644 src/features/workspaces/models/Workspace.js create mode 100644 src/features/workspaces/models/Workspace.ts (limited to 'src/features') diff --git a/src/features/appearance/index.js b/src/features/appearance/index.js deleted file mode 100644 index 0c935be32..000000000 --- a/src/features/appearance/index.js +++ /dev/null @@ -1,259 +0,0 @@ -import color from 'color'; -import { reaction } from 'mobx'; -import themeInfo from '../../assets/themeInfo.json'; -import { iconSizeBias } from '../../config'; -import { DEFAULT_APP_SETTINGS } from '../../environment'; - -const STYLE_ELEMENT_ID = 'custom-appearance-style'; - -function createStyleElement() { - const styles = document.createElement('style'); - styles.id = STYLE_ELEMENT_ID; - - document.querySelector('head')?.appendChild(styles); -} - -function setAppearance(style) { - const styleElement = document.querySelector(`#${STYLE_ELEMENT_ID}`); - - if (styleElement) { - styleElement.innerHTML = style; - } -} - -// See https://github.com/Qix-/color/issues/53#issuecomment-656590710 -function darkenAbsolute(originalColor, absoluteChange) { - const originalLightness = originalColor.lightness(); - return originalColor.lightness(originalLightness - absoluteChange); -} - -function generateAccentStyle(accentColorStr) { - let style = ''; - - for (const property of Object.keys(themeInfo)) { - style += ` - ${themeInfo[property]} { - ${property}: ${accentColorStr}; - } - `; - } - - let accentColor = color(DEFAULT_APP_SETTINGS.accentColor); - try { - accentColor = color(accentColorStr); - } catch { - // Ignore invalid accent color. - } - const darkerColorStr = darkenAbsolute(accentColor, 5).hex(); - style += ` - a.button:hover, button.button:hover { - background: ${darkenAbsolute(accentColor, 10).hex()}; - } - - .franz-form__button:hover, - .franz-form__button.franz-form__button--inverted:hover, - .settings .settings__close:hover, - .theme__dark .franz-form__button:hover, - .theme__dark .franz-form__button.franz-form__button--inverted:hover, - .theme__dark .settings .settings__close:hover { - background: ${darkerColorStr}; - } - - .franz-form__button:active, - .theme__dark .franz-form__button:active { - background: ${darkerColorStr}; - } - - .theme__dark .franz-form__button.franz-form__button--inverted, - .franz-form__button.franz-form__button--inverted { - background: none; - border-color: ${accentColorStr}; - } - - .tab-item.is-active { - background: ${accentColor.lighten(0.35).hex()}; - } - `; - - return style; -} - -function generateServiceRibbonWidthStyle(widthStr, iconSizeStr, vertical) { - const width = Number(widthStr); - const iconSize = Number(iconSizeStr) - iconSizeBias; - - return vertical - ? ` - .tab-item { - width: ${width - 2}px !important; - height: ${width - 5 + iconSize}px !important; - min-height: unset; - } - .tab-item .tab-item__icon { - width: ${width / 2 + iconSize}px !important; - } - .sidebar__button { - font-size: ${width / 3}px !important; - } - ` - : ` - .sidebar { - width: ${width}px !important; - } - .tab-item { - width: ${width}px !important; - height: ${width - 5 + iconSize}px !important; - } - .tab-item .tab-item__icon { - width: ${width / 2 + iconSize}px !important; - } - .sidebar__button { - font-size: ${width / 3}px !important; - } - .todos__todos-panel--expanded { - width: calc(100% - ${300 + width}px) !important; - } - `; -} - -function generateShowDragAreaStyle(accentColor) { - return ` - .sidebar { - padding-top: 0px !important; - } - .window-draggable { - position: initial; - background-color: ${accentColor}; - } - #root { - /** Remove 22px from app height, otherwise the page will be too high */ - height: calc(100% - 22px); - } - `; -} - -function generateVerticalStyle(widthStr, alwaysShowWorkspaces) { - if (!document.querySelector('#vertical-style')) { - const link = document.createElement('link'); - link.id = 'vertical-style'; - link.rel = 'stylesheet'; - link.type = 'text/css'; - link.href = './styles/vertical.css'; - - document.head.append(link); - } - const width = Number(widthStr); - const sidebarWidth = width - 4; - const verticalStyleOffset = 23; - - return ` - .sidebar { - height: ${sidebarWidth + verticalStyleOffset + 1}px !important; - ${ - alwaysShowWorkspaces - ? ` - width: calc(100% - 300px) !important; - ` - : '' - } - } - - .sidebar .sidebar__button { - width: ${width}px; - } - - .app .app__content { - padding-top: ${sidebarWidth + verticalStyleOffset + 1}px !important; - } - - .workspaces-drawer { - margin-top: -${sidebarWidth - verticalStyleOffset - 1}px !important; - } - - .todos__todos-panel--expanded { - width: calc(100% - 300px) !important; - } - `; -} - -function generateOpenWorkspaceStyle() { - return ` - .app .app__content { - width: 100%; - transform: translateX(0px); - } - .sidebar__button--workspaces { - display: none; - } - `; -} - -function generateStyle(settings) { - let style = ''; - - const { - accentColor, - serviceRibbonWidth, - iconSize, - showDragArea, - useVerticalStyle, - alwaysShowWorkspaces, - } = settings; - - if ( - accentColor.toLowerCase() !== DEFAULT_APP_SETTINGS.accentColor.toLowerCase() - ) { - style += generateAccentStyle(accentColor); - } - if ( - serviceRibbonWidth !== DEFAULT_APP_SETTINGS.serviceRibbonWidth || - iconSize !== DEFAULT_APP_SETTINGS.iconSize - ) { - style += generateServiceRibbonWidthStyle( - serviceRibbonWidth, - iconSize, - useVerticalStyle, - ); - } - if (showDragArea) { - style += generateShowDragAreaStyle(accentColor); - } - if (useVerticalStyle) { - style += generateVerticalStyle(serviceRibbonWidth, alwaysShowWorkspaces); - } else if (document.querySelector('#vertical-style')) { - const link = document.querySelector('#vertical-style'); - if (link) { - link.remove(); - } - } - if (alwaysShowWorkspaces) { - style += generateOpenWorkspaceStyle(); - } - - return style; -} -function updateStyle(settings) { - const style = generateStyle(settings); - setAppearance(style); -} - -export default function initAppearance(stores) { - const { settings } = stores; - createStyleElement(); - - // Update style when settings change - reaction( - () => [ - settings.all.app.accentColor, - settings.all.app.serviceRibbonWidth, - settings.all.app.iconSize, - settings.all.app.showDragArea, - settings.all.app.useVerticalStyle, - settings.all.app.alwaysShowWorkspaces, - ], - () => { - updateStyle(settings.all.app); - }, - { fireImmediately: true }, - ); -} diff --git a/src/features/appearance/index.ts b/src/features/appearance/index.ts new file mode 100644 index 000000000..b00b9df3d --- /dev/null +++ b/src/features/appearance/index.ts @@ -0,0 +1,250 @@ +import color from 'color'; +import { reaction } from 'mobx'; +import { iconSizeBias } from '../../config'; +import { DEFAULT_APP_SETTINGS } from '../../environment'; + +const STYLE_ELEMENT_ID = 'custom-appearance-style'; + +function createStyleElement() { + const styles = document.createElement('style'); + styles.id = STYLE_ELEMENT_ID; + + document.querySelector('head')?.appendChild(styles); +} + +function setAppearance(style) { + const styleElement = document.querySelector(`#${STYLE_ELEMENT_ID}`); + + if (styleElement) { + styleElement.innerHTML = style; + } +} + +// See https://github.com/Qix-/color/issues/53#issuecomment-656590710 +function darkenAbsolute(originalColor, absoluteChange) { + const originalLightness = originalColor.lightness(); + return originalColor.lightness(originalLightness - absoluteChange); +} + +function generateAccentStyle(accentColorStr) { + let style = ''; + + let accentColor = color(DEFAULT_APP_SETTINGS.accentColor); + try { + accentColor = color(accentColorStr); + } catch { + // Ignore invalid accent color. + } + const darkerColorStr = darkenAbsolute(accentColor, 5).hex(); + style += ` + a.button:hover, button.button:hover { + background: ${darkenAbsolute(accentColor, 10).hex()}; + } + + .franz-form__button:hover, + .franz-form__button.franz-form__button--inverted:hover, + .settings .settings__close:hover, + .theme__dark .franz-form__button:hover, + .theme__dark .franz-form__button.franz-form__button--inverted:hover, + .theme__dark .settings .settings__close:hover { + background: ${darkerColorStr}; + } + + .franz-form__button:active, + .theme__dark .franz-form__button:active { + background: ${darkerColorStr}; + } + + .theme__dark .franz-form__button.franz-form__button--inverted, + .franz-form__button.franz-form__button--inverted { + background: none; + border-color: ${accentColorStr}; + } + + .tab-item.is-active { + background: ${accentColor.lighten(0.35).hex()}; + } + `; + + return style; +} + +function generateServiceRibbonWidthStyle(widthStr, iconSizeStr, vertical) { + const width = Number(widthStr); + const iconSize = Number(iconSizeStr) - iconSizeBias; + + return vertical + ? ` + .tab-item { + width: ${width - 2}px !important; + height: ${width - 5 + iconSize}px !important; + min-height: unset; + } + .tab-item .tab-item__icon { + width: ${width / 2 + iconSize}px !important; + } + .sidebar__button { + font-size: ${width / 3}px !important; + } + ` + : ` + .sidebar { + width: ${width}px !important; + } + .tab-item { + width: ${width}px !important; + height: ${width - 5 + iconSize}px !important; + } + .tab-item .tab-item__icon { + width: ${width / 2 + iconSize}px !important; + } + .sidebar__button { + font-size: ${width / 3}px !important; + } + .todos__todos-panel--expanded { + width: calc(100% - ${300 + width}px) !important; + } + `; +} + +function generateShowDragAreaStyle(accentColor) { + return ` + .sidebar { + padding-top: 0px !important; + } + .window-draggable { + position: initial; + background-color: ${accentColor}; + } + #root { + /** Remove 22px from app height, otherwise the page will be too high */ + height: calc(100% - 22px); + } + `; +} + +function generateVerticalStyle(widthStr, alwaysShowWorkspaces) { + if (!document.querySelector('#vertical-style')) { + const link = document.createElement('link'); + link.id = 'vertical-style'; + link.rel = 'stylesheet'; + link.type = 'text/css'; + link.href = './styles/vertical.css'; + + document.head.append(link); + } + const width = Number(widthStr); + const sidebarWidth = width - 4; + const verticalStyleOffset = 23; + + return ` + .sidebar { + height: ${sidebarWidth + verticalStyleOffset + 1}px !important; + ${ + alwaysShowWorkspaces + ? ` + width: calc(100% - 300px) !important; + ` + : '' + } + } + + .sidebar .sidebar__button { + width: ${width}px; + } + + .app .app__content { + padding-top: ${sidebarWidth + verticalStyleOffset + 1}px !important; + } + + .workspaces-drawer { + margin-top: -${sidebarWidth - verticalStyleOffset - 1}px !important; + } + + .todos__todos-panel--expanded { + width: calc(100% - 300px) !important; + } + `; +} + +function generateOpenWorkspaceStyle() { + return ` + .app .app__content { + width: 100%; + transform: translateX(0px); + } + .sidebar__button--workspaces { + display: none; + } + `; +} + +function generateStyle(settings) { + let style = ''; + + const { + accentColor, + serviceRibbonWidth, + iconSize, + showDragArea, + useVerticalStyle, + alwaysShowWorkspaces, + } = settings; + + if ( + accentColor.toLowerCase() !== DEFAULT_APP_SETTINGS.accentColor.toLowerCase() + ) { + style += generateAccentStyle(accentColor); + } + if ( + serviceRibbonWidth !== DEFAULT_APP_SETTINGS.serviceRibbonWidth || + iconSize !== DEFAULT_APP_SETTINGS.iconSize + ) { + style += generateServiceRibbonWidthStyle( + serviceRibbonWidth, + iconSize, + useVerticalStyle, + ); + } + if (showDragArea) { + style += generateShowDragAreaStyle(accentColor); + } + if (useVerticalStyle) { + style += generateVerticalStyle(serviceRibbonWidth, alwaysShowWorkspaces); + } else if (document.querySelector('#vertical-style')) { + const link = document.querySelector('#vertical-style'); + if (link) { + link.remove(); + } + } + if (alwaysShowWorkspaces) { + style += generateOpenWorkspaceStyle(); + } + + return style; +} +function updateStyle(settings) { + const style = generateStyle(settings); + setAppearance(style); +} + +export default function initAppearance(stores) { + const { settings } = stores; + createStyleElement(); + + // Update style when settings change + reaction( + () => [ + settings.all.app.accentColor, + settings.all.app.serviceRibbonWidth, + settings.all.app.iconSize, + settings.all.app.showDragArea, + settings.all.app.useVerticalStyle, + settings.all.app.alwaysShowWorkspaces, + ], + () => { + updateStyle(settings.all.app); + }, + { fireImmediately: true }, + ); +} diff --git a/src/features/basicAuth/Form.js b/src/features/basicAuth/Form.js deleted file mode 100644 index 95721d0e9..000000000 --- a/src/features/basicAuth/Form.js +++ /dev/null @@ -1,17 +0,0 @@ -import Form from '../../lib/Form'; - -export default new Form({ - fields: { - user: { - label: 'user', - placeholder: 'Username', - value: '', - }, - password: { - label: 'Password', - placeholder: 'Password', - value: '', - type: 'password', - }, - }, -}); diff --git a/src/features/basicAuth/Form.ts b/src/features/basicAuth/Form.ts new file mode 100644 index 000000000..95721d0e9 --- /dev/null +++ b/src/features/basicAuth/Form.ts @@ -0,0 +1,17 @@ +import Form from '../../lib/Form'; + +export default new Form({ + fields: { + user: { + label: 'user', + placeholder: 'Username', + value: '', + }, + password: { + label: 'Password', + placeholder: 'Password', + value: '', + type: 'password', + }, + }, +}); diff --git a/src/features/basicAuth/mainIpcHandler.js b/src/features/basicAuth/mainIpcHandler.js deleted file mode 100644 index ae4e7cf93..000000000 --- a/src/features/basicAuth/mainIpcHandler.js +++ /dev/null @@ -1,9 +0,0 @@ -const debug = require('debug')('Ferdi:feature:basicAuth:main'); - -export default function mainIpcHandler(mainWindow, authInfo) { - debug('Sending basic auth call', authInfo); - - mainWindow.webContents.send('feature:basic-auth', { - authInfo, - }); -} diff --git a/src/features/basicAuth/mainIpcHandler.ts b/src/features/basicAuth/mainIpcHandler.ts new file mode 100644 index 000000000..4ec3848e8 --- /dev/null +++ b/src/features/basicAuth/mainIpcHandler.ts @@ -0,0 +1,11 @@ +import { BrowserWindow } from 'electron'; + +const debug = require('debug')('Ferdi:feature:basicAuth:main'); + +export default function mainIpcHandler(mainWindow: BrowserWindow, authInfo) { + debug('Sending basic auth call', authInfo); + + mainWindow.webContents.send('feature:basic-auth', { + authInfo, + }); +} diff --git a/src/features/basicAuth/store.js b/src/features/basicAuth/store.js deleted file mode 100644 index 0713ff572..000000000 --- a/src/features/basicAuth/store.js +++ /dev/null @@ -1,30 +0,0 @@ -import { observable } from 'mobx'; -import { ipcRenderer } from 'electron'; - -const debug = require('debug')('Ferdi:feature:basicAuth'); - -const defaultState = { - isModalVisible: true, - service: null, - authInfo: null, -}; - -export const state = observable(defaultState); - -export function resetState() { - Object.assign(state, defaultState); -} -export function sendCredentials(user, password) { - debug('Sending credentials to main', user, password); - - ipcRenderer.send('feature-basic-auth-credentials', { - user, - password, - }); -} - -export function cancelLogin() { - debug('Cancel basic auth event'); - - ipcRenderer.send('feature-basic-auth-cancel'); -} diff --git a/src/features/basicAuth/store.ts b/src/features/basicAuth/store.ts new file mode 100644 index 000000000..0713ff572 --- /dev/null +++ b/src/features/basicAuth/store.ts @@ -0,0 +1,30 @@ +import { observable } from 'mobx'; +import { ipcRenderer } from 'electron'; + +const debug = require('debug')('Ferdi:feature:basicAuth'); + +const defaultState = { + isModalVisible: true, + service: null, + authInfo: null, +}; + +export const state = observable(defaultState); + +export function resetState() { + Object.assign(state, defaultState); +} +export function sendCredentials(user, password) { + debug('Sending credentials to main', user, password); + + ipcRenderer.send('feature-basic-auth-credentials', { + user, + password, + }); +} + +export function cancelLogin() { + debug('Cancel basic auth event'); + + ipcRenderer.send('feature-basic-auth-cancel'); +} diff --git a/src/features/basicAuth/styles.js b/src/features/basicAuth/styles.js deleted file mode 100644 index 6bdaf9a6e..000000000 --- a/src/features/basicAuth/styles.js +++ /dev/null @@ -1,12 +0,0 @@ -export default { - modal: { - width: 300, - }, - buttons: { - display: 'flex', - justifyContent: 'space-between', - }, - form: { - marginTop: 15, - }, -}; diff --git a/src/features/basicAuth/styles.ts b/src/features/basicAuth/styles.ts new file mode 100644 index 000000000..6bdaf9a6e --- /dev/null +++ b/src/features/basicAuth/styles.ts @@ -0,0 +1,12 @@ +export default { + modal: { + width: 300, + }, + buttons: { + display: 'flex', + justifyContent: 'space-between', + }, + form: { + marginTop: 15, + }, +}; diff --git a/src/features/communityRecipes/index.js b/src/features/communityRecipes/index.js deleted file mode 100644 index 828c6d867..000000000 --- a/src/features/communityRecipes/index.js +++ /dev/null @@ -1,7 +0,0 @@ -import { CommunityRecipesStore } from './store'; - -export const communityRecipesStore = new CommunityRecipesStore(); - -export default function initCommunityRecipes(stores, actions) { - communityRecipesStore.start(stores, actions); -} diff --git a/src/features/communityRecipes/index.ts b/src/features/communityRecipes/index.ts new file mode 100644 index 000000000..828c6d867 --- /dev/null +++ b/src/features/communityRecipes/index.ts @@ -0,0 +1,7 @@ +import { CommunityRecipesStore } from './store'; + +export const communityRecipesStore = new CommunityRecipesStore(); + +export default function initCommunityRecipes(stores, actions) { + communityRecipesStore.start(stores, actions); +} diff --git a/src/features/utils/ActionBinding.js b/src/features/utils/ActionBinding.js deleted file mode 100644 index 787166d44..000000000 --- a/src/features/utils/ActionBinding.js +++ /dev/null @@ -1,29 +0,0 @@ -export default class ActionBinding { - action; - - isActive = false; - - constructor(action) { - this.action = action; - } - - start() { - if (!this.isActive) { - const { action } = this; - action[0].listen(action[1]); - this.isActive = true; - } - } - - stop() { - if (this.isActive) { - const { action } = this; - action[0].off(action[1]); - this.isActive = false; - } - } -} - -export const createActionBindings = (actions) => ( - actions.map((a) => new ActionBinding(a)) -); diff --git a/src/features/utils/ActionBinding.ts b/src/features/utils/ActionBinding.ts new file mode 100644 index 000000000..787166d44 --- /dev/null +++ b/src/features/utils/ActionBinding.ts @@ -0,0 +1,29 @@ +export default class ActionBinding { + action; + + isActive = false; + + constructor(action) { + this.action = action; + } + + start() { + if (!this.isActive) { + const { action } = this; + action[0].listen(action[1]); + this.isActive = true; + } + } + + stop() { + if (this.isActive) { + const { action } = this; + action[0].off(action[1]); + this.isActive = false; + } + } +} + +export const createActionBindings = (actions) => ( + actions.map((a) => new ActionBinding(a)) +); diff --git a/src/features/workspaces/actions.js b/src/features/workspaces/actions.js deleted file mode 100644 index 5b5db422e..000000000 --- a/src/features/workspaces/actions.js +++ /dev/null @@ -1,27 +0,0 @@ -import PropTypes from 'prop-types'; -import Workspace from './models/Workspace'; -import { createActionsFromDefinitions } from '../../actions/lib/actions'; - -export const workspaceActions = createActionsFromDefinitions({ - edit: { - workspace: PropTypes.instanceOf(Workspace).isRequired, - }, - create: { - name: PropTypes.string.isRequired, - }, - delete: { - workspace: PropTypes.instanceOf(Workspace).isRequired, - }, - update: { - workspace: PropTypes.instanceOf(Workspace).isRequired, - }, - activate: { - workspace: PropTypes.instanceOf(Workspace).isRequired, - }, - deactivate: {}, - toggleWorkspaceDrawer: {}, - openWorkspaceSettings: {}, - toggleKeepAllWorkspacesLoadedSetting: {}, -}, PropTypes.checkPropTypes); - -export default workspaceActions; diff --git a/src/features/workspaces/actions.ts b/src/features/workspaces/actions.ts new file mode 100644 index 000000000..5e7e6e721 --- /dev/null +++ b/src/features/workspaces/actions.ts @@ -0,0 +1,30 @@ +import PropTypes from 'prop-types'; +import Workspace from './models/Workspace'; +import { createActionsFromDefinitions } from '../../actions/lib/actions'; + +export const workspaceActions = createActionsFromDefinitions( + { + edit: { + workspace: PropTypes.instanceOf(Workspace).isRequired, + }, + create: { + name: PropTypes.string.isRequired, + }, + delete: { + workspace: PropTypes.instanceOf(Workspace).isRequired, + }, + update: { + workspace: PropTypes.instanceOf(Workspace).isRequired, + }, + activate: { + workspace: PropTypes.instanceOf(Workspace).isRequired, + }, + deactivate: {}, + toggleWorkspaceDrawer: {}, + openWorkspaceSettings: {}, + toggleKeepAllWorkspacesLoadedSetting: {}, + }, + PropTypes.checkPropTypes, +); + +export default workspaceActions; diff --git a/src/features/workspaces/api.js b/src/features/workspaces/api.js deleted file mode 100644 index 322695ed2..000000000 --- a/src/features/workspaces/api.js +++ /dev/null @@ -1,66 +0,0 @@ -import { pick } from 'lodash'; -import { sendAuthRequest } from '../../api/utils/auth'; -import Request from '../../stores/lib/Request'; -import Workspace from './models/Workspace'; -import apiBase from '../../api/apiBase'; - -const debug = require('debug')('Ferdi:feature:workspaces:api'); - -export const workspaceApi = { - getUserWorkspaces: async () => { - const url = `${apiBase()}/workspace`; - debug('getUserWorkspaces GET', url); - const result = await sendAuthRequest(url, { method: 'GET' }); - debug('getUserWorkspaces RESULT', result); - if (!result.ok) throw result; - const workspaces = await result.json(); - return workspaces.map((data) => new Workspace(data)); - }, - - createWorkspace: async (name) => { - const url = `${apiBase()}/workspace`; - const options = { - method: 'POST', - body: JSON.stringify({ name }), - }; - debug('createWorkspace POST', url, options); - const result = await sendAuthRequest(url, options); - debug('createWorkspace RESULT', result); - if (!result.ok) throw result; - return new Workspace(await result.json()); - }, - - deleteWorkspace: async (workspace) => { - const url = `${apiBase()}/workspace/${workspace.id}`; - debug('deleteWorkspace DELETE', url); - const result = await sendAuthRequest(url, { method: 'DELETE' }); - debug('deleteWorkspace RESULT', result); - if (!result.ok) throw result; - return true; - }, - - updateWorkspace: async (workspace) => { - const url = `${apiBase()}/workspace/${workspace.id}`; - const options = { - method: 'PUT', - body: JSON.stringify(pick(workspace, ['name', 'services'])), - }; - debug('updateWorkspace UPDATE', url, options); - const result = await sendAuthRequest(url, options); - debug('updateWorkspace RESULT', result); - if (!result.ok) throw result; - return new Workspace(await result.json()); - }, -}; - -export const getUserWorkspacesRequest = new Request(workspaceApi, 'getUserWorkspaces'); -export const createWorkspaceRequest = new Request(workspaceApi, 'createWorkspace'); -export const deleteWorkspaceRequest = new Request(workspaceApi, 'deleteWorkspace'); -export const updateWorkspaceRequest = new Request(workspaceApi, 'updateWorkspace'); - -export const resetApiRequests = () => { - getUserWorkspacesRequest.reset(); - createWorkspaceRequest.reset(); - deleteWorkspaceRequest.reset(); - updateWorkspaceRequest.reset(); -}; diff --git a/src/features/workspaces/api.ts b/src/features/workspaces/api.ts new file mode 100644 index 000000000..8447fc247 --- /dev/null +++ b/src/features/workspaces/api.ts @@ -0,0 +1,86 @@ +import { pick } from 'lodash'; +import { sendAuthRequest } from '../../api/utils/auth'; +import Request from '../../stores/lib/Request'; +import Workspace from './models/Workspace'; +import apiBase from '../../api/apiBase'; + +const debug = require('debug')('Ferdi:feature:workspaces:api'); + +export const workspaceApi = { + getUserWorkspaces: async () => { + const url = `${apiBase()}/workspace`; + debug('getUserWorkspaces GET', url); + const result = await sendAuthRequest(url, { method: 'GET' }); + debug('getUserWorkspaces RESULT', result); + if (!result.ok) { + throw new Error("Couldn't getUserWorkspaces"); + } + const workspaces = await result.json(); + return workspaces.map(data => new Workspace(data)); + }, + + createWorkspace: async name => { + const url = `${apiBase()}/workspace`; + const options = { + method: 'POST', + body: JSON.stringify({ name }), + }; + debug('createWorkspace POST', url, options); + const result = await sendAuthRequest(url, options); + debug('createWorkspace RESULT', result); + if (!result.ok) { + throw new Error("Couldn't createWorkspace"); + } + return new Workspace(await result.json()); + }, + + deleteWorkspace: async workspace => { + const url = `${apiBase()}/workspace/${workspace.id}`; + debug('deleteWorkspace DELETE', url); + const result = await sendAuthRequest(url, { method: 'DELETE' }); + debug('deleteWorkspace RESULT', result); + if (!result.ok) { + throw new Error("Couldn't deleteWorkspace"); + } + return true; + }, + + updateWorkspace: async workspace => { + const url = `${apiBase()}/workspace/${workspace.id}`; + const options = { + method: 'PUT', + body: JSON.stringify(pick(workspace, ['name', 'services'])), + }; + debug('updateWorkspace UPDATE', url, options); + const result = await sendAuthRequest(url, options); + debug('updateWorkspace RESULT', result); + if (!result.ok) { + throw new Error("Couldn't updateWorkspace"); + } + return new Workspace(await result.json()); + }, +}; + +export const getUserWorkspacesRequest = new Request( + workspaceApi, + 'getUserWorkspaces', +); +export const createWorkspaceRequest = new Request( + workspaceApi, + 'createWorkspace', +); +export const deleteWorkspaceRequest = new Request( + workspaceApi, + 'deleteWorkspace', +); +export const updateWorkspaceRequest = new Request( + workspaceApi, + 'updateWorkspace', +); + +export const resetApiRequests = () => { + getUserWorkspacesRequest.reset(); + createWorkspaceRequest.reset(); + deleteWorkspaceRequest.reset(); + updateWorkspaceRequest.reset(); +}; diff --git a/src/features/workspaces/constants.js b/src/features/workspaces/constants.js deleted file mode 100644 index 2d1416ee0..000000000 --- a/src/features/workspaces/constants.js +++ /dev/null @@ -1,4 +0,0 @@ -export const WORKSPACES_ROUTES = { - ROOT: '/settings/workspaces', - EDIT: '/settings/workspaces/:action/:id', -}; diff --git a/src/features/workspaces/constants.ts b/src/features/workspaces/constants.ts new file mode 100644 index 000000000..2d1416ee0 --- /dev/null +++ b/src/features/workspaces/constants.ts @@ -0,0 +1,4 @@ +export const WORKSPACES_ROUTES = { + ROOT: '/settings/workspaces', + EDIT: '/settings/workspaces/:action/:id', +}; diff --git a/src/features/workspaces/index.js b/src/features/workspaces/index.js deleted file mode 100644 index 83e4d9049..000000000 --- a/src/features/workspaces/index.js +++ /dev/null @@ -1,30 +0,0 @@ -import { reaction } from 'mobx'; -import WorkspacesStore from './store'; -import { resetApiRequests } from './api'; - -const debug = require('debug')('Ferdi:feature:workspaces'); - -export const workspaceStore = new WorkspacesStore(); - -export default function initWorkspaces(stores, actions) { - stores.workspaces = workspaceStore; - const { features } = stores; - - // Toggle workspace feature - reaction( - () => ( - features.features.isWorkspaceEnabled - ), - (isEnabled) => { - if (isEnabled && !workspaceStore.isFeatureActive) { - debug('Initializing `workspaces` feature'); - workspaceStore.start(stores, actions); - } else if (workspaceStore.isFeatureActive) { - debug('Disabling `workspaces` feature'); - workspaceStore.stop(); - resetApiRequests(); - } - }, - { fireImmediately: true }, - ); -} diff --git a/src/features/workspaces/index.ts b/src/features/workspaces/index.ts new file mode 100644 index 000000000..ecca64b41 --- /dev/null +++ b/src/features/workspaces/index.ts @@ -0,0 +1,28 @@ +import { reaction } from 'mobx'; +import WorkspacesStore from './store'; +import { resetApiRequests } from './api'; + +const debug = require('debug')('Ferdi:feature:workspaces'); + +export const workspaceStore = new WorkspacesStore(); + +export default function initWorkspaces(stores, actions) { + stores.workspaces = workspaceStore; + const { features } = stores; + + // Toggle workspace feature + reaction( + () => features.features.isWorkspaceEnabled, + isEnabled => { + if (isEnabled && !workspaceStore.isFeatureActive) { + debug('Initializing `workspaces` feature'); + workspaceStore.start(stores, actions); + } else if (workspaceStore.isFeatureActive) { + debug('Disabling `workspaces` feature'); + workspaceStore.stop(); + resetApiRequests(); + } + }, + { fireImmediately: true }, + ); +} diff --git a/src/features/workspaces/models/Workspace.js b/src/features/workspaces/models/Workspace.js deleted file mode 100644 index 14add9437..000000000 --- a/src/features/workspaces/models/Workspace.js +++ /dev/null @@ -1,37 +0,0 @@ -import { observable } from 'mobx'; - -import { KEEP_WS_LOADED_USID } from '../../../config'; - -export default class Workspace { - id = null; - - @observable name = null; - - @observable order = null; - - @observable services = []; - - @observable userId = null; - - constructor(data) { - if (!data.id) { - throw new Error('Workspace requires Id'); - } - - this.id = data.id; - this.name = data.name; - this.order = data.order; - - let { services } = data; - if (data.saving && Boolean(data.keepLoaded)) { - // Keep workspaces loaded - services.push(KEEP_WS_LOADED_USID); - } else if (data.saving && data.services.includes(KEEP_WS_LOADED_USID)) { - // Don't keep loaded - services = services.filter((e) => e !== KEEP_WS_LOADED_USID); - } - this.services.replace(services); - - this.userId = data.userId; - } -} diff --git a/src/features/workspaces/models/Workspace.ts b/src/features/workspaces/models/Workspace.ts new file mode 100644 index 000000000..cd3918fba --- /dev/null +++ b/src/features/workspaces/models/Workspace.ts @@ -0,0 +1,39 @@ +import { observable } from 'mobx'; + +import { KEEP_WS_LOADED_USID } from '../../../config'; + +export default class Workspace { + id = null; + + @observable name = null; + + @observable order = null; + + @observable services = []; + + @observable userId = null; + + constructor(data) { + if (!data.id) { + throw new Error('Workspace requires Id'); + } + + this.id = data.id; + this.name = data.name; + this.order = data.order; + + let { services } = data; + if (data.saving && Boolean(data.keepLoaded)) { + // Keep workspaces loaded + services.push(KEEP_WS_LOADED_USID); + } else if (data.saving && data.services.includes(KEEP_WS_LOADED_USID)) { + // Don't keep loaded + services = services.filter(e => e !== KEEP_WS_LOADED_USID); + } + + // @ts-expect-error Property 'replace' does not exist on type 'never[]'. + this.services.replace(services); + + this.userId = data.userId; + } +} -- cgit v1.2.3-70-g09d2