From 270ae41104bea0bcd210fec42416f75e3e77790a Mon Sep 17 00:00:00 2001 From: srgooglo Date: Mon, 6 Dec 2021 18:06:51 +0100 Subject: [PATCH] update all --- packages/app/.config.js | 14 +- packages/app/config/index.js | 8 +- .../defaultSettings.json | 0 packages/app/constants/defaultSidebar.json | 10 + packages/app/constants/defaultTheme.json | 30 ++ .../pathDecorators.json} | 2 +- .../settingsGroupsDecorator.json} | 0 packages/app/constants/settingsList.json | 59 ++++ packages/app/constants/sidebar.json | 99 ++++++ .../app/constants/vaultItemStatements.json | 22 ++ packages/app/constants/vaultItemsTypes.json | 15 + packages/app/package.json | 4 +- packages/app/schemas/contextMenu.json | 11 - packages/app/schemas/defaultSidebar.json | 4 - packages/app/schemas/post_options.json | 4 - packages/app/schemas/settings.json | 49 --- packages/app/schemas/sidebar.json | 14 - packages/app/schemas/theme.json | 38 --- packages/app/src/App.jsx | 134 +++++--- .../app/src/components/AboutApp/index.jsx | 4 +- .../app/src/components/ActionsBar/index.jsx | 13 +- .../app/src/components/ActionsBar/index.less | 39 ++- .../app/src/components/AppLoading/index.jsx | 9 - .../app/src/components/AppSearcher/index.less | 8 +- .../app/src/components/ElementsList/index.jsx | 166 ---------- .../components/operations/index.jsx | 2 +- .../src/components/FabricCreator/index.jsx | 299 +++++++++++++---- .../src/components/FabricCreator/index.less | 7 + .../app/src/components/ListedMenu/index.less | 84 ----- .../app/src/components/ListedMenu/index.tsx | 108 ------ .../src/components/LoadingSpinner/index.jsx | 7 - .../app/src/components/RenderError/index.jsx | 80 +++-- .../app/src/components/RenderError/index.less | 16 + packages/app/src/components/Roles/index.jsx | 22 -- packages/app/src/components/Roles/index.less | 4 - .../src/components/SelectableList/index.jsx | 109 +++--- .../src/components/SelectableList/index.less | 108 +++--- .../app/src/components/ServerStatus/index.jsx | 37 +++ .../app/src/components/Sessions/index.jsx | 2 +- .../app/src/components/Settings/index.jsx | 310 ++++++++---------- .../app/src/components/Settings/index.less | 123 ++++--- .../app/src/components/buttonMenu/index.tsx | 37 --- .../src/components/formGenerator/index.jsx | 2 +- .../app/src/components/googleMap/index.tsx | 19 -- packages/app/src/components/index.js | 38 +-- .../app/src/components/modifierTag/index.jsx | 76 +++++ .../app/src/controllers/settings/index.js | 16 +- packages/app/src/core/events.js | 14 - packages/app/src/core/handlers.js | 7 - packages/app/src/core/index.js | 186 ----------- .../app/src/core/libs/controller/index.js | 98 ------ packages/app/src/core/libs/djail/index.js | 157 --------- packages/app/src/core/libs/index.js | 5 - packages/app/src/core/libs/settings/index.js | 5 - .../app/src/core/models/settings/index.js | 70 ---- packages/app/src/core/models/sidebar/index.js | 46 --- packages/app/src/core/permissions/index.js | 15 - packages/app/src/debug/api/index.jsx | 7 - packages/app/src/debug/evite/index.jsx | 57 ---- packages/app/src/debug/evite/index.less | 23 -- packages/app/src/debug/index.js | 4 - packages/app/src/debug/less/index.jsx | 11 - packages/app/src/debug/workload/index.jsx | 54 --- packages/app/src/debug/workload/index.less | 14 - packages/app/src/extensions/api/index.js | 22 +- packages/app/src/extensions/debug/index.jsx | 129 -------- packages/app/src/extensions/index.js | 5 +- packages/app/src/extensions/render/index.jsx | 25 +- packages/app/src/extensions/sound/index.js | 14 +- packages/app/src/extensions/splash/index.jsx | 13 +- packages/app/src/extensions/splash/index.less | 9 +- packages/app/src/extensions/theme/index.jsx | 173 ++++++++-- packages/app/src/layout/drawer/index.jsx | 22 +- packages/app/src/layout/drawer/index.less | 20 ++ packages/app/src/layout/header/index.jsx | 8 + packages/app/src/layout/header/index.less | 6 +- .../sidebar/components/editor/index.jsx | 2 +- .../sidebar/components/selector/index.jsx | 4 +- packages/app/src/layout/sidebar/index.jsx | 18 +- packages/app/src/layout/sidebar/index.less | 8 +- packages/app/src/layout/sidedrawer/index.less | 2 +- packages/app/src/models/index.js | 4 +- packages/app/src/models/session/index.js | 123 ------- packages/app/src/models/user/index.js | 12 +- packages/app/src/pages/account/index.jsx | 5 +- packages/app/src/theme/fonts.css | 5 +- packages/app/src/theme/index.less | 149 ++++----- packages/app/src/theme/variations/dark.less | 78 +++++ packages/app/src/theme/vars.less | 17 +- 89 files changed, 1601 insertions(+), 2307 deletions(-) rename packages/app/{schemas => constants}/defaultSettings.json (100%) create mode 100644 packages/app/constants/defaultSidebar.json create mode 100644 packages/app/constants/defaultTheme.json rename packages/app/{schemas/routesDecorators.json => constants/pathDecorators.json} (92%) rename packages/app/{schemas/settingsGroups.json => constants/settingsGroupsDecorator.json} (100%) create mode 100644 packages/app/constants/settingsList.json create mode 100644 packages/app/constants/sidebar.json create mode 100644 packages/app/constants/vaultItemStatements.json create mode 100644 packages/app/constants/vaultItemsTypes.json delete mode 100644 packages/app/schemas/contextMenu.json delete mode 100644 packages/app/schemas/defaultSidebar.json delete mode 100644 packages/app/schemas/post_options.json delete mode 100644 packages/app/schemas/settings.json delete mode 100644 packages/app/schemas/sidebar.json delete mode 100644 packages/app/schemas/theme.json delete mode 100644 packages/app/src/components/AppLoading/index.jsx delete mode 100644 packages/app/src/components/ElementsList/index.jsx delete mode 100644 packages/app/src/components/ListedMenu/index.less delete mode 100644 packages/app/src/components/ListedMenu/index.tsx delete mode 100644 packages/app/src/components/LoadingSpinner/index.jsx create mode 100644 packages/app/src/components/RenderError/index.less delete mode 100644 packages/app/src/components/Roles/index.jsx delete mode 100644 packages/app/src/components/Roles/index.less create mode 100644 packages/app/src/components/ServerStatus/index.jsx delete mode 100644 packages/app/src/components/buttonMenu/index.tsx delete mode 100644 packages/app/src/components/googleMap/index.tsx create mode 100644 packages/app/src/components/modifierTag/index.jsx delete mode 100644 packages/app/src/core/events.js delete mode 100644 packages/app/src/core/handlers.js delete mode 100644 packages/app/src/core/index.js delete mode 100644 packages/app/src/core/libs/controller/index.js delete mode 100644 packages/app/src/core/libs/djail/index.js delete mode 100644 packages/app/src/core/libs/index.js delete mode 100644 packages/app/src/core/libs/settings/index.js delete mode 100644 packages/app/src/core/models/settings/index.js delete mode 100644 packages/app/src/core/models/sidebar/index.js delete mode 100644 packages/app/src/core/permissions/index.js delete mode 100644 packages/app/src/debug/api/index.jsx delete mode 100644 packages/app/src/debug/evite/index.jsx delete mode 100644 packages/app/src/debug/evite/index.less delete mode 100644 packages/app/src/debug/index.js delete mode 100644 packages/app/src/debug/less/index.jsx delete mode 100644 packages/app/src/debug/workload/index.jsx delete mode 100644 packages/app/src/debug/workload/index.less delete mode 100644 packages/app/src/extensions/debug/index.jsx create mode 100644 packages/app/src/layout/drawer/index.less delete mode 100644 packages/app/src/models/session/index.js create mode 100644 packages/app/src/theme/variations/dark.less diff --git a/packages/app/.config.js b/packages/app/.config.js index c85c821a..2b62ef9a 100644 --- a/packages/app/.config.js +++ b/packages/app/.config.js @@ -1,13 +1,15 @@ const path = require('path') const aliases = { - schemas: path.resolve(__dirname, './schemas'), - controllers: path.resolve(__dirname, "./src/controllers"), - extensions: path.resolve(__dirname, './src/extensions'), + "@antd": path.resolve(__dirname, "../../node_modules/antd"), + "@": path.resolve(__dirname, 'src'), + schemas: path.resolve(__dirname, 'constants'), + controllers: path.resolve(__dirname, 'src/controllers'), + extensions: path.resolve(__dirname, 'src/extensions'), theme: path.join(__dirname, 'src/theme'), locales: path.join(__dirname, 'src/locales'), core: path.join(__dirname, 'src/core'), - pages: path.join(__dirname, 'src/pages'), + "@pages": path.join(__dirname, 'src/pages'), components: path.join(__dirname, 'src/components'), models: path.join(__dirname, 'src/models'), } @@ -23,6 +25,10 @@ module.exports = (config) => { ...config.resolve.alias, ...aliases, } + config.aliases = { + ...config.resolve.alias, + ...aliases, + } config.css = { preprocessorOptions: { diff --git a/packages/app/config/index.js b/packages/app/config/index.js index c95e6d95..99f7be52 100644 --- a/packages/app/config/index.js +++ b/packages/app/config/index.js @@ -1,13 +1,15 @@ +import defaultTheme from "../constants/defaultTheme.json" + export default { + defaultTheme: defaultTheme, + logo: { alt: "https://dl.ragestudio.net/branding/comty/alt/SVG/t3t3.svg" }, api: { address: process.env.NODE_ENV !== 'production' ? `http://${window.location.hostname}:3000` : "https://api.amimet.es", }, - theme: { - "primary-color": "#32b7bb", - }, + app: { siteName: 'Comty™', copyright: 'RageStudio©', diff --git a/packages/app/schemas/defaultSettings.json b/packages/app/constants/defaultSettings.json similarity index 100% rename from packages/app/schemas/defaultSettings.json rename to packages/app/constants/defaultSettings.json diff --git a/packages/app/constants/defaultSidebar.json b/packages/app/constants/defaultSidebar.json new file mode 100644 index 00000000..6ae75ce2 --- /dev/null +++ b/packages/app/constants/defaultSidebar.json @@ -0,0 +1,10 @@ +[ + "main", + "fabric", + "workloads", + "users", + "geo", + "vault", + "statistics", + "reports" +] \ No newline at end of file diff --git a/packages/app/constants/defaultTheme.json b/packages/app/constants/defaultTheme.json new file mode 100644 index 00000000..22d4ca2f --- /dev/null +++ b/packages/app/constants/defaultTheme.json @@ -0,0 +1,30 @@ +{ + "staticVars": { + "primaryColor": "#32B7BB" + }, + "defaultVariant": "light", + "variants": { + "light": { + "background-color-primary": "#ffffff", + "background-color-accent": "#f0f2f5", + "background-color-contrast": "#4b4b4b", + "border-color": "var(--background-color-contrast)", + "sidebar-background-color": "var(--background-color-accent)", + "sidedrawer-background-color": "var(--background-color-accent)" + }, + "dark": { + "text-color": "#d2d2d2", + "svg-color": "var(--text-color)", + "background-color-primary": "#262626", + "background-color-accent": "#353535", + "background_disabled": "#0A0A0A", + "background-color-contrast": "#ffffff", + "border-color": "var(--background-color-contrast)", + "header-text-color": "#d2d2d2", + "button-background-color": "var(--primaryColor)", + "button-text-color": "var(--background-color-contrast)", + "sidebar-background-color": "var(--background-color-accent)", + "sidedrawer-background-color": "var(--background-color-accent)" + } + } +} \ No newline at end of file diff --git a/packages/app/schemas/routesDecorators.json b/packages/app/constants/pathDecorators.json similarity index 92% rename from packages/app/schemas/routesDecorators.json rename to packages/app/constants/pathDecorators.json index bafd64de..3162662e 100644 --- a/packages/app/schemas/routesDecorators.json +++ b/packages/app/constants/pathDecorators.json @@ -13,7 +13,7 @@ }, "regions": { "icon": "Globe", - "title": "Regions" + "title": "Locations" }, "vault": { "icon": "Archive", diff --git a/packages/app/schemas/settingsGroups.json b/packages/app/constants/settingsGroupsDecorator.json similarity index 100% rename from packages/app/schemas/settingsGroups.json rename to packages/app/constants/settingsGroupsDecorator.json diff --git a/packages/app/constants/settingsList.json b/packages/app/constants/settingsList.json new file mode 100644 index 00000000..b68bbc5b --- /dev/null +++ b/packages/app/constants/settingsList.json @@ -0,0 +1,59 @@ +[ + { + "id": "expire_session", + "group": "general", + "type": "Switch", + "icon": "Key", + "title": "Expire Session" + }, + { + "id": "edit_sidebar", + "group": "sidebar", + "type": "Button", + "icon": "Edit", + "title": "Edit Sidebar", + "emitEvent": "edit_sidebar", + "noStorage": true + }, + { + "id": "collapseOnLooseFocus", + "group": "sidebar", + "type": "Switch", + "title": "Collapse when loose focus" + }, + { + "id": "reduceAnimations", + "group": "aspect", + "type": "Switch", + "icon": "MdOutlineAnimation", + "title": "Reduce animation" + }, + { + "id": "darkMode", + "group": "aspect", + "type": "Switch", + "icon": "Moon", + "title": "Dark Mode", + "emitEvent": "darkMode", + "experimental": true + }, + { + "id": "primaryColor", + "group": "aspect", + "type": "SliderColorPicker", + "title": "Primary color", + "emitEvent": "modifyTheme", + "updateValueKey": "primaryColor" + }, + { + "id": "resetTheme", + "group": "aspect", + "type": "Button", + "title": "Reset theme", + "props": { + "children": "Default Theme" + }, + "emitEvent": "resetTheme", + "noStorage": true + } +] \ No newline at end of file diff --git a/packages/app/constants/sidebar.json b/packages/app/constants/sidebar.json new file mode 100644 index 00000000..052ddf8a --- /dev/null +++ b/packages/app/constants/sidebar.json @@ -0,0 +1,99 @@ +[ + { + "id": "main", + "title": "Dashboard", + "icon": "Home", + "locked": true + }, + { + "id": "workloads", + "title": "Workloads", + "icon": "GitCommit", + "children": [ + { + "id": "workloads/pool", + "title": "Pool", + "icon": "Archive" + }, + { + "id": "workloads/sections", + "title": "Sections", + "icon": "Target" + }, + { + "id": "workloads/items", + "title": "Items", + "icon": "Tag" + } + ] + }, + { + "id": "users", + "title": "Users", + "icon": "Users", + "children": [ + { + "id": "users/contracts", + "title": "Contracts", + "icon": "Briefcase" + }, + { + "id": "users/roles", + "title": "Roles", + "icon": "Link" + }, + { + "id": "users/workshifts", + "title": "Workshifts", + "icon": "Clock" + }, + { + "id": "users/accounts", + "title": "Accounts", + "icon": "User" + } + ] + }, + { + "id": "geo", + "title": "Geo", + "icon": "MapPin", + "children": [ + { + "id": "locations", + "title": "Locations", + "icon": "Map" + } + ] + }, + { + "id": "fabric", + "title": "Fabric", + "icon": "Box" + }, + { + "id": "vault", + "title": "Vault", + "icon": "Archive" + }, + { + "id": "reports", + "title": "Reports", + "icon": "Umbrella" + }, + { + "id": "server_manager", + "title": "Server", + "icon": "Database" + }, + { + "id": "launchpad", + "title": "Launchpad", + "icon": "Command" + }, + { + "id": "statistics", + "title": "Statistics", + "icon": "BarChart" + } +] \ No newline at end of file diff --git a/packages/app/constants/vaultItemStatements.json b/packages/app/constants/vaultItemStatements.json new file mode 100644 index 00000000..97c8c4cf --- /dev/null +++ b/packages/app/constants/vaultItemStatements.json @@ -0,0 +1,22 @@ +{ + "active": { + "value": "active", + "label": "Active", + "tagColor": "green" + }, + "retired": { + "value": "retired", + "label": "Retired", + "tagColor": "red" + }, + "storaged": { + "value": "storaged", + "label": "Storaged", + "tagColor": "blue" + }, + "unknown": { + "value": "unknown", + "label": "Unknown", + "tagColor": "gray" + } +} \ No newline at end of file diff --git a/packages/app/constants/vaultItemsTypes.json b/packages/app/constants/vaultItemsTypes.json new file mode 100644 index 00000000..34c02582 --- /dev/null +++ b/packages/app/constants/vaultItemsTypes.json @@ -0,0 +1,15 @@ +{ + "computers": [ + "desktop", + "laptop", + "phone", + "tablet" + ], + "peripherals": [ + "keyboard", + "mouse", + "monitor", + "printer", + "scanner" + ] +} \ No newline at end of file diff --git a/packages/app/package.json b/packages/app/package.json index 3b1ed273..a279a4dd 100644 --- a/packages/app/package.json +++ b/packages/app/package.json @@ -11,8 +11,7 @@ "timeago.js": "^4.0.2", "@ant-design/icons": "^4.7.0", "@corenode/utils": "^0.28.26", - "@react-pdf/renderer": "^1.6.17", - "antd": "^4.17.0", + "antd": "^4.17.2", "chart.js": "^3.5.1", "classnames": "^2.3.1", "corenode": "^0.28.26", @@ -26,7 +25,6 @@ "howler": "^2.2.3", "js-cookie": "^2.2.1", "less": "^4.1.2", - "less-vars-to-js": "^1.3.0", "linebridge": "^0.8.4", "moment": "^2.29.1", "mpegts.js": "^1.6.10", diff --git a/packages/app/schemas/contextMenu.json b/packages/app/schemas/contextMenu.json deleted file mode 100644 index 71f24f6b..00000000 --- a/packages/app/schemas/contextMenu.json +++ /dev/null @@ -1,11 +0,0 @@ -[ - { - "key": "inspect_element", - "title": "Inspect", - "icon": "Command", - "require": "embedded", - "params": { - "onClick": false - } - } -] \ No newline at end of file diff --git a/packages/app/schemas/defaultSidebar.json b/packages/app/schemas/defaultSidebar.json deleted file mode 100644 index 7385198d..00000000 --- a/packages/app/schemas/defaultSidebar.json +++ /dev/null @@ -1,4 +0,0 @@ -[ - "main", - "posts" -] \ No newline at end of file diff --git a/packages/app/schemas/post_options.json b/packages/app/schemas/post_options.json deleted file mode 100644 index 694d162a..00000000 --- a/packages/app/schemas/post_options.json +++ /dev/null @@ -1,4 +0,0 @@ -[ - {"key":"pro_boost","icon":"RocketOutlined","type":"switch","title":"CPRO™ Boost","description":"","require":"pro","value":false}, - {"key":"allow_comments","icon":"CommentOutlined","type":"switch","title":"Allow Comments","description":"","require":"","value":true} -] \ No newline at end of file diff --git a/packages/app/schemas/settings.json b/packages/app/schemas/settings.json deleted file mode 100644 index 93344f1a..00000000 --- a/packages/app/schemas/settings.json +++ /dev/null @@ -1,49 +0,0 @@ -[ - { - "id": "expire_session", - "icon": "Key", - "title": "Expire Session", - "group": "general", - "type": "Switch" - }, - { - "id": "post_autoposition", - "icon": "AlignCenter", - "type": "Switch", - "title": "Center on click", - "description": "Center posts element when then is clicked" - }, - { - "id": "search_ontype", - "icon": "CornerDownRight", - "type": "Switch", - "title": "Auto search on input", - "description": "Search automaticly when type something" - }, - { - "id": "post_hidebar", - "icon": "Menu", - "type": "Switch", - "title": "Auto hide postbar", - "description": "Hide post actions bar when loose focus" - }, - { - "id": "edit_sidebar", - "group": "sidebar", - "icon": "Edit", - "title": "Edit Sidebar", - "type": "Button" - }, - { - "id": "collapseOnLooseFocus", - "group": "sidebar", - "title": "Collapse when loose focus", - "type": "Switch" - }, - { - "id": "reduceAnimations", - "group": "aspect", - "title": "Reduce animations", - "type": "Switch" - } -] \ No newline at end of file diff --git a/packages/app/schemas/sidebar.json b/packages/app/schemas/sidebar.json deleted file mode 100644 index 274aba39..00000000 --- a/packages/app/schemas/sidebar.json +++ /dev/null @@ -1,14 +0,0 @@ -[ - { - "id": "main", - "title": "Dashboard", - "icon": "Home", - "locked": true - }, - { - "id": "posts", - "title": "Posts", - "icon": "Home", - "locked": true - } -] \ No newline at end of file diff --git a/packages/app/schemas/theme.json b/packages/app/schemas/theme.json deleted file mode 100644 index 56064c1c..00000000 --- a/packages/app/schemas/theme.json +++ /dev/null @@ -1,38 +0,0 @@ -[ - { - "id": "backgroundImage", - "icon": "Image", - "title": "Background", - "description": "Change the background of the app" - }, - { - "id": "overlay", - "icon": "Sidebar", - "title": "Overlay", - "description": "Description blah blah" - }, - { - "id": "color", - "icon": "Droplet", - "title": "Colors", - "description": "Texts, Buttons, Sliders ...etc" - }, - { - "id": "text", - "icon": "FontColorsOutlined", - "title": "Text", - "description": "Sizes, Fonts" - }, - { - "id": "sounds", - "icon": "Volume2", - "title": "Sounds", - "description": "BlipBlopBLup" - }, - { - "id": "darkmode", - "icon": "Moon", - "title": "Dark Mode", - "description": "Yeaah, no more daying" - } -] \ No newline at end of file diff --git a/packages/app/src/App.jsx b/packages/app/src/App.jsx index 407f07d8..6e8fa47f 100644 --- a/packages/app/src/App.jsx +++ b/packages/app/src/App.jsx @@ -1,27 +1,47 @@ -import React from "react" -import { Helmet } from "react-helmet" -import progressBar from "nprogress" -import * as antd from "antd" -import classnames from "classnames" - -import { Icons } from "components/Icons" -import { CreateEviteApp, BindPropsProvider } from "evite" - -import config from "config" -import { Session, User } from "models" -import { NotFound, RenderError } from "components" -import { SettingsController, SidebarController } from "controllers" -import { API, Render, Debug, Sound } from "extensions" - -import { Sidebar, Header, Drawer, Sidedrawer } from "./layout" -import "theme/index.less" - -// append method to array prototype +// Patch global prototypes Array.prototype.move = function (from, to) { this.splice(to, 0, this.splice(from, 1)[0]) return this } +String.prototype.toTitleCase = function () { + return this.replace(/\w\S*/g, function (txt) { + return txt.charAt(0).toUpperCase() + txt.substr(1).toLowerCase() + }) +} + +import React from "react" +import { CreateEviteApp, BindPropsProvider } from "evite" +import { Helmet } from "react-helmet" +import * as antd from "antd" +import progressBar from "nprogress" +import classnames from "classnames" + +import { SidebarController, SettingsController } from "controllers" +import { Session, User } from "models" +import { API, Render, Splash, Theme, Sound } from "extensions" +import config from "config" + +import { NotFound, RenderError, FabricCreator, Settings } from "components" +import { Sidebar, Header, Drawer, Sidedrawer } from "./layout" +import { Icons } from "components/Icons" + +import "theme/index.less" + +const SplashExtension = Splash.extension({ + logo: config.logo.alt, + preset: "fadeOut", + velocity: 1000, + props: { + logo: { + style: { + marginBottom: "10%", + stroke: "black", + }, + }, + }, +}) + class ThrowCrash { constructor(message, description) { this.message = message @@ -50,6 +70,9 @@ class App { this.eventBus = this.contexts.main.eventBus + this.eventBus.on("app_ready", () => { + this.setState({ initialized: true }) + }) this.eventBus.on("top_loadBar_start", () => { this.progressBar.start() }) @@ -123,6 +146,26 @@ class App { static windowContext() { return { + openSettings: (goTo) => { + window.app.DrawerController.open("settings", Settings, { + props: { + width: "40%", + }, + componentProps: { + goTo, + } + }) + }, + openFabric: (defaultType) => { + window.app.DrawerController.open("FabricCreator", FabricCreator, { + props: { + width: "70%", + }, + componentProps: { + defaultType, + } + }) + }, configuration: this.configuration, isValidSession: this.isValidSession, getSettings: (...args) => this.contexts.app.configuration?.settings?.get(...args), @@ -131,6 +174,7 @@ class App { static appContext() { return { + renderRef: this.renderRef, sessionController: this.sessionController, userController: this.userController, configuration: this.configuration, @@ -145,10 +189,14 @@ class App { RenderError: (props) => { return }, + initialization: () => { + return + } } state = { // app + initialized: false, isMobile: false, crash: false, isOnTransition: false, @@ -158,8 +206,6 @@ class App { data: null, } - layoutContentRef = React.createRef() - flushState = () => { this.setState({ session: null, data: null }) } @@ -174,12 +220,16 @@ class App { initialization = async () => { try { + this.eventBus.emit("splash_show") await this.contexts.app.initializeDefaultBridge() await this.__init_session() await this.__init_user() + this.eventBus.emit("app_ready") } catch (error) { + this.eventBus.emit("splash_close") throw new ThrowCrash(error.message, error.description) } + this.eventBus.emit("splash_close") } __init_session = async () => { @@ -228,34 +278,40 @@ class App { } + if (!this.state.initialized) { + return null + } + return ( {config.app.siteName} - - - - -
- -
- - - -
-
+ + + + + +
+ +
+ + + +
+
+ + - - + ) } } export default CreateEviteApp(App, { - extensions: [Sound.extension, Render.extension, API, Debug], + extensions: [Sound.extension, Render.extension, Theme.extension, API, SplashExtension], }) \ No newline at end of file diff --git a/packages/app/src/components/AboutApp/index.jsx b/packages/app/src/components/AboutApp/index.jsx index a38cf2ce..7b1bb656 100644 --- a/packages/app/src/components/AboutApp/index.jsx +++ b/packages/app/src/components/AboutApp/index.jsx @@ -7,7 +7,7 @@ import config from "config" import "./index.less" -export class AboutApp extends React.Component { +export class AboutCard extends React.Component { state = { visible: true, } @@ -68,5 +68,5 @@ export function openModal() { const component = document.createElement("div") document.body.appendChild(component) - ReactDOM.render(, component) + ReactDOM.render(, component) } diff --git a/packages/app/src/components/ActionsBar/index.jsx b/packages/app/src/components/ActionsBar/index.jsx index e611d780..bcda9a57 100644 --- a/packages/app/src/components/ActionsBar/index.jsx +++ b/packages/app/src/components/ActionsBar/index.jsx @@ -1,14 +1,13 @@ -import React from 'react' -import { Card } from 'antd' - -import './index.less' +import React from "react" +import classnames from "classnames" +import "./index.less" export default (props) => { - const { children } = props + const { children, float } = props - return + return
{children}
- +
} \ No newline at end of file diff --git a/packages/app/src/components/ActionsBar/index.less b/packages/app/src/components/ActionsBar/index.less index a6873ea2..d12e74d1 100644 --- a/packages/app/src/components/ActionsBar/index.less +++ b/packages/app/src/components/ActionsBar/index.less @@ -1,15 +1,30 @@ .actionsBar_card { - border-radius: 8px; - transition: all 200ms ease-in-out; + border: 1px solid #e0e0e0; + padding: 15px; + border-radius: 8px; + transition: all 200ms ease-in-out; + background-color: #0c0c0c15; + backdrop-filter: blur(10px); + + &.float { + z-index: 1000; + position: sticky; + top: 0; + right: 0; + width: 100%; + } } -.actionsBar_flexWrapper{ - transition: all 200ms ease-in-out; - display: flex; - flex-direction: row; - align-items: center; - - > div { - margin-right: 10px; - } - } \ No newline at end of file +.actionsBar_flexWrapper { + transition: all 200ms ease-in-out; + display: flex; + flex-direction: row; + align-items: center; + + > div { + margin-right: 10px; + display: flex; + flex-direction: column; + align-items: center; + } +} diff --git a/packages/app/src/components/AppLoading/index.jsx b/packages/app/src/components/AppLoading/index.jsx deleted file mode 100644 index c1b47b09..00000000 --- a/packages/app/src/components/AppLoading/index.jsx +++ /dev/null @@ -1,9 +0,0 @@ -import React from "react" -import { LoadingOutlined } from "@ant-design/icons" -import { Result } from "antd" - -export default (props = {}) => { - return
- } /> -
-} \ No newline at end of file diff --git a/packages/app/src/components/AppSearcher/index.less b/packages/app/src/components/AppSearcher/index.less index c6730b65..0f8de6c9 100644 --- a/packages/app/src/components/AppSearcher/index.less +++ b/packages/app/src/components/AppSearcher/index.less @@ -9,9 +9,9 @@ vertical-align: middle !important; .ant-input { - background-color: @app_background_accent!important; - border-color: @app_background_accent!important; - color: @app_background_contrast!important; + background-color: var(--background-color-accent)!important; + border-color: var(--background-color-accent)!important; + color: var(--background-color-contrast)!important; } .ant-input-group { @@ -27,7 +27,7 @@ } .ant-btn { - background-color: #eeeeee!important; + background-color: var(--background-color-primary)!important; border: 0 !important; } } diff --git a/packages/app/src/components/ElementsList/index.jsx b/packages/app/src/components/ElementsList/index.jsx deleted file mode 100644 index 635e99c6..00000000 --- a/packages/app/src/components/ElementsList/index.jsx +++ /dev/null @@ -1,166 +0,0 @@ -import React from "react" -import * as antd from "antd" -import { RefreshCw } from "feather-reactjs" -import { getCircularReplacer, decycle } from "@corenode/utils" - -const serializeFlags = { - __cycle_flag: true, // with id 0 -} - -function isFlagId(e, id) { - return serializeFlags[Object.keys(e)[id ?? 0]] -} - -const parseError = (error) => { - return ( -
-
- This could not be rendered -
-
- - -
- {error.toString()} -
-
-
-
-
- ) -} - -const parseDecorator = (data, json) => { - const type = typeof data - console.log(type) - switch (type) { - case "string": { - return `(${json.length}) characters` - } - case "object": { - if (data == null) { - return `Empty (null/undefined)` - } - if (isFlagId(data, 0)) { - return ( - - Cylic - - ) - } - if (typeof data.length !== "undefined") { - return `Length (${data.length})` - } - if (typeof Object.keys(data).length !== "undefined") { - return `Length (${Object.keys(data).length})` - } - return `Immeasurable` - } - case "array": { - return `Length (${data})` - } - case "boolean": { - return {data ? "true" : "false"} - } - case "number": { - return {data} - } - default: - return `Immeasurable / Invalid` - } -} - -const parseData = (data) => { - try { - switch (typeof data) { - case "object": { - if (data == null) { - return `${data}` - } - - if (isFlagId(data, 0)) { - return ( -
- Circular -
- ) - } - - if (Object.keys(data).length > 0) { - return
{ElementList(data)}
- } - - return JSON.stringify(data, getCircularReplacer()) - } - case "array": { - return JSON.stringify(data, getCircularReplacer()) - } - case "boolean": { - return false - } - default: - return `${data}` - } - } catch (error) { - return parseError(data, error) - } -} - -const parseType = (data) => { - if (data !== null && isFlagId(data, 0)) { - return `[loop]` - } - return `[${typeof data}]` -} - -const excludedTypesFromContent = ["boolean"] - -export default function ElementList(data) { - if (!data) return false - - data = decycle(data) - const keys = Object.keys(data) - - return keys.map((key) => { - const value = data[key] - const content = parseData(value) - const type = parseType(value) - const decorator = parseDecorator(value, content) - - const header = ( -
- {type} {key} | {decorator} -
- ) - - return ( - - {excludedTypesFromContent.includes(typeof value) ? ( - - ) : ( - -
- {content} -
-
- )} -
- ) - }) -} \ No newline at end of file diff --git a/packages/app/src/components/FabricCreator/components/operations/index.jsx b/packages/app/src/components/FabricCreator/components/operations/index.jsx index 1ec29aaf..8bed3b2b 100644 --- a/packages/app/src/components/FabricCreator/components/operations/index.jsx +++ b/packages/app/src/components/FabricCreator/components/operations/index.jsx @@ -2,7 +2,7 @@ import React from "react" import * as antd from "antd" import "./index.less" -const api = window.app.apiBridge +const api = window.app.request export default class Operations extends React.Component { state = { diff --git a/packages/app/src/components/FabricCreator/index.jsx b/packages/app/src/components/FabricCreator/index.jsx index ef06ae69..a893e7f5 100644 --- a/packages/app/src/components/FabricCreator/index.jsx +++ b/packages/app/src/components/FabricCreator/index.jsx @@ -2,18 +2,26 @@ import React from 'react' import * as antd from 'antd' import { Icons as FIcons, createIconRender } from "components/Icons" import * as MDIcons from "react-icons/md" +import loadable from "@loadable/component" + +import "./index.less" const Icons = { ...FIcons, ...MDIcons } -import "./index.less" - const FormComponents = { "input": antd.Input, "textarea": antd.Input.TextArea, "select": antd.Select, + "datepicker": antd.DatePicker, +} + +const requestModifyByType = { + "vaultItem": { + "additions": ["essc"] + } } // FIELDS @@ -40,25 +48,74 @@ const FieldsForms = { return update.target.value }, }, + location: { + label: "Location", + component: "select", + updateEvent: "onChange", + children: async () => { + const api = window.app.request + const regions = await api.get.regions() + + return regions.map(region => { + return {region.name} + }) + }, + props: { + placeholder: "Select a location", + } + }, vaultItemTypeSelector: { label: "Type", component: "select", updateEvent: "onChange", + children: async () => { + let types = await import("schemas/vaultItemsTypes.json") + + types = types.default || types + + return Object.keys(types).map((group) => { + return + {types[group].map((type) => { + return {String(type).toTitleCase()} + })} + + }) + }, props: { placeholder: "Select a type", - children: [ - - Desktop - Laptop - Phone - Tablet - Other - , - - Monitor - Printer - , - ] + } + }, + vaultItemSerial: { + label: "Serial number", + component: "input", + updateEvent: "onChange", + onUpdate: (update) => { + return update.target.value + }, + props: { + placeholder: "S/N 00000000X", + } + }, + vaultItemManufacturer: { + label: "Manufacturer", + component: "input", + updateEvent: "onChange", + onUpdate: (update) => { + return update.target.value + }, + props: { + placeholder: "e.g. Hewlett Packard", + } + }, + vaultItemManufacturedYear: { + label: "Manufactured Year", + component: "datepicker", + updateEvent: "onChange", + onUpdate: (update) => { + return update.year() + }, + props: { + picker: "year" } }, } @@ -94,7 +151,12 @@ const TaskFormula = { const VaultItemFormula = { defaultFields: [ + // TODO: include location "vaultItemTypeSelector", + "vaultItemSerial", + "vaultItemManufacturer", + "vaultItemManufacturedYear", + "location", ] } @@ -120,20 +182,34 @@ const FabricItemTypes = ["product", "operation", "phase", "task", "vaultItem"] export default class FabricCreator extends React.Component { state = { loading: true, - values: {}, - - fields: [], + submitting: false, + error: null, name: null, type: null, - uuid: null, + fields: [], + values: {}, } componentDidMount = async () => { - await this.setItemType("product") + await this.setItemType(this.props.defaultType ?? "product") this.setState({ loading: false }) } + toogleLoading = (to) => { + this.setState({ loading: to ?? !this.state.loading }) + } + + toogleSubmitting = (to) => { + this.setState({ submitting: to ?? !this.state.submitting }) + } + + clearError = () => { + if (this.state.error != null) { + this.setState({ error: null }) + } + } + clearValues = async () => { await this.setState({ values: {} }) } @@ -155,39 +231,58 @@ export default class FabricCreator extends React.Component { this.appendFieldByType(field) }) - this.setState({ type: type, name: "New item" }) + await this.setState({ type: type, name: "New item" }) } else { console.error(`Cannot load default fields from formula with type ${type}`) } } appendFieldByType = (fieldType) => { - const form = FieldsForms[fieldType] + const field = FieldsForms[fieldType] - if (typeof form === "undefined") { + if (typeof field === "undefined") { console.error(`No form available for field [${fieldType}]`) return null } const fields = this.state.fields - fields.push(this.generateFieldRender({ type: fieldType, ...form })) + + if (this.fieldsHasTypeKey(fieldType) && !field.allowMultiple) { + console.error(`Field [${fieldType}] already exists, and only can exists 1`) + return false + } + + fields.push(this.generateFieldRender({ type: fieldType, ...field })) this.setState({ fields: fields }) } + fieldsHasTypeKey = (key) => { + let isOnFields = false + + const fields = this.state.fields + + fields.forEach(field => { + field.props.type === key ? isOnFields = true : null + }) + + return isOnFields + } + renderFieldSelectorMenu = () => { return { this.appendFieldByType(e.key) }} > - {Object.keys(FieldsForms).map((field) => { - const form = FieldsForms[field] - const icon = form.icon && createIconRender(form.icon) + {Object.keys(FieldsForms).map((key) => { + const field = FieldsForms[key] + const icon = field.icon && createIconRender(field.icon) + const disabled = this.fieldsHasTypeKey(key) && !field.allowMultiple - return + return {icon ?? null} - {field.charAt(0).toUpperCase() + field.slice(1)} + {key.charAt(0).toUpperCase() + key.slice(1)} })} @@ -210,8 +305,50 @@ export default class FabricCreator extends React.Component { } - onDone = () => { - console.log(this.getValues()) + onDone = async () => { + this.clearError() + this.toogleSubmitting(true) + + const api = window.app.request + let properties = {} + + this.getProperties().forEach((property) => { + if (typeof properties[property.type] !== "undefined") { + return properties[property.id] = property.value + } + + return properties[property.type] = property.value + }) + + let payload = { + type: this.state.type, + name: this.state.name, + properties: properties, + } + + if (typeof requestModifyByType[this.state.type] !== "undefined") { + payload = { + ...payload, + ...requestModifyByType[this.state.type], + } + } + + await api.put.fabric(payload).catch((response) => { + console.error(response) + this.setState({ error: response }) + + return null + }) + + this.toogleSubmitting(false) + + if (!this.state.error && typeof this.props.close === "function") { + this.props.close() + } + } + + onChangeName = (event) => { + this.setState({ name: event.target.value }) } onUpdateValue = (event, value) => { @@ -224,46 +361,86 @@ export default class FabricCreator extends React.Component { } removeField = (key) => { - this.setState({ fields: this.state.fields.filter(field => field.key != key) }) + let values = this.state.values + let fields = this.state.fields.filter(field => field.key != key) + + delete values[key] + + this.setState({ fields: fields, values: values }) } - getValues = () => { + getProperties = () => { return this.state.fields.map((field) => { return { type: field.props.type, + id: field.props.id, value: this.state.values[field.key], } }) } - generateFieldRender = (field) => { - let { key, style, type, icon, component, label, updateEvent, props, onUpdate } = field + getKeyFromLatestFieldType = (type) => { + let latestByType = 0 - if (!key) { - key = this.state.fields.length + this.state.fields.forEach((field) => { + field.props.type === type ? latestByType++ : null + }) + + return `${type}-${latestByType}` + } + + generateFieldRender = (field) => { + if (!field.key) { + field.key = this.getKeyFromLatestFieldType(field.type) } - if (typeof FormComponents[component] === "undefined") { - console.error(`No component type available for field [${key}]`) + if (typeof FormComponents[field.component] === "undefined") { + console.error(`No component type available for field [${field.key}]`) return null } - return
-
{ this.removeField(key) }}>
-

{icon && createIconRender(icon)}{label}

-
- {React.createElement(FormComponents[component], { - ...props, - value: this.state.values[key], - [updateEvent]: (...args) => { - if (typeof onUpdate === "function") { - return this.onUpdateValue({ updateEvent, key }, onUpdate(...args)) - } - return this.onUpdateValue({ updateEvent, key }, ...args) - }, - })} -
+ const getSubmittingState = () => { + return this.state.submitting + } + let fieldComponentProps = { + ...field.props, + value: this.state.values[field.key], + disabled: getSubmittingState(), + [field.updateEvent]: (...args) => { + if (typeof field.onUpdate === "function") { + return this.onUpdateValue({ updateEvent: field.updateEvent, key: field.key }, field.onUpdate(...args)) + } + return this.onUpdateValue({ updateEvent: field.updateEvent, key: field.key }, ...args) + }, + } + + let RenderComponent = null + + if (typeof field.children === "function") { + RenderComponent = loadable(async () => { + try { + const children = await field.children() + return () => React.createElement(FormComponents[field.component], fieldComponentProps, children) + } catch (error) { + console.log(error) + return ()=>
+ Load Error +
+ } + }, { + fallback:
Loading...
, + }) + } else { + RenderComponent = () => React.createElement(FormComponents[field.component], fieldComponentProps) + } + + return
+
{ this.removeField(field.key) }}>
+

{field.icon && createIconRender(field.icon)}{field.label}

+
+ +
} @@ -271,7 +448,6 @@ export default class FabricCreator extends React.Component { if (this.state.loading) { return } - const TypeIcon = FabricItemTypesIcons[this.state.type] && createIconRender(FabricItemTypesIcons[this.state.type]) return
@@ -281,19 +457,24 @@ export default class FabricCreator extends React.Component { {TypeIcon ?? }
- +
+
- {this.state.fields} + {this.state.submitting ? : this.state.fields}
- Done + + Done
+ {this.state.error &&
+ {this.state.error} +
}
} -} \ No newline at end of file +} diff --git a/packages/app/src/components/FabricCreator/index.less b/packages/app/src/components/FabricCreator/index.less index 99c56318..2b769ff4 100644 --- a/packages/app/src/components/FabricCreator/index.less +++ b/packages/app/src/components/FabricCreator/index.less @@ -111,5 +111,12 @@ cursor: pointer; border-color: #5e5e5e; } + + .error { + color: red; + font-size: 12px; + margin-top: 5px; + transition: all 150ms ease-out; + } } } \ No newline at end of file diff --git a/packages/app/src/components/ListedMenu/index.less b/packages/app/src/components/ListedMenu/index.less deleted file mode 100644 index e947ab76..00000000 --- a/packages/app/src/components/ListedMenu/index.less +++ /dev/null @@ -1,84 +0,0 @@ -@import "~theme/index.less"; - -.main { - font-family: "Nunito", sans-serif; - margin: 20px 0 0; - display: flex; - width: 100%; - height: auto; - overflow: auto; - color: @__global_color; - background-color: @__global_background; - padding: 15px; - border-radius: 10px; - - :global { - .ant-list-item { - padding-top: 7px; - padding-bottom: 7px; - } - - .ant-list-split .ant-list-item { - border-bottom: 0; - } - - .ant-list-item-meta-title { - color: rgba(0, 0, 0, 0.733); - font-size: 14px; - } - } - - .menuList { - user-select: none; - width: 224px; - :global { - .ant-menu-inline { - color: @__global_color; - background-color: transparent; - border: none; - } - .ant-menu:not(.ant-menu-horizontal) .ant-menu-item-selected { - font-weight: bold; - } - } - } - - .menuContainer { - flex: 1; - padding-top: 8px; - padding-right: 40px; - padding-bottom: 8px; - padding-left: 40px; - - .title { - margin-bottom: 12px; - color: @__global_color; - font-weight: 500; - font-size: 20px; - line-height: 28px; - } - } - - &.horizontal { - flex-direction: column; - .menuList { - padding: 15px; - width: 100%; - } - } -} - -@media screen and (max-width: @screen-md) { - .main { - flex-direction: column; - - .leftMenu { - width: 100%; - border: none; - } - - .right { - padding: 40px; - } - } -} diff --git a/packages/app/src/components/ListedMenu/index.tsx b/packages/app/src/components/ListedMenu/index.tsx deleted file mode 100644 index fa917821..00000000 --- a/packages/app/src/components/ListedMenu/index.tsx +++ /dev/null @@ -1,108 +0,0 @@ -import React from 'react' -import { Menu, Result } from 'antd' -import classnames from 'classnames' -import { Icons } from 'components/Icons' - -import styles from './index.less' -import { objectToArrayMap } from '@corenode/utils' - -export default class ListedMenu extends React.Component { - state = { - renderOptionTitle: true, - loading: true, - selectKey: '', - menus: [], - mode: this.props.mode ?? "inline" - } - - async queryMenu() { - this.setState({ loading: true }) - this.setState({ menus: objectToArrayMap(this.props.menuArray), loading: false }) - } - - getMenu() { - return this.state.menus.map(item => ( - - {item.icon} {item.title} - - )) - } - - selectKey = (key) => { - this.setState({ - selectKey: key, - }) - } - - renderChildren = () => { - let titlesArray = [] - this.state.menus.forEach(e => { titlesArray[e.key] = e }) - - const OptionTitle = () => { - if (this.state.renderOptionTitle) { - return
-

