diff --git a/.gitignore b/.gitignore index 9d78a2b8be2f6beac79d4fa4c2ad357b5d73500d..65d271cb9af9982e1f437b7d583b6ca4596113b9 100644 --- a/.gitignore +++ b/.gitignore @@ -2,6 +2,7 @@ logs *.log npm-debug.log* +.yarn yarn-debug.log* yarn-error.log* pnpm-debug.log* @@ -29,3 +30,4 @@ coverage *.sw? *.tsbuildinfo +/.yarnrc.yml diff --git a/package.json b/package.json index 2ff40ecddc163a4d2ddb3a6aa753b1b30386b848..2870c72f7d559c49627160dd1d93f5223f823259 100644 --- a/package.json +++ b/package.json @@ -4,7 +4,7 @@ "private": true, "type": "module", "scripts": { - "dev": "vite", + "dev": "vite && npx tailwindcss -i ./src/input.css -o ./src/output.css --watch", "build": "run-p type-check \"build-only {@}\" --", "preview": "vite preview", "build-only": "vite build", @@ -62,5 +62,9 @@ "ecmaVersion": 2020 }, "rules": {} + }, + "volta": { + "node": "20.17.0", + "yarn": "4.5.0" } } diff --git a/src/app/assets/main.css b/src/app/assets/main.css index 700c0c50d2a455e96f37e462491da7a6554d1e29..0932c7d841603dcf520d95b766f2db03f91745ce 100644 --- a/src/app/assets/main.css +++ b/src/app/assets/main.css @@ -35,6 +35,15 @@ --orange-700: #c2410c; --orange-800: #9a3412; --orange-900: #7c2d12; + --amber-100: #fef3c7; + --amber-200: #fde68a; + --amber-300: #fcd34d; + --amber-400: #fbbf24; + --amber-500: #f59e0b; + --amber-600: #d97706; + --amber-700: #b45309; + --amber-800: #92400e; + --amber-900: #78350f; --yellow-100: #fef9c3; --yellow-200: #fef08a; --yellow-300: #fde047; @@ -276,10 +285,29 @@ input[type=file]::-webkit-file-upload-button { 0% { transform: scale(0); } - 50% { - transform: scale(1.25); - } 100% { transform: scale(1); } } +.v-enter-active, +.v-leave-active { + transition: all 0.5s ease; +} +.fading-enter-active, +.fading-leave-active { + transition: opacity 0.3s ease-in-out; +} +.fading-enter-active { + animation: fading-in 0.5s; +} +.fading-leave-active { + animation: fading-in 0.5s reverse; +} +@keyframes fading-in { + 0% { + opacity: 0; + } + 100% { + opacity: 1; + } +} diff --git a/src/app/components.d.ts b/src/app/components.d.ts index 4b32cae1cea132f61b42d754f17dcce82c192498..1128b7dafbe76045943ec66e6138aaa3b3d2c4d4 100644 --- a/src/app/components.d.ts +++ b/src/app/components.d.ts @@ -7,19 +7,23 @@ export {} /* prettier-ignore */ declare module 'vue' { export interface GlobalComponents { + AlignCenterIcon: typeof import('./../shared/icons/AlignCenterIcon.vue')['default'] + AlignLeftIcon: typeof import('./../shared/icons/AlignLeftIcon.vue')['default'] + AlignRightIcon: typeof import('./../shared/icons/AlignRightIcon.vue')['default'] App: typeof import('./App.vue')['default'] AuthorizationForm: typeof import('./../modules/authorization/AuthorizationForm.vue')['default'] BaseLoader: typeof import('./../shared/BaseLoader.vue')['default'] - BaseSidebarMenu: typeof import('./../modules/BaseSidebarMenu.vue')['default'] Button: typeof import('./../shared/ui/Button.vue')['default'] CloseCircle: typeof import('./../shared/icons/CloseCircle.vue')['default'] + ConfirmDeleteEntityModal: typeof import('./../modules/ConfirmDeleteEntityModal.vue')['default'] CreateEntityMenu: typeof import('./../components/CreateEntityMenu.vue')['default'] + CropIcon: typeof import('./../shared/icons/CropIcon.vue')['default'] CropImageModal: typeof import('./../modules/CropImageModal.vue')['default'] DashedIcon: typeof import('./../shared/icons/DashedIcon.vue')['default'] Divider: typeof import('./../shared/ui/Divider.vue')['default'] DividerItem: typeof import('./../modules/entities/DividerItem.vue')['default'] - DividerMenu: typeof import('./../modules/entities/settings/DividerMenu.vue')['default'] DividerSettings: typeof import('./../components/entities/settings/DividerSettings.vue')['default'] + DividerSettingsList: typeof import('./../components/entities/settings/lists/DividerSettingsList.vue')['default'] DottedIcon: typeof import('./../shared/icons/DottedIcon.vue')['default'] Drawer: typeof import('./../shared/ui/Drawer.vue')['default'] EntitiesList: typeof import('./../modules/entities/EntitiesList.vue')['default'] @@ -32,37 +36,36 @@ declare module 'vue' { HorizontalLineIcon: typeof import('./../shared/icons/HorizontalLineIcon.vue')['default'] ImageIcon: typeof import('./../shared/icons/ImageIcon.vue')['default'] ImageItem: typeof import('./../modules/entities/ImageItem.vue')['default'] - ImageMenu: typeof import('./../components/entities/settings/ImageMenu.vue')['default'] - ImagePositionMenu: typeof import('./../components/entities/image/ImagePositionMenu.vue')['default'] ImageSettings: typeof import('./../components/entities/settings/ImageSettings.vue')['default'] - ImageSizeMenu: typeof import('./../components/entities/image/ImageSizeMenu.vue')['default'] - ImageStateMenu: typeof import('./../components/entities/image/ImageStateMenu.vue')['default'] + ImageSettingsList: typeof import('./../components/entities/settings/lists/ImageSettingsList.vue')['default'] LogoAndLabel: typeof import('./../components/LogoAndLabel.vue')['default'] MenuDial: typeof import('./../shared/ui/MenuDial.vue')['default'] - MenuHeader: typeof import('./../components/MenuHeader.vue')['default'] Modal: typeof import('./../shared/ui/Modal.vue')['default'] NavigationIcon: typeof import('./../shared/icons/NavigationIcon.vue')['default'] PageBackgroundMenu: typeof import('./../modules/PageBackgroundMenu.vue')['default'] PageHeader: typeof import('./../modules/PageHeader.vue')['default'] PageMenuButton: typeof import('./../components/PageMenuButton.vue')['default'] ParagraphIcon: typeof import('./../shared/icons/ParagraphIcon.vue')['default'] + ParagraphItem: typeof import('./../modules/entities/ParagraphItem.vue')['default'] + ParagraphSettings: typeof import('./../components/entities/settings/ParagraphSettings.vue')['default'] + ParagraphSettingsList: typeof import('./../components/entities/settings/lists/ParagraphSettingsList.vue')['default'] PlusIcon: typeof import('./../shared/icons/PlusIcon.vue')['default'] RouterLink: typeof import('vue-router')['RouterLink'] RouterView: typeof import('vue-router')['RouterView'] + SaveIcon: typeof import('./../shared/icons/SaveIcon.vue')['default'] SettingsIcon: typeof import('./../shared/icons/SettingsIcon.vue')['default'] SheetPage: typeof import('./../pages/[uuid]/SheetPage.vue')['default'] SidebarMenuContent: typeof import('./../modules/SidebarMenuContent.vue')['default'] - SidebarMenuHeader: typeof import('./../modules/SidebarMenuHeader.vue')['default'] SignIn: typeof import('./../pages/authorization/signIn.vue')['default'] SignUp: typeof import('./../pages/authorization/signUp.vue')['default'] + Slider: typeof import('./../shared/ui/Slider.vue')['default'] SolidIcon: typeof import('./../shared/icons/SolidIcon.vue')['default'] TableIcon: typeof import('./../shared/icons/TableIcon.vue')['default'] TelegramSection: typeof import('./../modules/TelegramSection.vue')['default'] TextFontMenu: typeof import('./../components/entities/share/TextFontMenu.vue')['default'] - TextItem: typeof import('./../modules/entities/TextItem.vue')['default'] TextPositionMenu: typeof import('./../components/entities/text/TextPositionMenu.vue')['default'] - TextSettings: typeof import('./../components/entities/settings/TextSettings.vue')['default'] TextStateMenu: typeof import('./../components/entities/text/TextStateMenu.vue')['default'] + ToggleButton: typeof import('./../shared/ui/ToggleButton.vue')['default'] ToggleSwitch: typeof import('./../shared/ui/ToggleSwitch.vue')['default'] TrashIcon: typeof import('./../shared/icons/TrashIcon.vue')['default'] Tree: typeof import('./../shared/ui/Tree.vue')['default'] diff --git a/src/app/helpers/images.ts b/src/app/helpers/images.ts index df8889732a52ee6392ea610cbc4b8c83df855c19..4aa5cd235b6908b0769d45dfe3e0766e411e247c 100644 --- a/src/app/helpers/images.ts +++ b/src/app/helpers/images.ts @@ -3,6 +3,7 @@ import { useFilesWebsocketStore } from '@/app/stores/filesWebsocket'; import type { IImage } from '@/app/interfaces/entities'; import { useWebsocketStore } from '@/app/stores/websocket'; import { useInterfaceStore } from '@/app/stores/interface'; +import { imageScaleOptions } from '@/components/entities/settings/lists/constants/options'; export const setDefaultPageBackground = () => { const interfaceStore = useInterfaceStore(); @@ -15,14 +16,17 @@ export const addUrlsToImageEntities = (entities: IEntity[]) => { let index = 0; const entitiesToReturn = entities.map((entity: IEntity) => { if (!entity?.image_width) return entity; - if (entity.imageUrl) return entity; - if (filesWebsocketStore.imageUrl) { + if (entity.image_url) return entity; + if (filesWebsocketStore.image_url) { // редактирование сущности изображения - entity.imageUrl = filesWebsocketStore.imageUrl; + entity.image_url = filesWebsocketStore.image_url; filesWebsocketStore.cleanImageUrl(); } else { filesBuffer[index] = new Blob([filesBuffer[index].data], { type: 'image/jpeg' }); - entity.imageUrl = URL.createObjectURL(filesBuffer[index]); + entity.image_url = URL.createObjectURL(filesBuffer[index]); + index += 1; + filesBuffer[index] = new Blob([filesBuffer[index].data], { type: 'image/jpeg' }); + entity.image_url_initial = URL.createObjectURL(filesBuffer[index]); index += 1; } return entity; @@ -37,18 +41,33 @@ export const checkIsImage = (entity: IEntity) => { } const entityToReturn = { ...entity }; const filesWebsocketStore = useFilesWebsocketStore(); - filesWebsocketStore.saveImageUrl(entityToReturn.imageUrl!); - delete entityToReturn.imageUrl; + filesWebsocketStore.saveImageUrl(entityToReturn.image_url!); + delete entityToReturn.image_url; return entityToReturn; }; -export const cropImage = async (newUrl: string, entity: IImage) => { +export const calcImageWidth = (fileWidth: number, windowWidth: number) => { + let imageWidth = Math.ceil((fileWidth / (windowWidth - 128)) * 100); + if (imageWidth > 100) { + imageWidth = 100; + } + if (imageWidth < 5) { + imageWidth = 5; + } + return imageWidth; +}; + +export const sendCropImage = 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(); + const dataSetCropNow = { + event: 'setCropNow' + }; + websocketStore.sendData(dataSetCropNow); filesWebsocketStore.sendData(buffer); const data = { event: 'cropImage', @@ -57,73 +76,95 @@ export const cropImage = async (newUrl: string, entity: IImage) => { 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'); - } +export const getImageScalesToRemove = ( + entity: IImage, + isText?: boolean, + isEntityWidthFull: boolean +) => { + const valuesToRemove = []; + let scale = entity.image_scale; + if (scale[0] === 'x') scale = scale.slice(1); + const initialImageWidth = Math.ceil(+entity.image_width / +scale); + const initialImageHeight = +entity.file_height_initial; + if (initialImageWidth <= 20) { + valuesToRemove.push('x0.25'); + if (initialImageWidth <= 10) { + valuesToRemove.push('x0.5'); } } + if (initialImageWidth <= 7 || (!isEntityWidthFull && isText && initialImageWidth > 66)) { + valuesToRemove.push('x0.75'); + } + if (initialImageWidth > 75 && isText) { + valuesToRemove.push('x1'); + } if ( - (initialImageWidth >= 800 && entity.text_position) || - entity.image_width < initialImageWidth + initialImageWidth > 80 || + (initialImageWidth > 60 && isText) || + (!isEntityWidthFull && isText && initialImageWidth > 40) || + initialImageHeight * 1.25 > 1000 ) { - elementsLabelsToRemove.push('x1'); + valuesToRemove.push('x1.25'); } - 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 + initialImageWidth > 66 || + (initialImageWidth > 50 && isText) || + (!isEntityWidthFull && isText && initialImageWidth > 33) || + initialImageHeight * 1.5 > 1000 ) { - elementsLabelsToRemove.push('x1'); + valuesToRemove.push('x1.5'); } if ( - initialImageWidth >= 960 || - initialImageHeight >= 560 || - (initialImageWidth >= 640 && entity.text_position) + initialImageWidth > 57 || + (initialImageWidth > 42 && isText) || + (!isEntityWidthFull && isText && initialImageWidth > 28) || + initialImageHeight * 1.75 > 1000 ) { - elementsLabelsToRemove.push('x1.25'); - if ( - initialImageWidth >= 800 || - initialImageHeight >= 467 || - (initialImageWidth >= 533 && entity.text_position) - ) { - elementsLabelsToRemove.push('x1.5'); - if ( - initialImageWidth >= 685 || - initialImageHeight >= 400 || - (initialImageWidth >= 457 && entity.text_position) - ) { - elementsLabelsToRemove.push('x1.75'); - if ( - initialImageWidth >= 600 || - initialImageHeight >= 350 || - (initialImageWidth >= 400 && entity.text_position) - ) { - elementsLabelsToRemove.push('x2'); - } - } - } + valuesToRemove.push('x1.75'); } - return elementsLabelsToRemove; + if ( + initialImageWidth > 57 || + (initialImageWidth > 42 && isText) || + (!isEntityWidthFull && isText && initialImageWidth > 28) || + initialImageHeight * 1.75 > 1000 + ) { + valuesToRemove.push('x1.75'); + } + if ( + initialImageWidth > 50 || + (initialImageWidth > 37 && isText) || + (!isEntityWidthFull && isText && initialImageWidth > 25) || + initialImageHeight * 2 > 1000 + ) { + valuesToRemove.push('x2'); + } + return valuesToRemove; +}; + +export const filterImageScaleOptions = ( + entityData: IImage, + isText: boolean, + isEntityWidthFull: boolean +) => { + const scalesToRemove = getImageScalesToRemove(entityData, isText, isEntityWidthFull); + let initialScales = imageScaleOptions; + + if (!scalesToRemove.length) return imageScaleOptions; + + initialScales = initialScales.filter((item) => !~scalesToRemove.indexOf(item.label)); + + for (let i = 0; i < initialScales.length; i++) { + initialScales[i].value = i; + } + + return initialScales; +}; + +export const scaleImage = (entityData: IImage, prevScale: string) => { + let scale = entityData.image_scale; + if (scale[0] === 'x') scale = scale.slice(1); + if (prevScale[0] === 'x') prevScale = prevScale.slice(1); + const initialWidth = Math.ceil(+entityData.image_width / +prevScale); + entityData.image_width = Math.ceil(initialWidth * +scale); + return entityData; }; diff --git a/src/app/helpers/index.ts b/src/app/helpers/index.ts index e626cbb69dab9032afa4e1e695e7958776cfc1b8..db01ef4efe55d3af677aa884d23af716a2cf7a66 100644 --- a/src/app/helpers/index.ts +++ b/src/app/helpers/index.ts @@ -51,14 +51,24 @@ export const editEntity = (newState: IEntity) => { websocketStore.sendData(data); }; +export const sendReturnOriginalSize = (newState: IEntity) => { + const websocketStore = useWebsocketStore(); + const data = { + event: 'returnOriginalImageSize', + body: { ...newState } + }; + websocketStore.sendData(data); +}; + export const deleteEntity = (entityUuid: string) => { const dataStore = useDataStore(); const websocketStore = useWebsocketStore(); + const page_uuid = cookies.get('current_page_uuid'); const entities = dataStore.entities; const entityToDelete = entities.find((entity) => entity.entity_uuid === entityUuid); const data = { event: 'deleteEntity', - body: { ...entityToDelete } + body: { ...entityToDelete, page_uuid } }; websocketStore.sendData(data); }; @@ -100,6 +110,8 @@ export const convertThemeToColorWhiteDefault = (theme: string | undefined) => { return '#22c55e'; case 'yellow': return '#eab308'; + case 'amber': + return '#f59e0b'; case 'orange': return '#f97316'; case 'pink': @@ -119,3 +131,85 @@ export const convertThemeToColorWhiteDefault = (theme: string | undefined) => { } return '#ffffff'; }; + +export const convert800ThemeToColorGrayDefault = (theme: string | undefined) => { + if (!theme) return '#9294a1'; + switch (theme) { + case 'white': + return '#ffffff'; + case 'slate': + return '#1e293b'; + case 'blue': + return '#1e40af'; + case 'sky': + return '#075985'; + case 'teal': + return '#115e59'; + case 'lime': + return '#3f6212'; + case 'green': + return '#166534'; + case 'yellow': + return '#854d0e'; + case 'amber': + return '#92400e'; + case 'orange': + return '#9a3412'; + case 'pink': + return '#9d174d'; + case 'fuchsia': + return '#86198f'; + case 'purple': + return '#6b21a8'; + case 'indigo': + return '#3730a3'; + case 'rose': + return '#9f1239'; + case 'red': + return '#991b1b'; + case 'black': + return '#000000'; + } + return '#9294a1'; +}; + +export const convertThemeToColorBlackDefault = (theme: string | undefined) => { + if (!theme) return '#000000'; + switch (theme) { + case 'white': + return '#ffffff'; + case 'slate': + return '#64748b'; + case 'blue': + return '#3b82f6'; + case 'sky': + return '#0ea5e9'; + case 'teal': + return '#14b8a6'; + case 'lime': + return '#84cc16'; + case 'green': + return '#22c55e'; + case 'yellow': + return '#eab308'; + case 'amber': + return '#f59e0b'; + case 'orange': + return '#f97316'; + case 'pink': + return '#ec4899'; + case 'fuchsia': + return '#d946ef'; + case 'purple': + return '#a855f7'; + case 'indigo': + return '#6366f1'; + case 'rose': + return '#f43f5e'; + case 'red': + return '#ef4444'; + case 'black': + return '#000000'; + } + return '#000000'; +}; diff --git a/src/app/interfaces/entities.ts b/src/app/interfaces/entities.ts index 050bca6928ddbe72c06377bc32985449dea5fe3e..96afa4f83134389fd900164e806a2b83db9f54ec 100644 --- a/src/app/interfaces/entities.ts +++ b/src/app/interfaces/entities.ts @@ -52,9 +52,14 @@ export interface IImage extends IEntity { font_size?: '16' | '20' | '24' | '40' | '64' | null; paragraph_size?: 'full' | 'half' | null; text_position?: 'left' | 'right' | null; - imageUrl: string; + image_url_initial: string; + image_width_initial: number; + file_width_initial: number; + file_height_initial: number; + image_url: string; image_width: number; - image_height: number; + file_width: number; + file_height: number; image_scale: string; entity_title_position: 'left' | 'center' | 'right'; entity_position: 'left' | 'center' | 'right'; diff --git a/src/app/interfaces/environment.ts b/src/app/interfaces/environment.ts index f468b7fa11391eaaac9496658e7857ee2d21cc43..08052ba4d66f8642bc45b736c052f4208fd514b0 100644 --- a/src/app/interfaces/environment.ts +++ b/src/app/interfaces/environment.ts @@ -25,9 +25,14 @@ export interface IEntity { paragraph_size?: string | null; text_position?: string | null; image_buffer?: string; - imageUrl?: string; + image_url_initial?: string; + image_width_initial?: number; + file_width_initial?: number; + file_height_initial?: number; + image_url?: string; image_width?: number; - image_height?: number; + file_width?: number; + file_height?: number; entity_position?: string; entity_title_position?: string; image_scale?: string; @@ -38,12 +43,10 @@ export interface IEntity { } export type TTheme = - | 'white' | 'slate' | 'blue' | 'sky' | 'teal' - | 'lime' | 'green' | 'yellow' | 'orange' @@ -52,5 +55,4 @@ export type TTheme = | 'purple' | 'indigo' | 'rose' - | 'red' - | 'black'; + | 'red'; diff --git a/src/app/interfaces/index.ts b/src/app/interfaces/index.ts index b518d74ab4e5202f9a0e27135ffa581a3716aa42..852252c9b81a028cd3af260b1a7a59f185124552 100644 --- a/src/app/interfaces/index.ts +++ b/src/app/interfaces/index.ts @@ -1,5 +1,7 @@ export interface IImageMainInfo { - imageUrl: string; - image_width: number; - image_height: number; + image_url: string; + image_width?: number; + image_height?: number; + file_width?: number; + file_height?: number; } diff --git a/src/app/interfaces/ui.ts b/src/app/interfaces/ui.ts new file mode 100644 index 0000000000000000000000000000000000000000..e224bf26fb03442678db44a0eb69157d870e78c5 --- /dev/null +++ b/src/app/interfaces/ui.ts @@ -0,0 +1,16 @@ +import type { TTheme } from '@/app/interfaces/environment'; + +export interface IToggleButtonOption { + label: string; + value?: string | number | boolean; + textColor?: TTheme; + backgroundColor?: TTheme; + isLabelHidden?: boolean; + iconPos?: string; + textStyle?: 'bold' | 'italic'; +} +export interface ISliderOption { + label: string; + value: string | number; + color?: string; +} diff --git a/src/app/router/index.ts b/src/app/router/index.ts index 10f5fc7bd982c2edf7daa6f1dcff7a1b4ddfcb9f..6f89ee165adbe46401472e3d03be2038cd6fc932 100644 --- a/src/app/router/index.ts +++ b/src/app/router/index.ts @@ -12,6 +12,11 @@ const router = createRouter({ path: '/signUp', name: 'signUp', component: () => import('@/pages/authorization/signUp.vue') + }, + { + path: '/', + name: 'emptyPage', + component: () => import('@/pages/[uuid]/SheetPage.vue') } ] }); diff --git a/src/app/stores/filesWebsocket.ts b/src/app/stores/filesWebsocket.ts index 79087bcf14560870c570256ab032b0d4eb6fbeb6..d0f7c03d079a1ad416f6208065d88a71dbcfa492 100644 --- a/src/app/stores/filesWebsocket.ts +++ b/src/app/stores/filesWebsocket.ts @@ -6,13 +6,12 @@ export const useFilesWebsocketStore = defineStore('filesWebsocketStore', () => { const socket = ref(); const filesBuffer = ref([]); - const imageUrl = ref(); + const image_url = 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); } @@ -27,18 +26,17 @@ export const useFilesWebsocketStore = defineStore('filesWebsocketStore', () => { filesBuffer.value = []; } function saveImageUrl(url: string) { - imageUrl.value = url; + image_url.value = url; } function cleanImageUrl() { - imageUrl.value = ''; + image_url.value = ''; } function sendData(data: unknown) { - console.log('data: ', data); socket.value.send(data); } return { filesBuffer, - imageUrl, + image_url, cleanFilesBuffer, removeFirstFilesBuffer, saveImageUrl, diff --git a/src/app/stores/websocket.ts b/src/app/stores/websocket.ts index 450c42a962613f92c7d4f5a0a244ae7c81dff882..a67488edc35d888c3564ab2059fb7c06f85c3cbe 100644 --- a/src/app/stores/websocket.ts +++ b/src/app/stores/websocket.ts @@ -6,6 +6,7 @@ import { addUrlsToImageEntities } from '@/app/helpers/images'; import { useFilesWebsocketStore } from '@/app/stores/filesWebsocket'; import { useAuthorizationStore } from '@/app/stores/authorization'; import cookies from '@/app/plugins/Cookie'; +import { editEntity } from '@/app/helpers'; export const useWebsocketStore = defineStore('websocketStore', () => { const dataStore = useDataStore(); @@ -24,12 +25,12 @@ export const useWebsocketStore = defineStore('websocketStore', () => { const initialDataToSend = ref(); const isInitialAddUrlsToImageEntitiesFinished = ref(false); const file = ref(); + const originalUrl = ref(); onMounted(() => { socket.value = new WebSocket('ws://localhost:5000'); socket.value.onopen = async () => { const userUuid = cookies.get('user_uuid'); - console.log('userUuid', userUuid); if (userUuid) { const getUserData = { event: 'getUser', @@ -85,7 +86,8 @@ export const useWebsocketStore = defineStore('websocketStore', () => { case 'createEntity': { const newState = [...entities.value]; if (response.data?.image_width) { - response.data.imageUrl = filesWebsocketStore.imageUrl; + response.data.image_url_initial = filesWebsocketStore.image_url; + response.data.image_url = filesWebsocketStore.image_url; filesWebsocketStore.cleanImageUrl(); } newState.push(response.data); @@ -111,13 +113,11 @@ export const useWebsocketStore = defineStore('websocketStore', () => { authorizationStore.setUserNickName(response.data.nick_name); authorizationStore.setUserData(response.data); dataStore.setPagesData(response.data.pages_uuid); - console.log('getUser response.data: ', response.data); break; } case 'getPage': { dataStore.setCurrentPageUuid(response.data.page_uuid); dataStore.setCurrentPageData(response.data); - console.log('getPage response.data: ', response.data); break; } case 'getPageEntities': { @@ -144,7 +144,7 @@ export const useWebsocketStore = defineStore('websocketStore', () => { newState = newState.map((entity: IEntity) => { if (entity.entity_uuid !== response.data.entity_uuid) return entity; if (response.data?.image_width) { - response.data.imageUrl = filesWebsocketStore.imageUrl; + response.data.image_url = filesWebsocketStore.image_url; filesWebsocketStore.cleanImageUrl(); } return response.data; @@ -152,6 +152,22 @@ export const useWebsocketStore = defineStore('websocketStore', () => { dataStore.editEntities(newState); break; } + case 'returnOriginalSizeImage': { + let newState = [...entities.value]; + newState = newState.map((entity: IEntity) => { + if (entity.entity_uuid !== response.data.entity_uuid) return entity; + const filesBuffer = filesWebsocketStore.filesBuffer; + filesBuffer[0] = new Blob([filesBuffer[0].data], { type: 'image/jpeg' }); + entity.image_url = URL.createObjectURL(filesBuffer[0]); + originalUrl.value = entity.image_url; + // entity.file_width = entity.file_width_initial; + // entity.file_height = entity.file_height_initial; + editEntity(entity); + return entity; + }); + dataStore.editEntities(newState); + break; + } case 'changeEntitiesOrder': { const mainEntity = response.data.main; const mainEntityIndex = entities.value.findIndex( @@ -189,7 +205,7 @@ export const useWebsocketStore = defineStore('websocketStore', () => { watch([filesBufferLength, entities], () => { if ( (entities.value.length && - filesBufferLength.value === imageEntitiesCount.value && + filesBufferLength.value === imageEntitiesCount.value * 2 && imageEntitiesCount.value) || (isInitialAddUrlsToImageEntitiesFinished.value && filesBufferLength.value) ) { diff --git a/src/components/CreateEntityMenu.vue b/src/components/CreateEntityMenu.vue index a96c3f6180fb6bd8c63ad19d1a4ffe498513d800..66a54f558a639eb7d23dcd61558bcc76d1f043ab 100644 --- a/src/components/CreateEntityMenu.vue +++ b/src/components/CreateEntityMenu.vue @@ -4,6 +4,7 @@ import { useAuthorizationStore } from '@/app/stores/authorization'; import { useFilesWebsocketStore } from '@/app/stores/filesWebsocket'; import { useDataStore } from '@/app/stores/data'; import cookies from '@/app/plugins/Cookie'; +import { calcImageWidth } from '@/app/helpers/images'; const emit = defineEmits(['createEntity']); @@ -31,25 +32,29 @@ const addImage = async (files: FileList) => { const blob = await response.blob(); const buffer = await blob.arrayBuffer(); const { width: windowWidth } = useWindowSize(); - const maxWidth = windowWidth.value - 128; - const maxHeight = 700; - if (image.width > maxWidth) { - image.height = Math.floor((maxWidth / image.width) * image.height); - image.width = maxWidth; - } + const maxHeight = 1000; + const initWidth = image.width; if (image.height > maxHeight) { - image.width = Math.floor((maxHeight / image.height) * image.width); - image.height = maxHeight; + const coefficient = maxHeight / image.height; + image.width *= coefficient; } + const imageWidth = calcImageWidth(image.width, windowWidth.value); emit('createEntity', { entity_type: 'image', entity_order: entitiesCount.value + 1, image_buffer: buffer, entity_position: 'left', entity_title_position: 'center', - image_width: image.width, - image_height: image.height, - image_scale: '1' + font_size: '24', + text_position: 'right', + paragraph_size: 'full', + image_width: imageWidth, + image_width_initial: imageWidth, + file_width: initWidth, + file_height: image.height, + file_width_initial: initWidth, + file_height_initial: image.height, + image_scale: 'x1' }); }; }; @@ -123,7 +128,7 @@ const speedDialItems = ref([