Merge branch 'release/v2.5.0' of github.com:ONLYOFFICE/DocSpace-client into release/v2.5.0

This commit is contained in:
Elyor Djalilov 2024-04-02 16:01:19 +05:00
commit 357dba54a2
23 changed files with 154 additions and 97 deletions

View File

@ -5,7 +5,6 @@
"ErrorViewHeader": "Die Formular-Galerie ist momentan nicht verfügbar",
"SelectForm": "Formular auswählen",
"SubmitToGalleryDialogGuideInfo": "Erfahren Sie in unserem <1>Leitfaden</1>, wie Sie perfekte Formulare erstellen und Ihre Chancen auf eine Genehmigung erhöhen können.",
"GuideLink": "https://www.onlyoffice.com/blog/de/2022/07/wenn-design-wichtig-ist-erstellung-schoner-formulare",
"SubmitToGalleryDialogMainInfo": "Reichen Sie Ihr Formular in der öffentlichen Galerie ein, damit andere es für ihre Arbeit verwenden können. Sobald das Formular die Moderation bestanden hat, werden Sie benachrichtigt und für Ihren Beitrag belohnt.",
"SuggestChanges": "Änderungen vorschlagen",
"TemplateInfo": "Informationen zur Vorlage",

View File

@ -5,7 +5,6 @@
"ErrorViewHeader": "Form gallery is temporarily unavailable",
"SelectForm": "Select Form",
"SubmitToGalleryDialogGuideInfo": "Learn how to create perfect forms and increase your chance to get approval in our <1>guide</1>.",
"GuideLink": "https://www.onlyoffice.com/blog/2022/07/when-design-matters-how-to-create-beautiful-forms-with-oforms",
"SubmitToGalleryDialogMainInfo": "Submit your form to the public gallery to let others use it in their work. Once the form passes moderation, you will be notified and rewarded for your contribution.",
"SuggestChanges": "Suggest changes",
"TemplateInfo": "Template info",

View File

@ -5,7 +5,6 @@
"ErrorViewHeader": "La galería de formularios no está disponible temporalmente ",
"SelectForm": "Seleccionar formulario",
"SubmitToGalleryDialogGuideInfo": "Aprenda a crear formularios perfectos y a aumentar sus posibilidades de obtener la aprobación en nuestra <1>guía</1>.",
"GuideLink": "https://www.onlyoffice.com/blog/es/2022/07/como-crear-formularios-bonitos-con-oforms",
"SubmitToGalleryDialogMainInfo": "Envíe su formulario a la galería pública para que otros puedan utilizarlo en su trabajo. Una vez que el formulario pase la moderación, recibirá una notificación y una recompensa por su contribución.",
"SuggestChanges": "Sugerir cambios",
"TemplateInfo": "Información sobre la plantilla",

View File

@ -5,7 +5,6 @@
"ErrorViewHeader": "La galerie de formulaires est temporairement indisponible",
"SelectForm": "Sélectionner un formulaire",
"SubmitToGalleryDialogGuideInfo": "Apprenez à créer des formulaires parfaits et augmentez vos chances d'obtenir une approbation dans notre <1>guide</1>.",
"GuideLink": "https://www.onlyoffice.com/blog/fr/2022/07/creer-beaux-formulaires-avec-oforms",
"SubmitToGalleryDialogMainInfo": "Soumettez votre formulaire à la galerie publique pour permettre à d'autres personnes de l'utiliser dans leur travail. Une fois le formulaire modéré, vous serez informé et récompensé pour votre contribution.",
"SuggestChanges": "Proposer des modifications",
"TemplateInfo": "Informations sur le modèle",

View File

@ -5,7 +5,6 @@
"ErrorViewHeader": "La galleria dei moduli è temporaneamente non disponibile",
"SelectForm": "Seleziona modulo",
"SubmitToGalleryDialogGuideInfo": "Scopri come creare moduli perfetti e aumentare le tue possibilità di ottenere l'approvazione nella nostra <1>guida</1>.",
"GuideLink": "https://www.onlyoffice.com/blog/it/2022/07/2022-07-come-creare-bellissimi-moduli-con-oform",
"SubmitToGalleryDialogMainInfo": "Invia il tuo modulo alla galleria pubblica per consentire ad altri di utilizzarlo nel loro lavoro. Una volta che il modulo avrà superato la moderazione, riceverai una notifica e sarai ricompensato per il tuo contributo.",
"SuggestChanges": "Suggerire modifiche",
"TemplateInfo": "Informazioni sul modello",

