Commit 1ed1a30a authored by Дмитрий Малюгин's avatar Дмитрий Малюгин 🕓
Browse files

Merge branch 'refactor/entitiesSettings' into 'main'

Refactor entities settings

See merge request !14
parents 2a7d631d ec267328
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -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
+5 −1
Original line number Diff line number Diff line
@@ -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"
  }
}
+31 −3
Original line number Diff line number Diff line
@@ -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;
  }
}
+13 −10
Original line number Diff line number Diff line
@@ -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']
+106 −65
Original line number Diff line number Diff line
@@ -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 >= 800 && entity.text_position) ||
    entity.image_width < initialImageWidth
  ) {
    elementsLabelsToRemove.push('x1');
  if (initialImageWidth > 75 && isText) {
    valuesToRemove.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
    initialImageWidth > 80 ||
    (initialImageWidth > 60 && isText) ||
    (!isEntityWidthFull && isText && initialImageWidth > 40) ||
    initialImageHeight * 1.25 > 1000
  ) {
    elementsLabelsToRemove.push('x1');
    valuesToRemove.push('x1.25');
  }
  if (
    initialImageWidth >= 960 ||
    initialImageHeight >= 560 ||
    (initialImageWidth >= 640 && entity.text_position)
    initialImageWidth > 66 ||
    (initialImageWidth > 50 && isText) ||
    (!isEntityWidthFull && isText && initialImageWidth > 33) ||
    initialImageHeight * 1.5 > 1000
  ) {
    elementsLabelsToRemove.push('x1.25');
    valuesToRemove.push('x1.5');
  }
  if (
      initialImageWidth >= 800 ||
      initialImageHeight >= 467 ||
      (initialImageWidth >= 533 && entity.text_position)
    initialImageWidth > 57 ||
    (initialImageWidth > 42 && isText) ||
    (!isEntityWidthFull && isText && initialImageWidth > 28) ||
    initialImageHeight * 1.75 > 1000
  ) {
      elementsLabelsToRemove.push('x1.5');
    valuesToRemove.push('x1.75');
  }
  if (
        initialImageWidth >= 685 ||
        initialImageHeight >= 400 ||
        (initialImageWidth >= 457 && entity.text_position)
    initialImageWidth > 57 ||
    (initialImageWidth > 42 && isText) ||
    (!isEntityWidthFull && isText && initialImageWidth > 28) ||
    initialImageHeight * 1.75 > 1000
  ) {
        elementsLabelsToRemove.push('x1.75');
    valuesToRemove.push('x1.75');
  }
  if (
          initialImageWidth >= 600 ||
          initialImageHeight >= 350 ||
          (initialImageWidth >= 400 && entity.text_position)
    initialImageWidth > 50 ||
    (initialImageWidth > 37 && isText) ||
    (!isEntityWidthFull && isText && initialImageWidth > 25) ||
    initialImageHeight * 2 > 1000
  ) {
          elementsLabelsToRemove.push('x2');
        }
      }
    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 elementsLabelsToRemove;

  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;
};
Loading