Web: Added a component with an image.

This commit is contained in:
Tatiana Lopaeva 2024-05-13 20:42:56 +03:00
parent 80b943c0e7
commit df808d2e15
5 changed files with 347 additions and 110 deletions

View File

@ -0,0 +1,187 @@
// (c) Copyright Ascensio System SIA 2009-2024
//
// This program is a free software product.
// You can redistribute it and/or modify it under the terms
// of the GNU Affero General Public License (AGPL) version 3 as published by the Free Software
// Foundation. In accordance with Section 7(a) of the GNU AGPL its Section 15 shall be amended
// to the effect that Ascensio System SIA expressly excludes the warranty of non-infringement of
// any third-party rights.
//
// This program is distributed WITHOUT ANY WARRANTY, without even the implied warranty
// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. For details, see
// the GNU AGPL at: http://www.gnu.org/licenses/agpl-3.0.html
//
// You can contact Ascensio System SIA at Lubanas st. 125a-25, Riga, Latvia, EU, LV-1021.
//
// The interactive user interfaces in modified source and object code versions of the Program must
// display Appropriate Legal Notices, as required under Section 5 of the GNU AGPL version 3.
//
// Pursuant to Section 7(b) of the License you must retain the original Product logo when
// distributing the program. Pursuant to Section 7(e) we decline to grant you any rights under
// trademark law for use of our trademarks.
//
// All the Product's GUI elements, including illustrations and icon sets, as well as technical writing
// content are licensed under the terms of the Creative Commons Attribution-ShareAlike 4.0
// International. See the License terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
// (c) Copyright Ascensio System SIA 2009-2024
//
// This program is a free software product.
// You can redistribute it and/or modify it under the terms
// of the GNU Affero General Public License (AGPL) version 3 as published by the Free Software
// Foundation. In accordance with Section 7(a) of the GNU AGPL its Section 15 shall be amended
// to the effect that Ascensio System SIA expressly excludes the warranty of non-infringement of
// any third-party rights.
//
// This program is distributed WITHOUT ANY WARRANTY, without even the implied warranty
// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. For details, see
// the GNU AGPL at: http://www.gnu.org/licenses/agpl-3.0.html
//
// You can contact Ascensio System SIA at Lubanas st. 125a-25, Riga, Latvia, EU, LV-1021.
//
// The interactive user interfaces in modified source and object code versions of the Program must
// display Appropriate Legal Notices, as required under Section 5 of the GNU AGPL version 3.
//
// Pursuant to Section 7(b) of the License you must retain the original Product logo when
// distributing the program. Pursuant to Section 7(e) we decline to grant you any rights under
// trademark law for use of our trademarks.
//
// All the Product's GUI elements, including illustrations and icon sets, as well as technical writing
// content are licensed under the terms of the Creative Commons Attribution-ShareAlike 4.0
// International. See the License terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
import { useState, useRef, useEffect } from "react";
import { useTranslation } from "react-i18next";
import { Text } from "@docspace/shared/components/text";
import { ComboBox } from "@docspace/shared/components/combobox";
import { inject, observer } from "mobx-react";
import { StyledWatermark } from "./StyledComponent";
import { FileInput } from "@docspace/shared/components/file-input";
import { imageProcessing } from "@docspace/shared/utils/common";
const scaleOptions = () => [
{ key: 100, label: "100" },
{ key: 200, label: "200" },
{ key: 300, label: "300" },
{ key: 400, label: "400" },
{ key: 500, label: "500" },
];
const getInitialScale = (scale, isEdit) => {
const dataScale = scaleOptions();
if (!isEdit || scale === undefined || scale === 0) return dataScale[0];
return dataScale.find((item) => {
return item.key === scale;
});
};
const ImageWatermark = ({
getInitialRotate,
isEdit,
rotateOptions,
setWatermarks,
watermarksSettings,
}) => {
const { t } = useTranslation(["CreateEditRoomDialog", "Common"]);
const initialInfo = useRef(null);
if (initialInfo.current === null) {
initialInfo.current = {
dataScale: scaleOptions(),
dataRotate: rotateOptions(t),
rotate: getInitialRotate(watermarksSettings?.rotate, isEdit, true, t),
scale: getInitialScale(watermarksSettings?.imageScale, isEdit),
url: watermarksSettings?.imageUrl ?? "",
};
}
const initialInfoRef = initialInfo.current;
useEffect(() => {
setWatermarks({
rotate: initialInfoRef.rotate.key,
imageScale: initialInfoRef.scale.key,
imageUrl: initialInfoRef.url,
text: "",
enabled: true,
additions: 0,
});
}, []);
const [selectedRotate, setRotate] = useState(initialInfoRef.rotate);
const [selectedScale, setScale] = useState(initialInfoRef.scale);
const onInput = (file) => {
console.log("onInput", file);
imageProcessing(file)
.then((f) => {
if (f instanceof File)
setWatermarks({ ...watermarksSettings, image: f });
})
.catch((error) => {
if (
error instanceof Error &&
error.message === "recursion depth exceeded"
) {
toastr.error(t("Common:SizeImageLarge"));
}
});
};
const onScaleChange = (item) => {
setScale(item);
setWatermarks({ ...watermarksSettings, imageScale: item.key });
};
const onRotateChange = (item) => {
setRotate(item);
setWatermarks({ ...watermarksSettings, rotate: item.key });
};
return (
<StyledWatermark>
<FileInput accept={["image/png", "image/jpeg"]} onInput={onInput} scale />
<div className="options-wrapper">
<div>
<Text className="watermark-title" fontWeight={600} lineHeight="20px">
{t("Scale")}
</Text>
<ComboBox
selectedOption={selectedScale}
options={initialInfoRef.dataScale}
onSelect={onScaleChange}
scaled
scaledOptions
/>
</div>
<div>
<Text className="watermark-title" fontWeight={600} lineHeight="20px">
{t("Rotate")}
</Text>
<ComboBox
selectedOption={selectedRotate}
options={initialInfoRef.dataRotate}
onSelect={onRotateChange}
scaled
scaledOptions
/>
</div>
</div>
</StyledWatermark>
);
};
export default inject(({ createEditRoomStore }) => {
const { setWatermarks, watermarksSettings } = createEditRoomStore;
return {
setWatermarks,
watermarksSettings,
};
})(observer(ImageWatermark));