View File

@ -5,7 +5,6 @@
"ErrorViewHeader": "フォームギャラリーは一時的に利用できません",
"SelectForm": "フォームの選択",
"SubmitToGalleryDialogGuideInfo": "<1>ガイド</1>で、完璧なフォームを作成し、承認を得るチャンスを増やす方法を学びましょう。",
"GuideLink": "https://www.onlyoffice.com/blog/ja/2022/07/when-design-matters-how-to-create-beautiful-forms-with-oforms",
"SubmitToGalleryDialogMainInfo": "あなたのフォームを公開ギャラリーに投稿して、他の人に使ってもらいましょう。フォームがモデレーションを通過すると、あなたに通知され、あなたの貢献に対して報酬が与えられます。",
"SuggestChanges": "変更点のご提案",
"TemplateInfo": "テンプレート情報",

View File

@ -5,7 +5,6 @@
"ErrorViewHeader": "A galeria de formulários está temporariamente indisponível",
"SelectForm": "Selecione o formulário",
"SubmitToGalleryDialogGuideInfo": "Aprenda como criar formulários perfeitos e aumente suas chances de obter aprovação em nosso <1>guide</1>.",
"GuideLink": "https://www.onlyoffice.com/blog/es/2022/07/como-crear-formularios-bonitos-con-oforms",
"SubmitToGalleryDialogMainInfo": "Envie seu formulário para a galeria pública para permitir que outras pessoas o utilizem em seus trabalhos. Assim que o formulário for aprovado na moderação, você será notificado e recompensado por sua contribuição.",
"SuggestChanges": "Sugerir alterações",
"TemplateInfo": "Informações do modelo",

View File

@ -5,7 +5,6 @@
"ErrorViewHeader": "表单库暂时不可用",
"SelectForm": "选择表单",
"SubmitToGalleryDialogGuideInfo": "通过我们的<1>指南</1>,了解如何创建完备的表单,提高获得批准的机会。",
"GuideLink": "https://www.onlyoffice.com/blog/zh-hans/2024/02/when-design-matters-how-to-create-beautiful-forms-with-oforms",
"SubmitToGalleryDialogMainInfo": "将您的表单提交至公共表单库,让他人在工作中使用。表单通过审核,您就会收到通知、获得奖励。",
"SuggestChanges": "提出修改建议",
"TemplateInfo": "模板信息",

View File

