Merge branch 'hotfix/v2.0.1' into develop
This commit is contained in:
commit
69d3dadc13
3
.github/codeql/config-codeql.yml
vendored
Normal file
3
.github/codeql/config-codeql.yml
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
---
|
||||
paths:
|
||||
- ./**
|
67
.github/workflows/codeql.yaml
vendored
Normal file
67
.github/workflows/codeql.yaml
vendored
Normal file
@ -0,0 +1,67 @@
|
||||
name: "CodeQL"
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- 'master'
|
||||
- 'release/**'
|
||||
- 'hotfix/**'
|
||||
paths-ignore:
|
||||
- '**/README.md'
|
||||
- '**/LICENSE'
|
||||
- '.github/**'
|
||||
pull_request:
|
||||
# The branches below must be a subset of the branches above
|
||||
branches:
|
||||
- 'master'
|
||||
- 'release/**'
|
||||
- 'hotfix/**'
|
||||
paths-ignore:
|
||||
- '**/README.md'
|
||||
- '**/LICENSE'
|
||||
- '.github/**'
|
||||
schedule:
|
||||
- cron: '45 3 * * 5'
|
||||
|
||||
jobs:
|
||||
analyze:
|
||||
name: Analyze
|
||||
# Runner size impacts CodeQL analysis time. To learn more, please see:
|
||||
# - https://gh.io/recommended-hardware-resources-for-running-codeql
|
||||
# - https://gh.io/supported-runners-and-hardware-resources
|
||||
# - https://gh.io/using-larger-runners
|
||||
# Consider using larger runners for possible analysis time improvements.
|
||||
runs-on: ${{ (matrix.language == 'swift' && 'macos-latest') || 'ubuntu-latest' }}
|
||||
timeout-minutes: ${{ (matrix.language == 'swift' && 120) || 360 }}
|
||||
permissions:
|
||||
actions: read
|
||||
contents: read
|
||||
security-events: write
|
||||
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
language: [ 'javascript' ]
|
||||
# CodeQL supports [ 'c-cpp', 'csharp', 'go', 'java-kotlin', 'javascript-typescript', 'python', 'ruby', 'swift' ]
|
||||
# Use only 'java-kotlin' to analyze code written in Java, Kotlin or both
|
||||
# Use only 'javascript-typescript' to analyze code written in JavaScript, TypeScript or both
|
||||
# Learn more about CodeQL language support at https://aka.ms/codeql-docs/language-support
|
||||
|
||||
steps:
|
||||
- name: Checkout client
|
||||
uses: actions/checkout@v3
|
||||
|
||||
# Initializes the CodeQL tools for scanning.
|
||||
- name: Initialize CodeQL
|
||||
uses: github/codeql-action/init@v2
|
||||
with:
|
||||
languages: ${{ matrix.language }}
|
||||
config-file: .github/codeql/config-codeql.yml
|
||||
# If you wish to specify custom queries, you can do so here or in a config file.
|
||||
# By default, queries listed here will override any specified in a config file.
|
||||
# Prefix the list here with "+" to use these queries and those in the config file.
|
||||
|
||||
- name: Perform CodeQL Analysis
|
||||
uses: github/codeql-action/analyze@v2
|
||||
with:
|
||||
category: "/language:${{matrix.language}}"
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "docspace",
|
||||
"version": "2.0.0",
|
||||
"version": "2.0.1",
|
||||
"private": true,
|
||||
"workspaces": {
|
||||
"packages": [
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@docspace/client",
|
||||
"version": "2.0.0",
|
||||
"version": "2.0.1",
|
||||
"private": true,
|
||||
"homepage": "",
|
||||
"scripts": {
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"AddedToClipboard": "項目は、クリップボードに追加されました",
|
||||
"AdditionalLinks": "추가 링크",
|
||||
"AdditionalLinks": "追加リンク",
|
||||
"AddMembersDescription": "新しいチームメンバーを手動で追加したり、リンクで招待したりすることができます。",
|
||||
"AddNewLink": "新しいリンクの追加",
|
||||
"All": "すべて",
|
||||
|
@ -35,7 +35,7 @@ export default function withContent(WrappedContent) {
|
||||
}
|
||||
|
||||
getStatusByDate = (create) => {
|
||||
const { culture, item, personal } = this.props;
|
||||
const { culture, item } = this.props;
|
||||
const { created, updated } = item;
|
||||
|
||||
const locale = getCookie(LANGUAGE) || culture;
|
||||
|
@ -1,4 +1,4 @@
|
||||
import React, { useEffect } from "react";
|
||||
import { useEffect, useState } from "react";
|
||||
import { useHotkeys } from "react-hotkeys-hook";
|
||||
import { observer, inject } from "mobx-react";
|
||||
import { useNavigate } from "react-router-dom";
|
||||
@ -67,17 +67,24 @@ const withHotkeys = (Component) => {
|
||||
|
||||
const navigate = useNavigate();
|
||||
|
||||
const [isEnabled, setIsEnabled] = useState(true);
|
||||
|
||||
const hotkeysFilter = {
|
||||
filter: (ev) =>
|
||||
ev.target?.type === "checkbox" || ev.target?.tagName !== "INPUT",
|
||||
filterPreventDefault: false,
|
||||
enableOnTags: ["INPUT"],
|
||||
enabled: enabledHotkeys && !mediaViewerIsVisible && !filesIsLoading,
|
||||
enabled:
|
||||
enabledHotkeys && !mediaViewerIsVisible && !filesIsLoading && isEnabled,
|
||||
// keyup: true,
|
||||
// keydown: false,
|
||||
};
|
||||
|
||||
const onKeyDown = (e) => activateHotkeys(e);
|
||||
const onKeyDown = (e) => {
|
||||
const someDialogIsOpen = checkDialogsOpen();
|
||||
setIsEnabled(!someDialogIsOpen);
|
||||
activateHotkeys(e);
|
||||
};
|
||||
|
||||
const folderWithNoAction =
|
||||
isFavoritesFolder ||
|
||||
|
@ -18,7 +18,7 @@ import { I18nextProvider, useTranslation } from "react-i18next";
|
||||
import i18n from "./i18n";
|
||||
|
||||
import Snackbar from "@docspace/components/snackbar";
|
||||
import moment from "moment";
|
||||
import moment from "moment-timezone";
|
||||
//import ReactSmartBanner from "./components/SmartBanner";
|
||||
import { useThemeDetector } from "@docspace/common/utils/useThemeDetector";
|
||||
import { isMobile, isIOS, isFirefox } from "react-device-detect";
|
||||
@ -54,7 +54,7 @@ const Shell = ({ items = [], page = "home", ...rest }) => {
|
||||
standalone,
|
||||
userId,
|
||||
currentDeviceType,
|
||||
|
||||
timezone,
|
||||
showArticleLoader,
|
||||
} = rest;
|
||||
|
||||
@ -484,11 +484,15 @@ const ThemeProviderWrapper = inject(({ auth, loginStore }) => {
|
||||
currentColorScheme = settingsStore.currentColorScheme || false;
|
||||
}
|
||||
|
||||
const { timezone } = settingsStore;
|
||||
|
||||
window.theme = theme;
|
||||
window.timezone = timezone;
|
||||
|
||||
return {
|
||||
theme: { ...theme, interfaceDirection: i18n.dir() },
|
||||
currentColorScheme,
|
||||
timezone,
|
||||
};
|
||||
})(observer(ThemeProvider));
|
||||
|
||||
|
@ -139,7 +139,7 @@ const Item = ({
|
||||
labelBadge={labelBadge}
|
||||
onClickBadge={onBadgeClick}
|
||||
iconBadge={iconBadge}
|
||||
badgeTitle={t("RecycleBinAction")}
|
||||
badgeTitle={labelBadge ? "" : t("RecycleBinAction")}
|
||||
/>
|
||||
</StyledDragAndDrop>
|
||||
);
|
||||
|
@ -11,6 +11,8 @@ import Mute16ReactSvgUrl from "PUBLIC_DIR/images/icons/16/mute.react.svg?url";
|
||||
|
||||
import React, { useState } from "react";
|
||||
import styled from "styled-components";
|
||||
import { isMobile as isMobileDevice } from "react-device-detect";
|
||||
|
||||
import Badge from "@docspace/components/badge";
|
||||
import IconButton from "@docspace/components/icon-button";
|
||||
import commonIconsStyles from "@docspace/components/utils/common-icons-style";
|
||||
@ -23,7 +25,7 @@ import {
|
||||
import { Base } from "@docspace/components/themes";
|
||||
|
||||
import { ColorTheme, ThemeType } from "@docspace/components/ColorTheme";
|
||||
import { isTablet, isDesktop } from "@docspace/components/utils/device";
|
||||
import { isTablet, isDesktop, size } from "@docspace/components/utils/device";
|
||||
import { classNames } from "@docspace/components/utils/classNames";
|
||||
|
||||
const StyledWrapper = styled.div`
|
||||
@ -114,7 +116,10 @@ const Badges = ({
|
||||
|
||||
const contentNewItems = newItems > 999 ? "999+" : newItems;
|
||||
|
||||
const tabletViewBadge = !isTile && isTablet();
|
||||
const isLargeTabletDevice =
|
||||
isMobileDevice && window.innerWidth >= size.desktop;
|
||||
|
||||
const tabletViewBadge = !isTile && (isTablet() || isLargeTabletDevice);
|
||||
const desktopView = !isTile && isDesktop();
|
||||
|
||||
const sizeBadge = isTile || tabletViewBadge ? "medium" : "small";
|
||||
|
@ -71,6 +71,7 @@ export type useRootHelperProps = {
|
||||
onSetBaseFolderPath?: (
|
||||
value: number | string | undefined | BreadCrumb[]
|
||||
) => void;
|
||||
isUserOnly?: boolean;
|
||||
};
|
||||
|
||||
export type useRoomsHelperProps = {
|
||||
@ -129,6 +130,7 @@ export type FilesSelectorProps = {
|
||||
isThirdParty: boolean;
|
||||
rootThirdPartyId?: string;
|
||||
isRoomsOnly: boolean;
|
||||
isUserOnly: boolean;
|
||||
isRoomBackup: boolean;
|
||||
isEditorDialog: boolean;
|
||||
setMoveToPublicRoomVisible: (visible: boolean, operationData: object) => void;
|
||||
@ -217,5 +219,6 @@ export type FilesSelectorProps = {
|
||||
|
||||
embedded: boolean;
|
||||
withHeader: boolean;
|
||||
withCancelButton: boolean;
|
||||
settings: any;
|
||||
};
|
||||
|
@ -20,6 +20,7 @@ const useRootHelper = ({
|
||||
setIsNextPageLoading,
|
||||
setTotal,
|
||||
setHasNextPage,
|
||||
isUserOnly,
|
||||
}: useRootHelperProps) => {
|
||||
const [isRoot, setIsRoot] = React.useState<boolean>(false);
|
||||
|
||||
@ -41,7 +42,7 @@ const useRootHelper = ({
|
||||
const avatar = getCatalogIconUrlByType(folder.rootFolderType);
|
||||
|
||||
if (
|
||||
folder.rootFolderType === FolderType.Rooms ||
|
||||
(!isUserOnly && folder.rootFolderType === FolderType.Rooms) ||
|
||||
folder.rootFolderType === FolderType.USER
|
||||
) {
|
||||
newItems.push({
|
||||
|
@ -38,6 +38,7 @@ const FilesSelector = ({
|
||||
// withoutImmediatelyClose = false,
|
||||
isThirdParty = false,
|
||||
isRoomsOnly = false,
|
||||
isUserOnly = false,
|
||||
isEditorDialog = false,
|
||||
|
||||
rootThirdPartyId,
|
||||
@ -100,6 +101,7 @@ const FilesSelector = ({
|
||||
|
||||
embedded,
|
||||
withHeader,
|
||||
withCancelButton = true,
|
||||
getIcon,
|
||||
isRoomBackup,
|
||||
}: FilesSelectorProps) => {
|
||||
@ -164,6 +166,7 @@ const FilesSelector = ({
|
||||
setHasNextPage,
|
||||
setIsNextPageLoading,
|
||||
onSetBaseFolderPath,
|
||||
isUserOnly,
|
||||
});
|
||||
|
||||
const { getRoomList } = useRoomsHelper({
|
||||
@ -523,7 +526,7 @@ const FilesSelector = ({
|
||||
onSelect={onSelectAction}
|
||||
acceptButtonLabel={acceptButtonLabel}
|
||||
onAccept={onAcceptAction}
|
||||
withCancelButton
|
||||
withCancelButton={withCancelButton}
|
||||
cancelButtonLabel={t("Common:CancelButton")}
|
||||
onCancel={onCloseAction}
|
||||
emptyScreenImage={
|
||||
@ -567,7 +570,9 @@ const FilesSelector = ({
|
||||
currentFooterInputValue={currentFooterInputValue}
|
||||
footerCheckboxLabel={footerCheckboxLabel}
|
||||
descriptionText={
|
||||
!filterParam ? "" : descriptionText ?? t("Common:SelectDOCXFormat")
|
||||
!filterParam || filterParam === "ALL"
|
||||
? ""
|
||||
: descriptionText ?? t("Common:SelectDOCXFormat")
|
||||
}
|
||||
acceptButtonId={
|
||||
isMove || isCopy || isRestore ? "select-file-modal-submit" : ""
|
||||
|
@ -4,6 +4,7 @@ import { useTranslation } from "react-i18next";
|
||||
import { CreateRoomDialog } from "../dialogs";
|
||||
|
||||
const CreateRoomEvent = ({
|
||||
title,
|
||||
visible,
|
||||
onClose,
|
||||
|
||||
@ -57,6 +58,7 @@ const CreateRoomEvent = ({
|
||||
|
||||
return (
|
||||
<CreateRoomDialog
|
||||
title={title}
|
||||
t={t}
|
||||
visible={
|
||||
visible &&
|
||||
|
@ -31,6 +31,7 @@ const GlobalEvents = ({ enablePlugins, eventListenerItemsList }) => {
|
||||
});
|
||||
|
||||
const [createRoomDialogProps, setCreateRoomDialogProps] = useState({
|
||||
title: "",
|
||||
visible: false,
|
||||
onClose: null,
|
||||
});
|
||||
@ -101,9 +102,10 @@ const GlobalEvents = ({ enablePlugins, eventListenerItemsList }) => {
|
||||
|
||||
const onCreateRoom = useCallback((e) => {
|
||||
setCreateRoomDialogProps({
|
||||
title: e?.title,
|
||||
visible: true,
|
||||
onClose: () =>
|
||||
setCreateRoomDialogProps({ visible: false, onClose: null }),
|
||||
setCreateRoomDialogProps({ title: "", visible: false, onClose: null }),
|
||||
});
|
||||
}, []);
|
||||
|
||||
|
@ -107,6 +107,8 @@ const Layout = (props) => {
|
||||
};
|
||||
|
||||
const onScroll = (e) => {
|
||||
if (window.innerHeight < window.innerWidth) return;
|
||||
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
window.scrollTo(0, 0);
|
||||
|
@ -33,7 +33,7 @@ const StyledMain = styled.main`
|
||||
`;
|
||||
|
||||
const Main = (props) => {
|
||||
const { mainBarVisible, isBannerVisible } = props;
|
||||
const { mainBarVisible, isBannerVisible, isFrame } = props;
|
||||
//console.log("Main render");
|
||||
const [mainHeight, setMainHeight] = React.useState(window.innerHeight);
|
||||
const updateSizeRef = React.useRef(null);
|
||||
@ -51,7 +51,7 @@ const Main = (props) => {
|
||||
|
||||
React.useEffect(() => {
|
||||
onResize();
|
||||
}, [mainBarVisible, isBannerVisible]);
|
||||
}, [mainBarVisible, isBannerVisible, isFrame]);
|
||||
|
||||
const onResize = React.useCallback(
|
||||
(e) => {
|
||||
@ -89,13 +89,13 @@ const Main = (props) => {
|
||||
}
|
||||
|
||||
// 48 - its nav menu with burger, logo and user avatar
|
||||
if (isMobileUtils()) {
|
||||
if (isMobileUtils() && !isFrame) {
|
||||
correctHeight -= 48;
|
||||
}
|
||||
|
||||
setMainHeight(correctHeight);
|
||||
},
|
||||
[mainBarVisible, isBannerVisible]
|
||||
[mainBarVisible, isBannerVisible, isFrame]
|
||||
);
|
||||
|
||||
return <StyledMain className="main" mainHeight={mainHeight} {...props} />;
|
||||
@ -106,9 +106,10 @@ Main.displayName = "Main";
|
||||
export default inject(({ auth }) => {
|
||||
const { isBannerVisible } = auth.bannerStore;
|
||||
|
||||
const { mainBarVisible } = auth.settingsStore;
|
||||
const { mainBarVisible, isFrame } = auth.settingsStore;
|
||||
return {
|
||||
mainBarVisible,
|
||||
isBannerVisible,
|
||||
isFrame,
|
||||
};
|
||||
})(observer(Main));
|
||||
|
@ -43,7 +43,7 @@ const convertToItems = (folders) => {
|
||||
const icon = logo.medium ? logo.medium : getRoomLogo(roomType);
|
||||
const color = logo.color;
|
||||
|
||||
return { id, label: title, icon, color };
|
||||
return { id, label: title, icon, color, logo, roomType };
|
||||
});
|
||||
|
||||
return items;
|
||||
|
@ -35,6 +35,7 @@ const StyledModalDialog = styled(ModalDialog)`
|
||||
const CreateRoomDialog = ({
|
||||
t,
|
||||
visible,
|
||||
title,
|
||||
onClose,
|
||||
onCreate,
|
||||
|
||||
@ -59,7 +60,7 @@ const CreateRoomDialog = ({
|
||||
|
||||
const startRoomParams = {
|
||||
type: undefined,
|
||||
title: "",
|
||||
title: title,
|
||||
tags: [],
|
||||
isPrivate: false,
|
||||
storageLocation: {
|
||||
@ -93,7 +94,7 @@ const CreateRoomDialog = ({
|
||||
}));
|
||||
};
|
||||
|
||||
const isRoomTitleChanged = roomParams.title.trim() !== "" ? false : true;
|
||||
const isRoomTitleChanged = roomParams?.title?.trim() !== "" ? false : true;
|
||||
|
||||
const onKeyUpHandler = (e) => {
|
||||
if (isWrongTitle) return;
|
||||
@ -101,7 +102,7 @@ const CreateRoomDialog = ({
|
||||
};
|
||||
|
||||
const onCreateRoom = async () => {
|
||||
if (!roomParams.title.trim()) {
|
||||
if (!roomParams?.title?.trim()) {
|
||||
setIsValidTitle(false);
|
||||
return;
|
||||
}
|
||||
|
@ -87,7 +87,11 @@ const DeleteLinkDialogComponent = (props) => {
|
||||
<Button
|
||||
id="delete-file-modal_submit"
|
||||
key="OkButton"
|
||||
label={t("Common:Delete")}
|
||||
label={
|
||||
link.sharedTo.primary && isPublicRoomType
|
||||
? t("Files:RevokeLink")
|
||||
: t("Files:DeleteLink")
|
||||
}
|
||||
size="normal"
|
||||
primary
|
||||
scale
|
||||
|
@ -2,7 +2,7 @@ import React, { useState, useEffect } from "react";
|
||||
import { inject, observer } from "mobx-react";
|
||||
import { withTranslation, Trans } from "react-i18next";
|
||||
import { useNavigate } from "react-router-dom";
|
||||
import moment from "moment";
|
||||
import moment from "moment-timezone";
|
||||
import ModalDialog from "@docspace/components/modal-dialog";
|
||||
import Button from "@docspace/components/button";
|
||||
import Text from "@docspace/components/text";
|
||||
@ -32,9 +32,10 @@ const InviteUsersWarningDialog = (props) => {
|
||||
|
||||
useEffect(() => {
|
||||
moment.locale(language);
|
||||
if (window.timezone) moment().tz(window.timezone);
|
||||
|
||||
gracePeriodDays();
|
||||
}, [language, gracePeriodDays]);
|
||||
}, [language, gracePeriodDays, window.timezone]);
|
||||
|
||||
const gracePeriodDays = () => {
|
||||
const fromDateMoment = moment(dueDate);
|
||||
|
@ -130,7 +130,7 @@ export default inject(({ auth, pluginStore }) => {
|
||||
|
||||
const plugin = pluginList.find((p) => p.name === pluginName);
|
||||
|
||||
const withDelete = pluginOptions.includes("delete") && !plugin.system;
|
||||
const withDelete = pluginOptions.delete && !plugin.system;
|
||||
|
||||
const pluginSettings = plugin?.getAdminPluginSettings();
|
||||
|
||||
|
@ -17,7 +17,6 @@ const EmbeddingBody = ({ t, link, requestToken, roomId }) => {
|
||||
const [heightValue, setHeightValue] = useState("100%");
|
||||
|
||||
const config = {
|
||||
hash: `${API_JS_HASH}`,
|
||||
width: `${widthValue}`,
|
||||
height: `${heightValue}`,
|
||||
frameId: "ds-frame-embedding",
|
||||
|
@ -63,7 +63,7 @@ const ExternalLinks = ({
|
||||
const editLink = async () => {
|
||||
const type =
|
||||
roomType === RoomsType.PublicRoom
|
||||
? ShareAccessRights.RoomManager
|
||||
? ShareAccessRights.Collaborator
|
||||
: ShareAccessRights.ReadOnly;
|
||||
|
||||
const link = await setInvitationLinks(roomId, "Invite", type);
|
||||
|
@ -138,6 +138,8 @@ export const getCategoryType = (location) => {
|
||||
categoryType = CategoryType.Settings;
|
||||
} else if (pathname.startsWith("/accounts/filter")) {
|
||||
categoryType = CategoryType.Accounts;
|
||||
} else if (pathname.startsWith("/form-gallery")) {
|
||||
categoryType = CategoryType.Personal;
|
||||
}
|
||||
|
||||
return categoryType;
|
||||
|
@ -10,7 +10,7 @@ const Error401 = ({}) => {
|
||||
return <ErrorContainer headerText={t("Error401Text")} />;
|
||||
};
|
||||
|
||||
export default (
|
||||
export default () => (
|
||||
<I18nextProvider i18n={i18n}>
|
||||
<Error401 />
|
||||
</I18nextProvider>
|
||||
|
@ -1,4 +1,4 @@
|
||||
import moment from "moment";
|
||||
import moment from "moment-timezone";
|
||||
|
||||
import { LANGUAGE } from "@docspace/common/constants";
|
||||
import { getCookie } from "@docspace/components/utils/cookie";
|
||||
@ -6,7 +6,7 @@ import { getCookie } from "@docspace/components/utils/cookie";
|
||||
export const getRelativeDateDay = (t, date) => {
|
||||
moment.locale(getCookie(LANGUAGE));
|
||||
|
||||
const given = moment(date);
|
||||
const given = moment(date).tz(window.timezone || "");
|
||||
|
||||
const now = moment();
|
||||
const weekAgo = moment().subtract(1, "week");
|
||||
|
@ -19,7 +19,7 @@ import LockedReactSvgUrl from "PUBLIC_DIR/images/locked.react.svg?url";
|
||||
import LoadedReactSvgUrl from "PUBLIC_DIR/images/loaded.react.svg?url";
|
||||
import TrashReactSvgUrl from "PUBLIC_DIR/images/trash.react.svg?url";
|
||||
import ClockReactSvg from "PUBLIC_DIR/images/clock.react.svg";
|
||||
import moment from "moment";
|
||||
import moment from "moment-timezone";
|
||||
import { RoomsType } from "@docspace/common/constants";
|
||||
|
||||
import { StyledLinkRow } from "./StyledPublicRoom";
|
||||
@ -56,7 +56,9 @@ const LinkRow = (props) => {
|
||||
|
||||
const isLocked = !!password;
|
||||
const expiryDate = !!expirationDate;
|
||||
const date = moment(expirationDate).format("LLL");
|
||||
const date = moment(expirationDate)
|
||||
.tz(window.timezone || "")
|
||||
.format("LLL");
|
||||
|
||||
const tooltipContent = isExpired
|
||||
? t("Translations:LinkHasExpiredAndHasBeenDisabled")
|
||||
@ -235,7 +237,7 @@ const LinkRow = (props) => {
|
||||
size={16}
|
||||
iconName={CopyReactSvgUrl}
|
||||
onClick={onCopyExternalLink}
|
||||
title={t("Files:CopyGeneralLink")}
|
||||
title={primary ? t("Files:CopyGeneralLink") : t("Files:CopyLink")}
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
|
@ -258,33 +258,20 @@ const StyledSimpleFilesRow = styled(Row)`
|
||||
`}
|
||||
}
|
||||
|
||||
@media ${tablet} {
|
||||
.badges {
|
||||
flex-direction: row-reverse;
|
||||
gap: 24px;
|
||||
}
|
||||
.badges {
|
||||
flex-direction: row-reverse;
|
||||
gap: 24px;
|
||||
}
|
||||
|
||||
.file__badges,
|
||||
.room__badges,
|
||||
.folder__badges {
|
||||
> div {
|
||||
margin-left: 0;
|
||||
margin-right: 0;
|
||||
}
|
||||
}
|
||||
.file__badges,
|
||||
.room__badges,
|
||||
.folder__badges {
|
||||
margin-top: 0px;
|
||||
|
||||
.file__badges,
|
||||
.room__badges,
|
||||
.folder__badges {
|
||||
> div {
|
||||
margin-top: 0px;
|
||||
}
|
||||
}
|
||||
|
||||
.file__badges,
|
||||
.folder__badges,
|
||||
.room__badges {
|
||||
> div {
|
||||
margin-top: 0px;
|
||||
margin-left: 0;
|
||||
margin-right: 0;
|
||||
}
|
||||
}
|
||||
|
||||
@ -443,7 +430,7 @@ const SimpleFilesRow = (props) => {
|
||||
mode={"modern"}
|
||||
sectionWidth={sectionWidth}
|
||||
contentElement={
|
||||
isSmallContainer || isRooms ? null : quickButtonsComponent
|
||||
isMobileDevice || isRooms ? null : quickButtonsComponent
|
||||
}
|
||||
badgesComponent={!isMobileDevice && badgesComponent}
|
||||
onSelect={onContentFileSelect}
|
||||
@ -476,7 +463,7 @@ const SimpleFilesRow = (props) => {
|
||||
sectionWidth={sectionWidth}
|
||||
onFilesClick={onFilesClick}
|
||||
quickButtons={
|
||||
isSmallContainer || isRooms ? quickButtonsComponent : null
|
||||
isMobileDevice || isRooms ? quickButtonsComponent : null
|
||||
}
|
||||
isRooms={isRooms}
|
||||
badgesComponent={isMobileDevice && badgesComponent}
|
||||
|
@ -23,6 +23,8 @@ class FilesTableHeader extends React.Component {
|
||||
columnStorageName,
|
||||
columnInfoPanelStorageName,
|
||||
isPublicRoom,
|
||||
isFrame,
|
||||
frameTableColumns,
|
||||
} = this.props;
|
||||
|
||||
const defaultColumns = [];
|
||||
@ -232,13 +234,25 @@ class FilesTableHeader extends React.Component {
|
||||
defaultColumns.push(...columns);
|
||||
}
|
||||
|
||||
const columns = getColumns(defaultColumns);
|
||||
let columns = getColumns(defaultColumns);
|
||||
const storageColumns = localStorage.getItem(this.props.tableStorageName);
|
||||
const splitColumns = storageColumns && storageColumns.split(",");
|
||||
const resetColumnsSize =
|
||||
(splitColumns && splitColumns.length !== columns.length) || !splitColumns;
|
||||
(splitColumns && splitColumns.length !== columns.length) ||
|
||||
!splitColumns ||
|
||||
isFrame;
|
||||
|
||||
const tableColumns = columns.map((c) => c.enable && c.key);
|
||||
|
||||
if (isFrame && frameTableColumns) {
|
||||
const frameTableArray = frameTableColumns.split(",");
|
||||
|
||||
columns = columns.map((col) => {
|
||||
col.enable = frameTableArray.includes(col.key) ? true : false;
|
||||
return col;
|
||||
});
|
||||
}
|
||||
|
||||
this.setTableColumns(tableColumns);
|
||||
if (fromUpdate) {
|
||||
this.setState({
|
||||
@ -407,6 +421,7 @@ class FilesTableHeader extends React.Component {
|
||||
withPaging,
|
||||
tagRef,
|
||||
setHideColumns,
|
||||
isFrame,
|
||||
} = this.props;
|
||||
|
||||
const {
|
||||
@ -437,6 +452,7 @@ class FilesTableHeader extends React.Component {
|
||||
tagRef={tagRef}
|
||||
setHideColumns={setHideColumns}
|
||||
settingsTitle={t("Files:TableSettingsTitle")}
|
||||
showSettings={!isFrame}
|
||||
/>
|
||||
);
|
||||
}
|
||||
@ -470,7 +486,7 @@ export default inject(
|
||||
const isRooms = isRoomsFolder || isArchiveFolder;
|
||||
const withContent = canShare;
|
||||
const sortingVisible = !isRecentFolder;
|
||||
const { withPaging } = auth.settingsStore;
|
||||
const { withPaging, isFrame, frameConfig } = auth.settingsStore;
|
||||
|
||||
const {
|
||||
tableStorageName,
|
||||
@ -553,6 +569,9 @@ export default inject(
|
||||
isTrashFolder,
|
||||
isPublicRoom,
|
||||
publicRoomKey,
|
||||
|
||||
isFrame,
|
||||
frameTableColumns: frameConfig?.viewTableColumns,
|
||||
};
|
||||
}
|
||||
)(
|
||||
|
@ -28,6 +28,8 @@ import PersonUserReactSvgUrl from "PUBLIC_DIR/images/person.user.react.svg?url";
|
||||
import InviteAgainReactSvgUrl from "PUBLIC_DIR/images/invite.again.react.svg?url";
|
||||
import PublicRoomIconUrl from "PUBLIC_DIR/images/public-room.react.svg?url";
|
||||
import PluginMoreReactSvgUrl from "PUBLIC_DIR/images/plugin.more.react.svg?url";
|
||||
import LeaveRoomSvgUrl from "PUBLIC_DIR/images/logout.react.svg?url";
|
||||
import CatalogRoomsReactSvgUrl from "PUBLIC_DIR/images/catalog.rooms.react.svg?url";
|
||||
|
||||
import React from "react";
|
||||
import { inject, observer } from "mobx-react";
|
||||
@ -226,6 +228,9 @@ const SectionHeaderContent = (props) => {
|
||||
currentDeviceType,
|
||||
isFrame,
|
||||
onClickArchive,
|
||||
setLeaveRoomDialogVisible,
|
||||
inRoom,
|
||||
onClickCreateRoom,
|
||||
} = props;
|
||||
|
||||
const navigate = useNavigate();
|
||||
@ -484,6 +489,10 @@ const SectionHeaderContent = (props) => {
|
||||
onClickArchive(e);
|
||||
};
|
||||
|
||||
const onLeaveRoom = () => {
|
||||
setLeaveRoomDialogVisible(true);
|
||||
};
|
||||
|
||||
const renameAction = () => {
|
||||
const event = new Event(Events.RENAME);
|
||||
|
||||
@ -761,12 +770,28 @@ const SectionHeaderContent = (props) => {
|
||||
"data-action": "archive",
|
||||
action: "archive",
|
||||
},
|
||||
{
|
||||
id: "option_create-room",
|
||||
label: t("Files:CreateRoom"),
|
||||
key: "create-room",
|
||||
icon: CatalogRoomsReactSvgUrl,
|
||||
onClick: onClickCreateRoom,
|
||||
disabled: isArchiveFolder || !inRoom || isPublicRoom,
|
||||
},
|
||||
{
|
||||
id: "option_leave-room",
|
||||
key: "leave-room",
|
||||
label: t("LeaveTheRoom"),
|
||||
icon: LeaveRoomSvgUrl,
|
||||
onClick: onLeaveRoom,
|
||||
disabled: isArchiveFolder || !inRoom || isPublicRoom,
|
||||
},
|
||||
{
|
||||
id: "header_option_download",
|
||||
key: "download",
|
||||
label: t("Common:Download"),
|
||||
onClick: onDownloadAction,
|
||||
disabled: !isRoom || !security?.Download,
|
||||
disabled: !security?.Download,
|
||||
icon: DownloadReactSvgUrl,
|
||||
},
|
||||
{
|
||||
@ -1157,6 +1182,7 @@ export default inject(
|
||||
setInvitePanelOptions,
|
||||
setInviteUsersWarningDialogVisible,
|
||||
setRoomSharingPanelVisible,
|
||||
setLeaveRoomDialogVisible,
|
||||
} = dialogsStore;
|
||||
|
||||
const {
|
||||
@ -1177,13 +1203,14 @@ export default inject(
|
||||
onClickBack,
|
||||
emptyTrashInProgress,
|
||||
moveToPublicRoom,
|
||||
onClickCreateRoom
|
||||
} = filesActionsStore;
|
||||
|
||||
const { oformsFilter } = oformsStore;
|
||||
|
||||
const { setIsVisible, isVisible } = auth.infoPanelStore;
|
||||
|
||||
const { title, id, roomType, pathParts, navigationPath, security } =
|
||||
const { title, id, roomType, pathParts, navigationPath, security, inRoom } =
|
||||
selectedFolderStore;
|
||||
|
||||
const selectedFolder = { ...selectedFolderStore };
|
||||
@ -1320,6 +1347,7 @@ export default inject(
|
||||
selectedFolder,
|
||||
|
||||
onClickEditRoom,
|
||||
onClickCreateRoom,
|
||||
onClickInviteUsers,
|
||||
onShowInfoPanel,
|
||||
onClickArchive,
|
||||
@ -1362,6 +1390,8 @@ export default inject(
|
||||
setRoomSharingPanelVisible,
|
||||
isFrame,
|
||||
currentDeviceType,
|
||||
setLeaveRoomDialogVisible,
|
||||
inRoom,
|
||||
};
|
||||
}
|
||||
)(
|
||||
|
@ -301,13 +301,13 @@ const LanguageAndTimeZone = (props) => {
|
||||
|
||||
setState((val) => ({ ...val, isLoading: true }));
|
||||
setLanguageAndTime(language.key, timezone.key)
|
||||
.then(
|
||||
() =>
|
||||
!user.cultureName &&
|
||||
.then(() => {
|
||||
!user.cultureName &&
|
||||
setCookie(LANGUAGE, language.key || "en", {
|
||||
"max-age": COOKIE_EXPIRATION_YEAR,
|
||||
})
|
||||
)
|
||||
});
|
||||
window.timezone = timezone.key;
|
||||
})
|
||||
.then(() => toastr.success(t("SuccessfullySaveSettingsMessage")))
|
||||
.then(
|
||||
() => !user.cultureName && lng !== language.key && location.reload()
|
||||
|
@ -70,6 +70,7 @@ const WelcomePageSettings = (props) => {
|
||||
greetingTitleDefaultFromSessionStorage = getFromSessionStorage(
|
||||
"greetingTitleDefault"
|
||||
);
|
||||
getGreetingSettingsIsDefault();
|
||||
|
||||
setDocumentTitle(t("CustomTitlesWelcome"));
|
||||
|
||||
@ -193,8 +194,10 @@ const WelcomePageSettings = (props) => {
|
||||
toastr.success(t("SuccessfullySaveGreetingSettingsMessage"));
|
||||
})
|
||||
.catch((error) => toastr.error(error))
|
||||
.finally(() =>
|
||||
setState((val) => ({ ...val, isLoadingGreetingSave: false }))
|
||||
.finally(() => {
|
||||
getGreetingSettingsIsDefault();
|
||||
setState((val) => ({ ...val, isLoadingGreetingSave: false }));
|
||||
}
|
||||
);
|
||||
|
||||
setState((val) => ({ ...val, showReminder: false }));
|
||||
@ -206,9 +209,10 @@ const WelcomePageSettings = (props) => {
|
||||
const onRestoreGreetingSettings = () => {
|
||||
setState((val) => ({ ...val, isLoadingGreetingRestore: true }));
|
||||
restoreGreetingTitle()
|
||||
.then(() => {
|
||||
.then((defaultTitle) => {
|
||||
setState((val) => ({
|
||||
...val,
|
||||
greetingTitle: defaultTitle,
|
||||
showReminder: false,
|
||||
}));
|
||||
|
||||
@ -218,8 +222,10 @@ const WelcomePageSettings = (props) => {
|
||||
toastr.success(t("SuccessfullySaveGreetingSettingsMessage"));
|
||||
})
|
||||
.catch((error) => toastr.error(error))
|
||||
.finally(() =>
|
||||
setState((val) => ({ ...val, isLoadingGreetingRestore: false }))
|
||||
.finally(() => {
|
||||
getGreetingSettingsIsDefault();
|
||||
setState((val) => ({ ...val, isLoadingGreetingRestore: false }));
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
|
@ -284,7 +284,6 @@ const PortalIntegration = (props) => {
|
||||
);
|
||||
|
||||
const [config, setConfig] = useState({
|
||||
hash: `${API_JS_HASH}`,
|
||||
width: `${width}${widthDimension.label}`,
|
||||
height: `${height}${heightDimension.label}`,
|
||||
frameId: "ds-frame",
|
||||
|
@ -84,7 +84,7 @@ const CSP = ({ t, cspDomains, getCSPSettings, setCSPSettings }) => {
|
||||
const deleteDomain = (value) => {
|
||||
const domains = cspDomains.filter((item) => item !== value);
|
||||
|
||||
setCSPSettings({ domains });
|
||||
setCSPSettings({ domains, setDefaultIfEmpty: true });
|
||||
};
|
||||
|
||||
const addDomain = () => {
|
||||
|
@ -1,5 +1,5 @@
|
||||
import React from "react";
|
||||
import moment from "moment";
|
||||
import moment from "moment-timezone";
|
||||
import styled from "styled-components";
|
||||
|
||||
import Text from "@docspace/components/text";
|
||||
@ -46,7 +46,13 @@ const BarItem = styled.div`
|
||||
`;
|
||||
|
||||
const BarItemHeader = ({ children }) => (
|
||||
<Text as="h3" color="#A3A9AE" fontSize="12px" fontWeight={600} className="barItemHeader">
|
||||
<Text
|
||||
as="h3"
|
||||
color="#A3A9AE"
|
||||
fontSize="12px"
|
||||
fontWeight={600}
|
||||
className="barItemHeader"
|
||||
>
|
||||
{children}
|
||||
</Text>
|
||||
);
|
||||
@ -61,7 +67,12 @@ const DetailsBar = ({ eventDetails }) => {
|
||||
|
||||
const formatDate = (date) => {
|
||||
return (
|
||||
moment(date).locale(i18n.language).format("MMM D, YYYY, h:mm:ss A") + " " + t("Common:UTC")
|
||||
moment(date)
|
||||
.locale(i18n.language)
|
||||
.tz(window.timezone || "")
|
||||
.format("MMM D, YYYY, h:mm:ss A") +
|
||||
" " +
|
||||
t("Common:UTC")
|
||||
);
|
||||
};
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
import React, { useState, useEffect, useTransition, Suspense } from "react";
|
||||
import moment from "moment";
|
||||
import moment from "moment-timezone";
|
||||
import styled from "styled-components";
|
||||
|
||||
import HistoryFilterHeader from "./sub-components/HistoryFilterHeader";
|
||||
@ -23,9 +23,15 @@ const parseUrl = (url) => {
|
||||
params[key] = value;
|
||||
}
|
||||
params.deliveryDate =
|
||||
params.deliveryDate === "null" ? null : moment(params.deliveryDate, "YYYY-MM-DD");
|
||||
params.deliveryFrom = moment(params.deliveryFrom, "HH:mm");
|
||||
params.deliveryTo = moment(params.deliveryTo, "HH:mm");
|
||||
params.deliveryDate === "null"
|
||||
? null
|
||||
: moment(params.deliveryDate, "YYYY-MM-DD").tz(window.timezone || "");
|
||||
params.deliveryFrom = moment(params.deliveryFrom, "HH:mm").tz(
|
||||
window.timezone || ""
|
||||
);
|
||||
params.deliveryTo = moment(params.deliveryTo, "HH:mm").tz(
|
||||
window.timezone || ""
|
||||
);
|
||||
params.status = JSON.parse(params.status);
|
||||
|
||||
return params;
|
||||
|
@ -1,6 +1,6 @@
|
||||
import React, { useState, useEffect, useRef } from "react";
|
||||
import styled from "styled-components";
|
||||
import moment from "moment";
|
||||
import moment from "moment-timezone";
|
||||
|
||||
import Text from "@docspace/components/text";
|
||||
import { useTranslation } from "react-i18next";
|
||||
@ -71,8 +71,12 @@ const DeliveryDatePicker = ({
|
||||
setFilters((prevFilters) => ({
|
||||
...prevFilters,
|
||||
deliveryDate: null,
|
||||
deliveryFrom: moment().startOf("day"),
|
||||
deliveryTo: moment().endOf("day"),
|
||||
deliveryFrom: moment()
|
||||
.tz(window.timezone || "")
|
||||
.startOf("day"),
|
||||
deliveryTo: moment()
|
||||
.tz(window.timezone || "")
|
||||
.endOf("day"),
|
||||
}));
|
||||
setIsTimeOpen(false);
|
||||
setIsCalendarOpen(false);
|
||||
@ -91,8 +95,12 @@ const DeliveryDatePicker = ({
|
||||
setFilters((prevFilters) => ({
|
||||
...prevFilters,
|
||||
deliveryDate: date,
|
||||
deliveryFrom: moment().startOf("day"),
|
||||
deliveryTo: moment().endOf("day"),
|
||||
deliveryFrom: moment()
|
||||
.tz(window.timezone || "")
|
||||
.startOf("day"),
|
||||
deliveryTo: moment()
|
||||
.tz(window.timezone || "")
|
||||
.endOf("day"),
|
||||
}));
|
||||
};
|
||||
|
||||
@ -121,9 +129,9 @@ const DeliveryDatePicker = ({
|
||||
const SelectedDateTime = () => {
|
||||
const formattedTime = isTimeEqual
|
||||
? ""
|
||||
: ` ${filters.deliveryFrom.format("HH:mm")} - ${moment(
|
||||
filters.deliveryTo
|
||||
).format("HH:mm")}`;
|
||||
: ` ${filters.deliveryFrom.format("HH:mm")} - ${moment(filters.deliveryTo)
|
||||
.tz(window.timezone || "")
|
||||
.format("HH:mm")}`;
|
||||
|
||||
return (
|
||||
<div>
|
||||
@ -192,7 +200,8 @@ const DeliveryDatePicker = ({
|
||||
isInline
|
||||
fontWeight={600}
|
||||
color="#A3A9AE"
|
||||
className="mr-8">
|
||||
className="mr-8"
|
||||
>
|
||||
{t("From")}
|
||||
</Text>
|
||||
<TimePicker
|
||||
|
@ -1,6 +1,6 @@
|
||||
import React, { useState, useEffect } from "react";
|
||||
import { inject, observer } from "mobx-react";
|
||||
import moment from "moment";
|
||||
import moment from "moment-timezone";
|
||||
|
||||
import ModalDialog from "@docspace/components/modal-dialog";
|
||||
import styled, { css } from "styled-components";
|
||||
@ -54,7 +54,10 @@ Separator.defaultProps = { theme: Base };
|
||||
|
||||
const constructUrl = (baseUrl, filters) => {
|
||||
const url = new URL(baseUrl, "http://127.0.0.1:8092/");
|
||||
url.searchParams.append("deliveryDate", filters.deliveryDate?.format("YYYY-MM-DD") || null);
|
||||
url.searchParams.append(
|
||||
"deliveryDate",
|
||||
filters.deliveryDate?.format("YYYY-MM-DD") || null
|
||||
);
|
||||
url.searchParams.append("deliveryFrom", filters.deliveryFrom.format("HH:mm"));
|
||||
url.searchParams.append("deliveryTo", filters.deliveryTo.format("HH:mm"));
|
||||
url.searchParams.append("status", JSON.stringify(filters.status));
|
||||
@ -63,20 +66,33 @@ const constructUrl = (baseUrl, filters) => {
|
||||
};
|
||||
|
||||
function areArraysEqual(array1, array2) {
|
||||
return array1.length === array2.length && array1.every((val, index) => val === array2[index]);
|
||||
return (
|
||||
array1.length === array2.length &&
|
||||
array1.every((val, index) => val === array2[index])
|
||||
);
|
||||
}
|
||||
|
||||
const FilterDialog = (props) => {
|
||||
const { visible, closeModal, applyFilters, formatFilters, setHistoryFilters, historyFilters } =
|
||||
props;
|
||||
const {
|
||||
visible,
|
||||
closeModal,
|
||||
applyFilters,
|
||||
formatFilters,
|
||||
setHistoryFilters,
|
||||
historyFilters,
|
||||
} = props;
|
||||
const { t } = useTranslation(["Webhooks", "Files", "Common"]);
|
||||
const { id } = useParams();
|
||||
const navigate = useNavigate();
|
||||
|
||||
const [filters, setFilters] = useState({
|
||||
deliveryDate: null,
|
||||
deliveryFrom: moment().startOf("day"),
|
||||
deliveryTo: moment().endOf("day"),
|
||||
deliveryFrom: moment()
|
||||
.tz(window.timezone || "")
|
||||
.startOf("day"),
|
||||
deliveryTo: moment()
|
||||
.tz(window.timezone || "")
|
||||
.endOf("day"),
|
||||
status: [],
|
||||
});
|
||||
|
||||
@ -101,8 +117,12 @@ const FilterDialog = (props) => {
|
||||
if (filters.deliveryDate !== null || filters.status.length > 0) {
|
||||
setFilters({
|
||||
deliveryDate: null,
|
||||
deliveryFrom: moment().startOf("day"),
|
||||
deliveryTo: moment().endOf("day"),
|
||||
deliveryFrom: moment()
|
||||
.tz(window.timezone || "")
|
||||
.startOf("day"),
|
||||
deliveryTo: moment()
|
||||
.tz(window.timezone || "")
|
||||
.endOf("day"),
|
||||
status: [],
|
||||
});
|
||||
}
|
||||
@ -110,7 +130,12 @@ const FilterDialog = (props) => {
|
||||
} else {
|
||||
setFilters(historyFilters);
|
||||
setIsApplied(true);
|
||||
navigate(constructUrl(`/portal-settings/developer-tools/webhooks/${id}`, historyFilters));
|
||||
navigate(
|
||||
constructUrl(
|
||||
`/portal-settings/developer-tools/webhooks/${id}`,
|
||||
historyFilters
|
||||
)
|
||||
);
|
||||
}
|
||||
setIsLoaded(true);
|
||||
}, [historyFilters, visible]);
|
||||
@ -124,7 +149,12 @@ const FilterDialog = (props) => {
|
||||
: filters.deliveryDate === null && filters.status.length === 0;
|
||||
|
||||
return (
|
||||
<ModalDialogContainer withFooterBorder visible={visible} onClose={closeModal} displayType="aside">
|
||||
<ModalDialogContainer
|
||||
withFooterBorder
|
||||
visible={visible}
|
||||
onClose={closeModal}
|
||||
displayType="aside"
|
||||
>
|
||||
<ModalDialog.Header>{t("Files:Filter")}</ModalDialog.Header>
|
||||
<ModalDialog.Body>
|
||||
<DialogBodyWrapper>
|
||||
|
@ -1,5 +1,5 @@
|
||||
import React, { useEffect } from "react";
|
||||
import moment from "moment";
|
||||
import moment from "moment-timezone";
|
||||
import styled from "styled-components";
|
||||
import { inject, observer } from "mobx-react";
|
||||
|
||||
@ -42,11 +42,17 @@ const StatusBar = (props) => {
|
||||
return (
|
||||
<SelectedItem
|
||||
label={
|
||||
moment(historyFilters.deliveryDate).format("DD MMM YYYY") +
|
||||
moment(historyFilters.deliveryDate)
|
||||
.format("DD MMM YYYY")
|
||||
.tz(window.timezone || "") +
|
||||
" " +
|
||||
moment(historyFilters.deliveryFrom).format("HH:mm") +
|
||||
moment(historyFilters.deliveryFrom)
|
||||
.format("HH:mm")
|
||||
.tz(window.timezone || "") +
|
||||
" - " +
|
||||
moment(historyFilters.deliveryTo).format("HH:mm")
|
||||
moment(historyFilters.deliveryTo)
|
||||
.format("HH:mm")
|
||||
.tz(window.timezone || "")
|
||||
}
|
||||
onClose={clearDate}
|
||||
onClick={clearDate}
|
||||
|
@ -1,5 +1,5 @@
|
||||
import React from "react";
|
||||
import moment from "moment";
|
||||
import moment from "moment-timezone";
|
||||
import styled from "styled-components";
|
||||
|
||||
import Text from "@docspace/components/text";
|
||||
@ -33,6 +33,7 @@ export const HistoryRowContent = ({ sectionWidth, historyItem }) => {
|
||||
|
||||
const formattedDelivery =
|
||||
moment(historyItem.delivery)
|
||||
.tz(window.timezone || "")
|
||||
.locale(i18n.language)
|
||||
.format("MMM D, YYYY, h:mm:ss A") +
|
||||
" " +
|
||||
|
@ -1,5 +1,5 @@
|
||||
import React from "react";
|
||||
import moment from "moment";
|
||||
import moment from "moment-timezone";
|
||||
import styled, { css } from "styled-components";
|
||||
import { inject, observer } from "mobx-react";
|
||||
|
||||
@ -65,7 +65,8 @@ const HistoryTableRow = (props) => {
|
||||
const navigate = useNavigate();
|
||||
const { id } = useParams();
|
||||
|
||||
const redirectToDetails = () => navigate(window.location.pathname + `/${item.id}`);
|
||||
const redirectToDetails = () =>
|
||||
navigate(window.location.pathname + `/${item.id}`);
|
||||
const handleRetryEvent = async () => {
|
||||
if (isRetryPending) {
|
||||
return;
|
||||
@ -97,7 +98,10 @@ const HistoryTableRow = (props) => {
|
||||
];
|
||||
|
||||
const formattedDelivery =
|
||||
moment(item.delivery).locale(i18n.language).format("MMM D, YYYY, h:mm:ss A") +
|
||||
moment(item.delivery)
|
||||
.tz(window.timezone || "")
|
||||
.locale(i18n.language)
|
||||
.format("MMM D, YYYY, h:mm:ss A") +
|
||||
" " +
|
||||
t("Common:UTC");
|
||||
|
||||
@ -121,11 +125,22 @@ const HistoryTableRow = (props) => {
|
||||
const isChecked = isIdChecked(item.id);
|
||||
|
||||
return (
|
||||
<StyledWrapper className={isChecked ? "selected-table-row" : ""} onClick={onRowClick}>
|
||||
<StyledTableRow contextOptions={contextOptions} checked={isChecked} hideColumns={hideColumns}>
|
||||
<StyledWrapper
|
||||
className={isChecked ? "selected-table-row" : ""}
|
||||
onClick={onRowClick}
|
||||
>
|
||||
<StyledTableRow
|
||||
contextOptions={contextOptions}
|
||||
checked={isChecked}
|
||||
hideColumns={hideColumns}
|
||||
>
|
||||
<TableCell>
|
||||
<TableCell checked={isChecked} className="checkboxWrapper">
|
||||
<Checkbox className="checkbox" onChange={onCheckboxClick} isChecked={isChecked} />
|
||||
<Checkbox
|
||||
className="checkbox"
|
||||
onChange={onCheckboxClick}
|
||||
isChecked={isChecked}
|
||||
/>
|
||||
</TableCell>
|
||||
|
||||
<Text fontWeight={600}>{item.id}</Text>
|
||||
|
@ -82,7 +82,7 @@ const PluginPage = ({
|
||||
export default inject(({ auth, pluginStore }) => {
|
||||
const { pluginOptions, currentColorScheme, theme } = auth.settingsStore;
|
||||
|
||||
const withUpload = pluginOptions.includes("upload");
|
||||
const withUpload = pluginOptions.upload;
|
||||
|
||||
const {
|
||||
pluginList,
|
||||
|
@ -28,7 +28,7 @@ import {
|
||||
TableDataCell,
|
||||
} from "./styled-active-sessions";
|
||||
import { DeviceType } from "@docspace/common/constants";
|
||||
import moment from "moment";
|
||||
import moment from "moment-timezone";
|
||||
|
||||
const removeIcon = (
|
||||
<ReactSVG className="remove-icon" src={RemoveSessionSvgUrl} />
|
||||
@ -114,7 +114,10 @@ const ActiveSessions = ({
|
||||
};
|
||||
|
||||
const convertTime = (date) => {
|
||||
return moment(date).locale(locale).format("L, LTS");
|
||||
return moment(date)
|
||||
.tz(window.timezone || "")
|
||||
.locale(locale)
|
||||
.format("L, LTS");
|
||||
};
|
||||
const tableCell = (platform, browser) =>
|
||||
interfaceDirection === "rtl" && !isMobile ? (
|
||||
|
@ -12,6 +12,7 @@ import {
|
||||
createPasswordHash,
|
||||
frameCallCommand,
|
||||
} from "@docspace/common/utils";
|
||||
import { RoomsType } from "@docspace/common/constants";
|
||||
|
||||
const Sdk = ({
|
||||
frameConfig,
|
||||
@ -25,6 +26,8 @@ const Sdk = ({
|
||||
getSettings,
|
||||
user,
|
||||
updateProfileCulture,
|
||||
getRoomsIcon,
|
||||
getPrimaryLink,
|
||||
}) => {
|
||||
useEffect(() => {
|
||||
window.addEventListener("message", handleMessage, false);
|
||||
@ -118,8 +121,18 @@ const Sdk = ({
|
||||
};
|
||||
|
||||
const onSelectRoom = useCallback(
|
||||
(data) => {
|
||||
data[0].icon = toRelativeUrl(data[0].icon);
|
||||
async (data) => {
|
||||
if (data[0].logo.large !== "") {
|
||||
data[0].icon = toRelativeUrl(data[0].logo.large);
|
||||
} else {
|
||||
data[0].icon = await getRoomsIcon(data[0].roomType, false, 32);
|
||||
}
|
||||
|
||||
if (data[0].roomType === RoomsType.PublicRoom) {
|
||||
const { sharedTo } = await getPrimaryLink(data[0].id);
|
||||
data[0].requestToken = sharedTo?.requestToken;
|
||||
}
|
||||
|
||||
frameCallEvent({ event: "onSelectCallback", data });
|
||||
},
|
||||
[frameCallEvent]
|
||||
@ -150,8 +163,8 @@ const Sdk = ({
|
||||
case "room-selector":
|
||||
component = (
|
||||
<RoomSelector
|
||||
withCancelButton={true}
|
||||
withHeader={false}
|
||||
withCancelButton={frameConfig?.showSelectorCancel}
|
||||
withHeader={frameConfig?.showSelectorHeader}
|
||||
onAccept={onSelectRoom}
|
||||
onCancel={onClose}
|
||||
/>
|
||||
@ -162,11 +175,14 @@ const Sdk = ({
|
||||
<FilesSelector
|
||||
isPanelVisible={true}
|
||||
embedded={true}
|
||||
withHeader={false}
|
||||
withHeader={frameConfig?.showSelectorHeader}
|
||||
isSelect={true}
|
||||
onSelectFile={onSelectFile}
|
||||
onClose={onClose}
|
||||
filterParam={"ALL"}
|
||||
isUserOnly={selectorType === "userFolderOnly"}
|
||||
isRoomsOnly={selectorType === "roomsOnly"}
|
||||
withCancelButton={frameConfig?.showSelectorCancel}
|
||||
/>
|
||||
);
|
||||
break;
|
||||
@ -177,13 +193,14 @@ const Sdk = ({
|
||||
return component;
|
||||
};
|
||||
|
||||
export default inject(({ auth, settingsStore, peopleStore }) => {
|
||||
export default inject(({ auth, settingsStore, peopleStore, filesStore }) => {
|
||||
const { login, logout, userStore } = auth;
|
||||
const { theme, setFrameConfig, frameConfig, getSettings, isLoaded } =
|
||||
auth.settingsStore;
|
||||
const { loadCurrentUser, user } = userStore;
|
||||
const { updateProfileCulture } = peopleStore.targetUserStore;
|
||||
const { getIcon } = settingsStore;
|
||||
const { getIcon, getRoomsIcon } = settingsStore;
|
||||
const { getPrimaryLink } = filesStore;
|
||||
|
||||
return {
|
||||
theme,
|
||||
@ -194,8 +211,10 @@ export default inject(({ auth, settingsStore, peopleStore }) => {
|
||||
getSettings,
|
||||
loadCurrentUser,
|
||||
getIcon,
|
||||
getRoomsIcon,
|
||||
isLoaded,
|
||||
updateProfileCulture,
|
||||
user,
|
||||
getPrimaryLink,
|
||||
};
|
||||
})(observer(Sdk));
|
||||
|
@ -13,6 +13,8 @@ const StyledBody = styled.div`
|
||||
}
|
||||
|
||||
.loader-history-rows {
|
||||
padding-top: 12px;
|
||||
|
||||
${({ theme }) =>
|
||||
theme.interfaceDirection === "rtl"
|
||||
? `padding-left: 16px;`
|
||||
|
@ -19,7 +19,8 @@ import toastr from "@docspace/components/toast/toastr";
|
||||
import { Encoder } from "@docspace/common/utils/encoder";
|
||||
import { Base } from "@docspace/components/themes";
|
||||
import { MAX_FILE_COMMENT_LENGTH } from "@docspace/common/constants";
|
||||
import moment from "moment";
|
||||
import moment from "moment-timezone";
|
||||
import getCorrectDate from "@docspace/components/utils/getCorrectDate";
|
||||
|
||||
const StyledExternalLinkIcon = styled(ExternalLinkIcon)`
|
||||
${commonIconsStyles}
|
||||
@ -66,9 +67,7 @@ const VersionRow = (props) => {
|
||||
}
|
||||
}, [info.comment]);
|
||||
|
||||
const versionDate = `${moment(info.updated)
|
||||
.locale(culture)
|
||||
.format("L, LTS")}`;
|
||||
const versionDate = getCorrectDate(culture, info.updated, "L", "LTS");
|
||||
|
||||
const title = `${Encoder.htmlDecode(info.updatedBy?.displayName)}`;
|
||||
|
||||
|
@ -91,6 +91,12 @@ class AccessRightsStore {
|
||||
(userIsVisitor || userIsCollaborator)
|
||||
);
|
||||
};
|
||||
canMakePowerUser = (user) => {
|
||||
const { isVisitor: userIsVisitor, isCollaborator: userIsCollaborator } =
|
||||
user;
|
||||
|
||||
return userIsVisitor || userIsCollaborator;
|
||||
};
|
||||
|
||||
canActivateUser = (user) => {
|
||||
const { id, isOwner, isAdmin } = this.authStore.userStore.user;
|
||||
|
@ -430,9 +430,12 @@ class ContextOptionsStore {
|
||||
this.dialogsStore.setDownloadDialogVisible(true);
|
||||
};
|
||||
|
||||
onClickCreateRoom = () => {
|
||||
onClickCreateRoom = (item) => {
|
||||
this.filesActionsStore.setProcessCreatingRoomFromData(true);
|
||||
const event = new Event(Events.ROOM_CREATE);
|
||||
if (item && item.isFolder) {
|
||||
event.title = item.title;
|
||||
}
|
||||
window.dispatchEvent(event);
|
||||
};
|
||||
|
||||
@ -1355,7 +1358,7 @@ class ContextOptionsStore {
|
||||
key: "create-room",
|
||||
label: t("Files:CreateRoom"),
|
||||
icon: CatalogRoomsReactSvgUrl,
|
||||
onClick: this.onClickCreateRoom,
|
||||
onClick: () => this.onClickCreateRoom(item),
|
||||
disabled: this.selectedFolderStore.rootFolderType !== FolderType.USER,
|
||||
},
|
||||
{
|
||||
|
@ -175,27 +175,11 @@ class PeopleStore {
|
||||
setIsVisible(true);
|
||||
};
|
||||
|
||||
getHeaderMenu = (t) => {
|
||||
const {
|
||||
hasUsersToMakeEmployees,
|
||||
hasUsersToActivate,
|
||||
hasUsersToDisable,
|
||||
hasUsersToInvite,
|
||||
hasUsersToRemove,
|
||||
hasOnlyOneUserToRemove,
|
||||
hasFreeUsers,
|
||||
userSelectionRole,
|
||||
selection,
|
||||
} = this.selectionStore;
|
||||
|
||||
const { setSendInviteDialogVisible, setDeleteProfileDialogVisible } =
|
||||
this.dialogStore;
|
||||
const { toggleDeleteProfileEverDialog } = this.contextOptionsStore;
|
||||
getUsersRightsSubmenu = (t) => {
|
||||
const { userSelectionRole, selectionUsersRights } = this.selectionStore;
|
||||
|
||||
const { isOwner } = this.authStore.userStore.user;
|
||||
|
||||
const { isVisible } = this.authStore.infoPanelStore;
|
||||
|
||||
const options = [];
|
||||
|
||||
const adminOption = {
|
||||
@ -218,22 +202,71 @@ class PeopleStore {
|
||||
key: "manager",
|
||||
isActive: userSelectionRole === "manager",
|
||||
};
|
||||
const userOption = {
|
||||
id: "menu_change-user_user",
|
||||
className: "group-menu_drop-down",
|
||||
label: t("Common:User"),
|
||||
title: t("Common:User"),
|
||||
// const userOption = {
|
||||
// id: "menu_change-user_user",
|
||||
// className: "group-menu_drop-down",
|
||||
// label: t("Common:User"),
|
||||
// title: t("Common:User"),
|
||||
// onClick: (e) => this.onChangeType(e),
|
||||
// "data-action": "user",
|
||||
// key: "user",
|
||||
// isActive: userSelectionRole === "user",
|
||||
// };
|
||||
|
||||
const collaboratorOption = {
|
||||
id: "menu_change-collaborator",
|
||||
key: "collaborator",
|
||||
title: t("Common:PowerUser"),
|
||||
label: t("Common:PowerUser"),
|
||||
"data-action": "collaborator",
|
||||
onClick: (e) => this.onChangeType(e),
|
||||
"data-action": "user",
|
||||
key: "user",
|
||||
isActive: userSelectionRole === "user",
|
||||
isActive: userSelectionRole === "collaborator",
|
||||
};
|
||||
|
||||
isOwner && options.push(adminOption);
|
||||
const { isVisitor, isCollaborator, isRoomAdmin, isAdmin } =
|
||||
selectionUsersRights;
|
||||
|
||||
options.push(managerOption);
|
||||
if (isVisitor > 0) {
|
||||
isOwner && options.push(adminOption);
|
||||
options.push(managerOption);
|
||||
options.push(collaboratorOption);
|
||||
|
||||
hasFreeUsers && options.push(userOption);
|
||||
return options;
|
||||
}
|
||||
|
||||
if (isCollaborator > 0 || (isRoomAdmin > 0 && isAdmin > 0)) {
|
||||
isOwner && options.push(adminOption);
|
||||
options.push(managerOption);
|
||||
|
||||
return options;
|
||||
}
|
||||
|
||||
if (isRoomAdmin > 0) {
|
||||
isOwner && options.push(adminOption);
|
||||
|
||||
return options;
|
||||
}
|
||||
|
||||
if (isAdmin > 0) {
|
||||
options.push(managerOption);
|
||||
|
||||
return options;
|
||||
}
|
||||
};
|
||||
getHeaderMenu = (t) => {
|
||||
const {
|
||||
hasUsersToMakeEmployees,
|
||||
hasUsersToActivate,
|
||||
hasUsersToDisable,
|
||||
hasUsersToInvite,
|
||||
hasUsersToRemove,
|
||||
selection,
|
||||
} = this.selectionStore;
|
||||
|
||||
const { setSendInviteDialogVisible } = this.dialogStore;
|
||||
const { toggleDeleteProfileEverDialog } = this.contextOptionsStore;
|
||||
|
||||
const { isVisible } = this.authStore.infoPanelStore;
|
||||
|
||||
const headerMenu = [
|
||||
{
|
||||
@ -243,7 +276,7 @@ class PeopleStore {
|
||||
disabled: !hasUsersToMakeEmployees,
|
||||
iconUrl: ChangeToEmployeeReactSvgUrl,
|
||||
withDropDown: true,
|
||||
options: options,
|
||||
options: this.getUsersRightsSubmenu(t),
|
||||
},
|
||||
{
|
||||
id: "menu-info",
|
||||
|
@ -5,6 +5,12 @@ import { getUserStatus } from "../helpers/people-helpers";
|
||||
class SelectionStore {
|
||||
peopleStore = null;
|
||||
selection = [];
|
||||
selectionUsersRights = {
|
||||
isVisitor: 0,
|
||||
isCollaborator: 0,
|
||||
isRoomAdmin: 0,
|
||||
isAdmin: 0,
|
||||
};
|
||||
bufferSelection = null;
|
||||
selected = "none";
|
||||
|
||||
@ -20,9 +26,33 @@ class SelectionStore {
|
||||
});
|
||||
};
|
||||
|
||||
resetUsersRight = () => {
|
||||
for (const key in this.selectionUsersRights) {
|
||||
this.selectionUsersRights[key] = 0;
|
||||
}
|
||||
};
|
||||
|
||||
incrementUsersRights = (selection) => {
|
||||
for (const key in this.selectionUsersRights) {
|
||||
if (selection[key]) {
|
||||
this.selectionUsersRights[key]++;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
decrementUsersRights = (selection) => {
|
||||
for (const key in this.selectionUsersRights) {
|
||||
if (selection[key]) {
|
||||
this.selectionUsersRights[key]--;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
setSelection = (selection) => {
|
||||
//console.log("setSelection", { selection });
|
||||
// console.log("setSelection", { selection });
|
||||
this.selection = selection;
|
||||
|
||||
selection.length === 0 && this.resetUsersRight();
|
||||
};
|
||||
|
||||
setSelections = (added, removed, clear = false) => {
|
||||
@ -45,10 +75,14 @@ class SelectionStore {
|
||||
|
||||
const isFound = this.selection.findIndex((f) => f.id == id) === -1;
|
||||
|
||||
isFound &&
|
||||
newSelections.push(
|
||||
this.peopleStore.usersStore.peopleList.find((f) => f.id == id)
|
||||
if (isFound) {
|
||||
const user = this.peopleStore.usersStore.peopleList.find(
|
||||
(f) => f.id == id
|
||||
);
|
||||
newSelections.push(user);
|
||||
|
||||
this.incrementUsersRights(user);
|
||||
}
|
||||
}
|
||||
|
||||
for (let item of removed) {
|
||||
@ -61,7 +95,12 @@ class SelectionStore {
|
||||
const splitValue = value && value.split("_");
|
||||
const id = splitValue.slice(1, -3).join("_");
|
||||
|
||||
newSelections = newSelections.filter((f) => !(f.id == id));
|
||||
const index = newSelections.findIndex((item) => item.id == id);
|
||||
|
||||
if (index !== -1) {
|
||||
this.decrementUsersRights(newSelections[index]);
|
||||
newSelections.splice(index, 1);
|
||||
}
|
||||
}
|
||||
|
||||
this.setSelection(newSelections);
|
||||
@ -80,11 +119,13 @@ class SelectionStore {
|
||||
|
||||
const exists = index > -1;
|
||||
|
||||
//console.log("selectUser", { user, selection: this.selection, exists });
|
||||
// console.log("selectUser", { user, selection: this.selection, exists });
|
||||
|
||||
if (exists) return;
|
||||
|
||||
this.setSelection([...this.selection, user]);
|
||||
|
||||
this.incrementUsersRights(user);
|
||||
};
|
||||
|
||||
deselectUser = (user) => {
|
||||
@ -100,6 +141,8 @@ class SelectionStore {
|
||||
|
||||
newData.splice(index, 1);
|
||||
|
||||
this.decrementUsersRights(this.selection[index]);
|
||||
|
||||
this.setSelection(newData);
|
||||
};
|
||||
|
||||
@ -170,7 +213,12 @@ class SelectionStore {
|
||||
|
||||
return users.length > 0;
|
||||
}
|
||||
get hasUsersToMakePowerUser() {
|
||||
const { canMakePowerUser } = this.peopleStore.accessRightsStore;
|
||||
const users = this.selection.filter((x) => canMakePowerUser(x));
|
||||
|
||||
return users.length > 0;
|
||||
}
|
||||
get getUsersToMakeEmployees() {
|
||||
const { canMakeEmployeeUser } = this.peopleStore.accessRightsStore;
|
||||
|
||||
|
@ -25,6 +25,10 @@ import {
|
||||
import { combineUrl } from "@docspace/common/utils";
|
||||
import config from "PACKAGE_FILE";
|
||||
import { getUnexpectedErrorText } from "SRC_DIR/helpers/filesUtils";
|
||||
import {
|
||||
getCategoryTypeByFolderType,
|
||||
getCategoryUrl,
|
||||
} from "SRC_DIR/helpers/utils";
|
||||
|
||||
const UPLOAD_LIMIT_AT_ONCE = 5;
|
||||
|
||||
@ -1527,6 +1531,26 @@ class UploadDataStore {
|
||||
return operationItem;
|
||||
};
|
||||
|
||||
navigateToNewFolderLocation = async (folderId) => {
|
||||
const { filter } = this.filesStore;
|
||||
|
||||
filter.folder = folderId;
|
||||
|
||||
try {
|
||||
const { rootFolderType, parentId } = await getFolderInfo(folderId);
|
||||
const path = getCategoryUrl(
|
||||
getCategoryTypeByFolderType(rootFolderType, parentId),
|
||||
folderId
|
||||
);
|
||||
|
||||
window.DocSpace.navigate(`${path}?${filter.toUrlParams()}`, {
|
||||
replace: true,
|
||||
});
|
||||
} catch (e) {
|
||||
console.log(e);
|
||||
}
|
||||
};
|
||||
|
||||
moveToCopyTo = (destFolderId, pbData, isCopy, fileIds, folderIds) => {
|
||||
const {
|
||||
fetchFiles,
|
||||
@ -1539,6 +1563,7 @@ class UploadDataStore {
|
||||
const { clearSecondaryProgressData, setSecondaryProgressBarData, label } =
|
||||
this.secondaryProgressDataStore;
|
||||
const { withPaging } = this.authStore.settingsStore;
|
||||
const isMovingCurrentFolder = !isCopy && this.dialogsStore.isFolderActions;
|
||||
|
||||
let receivedFolder = destFolderId;
|
||||
let updatedFolder = this.selectedFolderStore.id;
|
||||
@ -1558,6 +1583,8 @@ class UploadDataStore {
|
||||
() => clearSecondaryProgressData(pbData.operationId),
|
||||
TIMEOUT
|
||||
);
|
||||
isMovingCurrentFolder &&
|
||||
this.navigateToNewFolderLocation(this.selectedFolderStore.id);
|
||||
this.dialogsStore.setIsFolderActions(false);
|
||||
return;
|
||||
}
|
||||
@ -1578,6 +1605,8 @@ class UploadDataStore {
|
||||
() => clearSecondaryProgressData(pbData.operationId),
|
||||
TIMEOUT
|
||||
);
|
||||
isMovingCurrentFolder &&
|
||||
this.navigateToNewFolderLocation(this.selectedFolderStore.id);
|
||||
this.dialogsStore.setIsFolderActions(false);
|
||||
});
|
||||
} else {
|
||||
|
@ -384,7 +384,6 @@ module.exports = (env, argv) => {
|
||||
return JSON.stringify(today.toISOString().split(".")[0] + "Z");
|
||||
}, true),
|
||||
IS_PERSONAL: env.personal || false,
|
||||
API_JS_HASH: JSON.stringify(runtime.checksums["api.js"] || dateHash),
|
||||
};
|
||||
|
||||
config.plugins.push(new DefinePlugin(defines));
|
||||
|
@ -3,8 +3,8 @@ import React from "react";
|
||||
import Avatar from "@docspace/components/avatar";
|
||||
import Text from "@docspace/components/text";
|
||||
import Checkbox from "@docspace/components/checkbox";
|
||||
import Loader from "@docspace/components/loader";
|
||||
import Loaders from "@docspace/common/components/Loaders";
|
||||
import Loaders from "../../Loaders";
|
||||
|
||||
const Option = ({
|
||||
style,
|
||||
isMultiSelect,
|
||||
|
@ -3,7 +3,7 @@ import { inject, observer } from "mobx-react";
|
||||
import { useNavigate } from "react-router-dom";
|
||||
import { useTranslation } from "react-i18next";
|
||||
|
||||
import { combineUrl } from "@docspace/common/utils";
|
||||
import { combineUrl } from "../../../utils";
|
||||
|
||||
import AlertComponent from "../../AlertComponent";
|
||||
import RectangleSkeleton from "@docspace/components/skeletons/rectangle";
|
||||
|
@ -1,7 +1,7 @@
|
||||
import React from "react";
|
||||
import PropTypes from "prop-types";
|
||||
import { useNavigate } from "react-router-dom";
|
||||
import Loaders from "@docspace/common/components/Loaders";
|
||||
import Loaders from "../../Loaders";
|
||||
|
||||
import { Link } from "react-router-dom";
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
import React, { useEffect } from "react";
|
||||
import Zendesk, { ZendeskAPI } from "@docspace/common/components/Zendesk";
|
||||
import Zendesk, { ZendeskAPI } from "../../Zendesk";
|
||||
import { LIVE_CHAT_LOCAL_STORAGE_KEY } from "../../../constants";
|
||||
import { inject, observer } from "mobx-react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
|
@ -3,7 +3,7 @@ import { inject, observer } from "mobx-react";
|
||||
import { useNavigate } from "react-router-dom";
|
||||
import { useTranslation, Trans } from "react-i18next";
|
||||
|
||||
import { combineUrl } from "@docspace/common/utils";
|
||||
import { combineUrl } from "../../../utils";
|
||||
|
||||
import AlertComponent from "../../AlertComponent";
|
||||
import RectangleSkeleton from "@docspace/components/skeletons/rectangle";
|
||||
|
@ -7,7 +7,7 @@ import ModalDialog from "@docspace/components/modal-dialog";
|
||||
import Textarea from "@docspace/components/textarea";
|
||||
import FieldContainer from "@docspace/components/field-container";
|
||||
import { mobile, tablet } from "@docspace/components/utils/device";
|
||||
import { sendRecoverRequest } from "@docspace/common/api/settings";
|
||||
import { sendRecoverRequest } from "../../../api/settings";
|
||||
import toastr from "@docspace/components/toast/toastr";
|
||||
import { useTranslation } from "react-i18next";
|
||||
|
||||
|
@ -14,7 +14,7 @@ import { Base } from "@docspace/components/themes";
|
||||
import SortDesc from "PUBLIC_DIR/images/sort.desc.react.svg";
|
||||
import SortReactSvgUrl from "PUBLIC_DIR/images/sort.react.svg?url";
|
||||
import Backdrop from "@docspace/components/backdrop";
|
||||
import { Events } from "@docspace/common/constants";
|
||||
import { Events } from "../../../constants";
|
||||
|
||||
const selectedViewIcon = css`
|
||||
svg {
|
||||
|
@ -1,4 +1,3 @@
|
||||
import { isMobile } from "react-device-detect";
|
||||
import React, {
|
||||
useState,
|
||||
useCallback,
|
||||
@ -7,25 +6,29 @@ import React, {
|
||||
useRef,
|
||||
} from "react";
|
||||
|
||||
import ViewerWrapper from "./sub-components/ViewerWrapper";
|
||||
import {
|
||||
isMobile as isMobileUtils,
|
||||
isTablet,
|
||||
} from "@docspace/components/utils/device";
|
||||
|
||||
import { FileStatus } from "../../constants";
|
||||
import { getFileExtension } from "../../utils";
|
||||
import { checkDialogsOpen } from "../../utils/checkDialogsOpen";
|
||||
|
||||
import { MediaViewerProps } from "./MediaViewer.props";
|
||||
import { FileStatus } from "@docspace/common/constants";
|
||||
import {
|
||||
isNullOrUndefined,
|
||||
KeyboardEventKeys,
|
||||
mapSupplied,
|
||||
mediaTypes,
|
||||
} from "./helpers";
|
||||
import { getFileExtension } from "@docspace/common/utils";
|
||||
|
||||
import {
|
||||
getDesktopMediaContextModel,
|
||||
getMobileMediaContextModel,
|
||||
getPDFContextModel,
|
||||
} from "./helpers/contextModel";
|
||||
import ViewerWrapper from "./sub-components/ViewerWrapper";
|
||||
|
||||
import { checkDialogsOpen } from "../../utils/checkDialogsOpen";
|
||||
import type { MediaViewerProps } from "./MediaViewer.props";
|
||||
|
||||
function MediaViewer({
|
||||
playlistPos,
|
||||
@ -244,6 +247,8 @@ function MediaViewer({
|
||||
});
|
||||
}
|
||||
|
||||
const isMobile = isMobileUtils() || isTablet();
|
||||
|
||||
return isMobile
|
||||
? model
|
||||
: isImage && !isMobile
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { Dispatch, SetStateAction } from "react";
|
||||
import type { Dispatch, SetStateAction } from "react";
|
||||
import { getCustomToolbar } from "../../helpers/getCustomToolbar";
|
||||
import { ContextMenuModel } from "../../types";
|
||||
import type { ContextMenuModel, DevicesType } from "../../types";
|
||||
|
||||
interface ImageViewerProps {
|
||||
src?: string;
|
||||
@ -14,6 +14,7 @@ interface ImageViewerProps {
|
||||
panelVisible: boolean;
|
||||
mobileDetails: JSX.Element;
|
||||
toolbar: ReturnType<typeof getCustomToolbar>;
|
||||
devices: DevicesType;
|
||||
|
||||
onPrev: VoidFunction;
|
||||
onNext: VoidFunction;
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { useGesture } from "@use-gesture/react";
|
||||
import { isMobile, isDesktop } from "react-device-detect";
|
||||
import { isDesktop as isDesktopDeviceDetect } from "react-device-detect";
|
||||
import { useSpring, config } from "@react-spring/web";
|
||||
import React, { SyntheticEvent, useEffect, useRef, useState } from "react";
|
||||
|
||||
@ -55,6 +55,7 @@ function ImageViewer({
|
||||
isTiff,
|
||||
contextModel,
|
||||
errorTitle,
|
||||
devices,
|
||||
}: ImageViewerProps) {
|
||||
const imgRef = useRef<HTMLImageElement>(null);
|
||||
const imgWrapperRef = useRef<HTMLDivElement>(null);
|
||||
@ -84,6 +85,8 @@ function ImageViewer({
|
||||
opacity: 1,
|
||||
}));
|
||||
|
||||
const { isMobile, isDesktop } = devices;
|
||||
|
||||
useEffect(() => {
|
||||
unmountRef.current = false;
|
||||
|
||||
@ -846,10 +849,15 @@ function ImageViewer({
|
||||
},
|
||||
|
||||
onClick: ({ pinching, event }) => {
|
||||
if (isDesktop && event.target === imgWrapperRef.current)
|
||||
if (isDesktopDeviceDetect && event.target === imgWrapperRef.current)
|
||||
return onMask();
|
||||
|
||||
if (!imgRef.current || !containerRef.current || pinching || isDesktop)
|
||||
if (
|
||||
!imgRef.current ||
|
||||
!containerRef.current ||
|
||||
pinching ||
|
||||
isDesktopDeviceDetect
|
||||
)
|
||||
return;
|
||||
|
||||
const time = new Date().getTime();
|
||||
@ -1030,7 +1038,7 @@ function ImageViewer({
|
||||
</ImageWrapper>
|
||||
</ImageViewerContainer>
|
||||
|
||||
{isDesktop && panelVisible && !isError && (
|
||||
{isDesktop && !isMobile && panelVisible && !isError && (
|
||||
<ImageViewerToolbar
|
||||
ref={toolbarRef}
|
||||
toolbar={toolbar}
|
||||
|
@ -1,5 +1,6 @@
|
||||
import { Dispatch, SetStateAction } from "react";
|
||||
import type { Dispatch, SetStateAction } from "react";
|
||||
import { getPDFToolbar } from "./../../helpers/getCustomToolbar";
|
||||
import type { DevicesType } from "../../types";
|
||||
interface PDFViewerProps {
|
||||
src: string;
|
||||
title: string;
|
||||
@ -9,6 +10,7 @@ interface PDFViewerProps {
|
||||
|
||||
isLastImage: boolean;
|
||||
isFistImage: boolean;
|
||||
devices: DevicesType;
|
||||
|
||||
onMask: VoidFunction;
|
||||
generateContextMenu: (
|
||||
|
@ -7,9 +7,8 @@ import React, {
|
||||
} from "react";
|
||||
import { isDesktop, isMobile } from "react-device-detect";
|
||||
|
||||
import { loadScript, combineUrl } from "@docspace/common/utils";
|
||||
//@ts-ignore
|
||||
import { getDocumentServiceLocation } from "@docspace/common/api/files";
|
||||
import { loadScript, combineUrl } from "../../../../utils";
|
||||
import { getDocumentServiceLocation } from "../../../../api/files";
|
||||
|
||||
import PDFViewerProps, { BookMark } from "./PDFViewer.props";
|
||||
import ViewerLoader from "../ViewerLoader";
|
||||
|
@ -3,6 +3,7 @@ interface PlayerMessageErrorProps {
|
||||
errorTitle: string;
|
||||
model: ContextMenuModel[];
|
||||
onMaskClick: VoidFunction;
|
||||
isMobile: boolean;
|
||||
}
|
||||
|
||||
export default PlayerMessageErrorProps;
|
||||
|
@ -1,5 +1,4 @@
|
||||
import React from "react";
|
||||
import { isMobile } from "react-device-detect";
|
||||
import { ReactSVG } from "react-svg";
|
||||
|
||||
import Text from "@docspace/components/text";
|
||||
@ -11,8 +10,9 @@ import {
|
||||
import { isSeparator } from "../../helpers";
|
||||
|
||||
function PlayerMessageError({
|
||||
errorTitle,
|
||||
model,
|
||||
isMobile,
|
||||
errorTitle,
|
||||
onMaskClick,
|
||||
}: PlayerMessageErrorProps) {
|
||||
const items = !isMobile
|
||||
|
@ -28,12 +28,10 @@ function PlayerSpeedControl({
|
||||
|
||||
const timerRef = useRef<NodeJS.Timeout>();
|
||||
|
||||
const [currentIndexSpeed, setCurrentIndexSpeed] = useState<number>(
|
||||
DefaultIndexSpeed
|
||||
);
|
||||
const [isOpenSpeedContextMenu, setIsOpenSpeedContextMenu] = useState<boolean>(
|
||||
false
|
||||
);
|
||||
const [currentIndexSpeed, setCurrentIndexSpeed] =
|
||||
useState<number>(DefaultIndexSpeed);
|
||||
const [isOpenSpeedContextMenu, setIsOpenSpeedContextMenu] =
|
||||
useState<boolean>(false);
|
||||
const [speedToastVisible, setSpeedToastVisible] = useState<boolean>(false);
|
||||
|
||||
useEffect(() => {
|
||||
|
@ -1,6 +1,7 @@
|
||||
import { isMobile } from "react-device-detect";
|
||||
import styled, { css } from "styled-components";
|
||||
|
||||
import { tablet } from "@docspace/components/utils/device";
|
||||
|
||||
export const HoverProgress = styled.div`
|
||||
display: none;
|
||||
position: absolute;
|
||||
@ -177,5 +178,7 @@ export const PlayerTimelineWrapper = styled.div`
|
||||
}
|
||||
}
|
||||
|
||||
${isMobile && mobileCss}
|
||||
@media ${tablet} {
|
||||
${mobileCss}
|
||||
}
|
||||
`;
|
||||
|
@ -1,7 +1,7 @@
|
||||
import { tablet } from "@docspace/components/utils/device";
|
||||
import { isMobile } from "react-device-detect";
|
||||
import styled, { css } from "styled-components";
|
||||
|
||||
import { tablet } from "@docspace/components/utils/device";
|
||||
|
||||
export const PlayerVolumeControlWrapper = styled.div`
|
||||
display: flex;
|
||||
align-items: center;
|
||||
@ -143,5 +143,7 @@ export const VolumeWrapper = styled.div`
|
||||
}
|
||||
}
|
||||
|
||||
${isMobile && mobilecss}
|
||||
@media ${tablet} {
|
||||
${mobilecss}
|
||||
}
|
||||
`;
|
||||
|
@ -32,6 +32,8 @@ interface ViewerProps {
|
||||
bottom?: string
|
||||
) => JSX.Element;
|
||||
onSetSelectionFile: VoidFunction;
|
||||
|
||||
currentDeviceType?: string;
|
||||
}
|
||||
|
||||
export default ViewerProps;
|
||||
|
@ -1,7 +1,14 @@
|
||||
import ReactDOM from "react-dom";
|
||||
import { isMobile } from "react-device-detect";
|
||||
import React, { useRef, useState, useEffect, useCallback } from "react";
|
||||
import { inject, observer } from "mobx-react";
|
||||
import React, {
|
||||
useRef,
|
||||
useState,
|
||||
useEffect,
|
||||
useCallback,
|
||||
useMemo,
|
||||
} from "react";
|
||||
|
||||
import { DeviceType } from "../../../../constants";
|
||||
import { StyledViewerContainer } from "../../StyledComponents";
|
||||
|
||||
import NextButton from "../NextButton";
|
||||
@ -33,6 +40,19 @@ function Viewer(props: ViewerProps) {
|
||||
const contextMenuRef = useRef<{ show: (e: any) => void }>(null);
|
||||
|
||||
const [isFullscreen, setIsFullScreen] = useState<boolean>(false);
|
||||
|
||||
const devices = useMemo(
|
||||
() => ({
|
||||
isMobileOnly: props.currentDeviceType === DeviceType.mobile,
|
||||
isMobile:
|
||||
props.currentDeviceType === DeviceType.tablet ||
|
||||
props.currentDeviceType === DeviceType.mobile,
|
||||
isDesktop: props.currentDeviceType === DeviceType.desktop,
|
||||
}),
|
||||
[props.currentDeviceType]
|
||||
);
|
||||
const { isMobile } = devices;
|
||||
|
||||
useEffect(() => {
|
||||
document.body.appendChild(containerRef.current);
|
||||
containerRef.current.style.direction = "ltr";
|
||||
@ -61,7 +81,7 @@ function Viewer(props: ViewerProps) {
|
||||
clearTimeout(timerIDRef.current);
|
||||
setPanelVisible(true);
|
||||
};
|
||||
}, [setImageTimer, setPanelVisible]);
|
||||
}, [setImageTimer, setPanelVisible, isMobile]);
|
||||
|
||||
const resetToolbarVisibleTimer = () => {
|
||||
if (panelToolbarRef.current) return;
|
||||
@ -210,6 +230,7 @@ function Viewer(props: ViewerProps) {
|
||||
resetToolbarVisibleTimer={resetToolbarVisibleTimer}
|
||||
contextModel={props.contextModel}
|
||||
errorTitle={props.errorTitle}
|
||||
devices={devices}
|
||||
/>,
|
||||
containerRef.current
|
||||
)
|
||||
@ -243,6 +264,7 @@ function Viewer(props: ViewerProps) {
|
||||
removeToolbarVisibleTimer={removeToolbarVisibleTimer}
|
||||
removePanelVisibleTimeout={removePanelVisibleTimeout}
|
||||
restartToolbarVisibleTimer={restartToolbarVisibleTimer}
|
||||
devices={devices}
|
||||
/>,
|
||||
containerRef.current
|
||||
)
|
||||
@ -262,6 +284,7 @@ function Viewer(props: ViewerProps) {
|
||||
isFistImage={!isNotFirstElement}
|
||||
onPrev={props.onPrevClick}
|
||||
onNext={props.onNextClick}
|
||||
devices={devices}
|
||||
/>,
|
||||
containerRef.current
|
||||
)}
|
||||
@ -269,4 +292,8 @@ function Viewer(props: ViewerProps) {
|
||||
);
|
||||
}
|
||||
|
||||
export default Viewer;
|
||||
export default inject<any>(({ auth }) => {
|
||||
const { currentDeviceType } = auth.settingsStore;
|
||||
|
||||
return { currentDeviceType };
|
||||
})(observer(Viewer));
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { ContextMenuModel } from "../../types";
|
||||
import type { ContextMenuModel, DevicesType } from "../../types";
|
||||
|
||||
interface ViewerPlayerProps {
|
||||
src?: string;
|
||||
@ -16,6 +16,7 @@ interface ViewerPlayerProps {
|
||||
isOpenContextMenu: boolean;
|
||||
mobileDetails: JSX.Element;
|
||||
thumbnailSrc?: string;
|
||||
devices: DevicesType;
|
||||
onMask: VoidFunction;
|
||||
onPrev: VoidFunction;
|
||||
onNext: VoidFunction;
|
||||
|
@ -1,7 +1,8 @@
|
||||
import { isMobile, isMobileOnly } from "react-device-detect";
|
||||
import styled, { css } from "styled-components";
|
||||
import styled from "styled-components";
|
||||
import { animated } from "@react-spring/web";
|
||||
|
||||
import { tablet, mobile } from "@docspace/components/utils/device";
|
||||
|
||||
export const ContainerPlayer = styled.div<{ $isFullScreen: boolean }>`
|
||||
position: fixed;
|
||||
inset: 0;
|
||||
@ -30,11 +31,6 @@ export const VideoWrapper = styled(animated.div)<{ $visible: boolean }>`
|
||||
}
|
||||
`;
|
||||
|
||||
const StyledMobilePlayerControls = css`
|
||||
background-color: rgba(0, 0, 0, 0.8);
|
||||
height: 80px;
|
||||
`;
|
||||
|
||||
export const StyledPlayerControls = styled.div<{ $isShow: boolean }>`
|
||||
position: fixed;
|
||||
right: 0px;
|
||||
@ -55,7 +51,10 @@ export const StyledPlayerControls = styled.div<{ $isShow: boolean }>`
|
||||
rgba(0, 0, 0, 0.89) 100%
|
||||
);
|
||||
|
||||
${isMobile && StyledMobilePlayerControls}
|
||||
@media ${tablet} {
|
||||
background-color: rgba(0, 0, 0, 0.8);
|
||||
height: 80px;
|
||||
}
|
||||
`;
|
||||
|
||||
export const ControlContainer = styled.div`
|
||||
@ -71,13 +70,12 @@ export const ControlContainer = styled.div`
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
${isMobile &&
|
||||
css`
|
||||
@media ${tablet} {
|
||||
margin-top: 8px;
|
||||
.player_right-control {
|
||||
margin-right: -8px;
|
||||
}
|
||||
`}
|
||||
}
|
||||
`;
|
||||
|
||||
export const PlayerControlsWrapper = styled.div`
|
||||
@ -85,13 +83,11 @@ export const PlayerControlsWrapper = styled.div`
|
||||
width: 100%;
|
||||
margin-top: 80px;
|
||||
|
||||
${isMobile &&
|
||||
css`
|
||||
@media ${tablet} {
|
||||
margin-top: 0px;
|
||||
`}
|
||||
}
|
||||
|
||||
${isMobileOnly &&
|
||||
css`
|
||||
@media ${mobile} {
|
||||
padding: 0 15px;
|
||||
`}
|
||||
}
|
||||
`;
|
||||
|
@ -1,7 +1,11 @@
|
||||
import lodash from "lodash";
|
||||
import { useGesture } from "@use-gesture/react";
|
||||
import { useSpring, animated } from "@react-spring/web";
|
||||
import { isMobile, isDesktop, isIOS, isMobileOnly } from "react-device-detect";
|
||||
import {
|
||||
isDesktop as isDesktopDeviceDetect,
|
||||
isIOS,
|
||||
isMobileOnly,
|
||||
} from "react-device-detect";
|
||||
import React, {
|
||||
useCallback,
|
||||
useEffect,
|
||||
@ -42,6 +46,7 @@ function ViewerPlayer({
|
||||
isAudio,
|
||||
isVideo,
|
||||
isError,
|
||||
devices,
|
||||
audioIcon,
|
||||
errorTitle,
|
||||
isLastImage,
|
||||
@ -72,6 +77,8 @@ function ViewerPlayer({
|
||||
|
||||
const isDurationInfinityRef = useRef<boolean>(false);
|
||||
|
||||
const { isDesktop, isMobile } = devices;
|
||||
|
||||
const [isLoading, setIsLoading] = useState<boolean>(false);
|
||||
const [isPlaying, setIsPlaying] = useState<boolean>(false);
|
||||
const [isWaiting, setIsWaiting] = useState<boolean>(false);
|
||||
@ -232,7 +239,8 @@ function ViewerPlayer({
|
||||
});
|
||||
},
|
||||
onClick: ({ dragging, event }) => {
|
||||
if (isDesktop && event.target === containerRef.current) return onMask();
|
||||
if (isDesktopDeviceDetect && event.target === containerRef.current)
|
||||
return onMask();
|
||||
|
||||
if (
|
||||
dragging ||
|
||||
@ -385,7 +393,7 @@ function ViewerPlayer({
|
||||
videoRef.current.play();
|
||||
setIsPlaying(true);
|
||||
}
|
||||
}, [isPlaying, isVideo]);
|
||||
}, [isPlaying, isVideo, isMobile]);
|
||||
|
||||
const handleBigPlayButtonClick = () => {
|
||||
togglePlay();
|
||||
@ -612,6 +620,7 @@ function ViewerPlayer({
|
||||
model={model}
|
||||
onMaskClick={onMask}
|
||||
errorTitle={errorTitle}
|
||||
isMobile={isMobile}
|
||||
/>
|
||||
) : (
|
||||
<StyledPlayerControls
|
||||
|
@ -1,5 +1,6 @@
|
||||
import React, { useMemo, memo, useCallback } from "react";
|
||||
import equal from "fast-deep-equal/react";
|
||||
import { useTheme } from "styled-components";
|
||||
import React, { useMemo, memo, useCallback } from "react";
|
||||
|
||||
import Viewer from "../Viewer";
|
||||
import { isSeparator } from "../../helpers";
|
||||
@ -12,7 +13,6 @@ import { ContextMenuModel } from "../../types";
|
||||
import { StyledDropDown } from "../StyledDropDown";
|
||||
import { StyledDropDownItem } from "../StyledDropDownItem";
|
||||
import ViewerWrapperProps from "./ViewerWrapper.props";
|
||||
import { useTheme } from "styled-components";
|
||||
|
||||
function ViewerWrapper(props: ViewerWrapperProps) {
|
||||
const { interfaceDirection } = useTheme();
|
||||
|
@ -17,6 +17,12 @@ export type NumberOrString = number | string;
|
||||
|
||||
export type NullOrUndefined = null | undefined;
|
||||
|
||||
export type DevicesType = {
|
||||
isMobile: boolean;
|
||||
isMobileOnly: boolean;
|
||||
isDesktop: boolean;
|
||||
};
|
||||
|
||||
export type PlaylistType = {
|
||||
id: number;
|
||||
canShare: boolean;
|
||||
|
@ -2,10 +2,10 @@ import React from "react";
|
||||
import ModalDialog from "@docspace/components/modal-dialog";
|
||||
import Text from "@docspace/components/text";
|
||||
import Button from "@docspace/components/button";
|
||||
import { providersData } from "@docspace/common/constants";
|
||||
import { providersData } from "../../constants";
|
||||
import styled, { css } from "styled-components";
|
||||
import { ReactSVG } from "react-svg";
|
||||
import { getProviderTranslation } from "@docspace/common/utils";
|
||||
import { getProviderTranslation } from "../../utils";
|
||||
import SsoReactSvgUrl from "PUBLIC_DIR/images/sso.react.svg?url";
|
||||
import { mobile } from "@docspace/components/utils/device";
|
||||
|
||||
|
@ -2,7 +2,7 @@
|
||||
import React from "react";
|
||||
import { Navigate, Route, useLocation } from "react-router-dom";
|
||||
//import AppLoader from "../AppLoader";
|
||||
import { combineUrl } from "@docspace/common/utils";
|
||||
import { combineUrl } from "../../utils";
|
||||
import { inject, observer } from "mobx-react";
|
||||
import { TenantStatus } from "../../constants";
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
import i18n from "i18next";
|
||||
import { initReactI18next } from "react-i18next";
|
||||
import Backend from "@docspace/common/utils/i18next-http-backend";
|
||||
import Backend from "../../utils/i18next-http-backend";
|
||||
import { LANGUAGE } from "../../constants";
|
||||
import { loadLanguagePath } from "../../utils";
|
||||
import { getCookie } from "@docspace/components/utils/cookie";
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@docspace/common",
|
||||
"version": "2.0.0",
|
||||
"version": "2.0.1",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"build": "echo 'skip it'",
|
||||
@ -20,6 +20,7 @@
|
||||
"mobx": "^6.8.0",
|
||||
"mobx-react": "^7.6.0",
|
||||
"moment": "^2.29.4",
|
||||
"moment-timezone": "^0.5.43",
|
||||
"prop-types": "^15.8.1",
|
||||
"query-string": "7.1.3",
|
||||
"re-resizable": "^6.9.9",
|
||||
|
@ -1,7 +1,7 @@
|
||||
import { makeAutoObservable, runInAction } from "mobx";
|
||||
import moment from "moment";
|
||||
import moment from "moment-timezone";
|
||||
|
||||
import { getDaysLeft, getDaysRemaining } from "@docspace/common/utils";
|
||||
import { getDaysLeft, getDaysRemaining } from "../utils";
|
||||
|
||||
import api from "../api";
|
||||
import { TariffState } from "../constants";
|
||||
@ -77,11 +77,17 @@ class CurrentTariffStatusStore {
|
||||
get paymentDate() {
|
||||
moment.locale(this.authStore.language);
|
||||
if (this.dueDate === null) return "";
|
||||
return moment(this.dueDate).format("LL");
|
||||
return moment(this.dueDate)
|
||||
.tz(window.timezone || "")
|
||||
.format("LL");
|
||||
}
|
||||
|
||||
isValidDate = (date) => {
|
||||
return moment(date).year() !== 9999;
|
||||
return (
|
||||
moment(date)
|
||||
.tz(window.timezone || "")
|
||||
.year() !== 9999
|
||||
);
|
||||
};
|
||||
get isPaymentDateValid() {
|
||||
if (this.dueDate === null) return false;
|
||||
@ -91,12 +97,14 @@ class CurrentTariffStatusStore {
|
||||
get isLicenseDateExpired() {
|
||||
if (!this.isPaymentDateValid) return;
|
||||
|
||||
return moment() > moment(this.dueDate);
|
||||
return moment() > moment(this.dueDate).tz(window.timezone || "");
|
||||
}
|
||||
get gracePeriodEndDate() {
|
||||
moment.locale(this.authStore.language);
|
||||
if (this.delayDueDate === null) return "";
|
||||
return moment(this.delayDueDate).format("LL");
|
||||
return moment(this.delayDueDate)
|
||||
.tz(window.timezone || "")
|
||||
.format("LL");
|
||||
}
|
||||
|
||||
get delayDaysCount() {
|
||||
|
@ -1,8 +1,8 @@
|
||||
import { makeAutoObservable } from "mobx";
|
||||
|
||||
import { getUserById } from "@docspace/common/api/people";
|
||||
import { combineUrl, getUserRole } from "@docspace/common/utils";
|
||||
import { FolderType } from "@docspace/common/constants";
|
||||
import { getUserById } from "../api/people";
|
||||
import { combineUrl, getUserRole } from "../utils";
|
||||
import { FolderType } from "../constants";
|
||||
import config from "PACKAGE_FILE";
|
||||
import Filter from "../api/people/filter";
|
||||
import { getRoomInfo } from "../api/rooms";
|
||||
@ -221,15 +221,15 @@ class InfoPanelStore {
|
||||
getInfoPanelItemIcon = (item, size) => {
|
||||
return item.isRoom || !!item.roomType
|
||||
? item.rootFolderType === FolderType.Archive
|
||||
? this.settingsStore.getIcon(
|
||||
size,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
item.roomType,
|
||||
true
|
||||
)
|
||||
: item.logo && item.logo.medium
|
||||
? item.logo && item.logo.medium
|
||||
: this.settingsStore.getIcon(
|
||||
size,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
item.roomType,
|
||||
true
|
||||
)
|
||||
? item.logo.medium
|
||||
: item.icon
|
||||
? item.icon
|
||||
|
@ -24,7 +24,7 @@ import {
|
||||
size as deviceSize,
|
||||
isTablet,
|
||||
} from "@docspace/components/utils/device";
|
||||
import { wrongPortalNameUrl } from "@docspace/common/constants";
|
||||
import { wrongPortalNameUrl } from "../constants";
|
||||
import { ARTICLE_ALERTS } from "@docspace/client/src/helpers/constants";
|
||||
import toastr from "@docspace/components/toast/toastr";
|
||||
//import { getFromLocalStorage } from "@docspace/client/src/pages/PortalSettings/utils";
|
||||
@ -167,7 +167,7 @@ class SettingsStore {
|
||||
currentColorScheme = null;
|
||||
|
||||
enablePlugins = false;
|
||||
pluginOptions = [];
|
||||
pluginOptions = { upload: false, delete: false };
|
||||
domainValidator = null;
|
||||
|
||||
additionalResourcesData = null;
|
||||
@ -495,7 +495,11 @@ class SettingsStore {
|
||||
|
||||
if (origSettings?.plugins?.enabled) {
|
||||
this.enablePlugins = origSettings.plugins.enabled;
|
||||
this.pluginOptions = origSettings.plugins.allow;
|
||||
|
||||
this.pluginOptions = {
|
||||
upload: origSettings.plugins.upload,
|
||||
delete: origSettings.plugins.delete,
|
||||
};
|
||||
}
|
||||
|
||||
if (origSettings?.tenantAlias) {
|
||||
@ -965,6 +969,7 @@ class SettingsStore {
|
||||
};
|
||||
|
||||
get isFrame() {
|
||||
console.log("get isFrame:", this.frameConfig?.name === window.name);
|
||||
return this.frameConfig?.name === window.name;
|
||||
}
|
||||
|
||||
|
@ -5,7 +5,7 @@ import { Workbox } from "workbox-window";
|
||||
import SnackBar from "@docspace/components/snackbar";
|
||||
import i18n from "i18next";
|
||||
import { useTranslation, initReactI18next } from "react-i18next";
|
||||
import Backend from "@docspace/common/utils/i18next-http-backend";
|
||||
import Backend from "../utils/i18next-http-backend";
|
||||
import { LANGUAGE } from "../constants";
|
||||
import { getCookie } from "@docspace/components/utils/cookie";
|
||||
|
||||
|
@ -13,8 +13,7 @@ class AxiosClient {
|
||||
|
||||
initCSR = () => {
|
||||
this.isSSR = false;
|
||||
const origin =
|
||||
window.DocSpaceConfig?.api?.origin || apiOrigin || window.location.origin;
|
||||
const origin = window.DocSpaceConfig?.api?.origin || apiOrigin || window.location.origin;
|
||||
const proxy = window.DocSpaceConfig?.proxy?.url || proxyURL;
|
||||
const prefix = window.DocSpaceConfig?.api?.prefix || apiPrefix;
|
||||
|
||||
@ -30,22 +29,16 @@ class AxiosClient {
|
||||
const sharedIndex = location.pathname.indexOf("shared");
|
||||
|
||||
const lastKeySymbol = location.search.indexOf("&");
|
||||
const lastIndex =
|
||||
lastKeySymbol === -1 ? location.search.length : lastKeySymbol;
|
||||
const lastIndex = lastKeySymbol === -1 ? location.search.length : lastKeySymbol;
|
||||
const publicRoomKey =
|
||||
shareIndex > -1 && sharedIndex === -1
|
||||
? location.search.substring(5, lastIndex)
|
||||
: null;
|
||||
shareIndex > -1 && sharedIndex === -1 ? location.search.substring(5, lastIndex) : null;
|
||||
|
||||
if (publicRoomKey) {
|
||||
headers = { ...headers, "Request-Token": publicRoomKey };
|
||||
}
|
||||
|
||||
const apiBaseURL = combineUrl(origin, proxy, prefix);
|
||||
const paymentsURL = combineUrl(
|
||||
proxy,
|
||||
"/portal-settings/payments/portal-payments"
|
||||
);
|
||||
const paymentsURL = combineUrl(proxy, "/portal-settings/payments/portal-payments");
|
||||
this.paymentsURL = paymentsURL;
|
||||
|
||||
const apxiosConfig = {
|
||||
@ -173,8 +166,7 @@ class AxiosClient {
|
||||
const pathname = window.location.pathname;
|
||||
const isArchived = pathname.indexOf("/rooms/archived") !== -1;
|
||||
|
||||
const isRooms =
|
||||
pathname.indexOf("/rooms/shared") !== -1 || isArchived;
|
||||
const isRooms = pathname.indexOf("/rooms/shared") !== -1 || isArchived;
|
||||
|
||||
if (isRooms && !skipRedirect) {
|
||||
setTimeout(() => {
|
||||
@ -183,6 +175,10 @@ class AxiosClient {
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case 429:
|
||||
error = { ...error, message: "Request limit exceeded" };
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { FolderType, PageType } from "@docspace/common/constants";
|
||||
import { FolderType, PageType } from "../constants";
|
||||
|
||||
import { isMobile, isTablet } from "@docspace/components/utils/device";
|
||||
|
||||
|
@ -1,5 +1,8 @@
|
||||
import moment from "moment";
|
||||
import moment from "moment-timezone";
|
||||
|
||||
export const convertTime = (date, locale) => {
|
||||
return moment(date).locale(locale).format("L, LTS");
|
||||
return moment(date)
|
||||
.tz(window.timezone || "")
|
||||
.locale(locale)
|
||||
.format("L, LTS");
|
||||
};
|
||||
|
@ -63,8 +63,9 @@ class FirebaseHelper {
|
||||
!!this.config["projectId"] &&
|
||||
!!this.config["storageBucket"] &&
|
||||
!!this.config["messagingSenderId"] &&
|
||||
!!this.config["appId"] /*&&
|
||||
this.config["measurementId"]*/
|
||||
!!this.config["appId"] &&
|
||||
!window.navigator.userAgent.includes("ZoomWebKit") && // Disabled firebase for Zoom - unknown 403 error inside iframe
|
||||
!window.navigator.userAgent.includes("ZoomApps")
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -15,7 +15,7 @@ import BackgroundPatternPurpleReactSvgUrl from "PUBLIC_DIR/images/background.pat
|
||||
import BackgroundPatternLightBlueReactSvgUrl from "PUBLIC_DIR/images/background.pattern.lightBlue.react.svg?url";
|
||||
import BackgroundPatternBlackReactSvgUrl from "PUBLIC_DIR/images/background.pattern.black.react.svg?url";
|
||||
|
||||
import moment from "moment";
|
||||
import moment from "moment-timezone";
|
||||
|
||||
import { LANGUAGE, ThemeKeys, RtlLanguages } from "../constants";
|
||||
import sjcl from "sjcl";
|
||||
@ -336,7 +336,7 @@ export const isLanguageRtl = (lng: string) => {
|
||||
|
||||
// temporary function needed to replace rtl language in Editor to ltr
|
||||
export const getLtrLanguageForEditor = (
|
||||
userLng: string,
|
||||
userLng: string | undefined,
|
||||
portalLng: string,
|
||||
isEditor: boolean = false
|
||||
): string => {
|
||||
@ -349,7 +349,6 @@ export const getLtrLanguageForEditor = (
|
||||
|
||||
if ((!isEditor && !isEditorPath) || (userLng && !isUserLngRtl))
|
||||
return userLng;
|
||||
if (portalLng && !isPortalLngRtl) return portalLng;
|
||||
|
||||
return "en";
|
||||
};
|
||||
|
@ -72,7 +72,7 @@ Badge.propTypes = {
|
||||
/** CSS font-size */
|
||||
fontSize: PropTypes.string,
|
||||
/** CSS font-weight */
|
||||
fontWeight: PropTypes.number,
|
||||
fontWeight: PropTypes.oneOfType([PropTypes.number, PropTypes.string]),
|
||||
/** CSS border-radius */
|
||||
borderRadius: PropTypes.string,
|
||||
/** CSS padding */
|
||||
|
@ -404,7 +404,7 @@ class ContextMenu extends Component {
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
<Text className="text" truncate={true}>
|
||||
<Text className="text" truncate={true} dir="auto">
|
||||
{this.props.header.title}
|
||||
</Text>
|
||||
</div>
|
||||
|
@ -18,7 +18,9 @@ import ModalBackdrop from "../components/ModalBackdrop";
|
||||
import Scrollbar from "../../scrollbar";
|
||||
import { classNames } from "../../utils/classNames";
|
||||
import FormWrapper from "../components/FormWrapper";
|
||||
import { isIOS, isMobileOnly } from "react-device-detect";
|
||||
import { isIOS, isTablet, isMobile } from "react-device-detect";
|
||||
|
||||
let isInitScroll = false;
|
||||
|
||||
const Modal = ({
|
||||
id,
|
||||
@ -53,17 +55,50 @@ const Modal = ({
|
||||
const contentRef = React.useRef(0);
|
||||
|
||||
React.useEffect(() => {
|
||||
if (isMobileOnly && isIOS) {
|
||||
if (isIOS && isMobile) {
|
||||
window.visualViewport.addEventListener("resize", onResize);
|
||||
window.visualViewport.addEventListener("scroll", onResize);
|
||||
}
|
||||
|
||||
return () => {
|
||||
window.visualViewport.removeEventListener("resize", onResize);
|
||||
window.visualViewport.removeEventListener("scroll", onResize);
|
||||
};
|
||||
}, []);
|
||||
|
||||
React.useEffect(() => {
|
||||
if (!visible) isInitScroll = false;
|
||||
}, [visible]);
|
||||
|
||||
const scrollPosition = () => {
|
||||
if (currentDisplayType !== "modal") return;
|
||||
|
||||
if (isInitScroll) return;
|
||||
|
||||
const dialogHeader = document
|
||||
.getElementById("modal-header-swipe")
|
||||
?.getBoundingClientRect();
|
||||
|
||||
const input = document
|
||||
.getElementsByClassName("input-component")[0]
|
||||
?.getBoundingClientRect();
|
||||
|
||||
if (dialogHeader && input) {
|
||||
dialogHeader.y < dialogHeader.height + input.height
|
||||
? window.scrollTo(0, input.y)
|
||||
: window.scrollTo(0, dialogHeader.y);
|
||||
}
|
||||
|
||||
isInitScroll = true;
|
||||
};
|
||||
|
||||
const onResize = (e) => {
|
||||
if (window.innerHeight < window.innerWidth || isTablet) {
|
||||
scrollPosition();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (!contentRef.current) return;
|
||||
|
||||
if (currentDisplayType === "modal") {
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@docspace/components",
|
||||
"version": "2.0.0",
|
||||
"version": "2.0.1",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"build": "echo 'skip it'",
|
||||
|
@ -89,6 +89,7 @@ const Item = React.memo(({ index, style, data }: ItemProps) => {
|
||||
fontSize={"14px"}
|
||||
noSelect
|
||||
truncate
|
||||
dir="auto"
|
||||
>
|
||||
{label}
|
||||
</Text>
|
||||
|
@ -221,7 +221,7 @@ SnackBar.propTypes = {
|
||||
/** Sets the font size */
|
||||
fontSize: PropTypes.string,
|
||||
/** Sets the font weight */
|
||||
fontWeight: PropTypes.string,
|
||||
fontWeight: PropTypes.oneOfType([PropTypes.number, PropTypes.string]),
|
||||
/** Specifies the text alignment */
|
||||
textAlign: PropTypes.string,
|
||||
/** Allows displaying content in HTML format */
|
||||
|
@ -28,14 +28,14 @@ const Input = ({
|
||||
|
||||
return props.mask != null ? (
|
||||
<MaskedInput
|
||||
className={`${className} not-selectable`}
|
||||
className={`${className} input-component not-selectable`}
|
||||
keepCharPositions={true}
|
||||
guide={false}
|
||||
{...props}
|
||||
/>
|
||||
) : (
|
||||
<input
|
||||
className={`${className} not-selectable`}
|
||||
className={`${className} input-component not-selectable`}
|
||||
dir={dir}
|
||||
{...props}
|
||||
{...rest}
|
||||
|
@ -1,6 +1,11 @@
|
||||
import moment from "moment";
|
||||
import moment from "moment-timezone";
|
||||
|
||||
export default function getCorrectDate(locale, date) {
|
||||
export default function getCorrectDate(
|
||||
locale,
|
||||
date,
|
||||
dateFormat = "L",
|
||||
timeFormat = "LT"
|
||||
) {
|
||||
// if something went wrong with 'moment' - change for on this method get correct time
|
||||
// const options = {
|
||||
// year: "numeric",
|
||||
@ -16,8 +21,10 @@ export default function getCorrectDate(locale, date) {
|
||||
|
||||
if (!date || date === "0001-01-01T00:00:00.0000000Z") return "—";
|
||||
|
||||
const curDate = moment(date).locale(locale).format("L");
|
||||
const curTime = moment(date).locale(locale).format("LT");
|
||||
const timezone = window.timezone;
|
||||
|
||||
const curDate = moment(date).locale(locale).tz(timezone).format(dateFormat);
|
||||
const curTime = moment(date).locale(locale).tz(timezone).format(timeFormat);
|
||||
|
||||
const correctDate = curDate + " " + curTime;
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@docspace/editor",
|
||||
"version": "2.0.0",
|
||||
"version": "2.0.1",
|
||||
"private": true,
|
||||
"homepage": "/doceditor",
|
||||
"scripts": {
|
||||
|
@ -12,9 +12,14 @@ export const StyledSimpleNav = styled.div`
|
||||
`;
|
||||
|
||||
export const StyledDeepLink = styled.div`
|
||||
width: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
z-index: 1;
|
||||
|
||||
@media ${mobile} {
|
||||
width: calc(100% - 32px);
|
||||
}
|
||||
`;
|
||||
|
||||
export const StyledBodyWrapper = styled.div`
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user