diff --git a/.biomelintrc-auto-import.json b/.biomelintrc-auto-import.json index 4a2b26f3f348c77093a5960967552ac47f057d4c..4c019968a117c0cd485960970175dda72ed733c7 100644 --- a/.biomelintrc-auto-import.json +++ b/.biomelintrc-auto-import.json @@ -14,8 +14,6 @@ "RouteLocationRaw", "VNode", "WritableComputedRef", - "[alias]", - "[import-names]", "axios", "computed", "createApp", diff --git a/.eslintrc.cjs b/.eslintrc.cjs deleted file mode 100644 index 3aa42f8ae43778cd689b283bb8d28a05e3e01e24..0000000000000000000000000000000000000000 --- a/.eslintrc.cjs +++ /dev/null @@ -1,15 +0,0 @@ -/* eslint-env node */ -require('@rushstack/eslint-patch/modern-module-resolution') - -module.exports = { - root: true, - 'extends': [ - 'plugin:vue/vue3-essential', - 'eslint:recommended', - '@vue/eslint-config-typescript', - '@vue/eslint-config-prettier/skip-formatting' - ], - parserOptions: { - ecmaVersion: 'latest' - }, -} diff --git a/.eslintrc.json b/.eslintrc.json new file mode 100644 index 0000000000000000000000000000000000000000..b49d0cfbcfc3b4c4010f683f09f2f68161eaf38c --- /dev/null +++ b/.eslintrc.json @@ -0,0 +1,78 @@ +{ + "env": { + "browser": true, + "es2021": true, + "node": true + }, + "extends": [ + "eslint:recommended", + "plugin:@typescript-eslint/recommended", + "plugin:vue/base", + "plugin:vue/vue3-essential", + "plugin:vue/vue3-strongly-recommended", + "plugin:vue/vue3-recommended", + "prettier" + ], + "parserOptions": { + "ecmaVersion": "latest", + "parser": "@typescript-eslint/parser", + "sourceType": "module" + }, + "plugins": ["vue", "@typescript-eslint", "prettier"], + "ignorePatterns": ["*.json", "*.html"], + "rules": { + "no-undef": "off", + "vue/no-unused-vars": "warn", + "no-unused-vars": "warn", + "no-empty-function": "warn", + "@typescript-eslint/no-empty-function": "warn", + + "prettier/prettier": [ + "error", + { + "tabWidth": 2, + "semi": true, + "singleQuote": true, + "arrowParens": "always", + "printWidth": 100, + "bracketSpacing": true, + "vueIndentScriptAndStyle": false, + "endOfLine": "auto" + } + ], + "radix": "off", + "camelcase": "off", + "global-require": "off", + "object-curly-newline": "off", + "import/first": "off", + "import/extensions": "off", + "import/prefer-default-export": "off", + "import/no-extraneous-dependencies": "off", + "import/named": "off", + "no-return-assign": ["error", "except-parens"], + "no-plusplus": ["error", { "allowForLoopAfterthoughts": true }], + "no-param-reassign": "off", + "no-confusing-arrow": "off", + "no-unused-expressions": "off", + "no-shadow": "off", + "no-restricted-syntax": "off", + "no-use-before-define": "off", + "no-redeclare": "off", + "@typescript-eslint/no-redeclare": ["error"], + "@typescript-eslint/no-use-before-define": "error", + "@typescript-eslint/no-shadow": "error", + "@typescript-eslint/no-unused-expressions": "error", + "@typescript-eslint/no-var-requires": "off", + "@typescript-eslint/explicit-module-boundary-types": "off", + "@typescript-eslint/no-non-null-assertion": "off", + "@typescript-eslint/ban-ts-comment": ["error", { "ts-ignore": "allow-with-description" }], + "vue/attribute-hyphenation": "off", + "vue/no-v-html": "off", + "vue/max-attributes-per-line": "off", + "vue/no-v-model-argument": "off", + "vue/v-on-event-hyphenation": "off", + "vue/require-default-prop": "off", + "vue/no-multiple-template-root": "off", + "vue/multi-word-component-names": "off" + } +} diff --git a/.idea/inspectionProfiles/Project_Default.xml b/.idea/inspectionProfiles/Project_Default.xml index 03d9549ea8e4ada36fb3ecbc30fef08175b7d728..9c69411050eac81b5dce09314516a30b38c41a20 100644 --- a/.idea/inspectionProfiles/Project_Default.xml +++ b/.idea/inspectionProfiles/Project_Default.xml @@ -2,5 +2,6 @@ \ No newline at end of file diff --git a/auto-imports.d.ts b/auto-imports.d.ts deleted file mode 100644 index 8b9bb3411cd0da18eead8dd10de1fe8c97718bb2..0000000000000000000000000000000000000000 --- a/auto-imports.d.ts +++ /dev/null @@ -1,78 +0,0 @@ -/* eslint-disable */ -/* prettier-ignore */ -// @ts-nocheck -// noinspection JSUnusedGlobalSymbols -// Generated by unplugin-auto-import -export {} -declare global { - const EffectScope: typeof import('vue')['EffectScope'] - const [alias]: typeof import('[package-name]')['[from]'] - const axios: typeof import('axios')['default'] - const computed: typeof import('vue')['computed'] - const createApp: typeof import('vue')['createApp'] - const customRef: typeof import('vue')['customRef'] - const defineAsyncComponent: typeof import('vue')['defineAsyncComponent'] - const defineComponent: typeof import('vue')['defineComponent'] - const effectScope: typeof import('vue')['effectScope'] - const getCurrentInstance: typeof import('vue')['getCurrentInstance'] - const getCurrentScope: typeof import('vue')['getCurrentScope'] - const h: typeof import('vue')['h'] - const inject: typeof import('vue')['inject'] - const isProxy: typeof import('vue')['isProxy'] - const isReactive: typeof import('vue')['isReactive'] - const isReadonly: typeof import('vue')['isReadonly'] - const isRef: typeof import('vue')['isRef'] - const markRaw: typeof import('vue')['markRaw'] - const nextTick: typeof import('vue')['nextTick'] - const onActivated: typeof import('vue')['onActivated'] - const onBeforeMount: typeof import('vue')['onBeforeMount'] - const onBeforeRouteLeave: typeof import('vue-router')['onBeforeRouteLeave'] - const onBeforeRouteUpdate: typeof import('vue-router')['onBeforeRouteUpdate'] - const onBeforeUnmount: typeof import('vue')['onBeforeUnmount'] - const onBeforeUpdate: typeof import('vue')['onBeforeUpdate'] - const onDeactivated: typeof import('vue')['onDeactivated'] - const onErrorCaptured: typeof import('vue')['onErrorCaptured'] - const onMounted: typeof import('vue')['onMounted'] - const onRenderTracked: typeof import('vue')['onRenderTracked'] - const onRenderTriggered: typeof import('vue')['onRenderTriggered'] - const onScopeDispose: typeof import('vue')['onScopeDispose'] - const onServerPrefetch: typeof import('vue')['onServerPrefetch'] - const onUnmounted: typeof import('vue')['onUnmounted'] - const onUpdated: typeof import('vue')['onUpdated'] - const provide: typeof import('vue')['provide'] - const reactive: typeof import('vue')['reactive'] - const readonly: typeof import('vue')['readonly'] - const ref: typeof import('vue')['ref'] - const resolveComponent: typeof import('vue')['resolveComponent'] - const shallowReactive: typeof import('vue')['shallowReactive'] - const shallowReadonly: typeof import('vue')['shallowReadonly'] - const shallowRef: typeof import('vue')['shallowRef'] - const toRaw: typeof import('vue')['toRaw'] - const toRef: typeof import('vue')['toRef'] - const toRefs: typeof import('vue')['toRefs'] - const toValue: typeof import('vue')['toValue'] - const triggerRef: typeof import('vue')['triggerRef'] - const unref: typeof import('vue')['unref'] - const useAttrs: typeof import('vue')['useAttrs'] - const useCssModule: typeof import('vue')['useCssModule'] - const useCssVars: typeof import('vue')['useCssVars'] - const useI18n: typeof import('vue-i18n')['useI18n'] - const useLink: typeof import('vue-router')['useLink'] - const useMyFetch: typeof import('@vueuse/core')['useFetch'] - const useRoute: typeof import('vue-router')['useRoute'] - const useRouter: typeof import('vue-router')['useRouter'] - const useSlots: typeof import('vue')['useSlots'] - const watch: typeof import('vue')['watch'] - const watchEffect: typeof import('vue')['watchEffect'] - const watchPostEffect: typeof import('vue')['watchPostEffect'] - const watchSyncEffect: typeof import('vue')['watchSyncEffect'] -} -// for type re-export -declare global { - // @ts-ignore - export type { Component, ComponentPublicInstance, ComputedRef, ExtractDefaultPropTypes, ExtractPropTypes, ExtractPublicPropTypes, InjectionKey, PropType, Ref, VNode, WritableComputedRef } from 'vue' - import('vue') - // @ts-ignore - export type { RouteLocationRaw } from 'vue-router' - import('vue-router') -} diff --git a/components.d.ts b/components.d.ts deleted file mode 100644 index 6a4a0991d610d32190c1ae66edd0d22c4b806934..0000000000000000000000000000000000000000 --- a/components.d.ts +++ /dev/null @@ -1,43 +0,0 @@ -/* eslint-disable */ -// @ts-nocheck -// Generated by unplugin-vue-components -// Read more: https://github.com/vuejs/core/pull/3399 -export {} - -/* prettier-ignore */ -declare module 'vue' { - export interface GlobalComponents { - Avatar: typeof import('primevue/avatar')['default'] - Button: typeof import('primevue/button')['default'] - CreateEntityMenu: typeof import('./src/components/CreateEntityMenu.vue')['default'] - Dialog: typeof import('primevue/dialog')['default'] - Divider: typeof import('primevue/divider')['default'] - Drawer: typeof import('primevue/drawer')['default'] - ImageItem: typeof import('@/modules/entities/ImageItem.vue')['default'] - ImageMoveMenu: typeof import('./src/components/editEntityMenu/ImageMoveMenu.vue')['default'] - ImagePositionMenu: typeof import('./src/components/editEntityMenu/ImagePositionMenu.vue')['default'] - ImageSizeMenu: typeof import('./src/components/editEntityMenu/ImageSizeMenu.vue')['default'] - ImageStateMenu: typeof import('./src/components/editEntityMenu/ImageStateMenu.vue')['default'] - LogoAndLabel: typeof import('./src/components/LogoAndLabel.vue')['default'] - MoveImageMenu: typeof import('./src/components/editEntityMenu/image/MoveImageMenu.vue')['default'] - MoveMenu: typeof import('./src/components/editEntityMenu/text/MoveMenu.vue')['default'] - MoveTextMenu: typeof import('./src/components/editEntityMenu/text/MoveTextMenu.vue')['default'] - RouterLink: typeof import('vue-router')['RouterLink'] - RouterView: typeof import('vue-router')['RouterView'] - SpeedDial: typeof import('primevue/speeddial')['default'] - Splitter: typeof import('primevue/splitter')['default'] - SplitterPanel: typeof import('primevue/splitterpanel')['default'] - StateImageMenu: typeof import('./src/components/editEntityMenu/image/StateImageMenu.vue')['default'] - StateMenu: typeof import('./src/components/editEntityMenu/text/StateMenu.vue')['default'] - StateTextMenu: typeof import('./src/components/editEntityMenu/text/StateTextMenu.vue')['default'] - TextFontMenu: typeof import('./src/components/editEntityMenu/TextFontMenu.vue')['default'] - TextItem: typeof import('@/modules/entities/TextItem.vue')['default'] - TextMoveMenu: typeof import('./src/components/editEntityMenu/TextMoveMenu.vue')['default'] - TextPositionMenu: typeof import('./src/components/editEntityMenu/TextPositionMenu.vue')['default'] - TextStateMenu: typeof import('./src/components/editEntityMenu/TextStateMenu.vue')['default'] - TextWidthMenu: typeof import('./src/components/editEntityMenu/TextWidthMenu.vue')['default'] - Toast: typeof import('primevue/toast')['default'] - Tree: typeof import('primevue/tree')['default'] - UserInfoHeaderWithSettings: typeof import('./src/components/UserInfoHeaderWithSettings.vue')['default'] - } -} diff --git a/package-lock.json b/package-lock.json index 6f490cb7a8595cf33c62d392f4fe34b0fd99903c..dadd3a1b4a6ccf8c5d69d83f2199a34f5f7977f2 100644 --- a/package-lock.json +++ b/package-lock.json @@ -3824,7 +3824,6 @@ "@types/node": "^18.0.0 || >=20.0.0", "less": "*", "lightningcss": "^1.21.0", - "sass": "*", "stylus": "*", "sugarss": "*", "terser": "^5.4.0" @@ -3839,9 +3838,6 @@ "lightningcss": { "optional": true }, - "sass": { - "optional": true - }, "stylus": { "optional": true }, diff --git a/package.json b/package.json index 131c67df188266078267b40d77bde9d730589760..7247e1161c74573076f36e5eb7ca65617a374e8a 100644 --- a/package.json +++ b/package.json @@ -14,10 +14,8 @@ }, "dependencies": { "@primevue/themes": "^4.0.4", - "@supabase/supabase-js": "^2.45.1", "@vueuse/core": "^10.11.0", "@vueuse/integrations": "^10.11.0", - "cropperjs": "^1.6.2", "pinia": "^2.1.7", "primeicons": "^7.0.0", "primevue": "^4.0.4", @@ -33,8 +31,11 @@ "@rushstack/eslint-patch": "^1.8.0", "@tsconfig/node20": "^20.1.4", "@types/node": "^20.14.5", + "@vue/cli-plugin-eslint": "~5.0.0", + "@vue/cli-service": "~5.0.0", "@types/uuid": "^10.0.0", "@vitejs/plugin-vue": "^5.0.5", + "@vue/cli-plugin-typescript": "~5.0.0", "@vue/eslint-config-prettier": "^9.0.0", "@vue/eslint-config-typescript": "^13.0.0", "@vue/tsconfig": "^0.5.1", @@ -43,10 +44,27 @@ "eslint-plugin-vue": "^9.23.0", "npm-run-all2": "^6.2.0", "prettier": "^3.2.5", + "sass": "^1.77.8", "typescript": "~5.4.0", "unplugin-auto-import": "^0.18.2", "unplugin-vue-components": "^0.27.3", "vite": "^5.3.1", "vue-tsc": "^2.0.21" + }, + "eslintConfig": { + "root": true, + "env": { + "node": true + }, + "extends": [ + "plugin:vue/vue3-essential", + "eslint:recommended", + "@vue/typescript/recommended", + "plugin:prettier/recommended" + ], + "parserOptions": { + "ecmaVersion": 2020 + }, + "rules": {} } } diff --git a/public/favicon.ico b/public/favicon.ico index b96e38e7cdbc6bd251e5ea2a7fb3d0d508d25cab..894d8a32e682da490dfdb1bca0e8ebe3a7f8148a 100644 Binary files a/public/favicon.ico and b/public/favicon.ico differ diff --git a/src/app/App.vue b/src/app/App.vue index 26bfa004a56c37378f5b75fd58ea71514ae507dc..c5176eec4e889513f0ff6f910bf98dba5ce89ae8 100644 --- a/src/app/App.vue +++ b/src/app/App.vue @@ -1,26 +1,31 @@ diff --git a/src/app/assets/main.css b/src/app/assets/main.css index 505547e067476dd811d6a43b440d96c9f5317671..47d862b137378901a236f2fa9f8c818a9ef0adff 100644 --- a/src/app/assets/main.css +++ b/src/app/assets/main.css @@ -1,3 +1,104 @@ +:root { + --gray-100: #f3f4f6; + --gray-200: #e5e7eb; + --gray-300: #d1d5db; + --gray-400: #9ca3af; + --gray-500: #6b7280; + --gray-600: #4b5563; + --gray-700: #374151; + --gray-800: #1f2937; + --gray-900: #111827; + --red-100: #fee2e2; + --red-200: #fecaca; + --red-300: #fca5a5; + --red-400: #f87171; + --red-500: #ef4444; + --red-600: #dc2626; + --red-700: #b91c1c; + --red-800: #991b1b; + --red-900: #7f1d1d; + --orange-100: #ffedd5; + --orange-200: #fed7aa; + --orange-300: #fdba74; + --orange-400: #fb923c; + --orange-500: #f97316; + --orange-600: #ea580c; + --orange-700: #c2410c; + --orange-800: #9a3412; + --orange-900: #7c2d12; + --yellow-100: #fef9c3; + --yellow-200: #fef08a; + --yellow-300: #fde047; + --yellow-400: #facc15; + --yellow-500: #eab308; + --yellow-600: #ca8a04; + --yellow-700: #a16207; + --yellow-800: #854d0e; + --yellow-900: #713f12; + --green-100: #dcfce7; + --green-200: #bbf7d0; + --green-300: #86efac; + --green-400: #4ade80; + --green-500: #22c55e; + --green-600: #16a34a; + --green-700: #15803d; + --green-800: #166534; + --green-900: #14532d; + --sky-100: #e0f2fe; + --sky-200: #bae6fd; + --sky-300: #7dd3fc; + --sky-400: #38bdf8; + --sky-500: #0ea5e9; + --sky-600: #0284c7; + --sky-700: #0369a1; + --sky-800: #075985; + --sky-900: #0c4a6e; + --blue-100: #dbeafe; + --blue-200: #bfdbfe; + --blue-300: #93c5fd; + --blue-400: #60a5fa; + --blue-500: #3b82f6; + --blue-600: #2563eb; + --blue-700: #1d4ed8; + --blue-800: #1e40af; + --blue-900: #1e3a8a; + --indigo-100: #e0e7ff; + --indigo-200: #c7d2fe; + --indigo-300: #a5b4fc; + --indigo-400: #818cf8; + --indigo-500: #6366f1; + --indigo-600: #4f46e5; + --indigo-700: #4338ca; + --indigo-800: #3730a3; + --indigo-900: #312e81; + --purple-100: #f3e8ff; + --purple-200: #e9d5ff; + --purple-300: #d8b4fe; + --purple-400: #c084fc; + --purple-500: #a855f7; + --purple-600: #9333ea; + --purple-700: #7e22ce; + --purple-800: #6b21a8; + --purple-900: #581c87; + --fuchsia-100: #fae8ff; + --fuchsia-200: #f5d0fe; + --fuchsia-300: #f0abfc; + --fuchsia-400: #e879f9; + --fuchsia-500: #d946ef; + --fuchsia-600: #c026d3; + --fuchsia-700: #a21caf; + --fuchsia-800: #86198f; + --fuchsia-900: #701a75; + --pink-100: #fce7f3; + --pink-200: #fbcfe8; + --pink-300: #f9a8d4; + --pink-400: #f472b6; + --pink-500: #ec4899; + --pink-600: #db2777; + --pink-700: #be185d; + --pink-800: #9d174d; + --pink-900: #831843; +} body { min-height: 100vh; } @@ -98,3 +199,23 @@ label { legend { display: block; } +::-webkit-scrollbar { + width: 10px; +} + +/* Track */ +::-webkit-scrollbar-track { + background: #484848; +} + +/* Handle */ +::-webkit-scrollbar-thumb { + border-radius: 5px; + background: #0055ff; + transition: all 0.5s ease; +} + +/* Handle on hover */ +::-webkit-scrollbar-thumb:hover { + background: #0033ff; +} diff --git a/src/app/auto-imports.d.ts b/src/app/auto-imports.d.ts index 07ab7b9a30efbaa1b1306ef5dbcca4153ce2d09b..14e2048e6074cb7210d02496ee63a678eb6e00b6 100644 --- a/src/app/auto-imports.d.ts +++ b/src/app/auto-imports.d.ts @@ -5,85 +5,74 @@ // Generated by unplugin-auto-import export {} declare global { - const EffectScope: (typeof import('vue'))['EffectScope']; - const [alias]: (typeof import('[package-name]'))['[from]']; - const axios: (typeof import('axios'))['default']; - const computed: (typeof import('vue'))['computed']; - const createApp: (typeof import('vue'))['createApp']; - const customRef: (typeof import('vue'))['customRef']; - const defineAsyncComponent: (typeof import('vue'))['defineAsyncComponent']; - const defineComponent: (typeof import('vue'))['defineComponent']; - const effectScope: (typeof import('vue'))['effectScope']; - const getCurrentInstance: (typeof import('vue'))['getCurrentInstance']; - const getCurrentScope: (typeof import('vue'))['getCurrentScope']; - const h: (typeof import('vue'))['h']; - const inject: (typeof import('vue'))['inject']; - const isProxy: (typeof import('vue'))['isProxy']; - const isReactive: (typeof import('vue'))['isReactive']; - const isReadonly: (typeof import('vue'))['isReadonly']; - const isRef: (typeof import('vue'))['isRef']; - const markRaw: (typeof import('vue'))['markRaw']; - const nextTick: (typeof import('vue'))['nextTick']; - const onActivated: (typeof import('vue'))['onActivated']; - const onBeforeMount: (typeof import('vue'))['onBeforeMount']; - const onBeforeRouteLeave: (typeof import('vue-router'))['onBeforeRouteLeave']; - const onBeforeRouteUpdate: (typeof import('vue-router'))['onBeforeRouteUpdate']; - const onBeforeUnmount: (typeof import('vue'))['onBeforeUnmount']; - const onBeforeUpdate: (typeof import('vue'))['onBeforeUpdate']; - const onDeactivated: (typeof import('vue'))['onDeactivated']; - const onErrorCaptured: (typeof import('vue'))['onErrorCaptured']; - const onMounted: (typeof import('vue'))['onMounted']; - const onRenderTracked: (typeof import('vue'))['onRenderTracked']; - const onRenderTriggered: (typeof import('vue'))['onRenderTriggered']; - const onScopeDispose: (typeof import('vue'))['onScopeDispose']; - const onServerPrefetch: (typeof import('vue'))['onServerPrefetch']; - const onUnmounted: (typeof import('vue'))['onUnmounted']; - const onUpdated: (typeof import('vue'))['onUpdated']; - const provide: (typeof import('vue'))['provide']; - const reactive: (typeof import('vue'))['reactive']; - const readonly: (typeof import('vue'))['readonly']; - const ref: (typeof import('vue'))['ref']; - const resolveComponent: (typeof import('vue'))['resolveComponent']; - const shallowReactive: (typeof import('vue'))['shallowReactive']; - const shallowReadonly: (typeof import('vue'))['shallowReadonly']; - const shallowRef: (typeof import('vue'))['shallowRef']; - const toRaw: (typeof import('vue'))['toRaw']; - const toRef: (typeof import('vue'))['toRef']; - const toRefs: (typeof import('vue'))['toRefs']; - const toValue: (typeof import('vue'))['toValue']; - const triggerRef: (typeof import('vue'))['triggerRef']; - const unref: (typeof import('vue'))['unref']; - const useAttrs: (typeof import('vue'))['useAttrs']; - const useCssModule: (typeof import('vue'))['useCssModule']; - const useCssVars: (typeof import('vue'))['useCssVars']; - const useLink: (typeof import('vue-router'))['useLink']; - const useMyFetch: (typeof import('@vueuse/core'))['useFetch']; - const useRoute: (typeof import('vue-router'))['useRoute']; - const useRouter: (typeof import('vue-router'))['useRouter']; - const useSlots: (typeof import('vue'))['useSlots']; - const watch: (typeof import('vue'))['watch']; - const watchEffect: (typeof import('vue'))['watchEffect']; - const watchPostEffect: (typeof import('vue'))['watchPostEffect']; - const watchSyncEffect: (typeof import('vue'))['watchSyncEffect']; + const EffectScope: typeof import('vue')['EffectScope'] + const [alias]: (typeof import('[package-name]'))['[from]'] + const axios: typeof import('axios')['default'] + const computed: typeof import('vue')['computed'] + const createApp: typeof import('vue')['createApp'] + const customRef: typeof import('vue')['customRef'] + const defineAsyncComponent: typeof import('vue')['defineAsyncComponent'] + const defineComponent: typeof import('vue')['defineComponent'] + const effectScope: typeof import('vue')['effectScope'] + const getCurrentInstance: typeof import('vue')['getCurrentInstance'] + const getCurrentScope: typeof import('vue')['getCurrentScope'] + const h: typeof import('vue')['h'] + const inject: typeof import('vue')['inject'] + const isProxy: typeof import('vue')['isProxy'] + const isReactive: typeof import('vue')['isReactive'] + const isReadonly: typeof import('vue')['isReadonly'] + const isRef: typeof import('vue')['isRef'] + const markRaw: typeof import('vue')['markRaw'] + const nextTick: typeof import('vue')['nextTick'] + const onActivated: typeof import('vue')['onActivated'] + const onBeforeMount: typeof import('vue')['onBeforeMount'] + const onBeforeRouteLeave: typeof import('vue-router')['onBeforeRouteLeave'] + const onBeforeRouteUpdate: typeof import('vue-router')['onBeforeRouteUpdate'] + const onBeforeUnmount: typeof import('vue')['onBeforeUnmount'] + const onBeforeUpdate: typeof import('vue')['onBeforeUpdate'] + const onDeactivated: typeof import('vue')['onDeactivated'] + const onErrorCaptured: typeof import('vue')['onErrorCaptured'] + const onMounted: typeof import('vue')['onMounted'] + const onRenderTracked: typeof import('vue')['onRenderTracked'] + const onRenderTriggered: typeof import('vue')['onRenderTriggered'] + const onScopeDispose: typeof import('vue')['onScopeDispose'] + const onServerPrefetch: typeof import('vue')['onServerPrefetch'] + const onUnmounted: typeof import('vue')['onUnmounted'] + const onUpdated: typeof import('vue')['onUpdated'] + const provide: typeof import('vue')['provide'] + const reactive: typeof import('vue')['reactive'] + const readonly: typeof import('vue')['readonly'] + const ref: typeof import('vue')['ref'] + const resolveComponent: typeof import('vue')['resolveComponent'] + const shallowReactive: typeof import('vue')['shallowReactive'] + const shallowReadonly: typeof import('vue')['shallowReadonly'] + const shallowRef: typeof import('vue')['shallowRef'] + const toRaw: typeof import('vue')['toRaw'] + const toRef: typeof import('vue')['toRef'] + const toRefs: typeof import('vue')['toRefs'] + const toValue: typeof import('vue')['toValue'] + const triggerRef: typeof import('vue')['triggerRef'] + const unref: typeof import('vue')['unref'] + const useAttrs: typeof import('vue')['useAttrs'] + const useCssModule: typeof import('vue')['useCssModule'] + const useCssVars: typeof import('vue')['useCssVars'] + const useI18n: (typeof import('vue-i18n'))['useI18n'] + const useLink: typeof import('vue-router')['useLink'] + const useMyFetch: typeof import('@vueuse/core')['useFetch'] + const useRoute: typeof import('vue-router')['useRoute'] + const useRouter: typeof import('vue-router')['useRouter'] + const useSlots: typeof import('vue')['useSlots'] + const watch: typeof import('vue')['watch'] + const watchEffect: typeof import('vue')['watchEffect'] + const watchPostEffect: typeof import('vue')['watchPostEffect'] + const watchSyncEffect: typeof import('vue')['watchSyncEffect'] } // for type re-export declare global { // @ts-ignore - export type { - Component, - ComponentPublicInstance, - ComputedRef, - ExtractDefaultPropTypes, - ExtractPropTypes, - ExtractPublicPropTypes, - InjectionKey, - PropType, - Ref, - VNode, - WritableComputedRef - } from 'vue'; - import('vue'); + export type { Component, ComponentPublicInstance, ComputedRef, ExtractDefaultPropTypes, ExtractPropTypes, ExtractPublicPropTypes, InjectionKey, PropType, Ref, VNode, WritableComputedRef } from 'vue' + import('vue') // @ts-ignore - export type { RouteLocationRaw } from 'vue-router'; - import('vue-router'); + export type { RouteLocationRaw } from 'vue-router' + import('vue-router') } diff --git a/src/app/components.d.ts b/src/app/components.d.ts new file mode 100644 index 0000000000000000000000000000000000000000..053d35139dc98b727a9a7a7354c0732cd08813c3 --- /dev/null +++ b/src/app/components.d.ts @@ -0,0 +1,46 @@ +/* eslint-disable */ +// @ts-nocheck +// Generated by unplugin-vue-components +// Read more: https://github.com/vuejs/core/pull/3399 +export {} + +/* prettier-ignore */ +declare module 'vue' { + export interface GlobalComponents { + App: typeof import('./App.vue')['default'] + Avatar: typeof import('primevue/avatar')['default'] + BaseDivider: typeof import('./../shared/BaseDivider.vue')['default'] + BaseLoader: typeof import('./../shared/BaseLoader.vue')['default'] + BaseSidebarMenu: typeof import('./../modules/BaseSidebarMenu.vue')['default'] + Button: typeof import('primevue/button')['default'] + CreateEntityMenu: typeof import('./../components/CreateEntityMenu.vue')['default'] + CropImageModal: typeof import('./../modules/CropImageModal.vue')['default'] + Dialog: typeof import('primevue/dialog')['default'] + Divider: typeof import('primevue/divider')['default'] + Drawer: typeof import('primevue/drawer')['default'] + EntitiesList: typeof import('./../modules/EntitiesList.vue')['default'] + EntityItem: typeof import('./../modules/EntityItem.vue')['default'] + EntityTitle: typeof import('./../components/entities/share/EntityTitle.vue')['default'] + HomePage: typeof import('./../pages/HomePage.vue')['default'] + ImageItem: typeof import('./../modules/entities/ImageItem.vue')['default'] + ImageMenu: typeof import('./../modules/entities/menu/ImageMenu.vue')['default'] + ImagePositionMenu: typeof import('./../components/entities/image/ImagePositionMenu.vue')['default'] + ImageSizeMenu: typeof import('./../components/entities/image/ImageSizeMenu.vue')['default'] + ImageStateMenu: typeof import('./../components/entities/image/ImageStateMenu.vue')['default'] + LogoAndLabel: typeof import('./../components/LogoAndLabel.vue')['default'] + PageBackgroundMenu: typeof import('./../modules/PageBackgroundMenu.vue')['default'] + RouterLink: typeof import('vue-router')['RouterLink'] + RouterView: typeof import('vue-router')['RouterView'] + SheetPage: typeof import('./../pages/[uuid]/SheetPage.vue')['default'] + SpeedDial: typeof import('primevue/speeddial')['default'] + Splitter: typeof import('primevue/splitter')['default'] + SplitterPanel: typeof import('primevue/splitterpanel')['default'] + TextFontMenu: typeof import('./../components/entities/share/TextFontMenu.vue')['default'] + TextItem: typeof import('./../modules/entities/TextItem.vue')['default'] + TextMenu: typeof import('./../modules/entities/menu/TextMenu.vue')['default'] + TextPositionMenu: typeof import('./../components/entities/text/TextPositionMenu.vue')['default'] + TextStateMenu: typeof import('./../components/entities/text/TextStateMenu.vue')['default'] + Tree: typeof import('primevue/tree')['default'] + UserInfoHeaderWithSettings: typeof import('./../components/UserInfoHeaderWithSettings.vue')['default'] + } +} diff --git a/src/app/helpers/images.ts b/src/app/helpers/images.ts new file mode 100644 index 0000000000000000000000000000000000000000..2372f5f92e96bbf7542e4d3cd865b6b28a2666c8 --- /dev/null +++ b/src/app/helpers/images.ts @@ -0,0 +1,52 @@ +import type { IEntity } from '@/app/interfaces/environment'; +import { useFilesWebsocketStore } from '@/app/stores/filesWebsocket'; +import type { IImage } from '@/app/interfaces/entities'; +import { useWebsocketStore } from '@/app/stores/websocket'; + +export const addUrlsToImageEntities = (entities: IEntity[]) => { + const filesWebsocketStore = useFilesWebsocketStore(); + const filesBuffer = filesWebsocketStore.filesBuffer; + let index = 0; + const entitiesToReturn = entities.map((entity: IEntity) => { + if (!entity.image_width) return entity; + if (entity.imageUrl) return entity; + if (filesWebsocketStore.imageUrl) { + // редактирование сущности изображения + entity.imageUrl = filesWebsocketStore.imageUrl; + filesWebsocketStore.cleanImageUrl(); + } else { + filesBuffer[index] = new Blob([filesBuffer[index].data], { type: 'image/jpeg' }); + entity.imageUrl = URL.createObjectURL(filesBuffer[index]); + index += 1; + } + return entity; + }); + filesWebsocketStore.cleanFilesBuffer(); + return entitiesToReturn; +}; + +export const checkIsImage = (entity: IEntity) => { + if (!entity.image_width) { + return entity; + } + const entityToReturn = { ...entity }; + const filesWebsocketStore = useFilesWebsocketStore(); + filesWebsocketStore.saveImageUrl(entityToReturn.imageUrl!); + delete entityToReturn.imageUrl; + return entityToReturn; +}; + +export const cropImage = async (newUrl: string, entity: IImage) => { + const filesWebsocketStore = useFilesWebsocketStore(); + filesWebsocketStore.saveImageUrl(newUrl); + const websocketStore = useWebsocketStore(); + const response = await fetch(newUrl); + const blob = await response.blob(); + const buffer = await blob.arrayBuffer(); + filesWebsocketStore.sendData(buffer); + const data = { + event: 'cropImage', + body: { ...entity } + }; + websocketStore.sendData(data); +}; diff --git a/src/app/helpers/index.ts b/src/app/helpers/index.ts index 675d2782caf4d15c6130ef5f8a6c7429071de55b..252d449dadb7a715ee7151633fba19996323f007 100644 --- a/src/app/helpers/index.ts +++ b/src/app/helpers/index.ts @@ -1,32 +1,51 @@ import { useInterfaceStore } from '@/app/stores/interface'; -import type { IEntity } from '@/app/interfaces/environment'; import { useDataStore } from '@/app/stores/data'; import { useWebsocketStore } from '@/app/stores/websocket'; +import type { IEntity } from '@/app/interfaces/environment'; +import { checkIsImage } from '@/app/helpers/images'; +import { useFilesWebsocketStore } from '@/app/stores/filesWebsocket'; +import type { IImage } from '@/app/interfaces/entities'; -export async function uploadFile($event: Event) { - const target = $event.target as HTMLInputElement; - if (target && target.files && target.files[0]) { - const file = target.files[0]; - const reader = new FileReader(); - reader.readAsDataURL(file); - reader.addEventListener('load', () => { - const url = reader.result; - const interfaceStore = useInterfaceStore(); - interfaceStore.changeHomeBackgroundUrl(url); - localStorage.setItem('homeBackgroundUrl', url); - }); - } -} +export const setDefaultHomeBackground = () => { + const interfaceStore = useInterfaceStore(); + interfaceStore.resetHomeBackground(); +}; -export function setDefaultHomeBackground() { +export const fetchForHomeEntities = () => { + const dataStore = useDataStore(); const interfaceStore = useInterfaceStore(); - interfaceStore.changeHomeBackgroundUrl( - 'https://wallpapers.com/images/featured/minimalist-7xpryajznty61ra3.jpg' - ); - localStorage.removeItem('homeBackgroundUrl'); -} + const websocketStore = useWebsocketStore(); + const filesWebsocketStore = useFilesWebsocketStore(); + const filesBuffer = filesWebsocketStore.filesBuffer; + if (filesBuffer.length) { + filesBuffer[0] = new Blob([filesBuffer[0].data], { type: 'image/jpeg' }); + interfaceStore.setHomeBackgroundFromDB(URL.createObjectURL(filesBuffer[0])); + } + if (!dataStore.homeEntities.length) { + const getHomeEntitiesData = { + event: 'getHomeEntities' + }; + websocketStore.sendData(getHomeEntitiesData); + } + filesWebsocketStore.removeFirstFilesBuffer(); +}; -export const editEntity = (newState: IEntity, entityUuid: string) => { +export const createHomeEntity = (newEntity: IEntity) => { + const websocketStore = useWebsocketStore(); + if (newEntity.image_buffer) { + websocketStore.setFileData(newEntity); + const filesWebsocketStore = useFilesWebsocketStore(); + return filesWebsocketStore.sendData(newEntity.image_buffer); + } + const data = { + event: 'createHomeEntity', + body: newEntity + }; + websocketStore.sendData(data); +}; + +export const editEntity = (newState: IEntity) => { + newState = checkIsImage(newState); const websocketStore = useWebsocketStore(); const data = { event: 'editHomeEntity', @@ -58,3 +77,74 @@ export const changeOrderHomeEntity = (entityUuid: string, direction: 'up' | 'dow }; websocketStore.sendData(data); }; + +export const getImageSpeedDialSizeSmallerLabelsToRemove = (entity: IImage) => { + const elementsLabelsToRemove = []; + const initialImageWidth = Math.ceil(entity.image_width / +entity.image_scale); + const initialImageHeight = Math.ceil(entity.image_height / +entity.image_scale); + if (initialImageWidth <= 400 || initialImageHeight <= 400) { + elementsLabelsToRemove.push('x0.25'); + if ( + initialImageWidth <= 200 || + initialImageHeight <= 200 || + (initialImageWidth >= 1600 && entity.text_position) + ) { + elementsLabelsToRemove.push('x0.5'); + if ( + initialImageWidth <= 95 || + initialImageHeight <= 95 || + (initialImageWidth >= 1066 && entity.text_position) + ) { + elementsLabelsToRemove.push('x0.75'); + } + } + } + if ( + (initialImageWidth >= 800 && entity.text_position) || + entity.image_width < initialImageWidth + ) { + elementsLabelsToRemove.push('x1'); + } + return elementsLabelsToRemove; +}; + +export const getImageSpeedDialSizeBiggerLabelsToRemove = (entity: IImage) => { + const elementsLabelsToRemove = []; + const initialImageWidth = Math.ceil(entity.image_width / +entity.image_scale); + const initialImageHeight = Math.ceil(entity.image_height / +entity.image_scale); + if ( + (initialImageWidth >= 800 && entity.text_position) || + entity.image_width > initialImageWidth + ) { + elementsLabelsToRemove.push('x1'); + } + if ( + initialImageWidth >= 960 || + initialImageHeight >= 960 || + (initialImageWidth >= 640 && entity.text_position) + ) { + elementsLabelsToRemove.push('x1.25'); + if ( + initialImageWidth >= 800 || + initialImageHeight >= 800 || + (initialImageWidth >= 533 && entity.text_position) + ) { + elementsLabelsToRemove.push('x1.5'); + if ( + initialImageWidth >= 685 || + initialImageHeight >= 685 || + (initialImageWidth >= 457 && entity.text_position) + ) { + elementsLabelsToRemove.push('x1.75'); + if ( + initialImageWidth >= 600 || + initialImageHeight >= 600 || + (initialImageWidth >= 400 && entity.text_position) + ) { + elementsLabelsToRemove.push('x2'); + } + } + } + } + return elementsLabelsToRemove; +}; diff --git a/src/app/interfaces/entities.ts b/src/app/interfaces/entities.ts index 956d3fbc7e354521e40a6886eb255e16f393376b..0767db1ca62f04565c4d7a52b3faa31126f43f12 100644 --- a/src/app/interfaces/entities.ts +++ b/src/app/interfaces/entities.ts @@ -3,18 +3,18 @@ import type { IEntity } from '@/app/interfaces/environment'; export interface ITable extends IEntity { entity_type: 'table'; entity_uuid: string; - title?: string; - text?: string; + title?: string | null; + text?: string | null; table_columns: ITableColumn[]; table_data: { - [key: string]: any; + [key: string]: never; }[]; } -interface ITableColumn { +export interface ITableColumn { column_uuid: string; name: string; type: ITableColumnTypes; - data: any; + data: never; } type ITableColumnTypes = | 'text' @@ -29,7 +29,7 @@ type ITableColumnTypes = export interface IText extends IEntity { entity_type: 'text'; entity_uuid: string; - title?: string; + title?: string | null; text: string; font_size?: '16' | '20' | '24' | '40' | '64'; paragraph_size?: 'full' | 'half'; @@ -40,12 +40,12 @@ export interface IText extends IEntity { export interface IImage extends IEntity { entity_type: 'image'; entity_uuid: string; - title?: string; - text?: string; - font_size?: '16' | '20' | '24' | '40' | '64'; - paragraph_size?: 'full' | 'half'; - text_position?: 'left' | 'right'; - image_url: string; + title?: string | null; + text?: string | null; + font_size?: '16' | '20' | '24' | '40' | '64' | null; + paragraph_size?: 'full' | 'half' | null; + text_position?: 'left' | 'right' | null; + imageUrl: string; image_width: number; image_height: number; image_scale: string; diff --git a/src/app/interfaces/environment.ts b/src/app/interfaces/environment.ts index a0f290d06f365453a4da8ded629dbfb8584c0921..c0a1f38281b1cc78fa79cc99d0c2b8a439f3b171 100644 --- a/src/app/interfaces/environment.ts +++ b/src/app/interfaces/environment.ts @@ -1,3 +1,5 @@ +import type { ITableColumn } from '@/app/interfaces/entities'; + export interface ISheet { sheet_uuid: string; title: string; @@ -11,19 +13,22 @@ export interface IEntity { user_nick_name?: string; entity_order?: number; entity_type: string; - title?: string; - text?: string; - font_size?: string; - paragraph_size?: string; - text_position?: string; - image_url?: string; + title?: string | null; + text?: string | null; + font_size?: string | null; + paragraph_size?: string | null; + text_position?: string | null; + image_buffer?: string; + imageUrl?: string; image_width?: number; image_height?: number; entity_position?: string; entity_title_position?: string; image_scale?: string; - table_columns?: string; - table_data?: string; + table_columns?: ITableColumn[]; + table_data?: { + [key: string]: never; + }[]; } export type TThemes = diff --git a/src/app/interfaces/index.ts b/src/app/interfaces/index.ts index fcaa1f8132010ef7b5c0ffad8643ea3ff0565535..b518d74ab4e5202f9a0e27135ffa581a3716aa42 100644 --- a/src/app/interfaces/index.ts +++ b/src/app/interfaces/index.ts @@ -1,5 +1,5 @@ export interface IImageMainInfo { - image_url: string; + imageUrl: string; image_width: number; image_height: number; } diff --git a/src/app/stores/data.ts b/src/app/stores/data.ts index bbd53f45806d3744512dff576e4ce2ea209e3e5d..c19d38965f5e4589fc433aab6cc0bc3285193bca 100644 --- a/src/app/stores/data.ts +++ b/src/app/stores/data.ts @@ -60,7 +60,7 @@ export const useDataStore = defineStore('dataStore', () => { } function setHomeEntities(entities: IEntity[]) { - homeEntities.value = entities; + homeEntities.value = [...entities]; } return { sheets, homeEntities, editHomeEntities, setHomeEntities }; }); diff --git a/src/app/stores/filesWebsocket.ts b/src/app/stores/filesWebsocket.ts new file mode 100644 index 0000000000000000000000000000000000000000..02dcc58b61115e5748b29c19ba1d3b23084aa821 --- /dev/null +++ b/src/app/stores/filesWebsocket.ts @@ -0,0 +1,47 @@ +import { defineStore } from 'pinia'; +import { useInterfaceStore } from '@/app/stores/interface'; + +export const useFilesWebsocketStore = defineStore('filesWebsocketStore', () => { + const interfaceStore = useInterfaceStore(); + + const socket = ref(); + const filesBuffer = ref([]); + const imageUrl = ref(); + + onMounted(() => { + socket.value = new WebSocket('ws://localhost:5001'); + socket.value.binaryType = 'arraybuffer'; + socket.value.onmessage = (response) => { + console.log('response: ', response); + if (response?.data?.byteLength) { + filesBuffer.value.push(response); + } + interfaceStore.setIsFetchedForBackground(); + }; + }); + + function removeFirstFilesBuffer() { + filesBuffer.value.shift(); + } + function cleanFilesBuffer() { + filesBuffer.value = []; + } + function saveImageUrl(url: string) { + imageUrl.value = url; + } + function cleanImageUrl() { + imageUrl.value = ''; + } + function sendData(data: unknown) { + socket.value.send(data); + } + return { + filesBuffer, + imageUrl, + cleanFilesBuffer, + removeFirstFilesBuffer, + saveImageUrl, + cleanImageUrl, + sendData + }; +}); diff --git a/src/app/stores/interface.ts b/src/app/stores/interface.ts index 2485d0c63952d64880d04009b8e0da95d29cff47..a98f1e4004eaa07da354030b6d048a8188736fd5 100644 --- a/src/app/stores/interface.ts +++ b/src/app/stores/interface.ts @@ -2,39 +2,58 @@ import { defineStore } from 'pinia'; import { useWebsocketStore } from '@/app/stores/websocket'; export const useInterfaceStore = defineStore('interfaceStore', () => { - const homeBackgroundUrl = ref( - 'https://wallpapers.com/images/featured/minimalist-7xpryajznty61ra3.jpg' - ); - const defaultHomeBackgroundUrl = ref( - 'https://wallpapers.com/images/featured/minimalist-7xpryajznty61ra3.jpg' + const websocketStore = useWebsocketStore(); + + const defaultHomeBackground = ref( + 'https://t3.ftcdn.net/jpg/05/01/28/98/360_F_501289843_4ITbthNCydFQGgJmoZe4IQKchItBubqZ.jpg' ); - onMounted(() => { - homeBackgroundUrl.value = - localStorage.getItem('homeBackgroundUrl') || defaultHomeBackgroundUrl.value; - }); - function changeHomeBackgroundUrl(newUrl: string) { - homeBackgroundUrl.value = newUrl; - const websocketStore = useWebsocketStore(); + const homeBackground = ref(defaultHomeBackground.value); + const isFetchedForBackground = ref(false); + + function setIsFetchedForBackground() { + isFetchedForBackground.value = true; + console.log('isFetchedForBackground.value', isFetchedForBackground.value); + } + + function resetHomeBackground() { + homeBackground.value = defaultHomeBackground.value; const data = { - event: 'changeHomeBackgroundUrl', - body: { - setting_name: 'homeBackgroundUrl', - setting_value: newUrl - } + event: 'removeHomeBackground' }; websocketStore.sendData(data); } - function setHomeBackgroundUrlFromDB(url: string | null) { + function changeHomeBackground(newUrl: string) { + homeBackground.value = newUrl; + const image = new Image(); + image.src = newUrl; + image.onload = async () => { + const response = await fetch(newUrl); + const blob = await response.blob(); + const data = { + event: 'changeHomeBackground', + body: { + setting_name: 'homeBackground', + setting_value: newUrl, + extension: blob.type + } + }; + websocketStore.sendData(data); + }; + } + function setHomeBackgroundFromDB(url: string | null) { if (!url) { return; } - homeBackgroundUrl.value = url; + homeBackground.value = url; } return { - homeBackgroundUrl, - defaultHomeBackgroundUrl, - changeHomeBackgroundUrl, - setHomeBackgroundUrlFromDB + homeBackground, + defaultHomeBackground, + isFetchedForBackground, + setIsFetchedForBackground, + resetHomeBackground, + changeHomeBackground, + setHomeBackgroundFromDB }; }); diff --git a/src/app/stores/websocket.ts b/src/app/stores/websocket.ts index 20ea30571b2ebf132a2ebfdf0f74bbec81511c17..6638f7ca530cc35d496d7ce830330bbcd2ed789e 100644 --- a/src/app/stores/websocket.ts +++ b/src/app/stores/websocket.ts @@ -2,53 +2,89 @@ import { defineStore } from 'pinia'; import { useDataStore } from '@/app/stores/data'; import type { IEntity } from '@/app/interfaces/environment'; import { useInterfaceStore } from '@/app/stores/interface'; +import { addUrlsToImageEntities } from '@/app/helpers/images'; +import { useFilesWebsocketStore } from '@/app/stores/filesWebsocket'; export const useWebsocketStore = defineStore('websocketStore', () => { - const socket = ref(); const dataStore = useDataStore(); const interfaceStore = useInterfaceStore(); + const filesWebsocketStore = useFilesWebsocketStore(); + + const filesBufferLength = computed(() => filesWebsocketStore.filesBuffer.length); const homeEntities = computed(() => dataStore.homeEntities); + const imageEntitiesCount = computed( + () => homeEntities.value.filter((entity) => entity.image_width).length + ); + + const socket = ref(); + const initialDataToSend = ref(); + const isInitialAddUrlsToImageEntitiesFinished = ref(false); + const file = ref(); onMounted(() => { socket.value = new WebSocket('ws://localhost:5000'); - socket.value.onopen = () => { - console.log('Websocket opened'); - const getHomeEntitiesData = { - event: 'getHomeEntities' - }; - socket.value.send(JSON.stringify(getHomeEntitiesData)); - const getHomeBackgroundUrlData = { - event: 'getHomeBackgroundUrl' - }; - socket.value.send(JSON.stringify(getHomeBackgroundUrlData)); + socket.value.onopen = async () => { + socket.value.send(JSON.stringify(initialDataToSend.value)); }; - socket.value.onmessage = (event: any) => { + socket.value.onmessage = async (event: any) => { const response = JSON.parse(event.data); console.log('response: ', response); switch (response.event) { - case 'getHomeEntities': - dataStore.editHomeEntities(response.data); + case 'getHomeEntities': { + const entities = response.data; + if (imageEntitiesCount.value && filesBufferLength.value === imageEntitiesCount.value) { + const entitiesAddedUrls = addUrlsToImageEntities(entities); + dataStore.editHomeEntities(entitiesAddedUrls); + } else { + dataStore.editHomeEntities(entities); + } break; - case 'getHomeBackgroundUrl': - interfaceStore.setHomeBackgroundUrlFromDB(response.data?.setting_value); + } + case 'getHomeBackground': { + const blob = new Blob([response.data.setting_value.data], { + type: `image/jpeg` + }); + const url = URL.createObjectURL(blob); + interfaceStore.setHomeBackgroundFromDB(url); break; + } case 'createHomeEntity': { const entities = [...homeEntities.value]; + if (response.data.image_width) { + response.data.imageUrl = filesWebsocketStore.imageUrl; + filesWebsocketStore.cleanImageUrl(); + } entities.push(response.data); dataStore.editHomeEntities([...entities]); break; } + case 'createImageHomeEntity': { + if (!file.value) break; + const data = { + event: 'createHomeEntity', + body: { + ...file.value + } + }; + file.value = null; + sendData(data); + break; + } case 'editHomeEntity': { - let entities = [...dataStore.homeEntities]; + let entities = [...homeEntities.value]; entities = entities.map((entity: IEntity) => { if (entity.entity_uuid !== response.data.entity_uuid) return entity; + if (response.data.image_width) { + response.data.imageUrl = filesWebsocketStore.imageUrl; + filesWebsocketStore.cleanImageUrl(); + } return response.data; }); dataStore.editHomeEntities(entities); break; } case 'deleteHomeEntity': { - let newState = [...dataStore.homeEntities]; + let newState = [...homeEntities.value]; newState = newState.filter( (entity: IEntity) => entity.entity_uuid !== response.data.entity_uuid ); @@ -56,7 +92,7 @@ export const useWebsocketStore = defineStore('websocketStore', () => { break; } case 'changeOrderHomeEntity': { - const newState = dataStore.homeEntities; + const newState = [...homeEntities.value]; const entityIndex = newState.findIndex( (entity: IEntity) => entity.entity_uuid === response.data.entity_uuid ); @@ -72,6 +108,7 @@ export const useWebsocketStore = defineStore('websocketStore', () => { ]; } dataStore.editHomeEntities(newState); + break; } } }; @@ -83,8 +120,28 @@ export const useWebsocketStore = defineStore('websocketStore', () => { }; }); + watch([filesBufferLength, homeEntities], () => { + if ( + (homeEntities.value.length && filesBufferLength.value === imageEntitiesCount.value) || + (isInitialAddUrlsToImageEntitiesFinished.value && filesBufferLength.value) + ) { + const entitiesAddedUrls = addUrlsToImageEntities(homeEntities.value); + dataStore.setHomeEntities(entitiesAddedUrls); + isInitialAddUrlsToImageEntitiesFinished.value = true; + } + }); + function setFileData(data: any) { + file.value = data; + } + function setInitialDataToSend(data: any) { + initialDataToSend.value = data; + } function sendData(data: any) { socket.value.send(JSON.stringify(data)); } - return { sendData }; + return { + setInitialDataToSend, + sendData, + setFileData + }; }); diff --git a/src/components/CreateEntityMenu.vue b/src/components/CreateEntityMenu.vue index 15d92a748f0101b770179f62d89866a103defc33..60176cdcaf8502f6414418daa2d8b610c54376be 100644 --- a/src/components/CreateEntityMenu.vue +++ b/src/components/CreateEntityMenu.vue @@ -1,28 +1,40 @@ @@ -126,8 +70,8 @@ const speedDialSizeBigger = computed(() => { :style="`width: ${props.entityData.image_width}px; height: ${props.entityData.image_height}px`" > -import { deleteEntity } from '@/app/helpers'; import type { IImage } from '@/app/interfaces/entities'; +import { deleteEntity } from '@/app/helpers'; interface Props { entityData: IImage; @@ -12,7 +12,7 @@ const emit = defineEmits([ 'removeTitle', 'addText', 'removeText', - 'openUploadFileModal' + 'openCropImageModal' ]); const speedDialState = computed(() => { @@ -51,7 +51,7 @@ const speedDialState = computed(() => { state.push({ label: 'Crop', icon: 'pi pi-expand', - command: () => emit('openUploadFileModal') + command: () => emit('openCropImageModal') }); } state.push({ @@ -82,7 +82,8 @@ const speedDialState = computed(() => {