View File

@ -38,6 +38,12 @@ const StyledWatermark = styled.div`
.watermark-checkbox {
margin: 18px 0 0 0;
}
.options-wrapper {
display: grid;
grid-template-columns: minmax(216px, 1fr) minmax(216px, 1fr);
gap: 16px;
}
`;
const StyledBody = styled.div`
.types-content {

View File

@ -24,7 +24,7 @@
// content are licensed under the terms of the Creative Commons Attribution-ShareAlike 4.0
// International. See the License terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
import { useState, useRef } from "react";
import { useState, useRef, useEffect } from "react";
import { useTranslation } from "react-i18next";
import { inject, observer } from "mobx-react";
@ -36,6 +36,34 @@ import { WatermarkAdditions } from "@docspace/shared/enums";
import { StyledWatermark } from "./StyledComponent";
const tabsOptions = (t) => [
{
key: "UserName",
title: t("UserName"),
index: 0,
},
{
key: "UserEmail",
title: t("UserEmail"),
index: 1,
},
{
key: "UserIpAdress",
title: t("UserIPAddress"),
index: 2,
},
{
key: "CurrentDate",
title: t("Common:CurrentDate"),
index: 3,
},
{
key: "RoomName",
title: t("Common:RoomName"),
index: 4,
},
];
const getInitialState = (initialTab) => {
const state = {
UserName: false,
@ -52,19 +80,59 @@ const getInitialState = (initialTab) => {
return state;
};
const getInitialText = (text, isEdit) => {
return isEdit && text ? text : "";
};
const getInitialTabs = (additions, isEdit, t) => {
const dataTabs = tabsOptions(t);
if (!isEdit || !additions) return [dataTabs[0]];
return dataTabs.filter((item) => additions & WatermarkAdditions[item.key]);
};
const ViewerInfoWatermark = ({
getInitialRotate,
rotateOptions,
isEdit,
setWatermarks,
initialPosition,
dataPosition,
dataTabs,
initialTab,
initialText,
watermarksSettings,
}) => {
const { t } = useTranslation(["CreateEditRoomDialog", "Common"]);
const elements = useRef(getInitialState(initialTab));
const [selectedPosition, setSelectedPosition] = useState(initialPosition);
const [textValue, setTextValue] = useState(initialText ?? "");
const elements = useRef(null);
const initialInfo = useRef(null);
if (initialInfo.current === null) {
initialInfo.current = {
dataRotate: rotateOptions(t),
dataTabs: tabsOptions(t),
rotate: getInitialRotate(watermarksSettings?.rotate, isEdit, false, t),
tabs: getInitialTabs(watermarksSettings?.additions, isEdit, t),
text: getInitialText(watermarksSettings?.text, isEdit),
additions: watermarksSettings?.additions ?? WatermarkAdditions.UserName,
};
elements.current = getInitialState(initialInfo.current.tabs);
}
const initialInfoRef = initialInfo.current;
useEffect(() => {
setWatermarks({
rotate: initialInfoRef.rotate.key,
text: initialInfoRef.text,
enabled: true,
additions: initialInfoRef.additions,
});
}, []);
const [selectedPosition, setSelectedPosition] = useState(
initialInfoRef.rotate,
);
const [textValue, setTextValue] = useState(initialInfoRef.text);
const onSelect = (item) => {
let elementsData = elements.current;
@ -81,21 +149,20 @@ const ViewerInfoWatermark = ({
flagsCount += WatermarkAdditions[key];
}
}
setWatermarks({ additions: flagsCount });
setWatermarks({ ...watermarksSettings, additions: flagsCount });
};
const onPositionChange = (item) => {
setSelectedPosition(item);
setWatermarks({ rotate: item.key });
setWatermarks({ ...watermarksSettings, rotate: item.key });
};
const onTextChange = (e) => {
const { value } = e.target;
setTextValue(value);
setWatermarks({ text: value });
setWatermarks({ ...watermarksSettings, text: value });
};
return (
@ -104,9 +171,9 @@ const ViewerInfoWatermark = ({
{t("AddWatermarkElements")}
</Text>
<TabsContainer
elements={dataTabs}
elements={initialInfoRef.dataTabs}
onSelect={onSelect}
selectedItem={initialTab.map((item) => item.index)}
selectedItem={initialInfoRef.tabs.map((item) => item.index)}
multiple
withBorder
/>
@ -126,7 +193,7 @@ const ViewerInfoWatermark = ({
</Text>
<ComboBox
selectedOption={selectedPosition}
options={dataPosition}
options={initialInfoRef.dataRotate}
onSelect={onPositionChange}
scaled
scaledOptions
@ -136,8 +203,9 @@ const ViewerInfoWatermark = ({
};
export default inject(({ createEditRoomStore }) => {
const { setWatermarks } = createEditRoomStore;
const { setWatermarks, watermarksSettings } = createEditRoomStore;
return {
setWatermarks,
watermarksSettings,
};
})(observer(ViewerInfoWatermark));

View File

@ -24,15 +24,15 @@
// content are licensed under the terms of the Creative Commons Attribution-ShareAlike 4.0
// International. See the License terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
import { useState, useEffect, useRef } from "react";
import { useState } from "react";
import { useTranslation } from "react-i18next";
import { inject, observer } from "mobx-react";
import { RadioButtonGroup } from "@docspace/shared/components/radio-button-group";
import { WatermarkAdditions } from "@docspace/shared/enums";
import ViewerInfoWatermark from "./ViewerInfo";
import { StyledBody } from "./StyledComponent";
import ImageWatermark from "./ImageWatermark";
const imageWatermark = "image",
viewerInfoWatermark = "viewerInfo";
@ -53,44 +53,16 @@ const rotateOptions = (t) => [
{ key: 0, label: t("Horizontal") },
];
const tabsOptions = (t) => [
{
key: "UserName",
title: t("UserName"),
index: 0,
},
{
key: "UserEmail",
title: t("UserEmail"),
index: 1,
},
{
key: "UserIpAdress",
title: t("UserIPAddress"),
index: 2,
},
{
key: "CurrentDate",
title: t("Common:CurrentDate"),
index: 3,
},
{
key: "RoomName",
title: t("Common:RoomName"),
index: 4,
},
const imageRotateOptions = () => [
{ key: 0, label: "0" },
{ key: 30, label: "30" },
{ key: 45, label: "45" },
{ key: 60, label: "60" },
{ key: 90, label: "90" },
];
const getInitialTabs = (additions, isEdit, t) => {
const dataTabs = tabsOptions(t);
if (!isEdit || !additions) return [dataTabs[0]];
return dataTabs.filter((item) => additions & WatermarkAdditions[item.key]);
};
const getInitialRotate = (rotate, isEdit, t) => {
const dataRotate = rotateOptions(t);
const getInitialRotate = (rotate, isEdit, isImage, t) => {
const dataRotate = isImage ? imageRotateOptions() : rotateOptions(t);
if (!isEdit || rotate === undefined) return dataRotate[0];
@ -99,40 +71,18 @@ const getInitialRotate = (rotate, isEdit, t) => {
});
};
const getInitialText = (text, isEdit) => {
return isEdit && text ? text : "";
};
const Watermarks = ({ setWatermarks, watermarksSettings, isEdit }) => {
const { t } = useTranslation(["CreateEditRoomDialog", "Common"]);
const [type, setType] = useState(viewerInfoWatermark);
const initialInfo = useRef(null);
if (initialInfo.current === null) {
initialInfo.current = {
dataRotate: rotateOptions(t),
dataTabs: tabsOptions(t),
initialRotate: getInitialRotate(watermarksSettings?.rotate, isEdit, t),
initialTabs: getInitialTabs(watermarksSettings?.additions, isEdit, t),
initialText: getInitialText(watermarksSettings?.text, isEdit),
};
const getOptionType = (additions, isEdit) => {
if (isEdit) {
return additions === 0 ? imageWatermark : viewerInfoWatermark;
}
const initialInfoRef = initialInfo.current;
useEffect(() => {
if (!isEdit) {
setWatermarks(
{
rotate: initialInfoRef.initialRotate.key,
text: "",
additions: WatermarkAdditions.UserName,
enabled: true,
},
true,
);
}
}, []);
return viewerInfoWatermark;
};
const Watermarks = ({ isEdit, watermarksSettings }) => {
const { t } = useTranslation(["CreateEditRoomDialog", "Common"]);
const [type, setType] = useState(
getOptionType(watermarksSettings?.additions, isEdit),
);
const onSelectType = (e) => {
const { value } = e.target;
@ -142,8 +92,6 @@ const Watermarks = ({ setWatermarks, watermarksSettings, isEdit }) => {
const typeOptions = options(t);
console.log("============Watermarks render", watermarksSettings);
return (
<StyledBody>
<RadioButtonGroup
@ -158,11 +106,16 @@ const Watermarks = ({ setWatermarks, watermarksSettings, isEdit }) => {
{type === viewerInfoWatermark && (
<ViewerInfoWatermark
initialPosition={initialInfoRef.initialRotate}
dataPosition={initialInfoRef.dataRotate}
dataTabs={initialInfoRef.dataTabs}
initialTab={initialInfoRef.initialTabs}
initialText={initialInfoRef.initialText}
isEdit={isEdit}
getInitialRotate={getInitialRotate}
rotateOptions={rotateOptions}
/>
)}
{type === imageWatermark && (
<ImageWatermark
isEdit={isEdit}
getInitialRotate={getInitialRotate}
rotateOptions={imageRotateOptions}
/>
)}
</StyledBody>
@ -170,9 +123,8 @@ const Watermarks = ({ setWatermarks, watermarksSettings, isEdit }) => {
};
export default inject(({ createEditRoomStore }) => {
const { setWatermarks, watermarksSettings } = createEditRoomStore;
const { watermarksSettings } = createEditRoomStore;
return {
setWatermarks,
watermarksSettings,
};
})(observer(Watermarks));

View File

@ -98,26 +98,46 @@ class CreateEditRoomStore {
setWatermarks = (watermarksSettings, isInit = false) => {
if (isInit) {
this.initialWatermarksSettings = watermarksSettings;
this.watermarksSettings = watermarksSettings;
return;
}
if (!watermarksSettings) {
this.watermarksSettings = null;
return;
}
this.watermarksSettings = {
...this.watermarksSettings,
...watermarksSettings,
};
this.watermarksSettings = watermarksSettings;
};
isEqualWatermarkChanges = () => {
return isEqual(this.watermarksSettings, this.initialWatermarksSettings);
};
getWatermarkRequest = async (room) => {
if (!this.watermarksSettings.image) {
return setWatermarkSettings(room.id, this.watermarksSettings);
}
const { uploadRoomLogo } = this.filesStore;
const watermarkImage = this.watermarksSettings.image;
const uploadWatermarkData = new FormData();
uploadWatermarkData.append(0, watermarkImage);
const response = await uploadRoomLogo(uploadWatermarkData);
let newImage = new Image();
newImage.src = URL.createObjectURL(watermarkImage);
newImage.onload = () => {
let width = newImage.width;
let height = newImage.height;
return setWatermarkSettings(room.id, {
enabled: true,
imageScale: this.watermarksSettings.imageScale,
rotate: this.watermarksSettings.rotate,
imageUrl: response.data,
imageWidth: width,
imageHeight: height,
});
};
};
onCreateRoom = async (withConfirm = false, t) => {
const roomParams = this.roomParams;
@ -184,13 +204,16 @@ class CreateEditRoomStore {
const actions = [];
const requests = [];
if (this.watermarksSettings) {
await setWatermarkSettings(room.id, this.watermarksSettings);
requests.push(this.getWatermarkRequest(room));
}
// delete thirdparty account if not needed
if (!isThirdparty && storageFolderId)
await deleteThirdParty(thirdpartyAccount.providerId);
requests.push(deleteThirdParty(thirdpartyAccount.providerId));
await Promise.all(requests);
// create new tags
for (let i = 0; i < createTagsData.length; i++) {
actions.push(createTag(createTagsData[i]));
@ -205,6 +228,7 @@ class CreateEditRoomStore {
await uploadRoomLogo(uploadLogoData).then(async (response) => {
const url = URL.createObjectURL(roomParams.icon.uploadedFile);
const img = new Image();
img.onload = async () => {
const { x, y, zoom } = roomParams.icon;
try {