@ -116,8 +116,6 @@ export default function withBadges(WrappedComponent) {
};
onCopyPrimaryLink = async () => {
if (isMobileOnly) return;
const { t, item, getPrimaryLink } = this.props;
const primaryLink = await getPrimaryLink(item.id);
if (primaryLink) {

View File

@ -117,13 +117,8 @@ const QuickButtons = (props) => {
!isArchiveFolder &&
!isTile;
const onShare = () => {
if (isMobile()) return;
onClickShare();
};
return (
<div className="badges additional-badges badges__quickButtons">
<div className="badges additional-badges badges__quickButtons">
{isAvailableLockFile && (
<ColorTheme
themeId={ThemeId.IconButton}
@ -171,7 +166,7 @@ const QuickButtons = (props) => {
iconName={LinkReactSvgUrl}
className="badge copy-link icons-group"
size={sizeQuickButton}
onClick={onShare}
onClick={onClickShare}
color={colorShare}
isDisabled={isDisabled}
hoverColor={theme.filesQuickButtons.sharedColor}

View File

@ -27,7 +27,7 @@
import { Link } from "@docspace/shared/components/link";
import { ModalDialog } from "@docspace/shared/components/modal-dialog";
import { Button } from "@docspace/shared/components/button";
import { useState, useRef } from "react";
import { useState, useRef, useEffect } from "react";
import { observer, inject } from "mobx-react";
import { Trans, withTranslation } from "react-i18next";
import { ReactSVG } from "react-svg";
@ -49,9 +49,12 @@ const SubmitToFormGallery = ({
currentColorScheme,
canSubmitToFormGallery,
submitToFormGallery,
fetchGuideLink,
}) => {
const [isSubmitting, setIsSubmitting] = useState(false);
const [guideLink, setGuideLink] = useState(null);
const abortControllerRef = useRef(new AbortController());
let formItemIsSet = !!formItem;
@ -118,6 +121,13 @@ const SubmitToFormGallery = ({
onClose();
};
useEffect(() => {
(async () => {
const fetchedGuideLink = await fetchGuideLink();
setGuideLink(fetchedGuideLink);
})();
}, []);
if (!canSubmitToFormGallery()) return null;
if (isSelectingForm)
@ -153,7 +163,7 @@ const SubmitToFormGallery = ({
approval in our
<Link
color={currentColorScheme.main?.accent}
href={t("FormGallery:GuideLink")}
href={guideLink || "#"}
type={"page"}
target={"_blank"}
isBold
@ -233,5 +243,6 @@ export default inject(
currentColorScheme: settingsStore.currentColorScheme,
canSubmitToFormGallery: accessRightsStore.canSubmitToFormGallery,
submitToFormGallery: oformsStore.submitToFormGallery,
fetchGuideLink: oformsStore.fetchGuideLink,
}),
)(withTranslation("Common", "FormGallery")(observer(SubmitToFormGallery)));

View File

@ -216,6 +216,7 @@ const Item = ({
displayType="auto"
offsetRight={0}
tooltipContent={t("EmailErrorMessage")}
openOnClick={false}
size={16}
color="#F21C0E"
/>

View File

@ -83,7 +83,7 @@ export const LanguageFilterSelectedItem = styled(DropDownItem)`
margin: 0;
width: 16px;
height: 16px;
& > div {
div {
display: flex;
align-items: center;
justify-content: center;

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 React from "react";
import React, { createRef } from "react";
import PropTypes from "prop-types";
import { Trans } from "react-i18next";
import { inject, observer } from "mobx-react";
@ -58,15 +58,20 @@ class ConsumerModalDialog extends React.Component {
constructor(props) {
super(props);
this.state = {};
const required = createRef();
required.current = [];
this.requiredRef = required.current;
}
mapTokenNameToState = () => {
const { selectedConsumer } = this.props;
selectedConsumer.props.map((prop) =>
selectedConsumer.props.map((prop) => {
this.requiredRef.push(prop.name);
this.setState({
[`${prop.name}`]: prop.value,
}),
);
});
});
};
onChangeHandler = (e) => {
@ -214,18 +219,54 @@ class ConsumerModalDialog extends React.Component {
</StyledBox>
);
inputsRender = (item, index) => {
const { onChangeHandler, state, props } = this;
const { selectedConsumer, isLoading } = props;
return (
<React.Fragment key={item.name}>
<Box
displayProp="flex"
flexDirection="column"
marginProp={
selectedConsumer.props.length == index + 1 ? "0" : "0 0 16px 0"
}
>
<Box marginProp="0 0 4px 0">
<Text isBold>{item.title}:</Text>
</Box>
<Box>
<TextInput
scale
id={item.name}
name={item.name}
placeholder={item.title}
isAutoFocussed={index === 0}
tabIndex={1}
value={Object.values(state)[index]}
isDisabled={isLoading}
onChange={onChangeHandler}
maxLength={maxLength[item.name] ?? defaultMaxLength}
/>
</Box>
</Box>
</React.Fragment>
);
};
render() {
const { selectedConsumer, onModalClose, dialogVisible, isLoading, t } =
this.props;
const {
state,
onChangeHandler,
updateConsumerValues,
consumerInstruction,
helpCenterDescription,
supportTeamDescription,
requiredRef,
} = this;
const isDisabled = requiredRef.some((name) => state[name].trim() === "");
return (
<ModalDialogContainer
visible={dialogVisible}
@ -237,35 +278,9 @@ class ConsumerModalDialog extends React.Component {
<ModalDialog.Body>
<Box paddingProp="0 0 16px">{consumerInstruction}</Box>
<React.Fragment>
{selectedConsumer.props.map((prop, i) => (
<React.Fragment key={prop.name}>
<Box
displayProp="flex"
flexDirection="column"
marginProp={
selectedConsumer.props.length == i + 1 ? "0" : "0 0 16px 0"
}
>
<Box marginProp="0 0 4px 0">
<Text isBold>{prop.title}:</Text>
</Box>
<Box>
<TextInput
scale
id={prop.name}
name={prop.name}
placeholder={prop.title}
isAutoFocussed={i === 0}
tabIndex={1}
value={Object.values(state)[i]}
isDisabled={isLoading}
onChange={onChangeHandler}
maxLength={maxLength[prop.name] ?? defaultMaxLength}
/>
</Box>
</Box>
</React.Fragment>
))}
{selectedConsumer.props.map((prop, i) =>
this.inputsRender(prop, i),
)}
</React.Fragment>
<Text as="div">{supportTeamDescription}</Text>
<Text as="div">{helpCenterDescription}</Text>
@ -277,7 +292,7 @@ class ConsumerModalDialog extends React.Component {
id="enable-button"
label={isLoading ? t("Common:Sending") : t("Common:Enable")}
isLoading={isLoading}
isDisabled={isLoading}
isDisabled={isLoading || isDisabled}
scale
onClick={updateConsumerValues}
/>

View File

@ -145,8 +145,9 @@ const StyledDiagramComponent = styled.div`
const StyledFolderTagSection = styled.div`
height: 12px;
border-right: ${(props) =>
`1px solid ${props.theme.client.settings.payment.backgroundColor}`};
${(props) =>
props.width !== 0 &&
`border-right: 1px solid ${props.theme.client.settings.payment.backgroundColor}`};
background: ${(props) => props.color};
width: ${(props) => props.width + "%"};

View File

@ -42,21 +42,30 @@ const calculateSize = (size, common) => {
return (size * 100) / common;
};
const getTags = (obj, tenantCustomQuota, usedPortalSpace, t) => {
const getTags = (
t,
standalone,
catalogs,
tenantCustomQuota,
maxTotalSizeByQuota,
usedPortalSpace,
) => {
const array = [];
const colors = ["#13B7EC", "#22C386", "#FF9933", "#FFD30F"];
let i = 0;
const commonSize =
tenantCustomQuota < usedPortalSpace && tenantCustomQuota !== -1
? usedPortalSpace
: tenantCustomQuota;
let commonSize = standalone ? tenantCustomQuota : maxTotalSizeByQuota;
for (let key in obj) {
const item = obj[key];
if (standalone && tenantCustomQuota < usedPortalSpace)
commonSize = usedPortalSpace;
for (let key in catalogs) {
const item = catalogs[key];
const { usedSpace, title } = item;
const percentageSize = calculateSize(usedSpace, commonSize);
let percentageSize = calculateSize(usedSpace, commonSize);
if (percentageSize < 0.05 && percentageSize !== 0) percentageSize = 0.5;
const size = getConvertedSize(t, usedSpace);
array.push({
@ -73,26 +82,38 @@ const getTags = (obj, tenantCustomQuota, usedPortalSpace, t) => {
};
const Diagram = (props) => {
const {
tenantCustomQuota,
maxWidth = 660,
filesUsedSpace,
usedSpace,
usedPortalSpace,
maxTotalSizeByQuota,
standalone,
tenantCustomQuota,
} = props;
const { t } = useTranslation("Common");
const elementsTags = getTags(filesUsedSpace, tenantCustomQuota, usedSpace, t);
const elementsTags = getTags(
t,
standalone,
filesUsedSpace,
tenantCustomQuota,
maxTotalSizeByQuota,
usedPortalSpace,
);
const hidingSlider = standalone && tenantCustomQuota === -1;
return (
<StyledDiagramComponent maxWidth={maxWidth}>
<div className="diagram_slider">
{elementsTags.map((tag, index) => (
<StyledFolderTagSection
width={tag.percentageSize}
key={index}
color={tag.color}
/>
))}
{!hidingSlider &&
elementsTags.map((tag, index) => (
<StyledFolderTagSection
width={tag.percentageSize}
key={index}
color={tag.color}
/>
))}
</div>
<div className="diagram_description">
{elementsTags.map((tag, index) => (
@ -107,13 +128,22 @@ const Diagram = (props) => {
);
};
export default inject(({ storageManagement, currentQuotaStore }) => {
const { filesUsedSpace } = storageManagement;
const { tenantCustomQuota, usedTotalStorageSizeCount } = currentQuotaStore;
export default inject(
({ storageManagement, currentQuotaStore, settingsStore }) => {
const { filesUsedSpace } = storageManagement;
const {
tenantCustomQuota,
usedTotalStorageSizeCount,
maxTotalSizeByQuota,
} = currentQuotaStore;
const { standalone } = settingsStore;
return {
tenantCustomQuota,
filesUsedSpace,
usedSpace: usedTotalStorageSizeCount,
};
})(observer(Diagram));
return {
tenantCustomQuota,
filesUsedSpace,
usedPortalSpace: usedTotalStorageSizeCount,
maxTotalSizeByQuota,
standalone,
};
},
)(observer(Diagram));

View File

@ -400,14 +400,14 @@ export const settingsTree = [
children: [
{
id: "portal-settings_catalog-storageManagement_quota-per-room",
key: "6-1-0",
key: "6-0-1",
icon: "",
link: "quota-per-room",
tKey: "QuotaPerRoom",
},
{
id: "portal-settings_catalog-storageManagement_quota-per-user",
key: "6-1-1",
key: "6-0-2",
icon: "",
link: "quota-per-user",
tKey: "QuotaPerUser",

View File

@ -27,7 +27,10 @@
import { makeAutoObservable, runInAction } from "mobx";
import OformsFilter from "@docspace/shared/api/oforms/filter";
import { submitToGallery } from "@docspace/shared/api/oforms";
import {
getGuideLinkByLocale,
submitToGallery,
} from "@docspace/shared/api/oforms";
import {
getOformLocales,
@ -295,6 +298,13 @@ class OformsStore {
return categories;
};
fetchGuideLink = async (locale = this.defaultOformLocale) => {
const { uploadDomain, uploadDashboard } = this.settingsStore.formGallery;
const url = combineUrl(uploadDomain, uploadDashboard, `/blog-links`);
const guideLink = await getGuideLinkByLocale(url, locale);
return guideLink;
};
filterOformsByCategory = (categorizeBy, categoryId) => {
if (!categorizeBy || !categoryId) this.currentCategory = null;

View File

@ -52,6 +52,11 @@ export const getCategoriesOfCategoryType = async (url, locale = "en") => {
return res?.data?.data;
};
export const getGuideLinkByLocale = async (url, locale = "en") => {
const res = await axios.get(`${url}?locale=${locale}`);
return res?.data?.data?.[0].attributes?.link;
};
export function submitToGallery(url, file, formName, language, signal) {
const formData = new FormData();
formData.append("file", file);

View File

@ -25,7 +25,7 @@
// International. See the License terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
import styled from "styled-components";
import { commonIconsStyles, desktop } from "../../../utils";
import { commonIconsStyles } from "../../../utils";
import { TColorScheme } from "../../../themes";
import { StyledIcon } from "../sub-components/StyledIcon";
@ -43,12 +43,10 @@ const StyledIconTheme = styled(StyledIcon)<
}
}
@media ${desktop} {
&:hover {
svg {
path {
fill: ${(props) => props.$currentColorScheme?.main?.accent};
}
&:hover {
svg {
path {
fill: ${(props) => props.$currentColorScheme?.main?.accent};
}
}
}

View File

@ -51,6 +51,7 @@ const HelpButton = (props: HelpButtonProps) => {
afterHide,
tooltipMaxWidth,
tooltipContent,
openOnClick = true,
} = props;
const currentId = id || uniqueId();
@ -74,7 +75,7 @@ const HelpButton = (props: HelpButtonProps) => {
{getContent ? (
<Tooltip
clickable
openOnClick
openOnClick={openOnClick}
place={place || "top"}
offset={offset}
afterShow={afterShow}
@ -86,7 +87,7 @@ const HelpButton = (props: HelpButtonProps) => {
) : (
<Tooltip
clickable
openOnClick
openOnClick={openOnClick}
place={place}
offset={offset}
afterShow={afterShow}

View File

@ -62,4 +62,5 @@ export interface HelpButtonProps {
offsetRight?: number;
offsetBottom?: number;
offsetLeft?: number;
openOnClick?: boolean;
}

View File

@ -115,7 +115,6 @@ const Navigation = ({
const onMissClick = React.useCallback(
(e: MouseEvent) => {
e.preventDefault();
const path = e.composedPath && e.composedPath();
if (!firstClick) {