{React.createElement(Icons[titlesArray[this.state.selectKey].icon]) || null}{titlesArray[this.state.selectKey].title || null}

-
- } - return null - } - - if (this.state.selectKey && titlesArray[this.state.selectKey]) { - return <> - - {this.props.childrens[this.state.selectKey]} - - } else { - return ( - - ) - } - } - - componentDidMount() { - const { childrens, menuArray, defaultKey } = this.props - const keyIndex = new URLSearchParams(location.search).get('key') - - if (keyIndex && typeof (this.props.childrens[keyIndex]) !== "undefined") { - this.selectKey(keyIndex) - } else if (defaultKey != null) { - this.selectKey(defaultKey) - } - - if (this.props.renderOptionTitle != null) { - this.setState({ renderOptionTitle: this.props.renderOptionTitle }) - } - - if (childrens != null && menuArray != null) { - this.queryMenu() - } - } - - render() { - const { selectKey, loading } = this.state - const isMode = (e) => { - return this.state.mode === `${e}` - } - - if (loading) { - return <> - } - return ( -
-
-

- {React.createElement(Icons[this.props.icon]) ?? null} {this.props.title ?? "Menu"} -

- this.selectKey(key)} - > - {this.getMenu()} - -
-
{this.renderChildren()}
-
- ) - } -} \ No newline at end of file diff --git a/packages/app/src/components/LoadingSpinner/index.jsx b/packages/app/src/components/LoadingSpinner/index.jsx deleted file mode 100644 index a4bef86f..00000000 --- a/packages/app/src/components/LoadingSpinner/index.jsx +++ /dev/null @@ -1,7 +0,0 @@ -import React from "react" -import { LoadingOutlined } from "@ant-design/icons" -import { Result } from "antd" - -export default (props = {}) => { - return } /> -} diff --git a/packages/app/src/components/RenderError/index.jsx b/packages/app/src/components/RenderError/index.jsx index 05e2c851..825d8aef 100644 --- a/packages/app/src/components/RenderError/index.jsx +++ b/packages/app/src/components/RenderError/index.jsx @@ -1,27 +1,30 @@ -import React from 'react' +import React from "react" import { Result, Button, Typography } from "antd" import { CloseCircleOutlined } from "@ant-design/icons" +import config from "config" + +import "./index.less" const { Paragraph, Text } = Typography +const ErrorEntry = (props) => { + const { error } = props + + if (!error) { + return
+ + Unhandled error +
+ } + + return
+ + {error.info.toString()} +
+} + export default (props) => { let errors = [] - const getErrors = () => { - return errors.map((err) => { - if (err instanceof Error) { - return ( - - - {err.toString()} - - ) - } - return
- }) - } if (Array.isArray(props.error)) { errors = props.error @@ -29,27 +32,42 @@ export default (props) => { errors.push(props.error) } + const onClickGoMain = () => { + window.app.setLocation(config.app.mainPath ?? "/main") + } + const onClickReload = () => { + window.location.reload() + } + return (
+ Go Main + , + , + ]} > -
- - - We have detected the following errors: - - - {getErrors()} -
+ + + We catch the following errors: + +
+ {errors.map((error, index) => { + return + })} +
+
) -} +} \ No newline at end of file diff --git a/packages/app/src/components/RenderError/index.less b/packages/app/src/components/RenderError/index.less new file mode 100644 index 00000000..3099168c --- /dev/null +++ b/packages/app/src/components/RenderError/index.less @@ -0,0 +1,16 @@ +.errors { + margin-top: 12px; + + .error { + margin-bottom: 10px; + + svg { + color: red; + margin-right: 10px; + } + .stack { + margin-left: 24px; + word-wrap: break-word; + } + } +} diff --git a/packages/app/src/components/Roles/index.jsx b/packages/app/src/components/Roles/index.jsx deleted file mode 100644 index e24d64e2..00000000 --- a/packages/app/src/components/Roles/index.jsx +++ /dev/null @@ -1,22 +0,0 @@ -import React from "react" -import * as antd from "antd" - -import "./index.less" - -export default class Roles extends React.Component { - render() { - const roles = [] - - if (Array.isArray(this.props.roles)) { - this.props.roles.forEach((role) => { - roles.push( -
- {role} -
- ) - }) - } - - return
{roles}
- } -} diff --git a/packages/app/src/components/Roles/index.less b/packages/app/src/components/Roles/index.less deleted file mode 100644 index 7c867569..00000000 --- a/packages/app/src/components/Roles/index.less +++ /dev/null @@ -1,4 +0,0 @@ -.roles_wrapper{ - display: flex; - flex-direction: row; -} \ No newline at end of file diff --git a/packages/app/src/components/SelectableList/index.jsx b/packages/app/src/components/SelectableList/index.jsx index 95f0dede..b0d1f912 100644 --- a/packages/app/src/components/SelectableList/index.jsx +++ b/packages/app/src/components/SelectableList/index.jsx @@ -19,21 +19,23 @@ export default class SelectableList extends React.Component { } } - onClickKey = (key) => { - if (typeof this.props.selectionEnabled !== "undefined") { - if (!Boolean(this.props.selectionEnabled)) { - return false - } + selectAll = () => { + if (this.props.items.length > 0) { + this.setState({ + selectedKeys: [...this.props.items.map((item) => item.key ?? item.id ?? item._id)], + }) } + } + selectKey = (key) => { let list = this.state.selectedKeys ?? [] + list.push(key) + return this.setState({ selectedKeys: list }) + } - if (!list.includes(key)) { - list.push(key) - } else { - list = list.filter((_key) => key !== _key) - } - + unselectKey = (key) => { + let list = this.state.selectedKeys ?? [] + list = list.filter((_key) => key !== _key) return this.setState({ selectedKeys: list }) } @@ -41,7 +43,7 @@ export default class SelectableList extends React.Component { if (typeof this.props.onDone === "function") { this.props.onDone(this.state.selectedKeys) } - + this.setState({ selectedKeys: [], }) @@ -57,6 +59,16 @@ export default class SelectableList extends React.Component { }) } + componentDidUpdate(prevProps, prevState) { + if (typeof this.props.selectionEnabled !== "undefined") { + if (!Boolean(this.props.selectionEnabled) && this.state.selectedKeys.length > 0) { + this.setState({ + selectedKeys: [], + }) + } + } + } + renderActions = () => { if (typeof this.props.renderActions !== "undefined" && !this.props.renderActions) { return false @@ -65,7 +77,7 @@ export default class SelectableList extends React.Component { return false } - const renderExtraActions = () => { + const renderProvidedActions = () => { if (Array.isArray(this.props.actions)) { return this.props.actions.map((action) => { return ( @@ -113,45 +125,64 @@ export default class SelectableList extends React.Component {
-
- -
- - {renderExtraActions()} + {renderProvidedActions()}
) } render() { + const validSelectionMethods = ["onClick", "onDoubleClick"] + const renderMethod = (item) => { + const selectionMethod = validSelectionMethods.includes(this.props.selectionMethod) ? this.props.selectionMethod : "onClick" + if (typeof this.props.renderItem === "function") { const _key = item.key ?? item.id ?? item._id + const list = this.state.selectedKeys + const isSelected = list.includes(_key) + + let props = { + key: _key, + id: _key, + className: classnames("selectableList_item", this.props.itemClassName, { + selected: this.state.selectedKeys.includes(_key), + }), + [selectionMethod]: () => { + if (typeof this.props.selectionEnabled !== "undefined") { + if (!Boolean(this.props.selectionEnabled)) { + return false + } + } + + if (isSelected) { + this.unselectKey(_key) + } else { + this.selectKey(_key) + } + } + } + + if (selectionMethod == "onDoubleClick") { + props.onClick = () => { + if (list.length > 0) { + if (isSelected) { + this.unselectKey(_key) + } + } + } + } return ( -
this.onClickKey(_key)} - className={classnames("selectableList_item", this.props.itemClassName, { - selection: this.state.selectionEnabled, - selected: this.state.selectedKeys.includes(_key), - })} - > +
{this.props.renderItem(item)}
) @@ -178,8 +209,7 @@ export default class SelectableList extends React.Component { } return ( -
- {this.renderActions()} +
+ {this.renderActions()}
) } -} +} \ No newline at end of file diff --git a/packages/app/src/components/SelectableList/index.less b/packages/app/src/components/SelectableList/index.less index 5af624db..3fe722a2 100644 --- a/packages/app/src/components/SelectableList/index.less +++ b/packages/app/src/components/SelectableList/index.less @@ -1,59 +1,65 @@ -@selectableList_item_borderColor_active: rgba(51,51,51,1); -@selectableList_item_borderColor_normal: rgba(51,51,51,0.3); +@selectableList_item_borderColor_active: rgba(51, 51, 51, 1); +@selectableList_item_borderColor_normal: rgba(51, 51, 51, 0.3); -.selectableList_item { - user-select: none; - width: 100%; +.selectableList { + &.selectionEnabled { + .selectableList_item { + cursor: pointer; - border: @selectableList_item_borderColor_normal 1px solid; - border-radius: 8px; + border: rgba(51, 51, 51, 0.3) 1px solid; + border-radius: 8px; + margin-bottom: 12px; - transition: all 150ms ease-in-out; - - margin-bottom: 12px; - padding: 10px; - - > div { - margin: 7px; - } - - &.selection{ - cursor: pointer; - background-color: #f5f5f5; - - h1 { - user-select: none; - } - h3 { - user-select: none; - } - } - - &.selected { - background-color: #dadada; - transform: translate(10px, 0); - } + h1 { + user-select: none; + } + h3 { + user-select: none; + } + } + .selectableList_item:hover { + box-shadow: 2px 2px 8px 0px rgba(51, 51, 51, 0.5); + border: @selectableList_item_borderColor_active 1px solid; + } + } } -.selectableList_item:hover { - // transform: translate(2px, 2px); - box-shadow: 2px 2px 8px 0px rgba(51,51,51,0.5); - border: @selectableList_item_borderColor_active 1px solid; - } - -.bottomActions_wrapper{ - position: absolute; - bottom: 0; - z-index: 10; - width: 100%; +.selectableList_item { + user-select: none; + width: 100%; - left: 0; - right: 0; + border: @selectableList_item_borderColor_normal 1px solid; + border-radius: 4px; + + margin-bottom: 6px; + padding: 10px; + + transition: all 150ms ease-in-out; - border-radius: 0; + > div { + margin: 7px; + } - display: flex; - flex-direction: row; - align-items: center; - justify-content: center; -} \ No newline at end of file + &.selected { + background-color: #f5f5f5; + transform: translate(10px, 0); + } +} + +.bottomActions_wrapper { + position: sticky; + z-index: 1000; + + width: 100%; + + bottom: 0; + left: 0; + right: 0; + + border-radius: 0; + + display: flex; + flex-direction: row; + align-items: center; + justify-content: center; +} diff --git a/packages/app/src/components/ServerStatus/index.jsx b/packages/app/src/components/ServerStatus/index.jsx new file mode 100644 index 00000000..1a627649 --- /dev/null +++ b/packages/app/src/components/ServerStatus/index.jsx @@ -0,0 +1,37 @@ +import React from "react" +import * as antd from "antd" +import { Icons } from "components/Icons" + +export default () => { + const [connected, setConnected] = React.useState(window.app.ws.connected ?? false) + + window.app.eventBus.on("websocket_connected", (status) => { + setConnected(true) + }) + + window.app.eventBus.on("websocket_disconnected", (status) => { + setConnected(false) + }) + + const getColor = () => { + if (!connected) { + return "red" + } + + return "blue" + } + + return
+
+ {window.app?.api?.origin ?? "unavailable"} +
+
+ {window.app?.ws?.io?.uri ?? "unavailable"} +
+
+ + {connected ? "Connected" : "Disconnected"} + +
+
+} \ No newline at end of file diff --git a/packages/app/src/components/Sessions/index.jsx b/packages/app/src/components/Sessions/index.jsx index 32f92ede..8420bd34 100644 --- a/packages/app/src/components/Sessions/index.jsx +++ b/packages/app/src/components/Sessions/index.jsx @@ -1,6 +1,6 @@ import React from "react" import * as antd from "antd" -import { Icons } from "components/Icons" +import { Icons } from "components/icons" import "./index.less" diff --git a/packages/app/src/components/Settings/index.jsx b/packages/app/src/components/Settings/index.jsx index 2c3a5901..9c78fd14 100644 --- a/packages/app/src/components/Settings/index.jsx +++ b/packages/app/src/components/Settings/index.jsx @@ -1,10 +1,14 @@ import React from "react" -import { Icons } from "components/Icons" +import { Icons } from "components/icons" +import { SliderPicker } from "react-color" import * as antd from "antd" -import { SketchPicker } from "react-color" -import { AboutApp } from ".." import config from "config" +import settingList from "schemas/settingsList.json" +import groupsDecorator from "schemas/settingsGroupsDecorator.json" + +import { AboutApp } from ".." + import "./index.less" const ItemTypes = { @@ -15,221 +19,165 @@ const ItemTypes = { Input: antd.Input, InputNumber: antd.InputNumber, Select: antd.Select, - ColorPicker: SketchPicker, + SliderColorPicker: SliderPicker, } -import settingList from "schemas/settings.json" -import groupsDecorator from "schemas/settingsGroups.json" -import { Session } from "models" - -export class SettingsMenu extends React.Component { +export default class SettingsMenu extends React.Component { state = { settings: window.app.configuration.settings.get() ?? {}, } - _set(key, value) { - this.setState({ settings: window.app.configuration.settings.change(key, value) }) + handleEvent = (event, item, to) => { + const id = item.id + + if (typeof id === "undefined") { + console.error("SettingsMenu: Cannot update, item has no id") + return false + } + + const currentValue = window.app.configuration.settings.get(id) ?? null + + // by default we set the opposite value to the current value + if (typeof to === "undefined") { + to = !currentValue + } + + if (typeof item.updateValueKey === "string") { + to = { [item.updateValueKey]: to } + } + + if (typeof item.emitEvent === "string") { + window.app.eventBus.emit(item.emitEvent, { event, to }) + } + + if (!item.noStorage) { + window.app.configuration.settings.change(id, to) + } + + this.setState({ settings: { ...this.state.settings, [id]: to } }) } - handleEvent(event, id, type) { - if (typeof id === "undefined") { - console.error(`No setting id provided!`) - return false + renderItem = (item) => { + if (!item.type) { + console.error(`Item [${item.id}] has no an type!`) + return null } - if (typeof type !== "string") { - console.error(`Invalid eventType data-type, expecting string!`) - return false + if (typeof ItemTypes[item.type] === "undefined") { + console.error(`Item [${item.id}] has an invalid type: ${item.type}`) + return null } - const value = window.app.configuration.settings.get(id) ?? false - let to = !value + if (typeof item.props === "undefined") { + item.props = {} + } - switch (type.toLowerCase()) { - case "button": { - window.app.configuration.settings.events.emit("changeSetting", { event, id, value, to }) + // fix handlers + switch (item.type.toLowerCase()) { + case "slidercolorpicker": { + item.props.onChange = (color) => { + item.props.color = color.hex + } + item.props.onChangeComplete = (color, event) => { + this.handleEvent(event, item, color.hex) + } + break + } + case "switch": { + item.props.checked = this.state.settings[item.id] + item.props.onClick = (event) => this.handleEvent(event, item) break } default: { - this._set(id, to) + if (!item.props.children) { + item.props.children = item.title ?? item.id + } + item.props.value = this.state.settings[item.id] + item.props.onClick = (event) => this.handleEvent(event, item) break } } - } - generateMenu(data) { - let items = {} - - const renderGroupItems = (group) => { - return items[group].map((item) => { - if (!item.type) { - console.error(`Item [${item.id}] has no an type!`) - return null - } - if (typeof ItemTypes[item.type] === "undefined") { - console.error(`Item [${item.id}] has an invalid type: ${item.type}`) - return null - } - - if (typeof item.props === "undefined") { - item.props = {} - } - - // fix handlers - switch (item.type.toLowerCase()) { - case "colorpicker": { - item.props.onChange = (value) => { - item.props.color = value.hex - } - item.props.onChangeComplete = (color, event) => { - window.app.configuration.settings.events.emit("changeSetting", { id: item.id, event, value: color }) - this._set(item.id, color.hex) - } - break - } - case "switch": { - item.props.children = item.title ?? item.id - item.props.checked = this.state.settings[item.id] - item.props.onClick = (e) => this.handleEvent(e, item.id ?? "anon", item.type) - break - } - - default: { - item.props.children = item.title ?? item.id - item.props.value = this.state.settings[item.id] - item.props.onClick = (e) => this.handleEvent(e, item.id ?? "anon", item.type) - break - } - } - - return ( -
+ return ( +
+
+
{item.icon ? React.createElement(Icons[item.icon]) : null} {item.title ?? item.id}
- {item.render ?? - React.createElement(ItemTypes[item.type], { - ...item.props, - })}
- ) - }) - } - - const renderGroupDecorator = (group) => { - if (group === "none") { - return null - } - const fromDecoratorIcon = groupsDecorator[group]?.icon - const fromDecoratorTitle = groupsDecorator[group]?.title - - return ( -
-

- {fromDecoratorIcon ? React.createElement(Icons[fromDecoratorIcon]) : null}{" "} - {fromDecoratorTitle ?? group} -

-
- ) - } - - if (Array.isArray(data)) { - data.forEach((item) => { - if (typeof item.group == "undefined") { - item.group = "none" - } - - if (!items[item.group]) { - items[item.group] = [] - } - - items[item.group].push(item) - }) - } - - return Object.keys(items).map((group) => { - return ( -
- {renderGroupDecorator(group)} -
- {renderGroupItems(group)} +
+ {item.experimental && Experimental }
- ) - }) - } - - renderAboutApp() { - const appConfig = config.app - const eviteNamespace = window.__evite - const isDevMode = eviteNamespace.env.NODE_ENV !== "production" - - return ( -
-
{appConfig.siteName}
-
- - v{eviteNamespace.projectVersion} - -
-
- - {isDevMode ? : } - {isDevMode ? "development" : "stable"} - +
+ {React.createElement(ItemTypes[item.type], item.props)}
) } - renderLogout() { - if (window.app.isValidSession()) { - return ( -
- { - Session.logout() - }} - type="danger" - > - Logout - -
- ) - } + renderGroup = (key, group) => { + const fromDecoratorIcon = groupsDecorator[key]?.icon + const fromDecoratorTitle = groupsDecorator[key]?.title - return
+ return ( +
+

+ {fromDecoratorIcon ? React.createElement(Icons[fromDecoratorIcon]) : null} + {fromDecoratorTitle ?? key} +

+
+ {group.map((item) => this.renderItem(item))} +
+
+ ) + } + + generateSettings = (data) => { + let groups = {} + + data.forEach((item) => { + if (!groups[item.group]) { + groups[item.group] = [] + } + + groups[item.group].push(item) + }) + + return Object.keys(groups).map((groupKey) => { + return this.renderGroup(groupKey, groups[groupKey]) + }) } render() { + const isDevMode = window.__evite.env.NODE_ENV !== "production" + return ( -
- {this.generateMenu(settingList)} -
- {this.renderLogout()} - {this.renderAboutApp()} - AboutApp.openModal()}> - About - +
+ {this.generateSettings(settingList)} +
+
+
{config.app?.siteName}
+
+ + v{window.__evite.projectVersion} + +
+
+ + {isDevMode ? : } + {isDevMode ? "development" : "stable"} + +
+
+
+ AboutApp.openModal()}> + About + +
) } -} - -const controller = { - open: (key) => { - // TODO: Scroll to content - window.app.DrawerController.open("settings", SettingsMenu, { - props: { - width: "45%", - }, - }) - }, - - close: () => { - window.app.DrawerController.close("settings") - }, -} - -export default controller +} \ No newline at end of file diff --git a/packages/app/src/components/Settings/index.less b/packages/app/src/components/Settings/index.less index e0332d48..d9de886b 100644 --- a/packages/app/src/components/Settings/index.less +++ b/packages/app/src/components/Settings/index.less @@ -1,44 +1,81 @@ -.settings_groupItems{ - > div { - padding: 12px 30px; - } +.settings { + display: flex; + flex-direction: column; + + > div { + margin-bottom: 25px; + } + + .group { + display: flex; + flex-direction: column; + + .content { + > div { + margin-bottom: 25px; + } + } + } + + .settingItem { + padding: 0 20px; + + > div { + margin-bottom: 10px; + } + + .header { + display: flex; + align-items: center; + + h5{ + margin: 0; + } + + > div { + margin-right: 10px; + } + } + + .component { + padding: 0 20px; + } + } + + .footer { + position: relative; + width: 100%; + + padding-top: 20px; + padding-bottom: 20px; + + display: flex; + flex-direction: column; + + justify-content: center; + align-items: center; + + > div { + margin-bottom: 10px; + + font-family: "Space Mono", monospace; + font-size: 10px; + + display: flex; + flex-direction: row; + + align-items: center; + justify-content: center; + + .ant-tag { + height: 18px; + line-height: 18px; + font-size: 10px; + } + + > div { + padding: 0 7px; + } + } + } } - -.settings_about_app{ - font-family: 'Space Mono', monospace; - font-size: 10px; - - display: flex; - flex-direction: row; - - align-items: center; - justify-content: center; - - .ant-tag{ - height: 18px; - line-height: 18px; - font-size: 10px; - } - - > div { - padding: 0 7px; - } -} - -.settings_bottom_items { - position: relative; - bottom: 0; - right: 0; - width: 100%; - padding-bottom: 20px; - - display: flex; - flex-direction: column; - - justify-content: center; - align-items: center; - - > div { - padding: 10px 0; - } -} \ No newline at end of file diff --git a/packages/app/src/components/buttonMenu/index.tsx b/packages/app/src/components/buttonMenu/index.tsx deleted file mode 100644 index a41b57af..00000000 --- a/packages/app/src/components/buttonMenu/index.tsx +++ /dev/null @@ -1,37 +0,0 @@ -import React from 'react' -import * as antd from 'antd' -import { Icons } from 'components/Icons' -import { FormattedMessage } from 'react-intl' - -export default class ButtonMenu extends React.Component { - handleClickMenu(id) { - const element = document.getElementById(id) - if (typeof (element) !== "undefined") { - try { - element.focus() - } catch (error) { - console.log(error) - } - } - if (typeof (this.props.onClick) !== "undefined") { - this.props.onClick(id) - } - } - - renderMenus() { - return this.props?.menus?.map((e) => { - return this.handleClickMenu(e.id)} id={e.id ?? Math.random} key={e.id} className={window.classToStyle("indexMenuItem")}> -
{e.icon ? React.createElement(Icons[e.icon], { style: e.iconStyle ?? null }) : null}
-
-
- }) - } - - render() { - return ( -
- {this.renderMenus()} -
- ) - } -} \ No newline at end of file diff --git a/packages/app/src/components/formGenerator/index.jsx b/packages/app/src/components/formGenerator/index.jsx index 55c035dd..af22be99 100644 --- a/packages/app/src/components/formGenerator/index.jsx +++ b/packages/app/src/components/formGenerator/index.jsx @@ -392,4 +392,4 @@ export default class FormGenerator extends React.Component {
) } -} +} \ No newline at end of file diff --git a/packages/app/src/components/googleMap/index.tsx b/packages/app/src/components/googleMap/index.tsx deleted file mode 100644 index 06f95d0c..00000000 --- a/packages/app/src/components/googleMap/index.tsx +++ /dev/null @@ -1,19 +0,0 @@ -import React from 'react' - -const Marker = ({ text }) =>
-
-
- -export default (props) => { - if (typeof(props.size) == "undefined") { - props.size = "420px" - } - return
-