Merge branch 'hotfix/v2.6.1' into develop

# Conflicts:
#	packages/shared/components/room-icon/index.tsx
#	packages/shared/themes/base.ts
#	packages/shared/themes/dark.ts
#	packages/shared/themes/globalColors.ts
This commit is contained in:
Alexey Safronov 2024-08-22 12:29:56 +04:00
commit e9f5327d7c
53 changed files with 583 additions and 310 deletions

View File

@ -19,6 +19,7 @@
href="/logo.ashx?logotype=3"
/>
<link rel="mask-icon" href="/logo.ashx?logotype=3" />
<link rel="apple-touch-icon" sizes="32x32" href="/logo.ashx?logotype=3" />
<link rel="manifest" href="/manifest.json" />
<!-- Tell the browser it's a PWA -->

View File

@ -33,7 +33,7 @@ import { Provider as MobxProvider } from "mobx-react";
import ThemeProvider from "./components/ThemeProviderWrapper";
import ErrorBoundary from "./components/ErrorBoundaryWrapper";
import store from "client/store";
import store from "SRC_DIR/store";
import i18n from "./i18n";
import "@docspace/shared/polyfills/broadcastchannel";

View File

@ -160,7 +160,7 @@ export default function withFileActions(WrappedFileItem) {
if (
e.target?.tagName === "INPUT" ||
e.target?.tagName === "SPAN" ||
// e.target?.tagName === "SPAN" ||
e.target?.tagName === "A" ||
e.target.closest(".checkbox") ||
e.target.closest(".table-container_row-checkbox") ||

View File

@ -169,6 +169,10 @@ const withHotkeys = (Component) => {
};
const onPaste = async (e) => {
const someDialogIsOpen = checkDialogsOpen();
if (someDialogIsOpen) return;
uploadClipboardFiles(t, e);
};

View File

@ -170,7 +170,7 @@ const PureConnectDialogContainer = (props) => {
provider_id,
)
.then(async () => {
await setThirdPartyAccountsInfo();
await setThirdPartyAccountsInfo(t);
})
.catch((err) => {
toastr.error(err);

View File

@ -24,18 +24,23 @@
// content are licensed under the terms of the Creative Commons Attribution-ShareAlike 4.0
// International. See the License terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
import React, { useEffect, useState, useRef } from "react";
import { useEffect, useState } from "react";
import styled from "styled-components";
import { ReactSVG } from "react-svg";
import { isMobileOnly, isMobile } from "react-device-detect";
import { Button } from "@docspace/shared/components/button";
import { DropDownItem } from "@docspace/shared/components/drop-down-item";
import { Text } from "@docspace/shared/components/text";
import { Tooltip } from "@docspace/shared/components/tooltip";
import { connectedCloudsTypeTitleTranslation as ProviderKeyTranslation } from "@docspace/client/src/helpers/filesUtils";
import { Base } from "@docspace/shared/themes";
import { toastr } from "@docspace/shared/components/toast";
import { ComboBox } from "@docspace/shared/components/combobox";
import ExternalLinkReactSvgUrl from "PUBLIC_DIR/images/external.link.react.svg?url";
import { ThirdPartyServicesUrlName } from "../../../../../helpers/constants";
import { isDesktop } from "@docspace/shared/utils";
const StyledStorageLocation = styled.div`
display: flex;
@ -91,16 +96,29 @@ const StyledStorageLocation = styled.div`
StyledStorageLocation.defaultProps = { theme: Base };
const services = {
GoogleDrive: "google",
Box: "box",
Dropbox: "dropbox",
OneDrive: "skydrive",
Nextcloud: "nextcloud",
kDrive: "kdrive",
ownCloud: "owncloud",
WebDav: "webdav",
};
const StyledComboBoxItem = styled.div`
display: flex;
.drop-down-item_text {
color: ${({ theme, isDisabled }) =>
isDisabled ? theme.dropDownItem.disableColor : theme.dropDownItem.color};
}
.drop-down-item_icon {
display: flex;
align-items: center;
div {
display: flex;
}
margin-inline-start: auto;
svg {
min-height: 16px;
min-width: 16px;
}
}
`;
const ThirdPartyComboBox = ({
t,
@ -124,15 +142,16 @@ const ThirdPartyComboBox = ({
isDisabled,
setIsScrollLocked,
isAdmin,
}) => {
const deafultSelectedItem = {
const defaultSelectedItem = {
key: "length",
label:
storageLocation?.provider?.title ||
t("ThirdPartyStorageComboBoxPlaceholder"),
};
const [selectedItem, setSelectedItem] = useState(deafultSelectedItem);
const [selectedItem, setSelectedItem] = useState(defaultSelectedItem);
const thirdparties = connectItems.map((item) => ({
...item,
@ -142,7 +161,7 @@ const ThirdPartyComboBox = ({
const setStorageLocaiton = (thirparty, isConnected) => {
if (!isConnected) {
window.open(
`/portal-settings/integration/third-party-services?service=${services[thirparty.id]}`,
`/portal-settings/integration/third-party-services?service=${ThirdPartyServicesUrlName[thirparty.id]}`,
"_blank",
);
return;
@ -207,35 +226,79 @@ const ThirdPartyComboBox = ({
setSaveThirdpartyResponse(null);
}, [saveThirdpartyResponse]);
const options = thirdparties
.sort((storage) => (storage.isConnected ? -1 : 1))
.map((item) => ({
label:
item.title + (item.isConnected ? "" : ` (${t("ActivationRequired")})`),
title: item.title,
key: item.id,
icon: item.isConnected ? undefined : ExternalLinkReactSvgUrl,
className: item.isConnected ? "" : "storage-unavailable",
}));
const onSelect = (event) => {
const data = event.currentTarget.dataset;
const onSelect = (elem) => {
const thirdparty = thirdparties.find((t) => {
return elem.key === t.id;
return t.id === data.thirdPartyId;
});
thirdparty && setStorageLocaiton(thirdparty, thirdparty.isConnected);
thirdparty.isConnected
? setSelectedItem(elem)
: setSelectedItem({ ...deafultSelectedItem });
? setSelectedItem({ key: thirdparty.id, label: thirdparty.title })
: setSelectedItem({ ...defaultSelectedItem });
};
const getTextTooltip = () => {
return (
<Text fontSize="12px" noSelect>
{t("Common:EnableThirdPartyIntegration")}
</Text>
);
};
const advancedOptions = thirdparties
.sort((storage) => (storage.isConnected ? -1 : 1))
?.map((item) => {
const isDisabled = !item.isConnected && !isAdmin;
const itemLabel =
item.title + (item.isConnected ? "" : ` (${t("ActivationRequired")})`);
const disabledData = isDisabled
? { "data-tooltip-id": "file-links-tooltip", "data-tip": "tooltip" }
: {};
return (
<StyledComboBoxItem isDisabled={isDisabled} key={item.id}>
<DropDownItem
onClick={onSelect}
data-third-party-id={item.id}
disabled={isDisabled}
{...disabledData}
>
<Text className="drop-down-item_text" fontWeight={600}>
{itemLabel}
</Text>
{!isDisabled && !item.isConnected ? (
<ReactSVG
src={ExternalLinkReactSvgUrl}
className="drop-down-item_icon"
/>
) : (
<></>
)}
</DropDownItem>
{isDisabled && (
<Tooltip
float={isDesktop()}
id="file-links-tooltip"
getContent={getTextTooltip}
place="bottom"
/>
)}
</StyledComboBoxItem>
);
});
return (
<StyledStorageLocation>
<div className="set_room_params-thirdparty">
<ComboBox
className="thirdparty-combobox"
selectedOption={selectedItem}
options={options}
options={[]}
advancedOptions={advancedOptions}
scaled
withBackdrop={isMobile}
size="content"
@ -244,12 +307,12 @@ const ThirdPartyComboBox = ({
directionY="both"
displaySelectedOption
noBorder={false}
// fixedDirection
isDefaultMode={true}
hideMobileView={false}
forceCloseClickOutside
scaledOptions
onSelect={onSelect}
showDisabledItems
displayArrow
/>
<Button
id="shared_third-party-storage_connect"

View File

@ -71,6 +71,7 @@ const ThirdPartyStorage = ({
isDisabled,
currentColorScheme,
isRoomAdmin,
isAdmin,
createNewFolderIsChecked,
onCreateFolderChange,
@ -168,6 +169,7 @@ const ThirdPartyStorage = ({
setIsScrollLocked={setIsScrollLocked}
setIsOauthWindowOpen={setIsOauthWindowOpen}
isDisabled={isDisabled}
isAdmin={isAdmin}
/>
)}
@ -213,7 +215,7 @@ export default inject(
const connectItems = thirdPartyStore.connectingStorages;
const { isRoomAdmin } = authStore;
const { isRoomAdmin, isAdmin } = authStore;
return {
connectItems,
@ -232,6 +234,7 @@ export default inject(
getOAuthToken,
currentColorScheme,
isRoomAdmin,
isAdmin,
fetchConnectingStorages: thirdPartyStore.fetchConnectingStorages,
};
},

View File

@ -56,7 +56,6 @@ const StyledInvitePanel = styled.div`
height: auto;
width: auto;
background: ${(props) => props.theme.infoPanel.blurColor};
backdrop-filter: blur(3px);
z-index: 309;
position: fixed;
inset: 0;

View File

@ -85,7 +85,7 @@ export const TableVersions = Object.freeze({
Files: "3",
People: "3",
Trash: "4",
Groups: "5",
Groups: "6",
InsideGroup: "6",
Recent: "1",
});
@ -169,3 +169,14 @@ export const SortByFieldName = Object.freeze({
LastOpened: "LastOpened",
UsedSpace: "usedspace",
});
export const ThirdPartyServicesUrlName = Object.freeze({
GoogleDrive: "google",
Box: "box",
Dropbox: "dropbox",
OneDrive: "skydrive",
Nextcloud: "nextcloud",
kDrive: "kdrive",
ownCloud: "owncloud",
WebDav: "webdav",
});

View File

@ -53,11 +53,9 @@ export const GreetingContainer = styled.div`
}
.tooltip {
.invitation-text {
display: flex;
flex-direction: column;
align-items: center;
p {
text-align: center;
overflow-wrap: break-word;
}
@media ${mobile} {

View File

@ -487,7 +487,7 @@ const CreateUserForm = (props) => {
<PortalLogo className="portal-logo" />
{linkData.type === "LinkInvite" && (
<div className="tooltip">
<Text fontSize="16px" as="div" className="invitation-text">
<Text fontSize="16px">
{roomName ? (
<Trans
t={t}

View File

@ -30,9 +30,9 @@ import { withTranslation } from "react-i18next";
import { TableHeader } from "@docspace/shared/components/table";
import { Events } from "@docspace/shared/enums";
import { TableVersions } from "SRC_DIR/helpers/constants";
const TABLE_VERSION = "5";
const TABLE_COLUMNS = `groupsTableColumns_ver-${TABLE_VERSION}`;
const TABLE_COLUMNS = `groupsTableColumns_ver-${TableVersions.Groups}`;
class GroupsTableHeader extends React.Component {
constructor(props) {
@ -49,6 +49,15 @@ class GroupsTableHeader extends React.Component {
minWidth: 210,
onClick: this.onFilter,
},
{
key: "People",
title: props.t("Common:People"),
enable: props.peopleAccountsGroupsColumnIsEnabled,
sortBy: "membersCount",
onClick: this.onFilter,
resizable: true,
onChange: this.onColumnChange,
},
{
key: "Head of Group",
title: props.t("Common:HeadOfGroup"),
@ -161,6 +170,8 @@ export default inject(
setColumnEnable: tableStore.setColumnEnable,
managerAccountsGroupsColumnIsEnabled:
tableStore.managerAccountsGroupsColumnIsEnabled,
peopleAccountsGroupsColumnIsEnabled:
tableStore.peopleAccountsGroupsColumnIsEnabled,
}),
)(
withTranslation(["People", "Common", "PeopleTranslations"])(

View File

@ -46,6 +46,7 @@ const GroupsTableItem = ({
getGroupContextOptions,
getModel,
openGroupAction,
peopleAccountsGroupsColumnIsEnabled,
managerAccountsGroupsColumnIsEnabled,
changeGroupSelection,
@ -140,6 +141,23 @@ const GroupsTableItem = ({
<Badges isLDAP={item.isLDAP} />
</TableCell>
{peopleAccountsGroupsColumnIsEnabled ? (
<TableCell className="table-container_group-people">
<Text
title={item.membersCount}
fontWeight="600"
fontSize="13px"
isTextOverflow
className="table-cell_group-people"
color={theme.filesSection.tableView.row.sideColor}
>
{item.membersCount}
</Text>
</TableCell>
) : (
<div />
)}
{managerAccountsGroupsColumnIsEnabled ? (
<TableCell className={"table-container_group-manager"}>
<Text

View File

@ -57,6 +57,7 @@ const GroupsTableView = ({
groupsIsFiltered,
groupsFilterTotal,
peopleAccountsGroupsColumnIsEnabled,
managerAccountsGroupsColumnIsEnabled,
}) => {
const ref = useRef(null);
@ -110,6 +111,9 @@ const GroupsTableView = ({
managerAccountsGroupsColumnIsEnabled={
managerAccountsGroupsColumnIsEnabled
}
peopleAccountsGroupsColumnIsEnabled={
peopleAccountsGroupsColumnIsEnabled
}
/>
))}
</TableBody>
@ -155,7 +159,10 @@ export default inject(
const { isVisible: infoPanelVisible } = infoPanelStore;
const { managerAccountsGroupsColumnIsEnabled } = tableStore;
const {
managerAccountsGroupsColumnIsEnabled,
peopleAccountsGroupsColumnIsEnabled,
} = tableStore;
return {
groups,
@ -177,6 +184,7 @@ export default inject(
groupsIsFiltered,
groupsFilterTotal,
peopleAccountsGroupsColumnIsEnabled,
managerAccountsGroupsColumnIsEnabled,
};
},

View File

@ -2021,6 +2021,13 @@ const SectionFilterContent = ({
default: true,
};
const people = {
id: "sort-by_people",
key: "membersCount",
label: t("Common:People"),
default: true,
};
const manager = {
id: "sort-by_manager",
key: "manager",
@ -2028,7 +2035,7 @@ const SectionFilterContent = ({
default: true,
};
groupsOptions.push(title, manager);
groupsOptions.push(title, people, manager);
return groupsOptions;
}

View File

@ -26,7 +26,7 @@
import React, { useEffect } from "react";
import { Provider as MobxProvider } from "mobx-react";
import store from "client/store";
import store from "SRC_DIR/store";
import CommonWhiteLabel from "./CommonWhiteLabel";
const { authStore } = store;

View File

@ -496,6 +496,12 @@ const StyledBackup = styled.div`
}
.backup_third-party-context {
margin-top: 4px;
svg {
width: 16px;
height: 16px;
padding: 7px;
}
}
`;
const StyledBackupList = styled.div`
@ -603,6 +609,31 @@ const StyledSettingsHeader = styled.div`
margin: auto 0;
}
`;
const StyledComboBoxItem = styled.div`
display: flex;
.drop-down-item_text {
color: ${({ theme, isDisabled }) =>
isDisabled ? theme.dropDownItem.disableColor : theme.dropDownItem.color};
}
.drop-down-item_icon {
display: flex;
align-items: center;
div {
display: flex;
}
margin-inline-start: auto;
svg {
min-height: 16px;
min-width: 16px;
}
}
`;
export {
StyledModules,
StyledRestoreBackup,
@ -613,4 +644,5 @@ export {
StyledAutoBackup,
StyledStoragesModule,
StyledSettingsHeader,
StyledComboBoxItem,
};

View File

@ -27,10 +27,15 @@
import VerticalDotsReactSvgUrl from "PUBLIC_DIR/images/vertical-dots.react.svg?url";
import RefreshReactSvgUrl from "PUBLIC_DIR/images/refresh.react.svg?url";
import AccessNoneReactSvgUrl from "PUBLIC_DIR/images/access.none.react.svg?url";
import React, { useEffect, useReducer } from "react";
import ExternalLinkReactSvgUrl from "PUBLIC_DIR/images/external.link.react.svg?url";
import { useEffect, useReducer } from "react";
import { ReactSVG } from "react-svg";
import { Button } from "@docspace/shared/components/button";
import { DropDownItem } from "@docspace/shared/components/drop-down-item";
import { Text } from "@docspace/shared/components/text";
import { saveSettingsThirdParty } from "@docspace/shared/api/files";
import { StyledBackup } from "../StyledBackup";
import { StyledBackup, StyledComboBoxItem } from "../StyledBackup";
import { ComboBox } from "@docspace/shared/components/combobox";
import { toastr } from "@docspace/shared/components/toast";
import { inject, observer } from "mobx-react";
@ -39,6 +44,7 @@ import DeleteThirdPartyDialog from "../../../../../../components/dialogs/DeleteT
import { getOAuthToken } from "@docspace/shared/utils/common";
import FilesSelectorInput from "SRC_DIR/components/FilesSelectorInput";
import { useTranslation } from "react-i18next";
import { ThirdPartyServicesUrlName } from "../../../../../../helpers/constants";
const initialState = {
folderList: {},
@ -83,7 +89,7 @@ const DirectThirdPartyConnection = (props) => {
const onSetSettings = async () => {
try {
await setThirdPartyAccountsInfo();
await setThirdPartyAccountsInfo(t);
setState({
isLoading: false,
@ -157,7 +163,7 @@ const DirectThirdPartyConnection = (props) => {
provider_id,
);
await setThirdPartyAccountsInfo();
await setThirdPartyAccountsInfo(t);
} catch (e) {
toastr.error(e);
}
@ -165,9 +171,24 @@ const DirectThirdPartyConnection = (props) => {
setState({ isLoading: false, isUpdatingInfo: false });
};
const onSelectAccount = (options) => {
const key = options.key;
setSelectedThirdPartyAccount({ ...accounts[+key] });
const onSelectAccount = (event) => {
const data = event.currentTarget.dataset;
const account = accounts.find((t) => t.key === data.thirdPartyKey);
if (!account.connected) {
setSelectedThirdPartyAccount({
key: 0,
label: selectedThirdPartyAccount?.label,
});
return window.open(
`/portal-settings/integration/third-party-services?service=${ThirdPartyServicesUrlName[data.thirdPartyKey]}`,
"_blank",
);
}
setSelectedThirdPartyAccount(account);
};
const onDisconnect = () => {
@ -187,7 +208,7 @@ const DirectThirdPartyConnection = (props) => {
key: "Disconnect-settings",
label: t("Common:Disconnect"),
onClick: onDisconnect,
disabled: selectedThirdPartyAccount?.connected ? false : true,
disabled: selectedThirdPartyAccount?.storageIsConnected ? false : true,
icon: AccessNoneReactSvgUrl,
},
];
@ -201,6 +222,33 @@ const DirectThirdPartyConnection = (props) => {
const isDisabledSelector = isLoading || isDisabled;
const folderList = connectedThirdPartyAccount ?? {};
const advancedOptions = accounts?.map((item) => {
return (
<StyledComboBoxItem isDisabled={item.disabled} key={item.key}>
<DropDownItem
onClick={onSelectAccount}
className={item.className}
data-third-party-key={item.key}
disabled={item.disabled}
>
<Text className="drop-down-item_text" fontWeight={600}>
{item.title}
</Text>
{!item.disabled && !item.connected ? (
<ReactSVG
src={ExternalLinkReactSvgUrl}
className="drop-down-item_icon"
/>
) : (
<></>
)}
</DropDownItem>
</StyledComboBoxItem>
);
});
return (
<StyledBackup
isConnectedAccount={
@ -210,17 +258,25 @@ const DirectThirdPartyConnection = (props) => {
>
<div className="backup_connection">
<ComboBox
options={accounts}
className="thirdparty-combobox"
selectedOption={{
key: 0,
label: selectedThirdPartyAccount?.label,
}}
onSelect={onSelectAccount}
options={[]}
advancedOptions={advancedOptions}
scaled
size="content"
manualWidth={"auto"}
directionY="both"
displaySelectedOption
noBorder={false}
isDefaultMode={true}
hideMobileView={false}
forceCloseClickOutside
scaledOptions
dropDownMaxHeight={300}
tabIndex={1}
showDisabledItems
displayArrow
isDisabled={isDisabledComponent}
/>

View File

@ -28,7 +28,7 @@ import { makeAutoObservable } from "mobx";
import { isMobile } from "@docspace/shared/utils";
import { checkDialogsOpen } from "@docspace/shared/utils/checkDialogsOpen";
import { TUser, TUserGroup } from "@docspace/shared/api/people/types";
import { TABLE_HEADER_HEIGHT } from "@docspace/shared/utils/device";
import { TABLE_HEADER_HEIGHT } from "@docspace/shared/components/table/Table.constants";
type AccountsType = TUser | TUserGroup;

View File

@ -37,13 +37,16 @@ import { combineUrl } from "@docspace/shared/utils/combineUrl";
import config from "PACKAGE_FILE";
import {
getSettingsThirdParty,
getThirdPartyCapabilities,
uploadBackup,
} from "@docspace/shared/api/files";
import i18n from "../i18n";
import { connectedCloudsTypeTitleTranslation } from "../helpers/filesUtils.js";
const { EveryDayType, EveryWeekType } = AutoBackupPeriod;
class BackupStore {
authStore = null;
thirdPartyStore = null;
restoreResource = null;
backupSchedule = {};
@ -100,11 +103,13 @@ class BackupStore {
selectedThirdPartyAccount = null;
connectedThirdPartyAccount = null;
accounts = [];
capabilities = [];
connectedAccount = [];
constructor() {
constructor(authStore, thirdPartyStore) {
makeAutoObservable(this);
this.authStore = authStore;
this.thirdPartyStore = thirdPartyStore;
}
setConnectedThirdPartyAccount = (account) => {
@ -195,37 +200,20 @@ class BackupStore {
return false;
}
setThirdPartyAccountsInfo = async () => {
const [connectedAccount, capabilities] = await Promise.all([
setThirdPartyAccountsInfo = async (t) => {
const [connectedAccount, providers] = await Promise.all([
getSettingsThirdParty(),
getThirdPartyCapabilities(),
this.thirdPartyStore.fetchConnectingStorages(),
]);
this.setCapabilities(capabilities);
this.setConnectedThirdPartyAccount(connectedAccount);
const providerNames = [
["GoogleDrive", i18n.t("Translations:TypeTitleGoogle")],
["Box", i18n.t("Translations:TypeTitleBoxNet")],
["DropboxV2", i18n.t("Translations:TypeTitleDropBox")],
["SharePoint", i18n.t("Translations:TypeTitleSharePoint")],
["OneDrive", i18n.t("Translations:TypeTitleSkyDrive")],
["WebDav", "Nextcloud"],
["WebDav", "ownCloud"],
["kDrive", i18n.t("Translations:TypeTitlekDrive")],
["Yandex", i18n.t("Translations:TypeTitleYandex")],
["WebDav", i18n.t("Translations:TypeTitleWebDav")],
];
let accounts = [],
selectedAccount = {};
let index = 0;
providerNames.map((item) => {
const { account, isConnected } = this.getThirdPartyAccount(
item[0],
item[1],
index,
);
providers.map((item) => {
const { account, isConnected } = this.getThirdPartyAccount(item, t);
if (!account) return;
@ -237,51 +225,53 @@ class BackupStore {
index++;
});
accounts = accounts.sort((storage) => (storage.connected ? -1 : 1));
this.setThirdPartyAccounts(accounts);
console.log(selectedAccount, accounts);
const connectedThirdPartyAccount = accounts.findLast((a) => a.connected);
this.setSelectedThirdPartyAccount(
Object.keys(selectedAccount).length !== 0
? selectedAccount
: { ...accounts[0] },
: connectedThirdPartyAccount,
);
};
getThirdPartyAccount = (providerKey, serviceTitle, index) => {
const accountIndex =
this.capabilities &&
this.capabilities.findIndex((x) => x[0] === providerKey);
if (accountIndex === -1) return { account: null, isConnected: false };
getThirdPartyAccount = (provider, t) => {
const serviceTitle = connectedCloudsTypeTitleTranslation(provider.name, t);
const serviceLabel = provider.connected
? serviceTitle
: `${serviceTitle} (${t("CreateEditRoomDialog:ActivationRequired")})`;
const isConnected =
this.connectedThirdPartyAccount?.providerKey === "WebDav"
? serviceTitle === this.connectedThirdPartyAccount?.title
: this.capabilities[accountIndex][0] ===
this.connectedThirdPartyAccount?.providerKey;
: provider.key === this.connectedThirdPartyAccount?.providerKey;
const isDisabled = !provider.connected && !this.authStore.isAdmin;
const account = {
key: index.toString(),
label: serviceTitle,
title: serviceTitle,
provider_key: this.capabilities[accountIndex][0],
...(this.capabilities[accountIndex][1] && {
provider_link: this.capabilities[accountIndex][1],
key: provider.name,
label: serviceLabel,
title: serviceLabel,
provider_key: provider.key,
...(provider.clientId && {
provider_link: provider.clientId,
}),
connected: isConnected,
storageIsConnected: isConnected,
connected: provider.connected,
...(isConnected && {
provider_id: this.connectedThirdPartyAccount?.providerId,
id: this.connectedThirdPartyAccount.id,
}),
disabled: isDisabled,
};
return { account, isConnected };
};
setCapabilities = (capabilities) => {
this.capabilities = capabilities;
};
setThirdPartyAccounts = (accounts) => {
this.accounts = accounts;
};

View File

@ -2476,7 +2476,15 @@ class FilesActionStore {
? getObjectByLocation(shareWebUrl)?.share
: "";
return openDocEditor(id, false, shareKey);
const isPDF = item.fileExst === ".pdf";
const canEditForm =
isPDF &&
item.isPDFForm &&
item.security?.EditForm &&
!item.startFilling;
return openDocEditor(id, false, shareKey, canEditForm);
}
if (isMediaOrImage) {

View File

@ -37,7 +37,7 @@ import getFilesFromEvent from "@docspace/shared/components/drag-and-drop/get-fil
import config from "PACKAGE_FILE";
import { getCategoryUrl } from "SRC_DIR/helpers/utils";
import { encryptionUploadDialog } from "../helpers/encryptionUploadDialog";
import { TABLE_HEADER_HEIGHT } from "@docspace/shared/utils/device";
import { TABLE_HEADER_HEIGHT } from "@docspace/shared/components/table/Table.constants";
class HotkeyStore {
filesStore;

View File

@ -432,10 +432,10 @@ class LdapFormStore {
scrollToField = () => {
for (let key in this.errors) {
const element = document.getElementsByName(key)[0];
const element = document.getElementsByName(key)?.[0];
element.focus();
element.blur();
element?.focus();
element?.blur();
return;
}
};

View File

@ -388,11 +388,11 @@ class SsoFormStore {
this.isSubmitLoading = true;
try {
await submitSsoForm(data);
const res = await submitSsoForm(data);
toastr.success(t("Settings:SuccessfullySaveSettingsMessage"));
this.isSubmitLoading = false;
this.setSpMetadata(true);
this.setDefaultSettings(settings);
this.setDefaultSettings(res);
this.setIsSsoEnabled(settings.enableSso);
} catch (err) {
toastr.error(err);
@ -406,6 +406,7 @@ class SsoFormStore {
const config = await resetSsoForm();
this.setFields(config);
this.hideErrors();
} catch (err) {
toastr.error(err);
console.error(err);
@ -902,8 +903,14 @@ class SsoFormStore {
checkRequiredFields = () => {
this.setError("entityId", this.entityId);
this.setError("ssoUrlPost", this.ssoUrlPost);
this.setError("sloUrlPost", this.sloUrlPost);
this.ssoBinding === BINDING_POST &&
this.setError("ssoUrlPost", this.ssoUrlPost);
this.ssoBinding === BINDING_REDIRECT &&
this.setError("ssoUrlRedirect", this.ssoUrlRedirect);
this.sloBinding === BINDING_POST &&
this.setError("sloUrlPost", this.sloUrlPost);
this.sloBinding === BINDING_REDIRECT &&
this.setError("sloUrlRedirect", this.sloUrlRedirect);
this.setError("firstName", this.firstName);
this.setError("lastName", this.lastName);
this.setError("email", this.email);
@ -977,9 +984,9 @@ class SsoFormStore {
for (let key in this) {
if (key.includes("HasError") && this[key] !== false) {
const name = key.replace("HasError", "");
const element = document.getElementsByName(name)[0];
element.focus();
element.blur();
const element = document.getElementsByName(name)?.[0];
element?.focus();
element?.blur();
return;
}
}

View File

@ -78,6 +78,7 @@ class TableStore {
emailAccountsColumnIsEnabled = true;
storageAccountsColumnIsEnabled = true;
peopleAccountsGroupsColumnIsEnabled = true;
managerAccountsGroupsColumnIsEnabled = true;
typeAccountsInsideGroupColumnIsEnabled = true;
@ -157,6 +158,8 @@ class TableStore {
setAccountsColumnStorage = (enable) =>
(this.storageAccountsColumnIsEnabled = enable);
setAccountsGroupsColumnPeople = (enable) =>
(this.peopleAccountsGroupsColumnIsEnabled = enable);
setAccountsGroupsColumnManager = (enable) =>
(this.managerAccountsGroupsColumnIsEnabled = enable);
@ -204,6 +207,7 @@ class TableStore {
}
if (getIsAccountsGroups()) {
this.setAccountsGroupsColumnPeople(splitColumns.includes("People"));
this.setAccountsGroupsColumnManager(
splitColumns.includes("Head of Group"),
);
@ -337,6 +341,12 @@ class TableStore {
: this.setRoomColumnQuota(!this.roomQuotaColumnIsEnable);
return;
case "People":
this.setAccountsGroupsColumnPeople(
!this.peopleAccountsGroupsColumnIsEnabled,
);
return;
case "Head of Group":
this.setAccountsGroupsColumnManager(
!this.managerAccountsGroupsColumnIsEnabled,

View File

@ -84,7 +84,10 @@ class ThirdPartyStore {
oauthHref: storage.redirectUrl,
category: storage.name,
requiredConnectionUrl: storage.requiredConnectionUrl,
clientId: storage.clientId,
}));
return res;
};
saveThirdParty = (

View File

@ -102,7 +102,7 @@ const paymentStore = new PaymentStore(
);
const wizardStore = new WizardStore();
const confirmStore = new ConfirmStore();
const backupStore = new BackupStore();
const backupStore = new BackupStore(authStore, thirdPartyStore);
const commonStore = new CommonStore(settingsStore);
const ssoStore = new SsoFormStore();

View File

@ -324,16 +324,11 @@ module.exports = (env, argv) => {
};
}
const remotes = {
client: "client@/remoteEntry.js",
login: "login@/login/remoteEntry.js",
};
config.plugins.push(
new ModuleFederationPlugin({
name: "client",
filename: "remoteEntry.js",
remotes: remotes,
remotes: [],
exposes: {
"./shell": "./src/Shell",
"./store": "./src/store",

View File

@ -24,16 +24,17 @@
// content are licensed under the terms of the Creative Commons Attribution-ShareAlike 4.0
// International. See the License terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
import type { Metadata } from "next";
import { headers } from "next/headers";
import Script from "next/script";
import { getSelectorsByUserAgent } from "react-device-detect";
import { ValidationStatus } from "@docspace/shared/enums";
import { getData, validatePublicRoomKey } from "@/utils/actions";
import { RootPageProps } from "@/types";
import Root from "@/components/Root";
import FilePassword from "@/components/file-password";
import { ValidationStatus } from "@docspace/shared/enums";
const initialSearchParams: RootPageProps["searchParams"] = {
fileId: undefined,
@ -71,8 +72,6 @@ async function Page({ searchParams }: RootPageProps) {
}
}
const startDate = new Date();
const data = await getData(
fileId ?? fileid ?? "",
version,
@ -82,13 +81,22 @@ async function Page({ searchParams }: RootPageProps) {
type,
);
const timer = new Date().getTime() - startDate.getTime();
if (data.error?.status === "not-found" && error) {
data.error.message = error;
}
return <Root {...data} timer={timer} />;
let url = data.config?.editorUrl ?? data.error?.editorUrl;
if (url && !url.endsWith("/")) url += "/";
const docApiUrl = `${url}web-apps/apps/api/documents/api.js`;
return (
<>
<Root {...data} />
<Script id="editor-api" strategy="beforeInteractive" src={docApiUrl} />
</>
);
}
export default Page;

View File

@ -24,6 +24,8 @@
// content are licensed under the terms of the Creative Commons Attribution-ShareAlike 4.0
// International. See the License terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
/* eslint-disable @next/next/no-before-interactive-script-outside-document */
import Script from "next/script";
import runtime from "../../../runtime.json";
@ -35,9 +37,11 @@ const Scripts = () => {
<>
<Script
id="browser-detector"
strategy="beforeInteractive"
src={`/static/scripts/browserDetector.js?hash=${runtime?.checksums?.["browserDetector.js"] ?? hashDate}`}
/>
<Script id="portal-config">
<Script id="portal-config" strategy="beforeInteractive">
{`
console.log("It's DocEditor INIT");
fetch("/static/scripts/config.json?hash=${runtime?.checksums["config.json"] ?? hashDate}")

View File

@ -111,6 +111,11 @@ export default async function RootLayout({
<head>
<link rel="icon" type="image/x-icon" href="/logo.ashx?logotype=3" />
<link rel="mask-icon" href="/logo.ashx?logotype=3" />
<link
rel="apple-touch-icon"
sizes="32x32"
href="/logo.ashx?logotype=3"
/>
<meta charSet="utf-8" />
<meta
name="viewport"

View File

@ -13,6 +13,7 @@
-->
<link rel="icon" type="image/x-icon" href="/logo.ashx?logotype=3" />
<link rel="mask-icon" href="/logo.ashx?logotype=3" />
<link rel="apple-touch-icon" sizes="32x32" href="/logo.ashx?logotype=3" />
<!-- Tell the browser it's a PWA -->
<!-- <meta name="mobile-web-app-capable" content="yes" /> -->

View File

@ -24,7 +24,7 @@
// content are licensed under the terms of the Creative Commons Attribution-ShareAlike 4.0
// International. See the License terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
import styled, { css } from "styled-components";
import styled from "styled-components";
import { Base } from "../../themes";
import { BackdropProps } from "./Backdrop.types";
@ -33,11 +33,6 @@ const StyledBackdrop = styled.div<BackdropProps & { needBackground: boolean }>`
props.needBackground
? props.theme.backdrop.backgroundColor
: props.theme.backdrop.unsetBackgroundColor};
${(props) =>
props.needBackground &&
css`
backdrop-filter: ${`blur(${props.theme.modalDialog.backdrop.blur}px)`};
`};
display: ${(props) => (props.visible ? "block" : "none")};
height: 100vh;

View File

@ -173,6 +173,7 @@ const ComboBoxPure = (props: ComboboxProps) => {
optionStyle,
style,
withLabel = true,
displayArrow,
} = props;
const { tabIndex, onClickSelectedItem } = props;
@ -297,6 +298,7 @@ const ComboBoxPure = (props: ComboboxProps) => {
isLoading={isLoading}
type={type}
plusBadgeValue={plusBadgeValue}
displayArrow={displayArrow}
/>
{displayType !== "toggle" && (

View File

@ -167,6 +167,7 @@ export interface ComboboxProps {
title?: string;
plusBadgeValue?: number;
withLabel?: boolean;
displayArrow?: boolean;
}
export interface ComboButtonProps {
@ -189,6 +190,7 @@ export interface ComboButtonProps {
isLoading?: boolean;
type?: TCombobox;
plusBadgeValue?: number;
displayArrow?: boolean;
}
export interface ComboButtonThemeProps extends ComboButtonProps {

View File

@ -72,11 +72,12 @@ const ComboButton = (props: ComboButtonProps) => {
modernView = false,
tabIndex = -1,
isLoading = false,
displayArrow: displayArrowProp,
} = props;
const defaultOption = selectedOption?.default;
// const isSelected = selectedOption?.key !== 0;
const displayArrow = withOptions || withAdvancedOptions;
const displayArrow = withOptions || withAdvancedOptions || displayArrowProp;
const comboButtonClassName = `combo-button combo-button_${isOpen ? "open" : "closed"}`;

View File

@ -37,6 +37,7 @@ import { Row } from "./sub-components/Row";
import { DropDownProps } from "./DropDown.types";
import { DEFAULT_PARENT_HEIGHT } from "./DropDown.constants";
import { isIOS, isMobile } from "react-device-detect";
const DropDown = ({
directionY = "bottom",
@ -284,12 +285,25 @@ const DropDown = ({
};
window.addEventListener("resize", documentResizeListener.current);
if (isIOS && isMobile)
window.visualViewport?.addEventListener(
"resize",
documentResizeListener.current,
);
}
}, [checkPosition, checkPositionPortal, isDefaultMode, open]);
const unbindDocumentResizeListener = React.useCallback(() => {
if (documentResizeListener.current) {
window.removeEventListener("resize", documentResizeListener.current);
if (isIOS && isMobile)
window.visualViewport?.removeEventListener(
"resize",
documentResizeListener.current,
);
documentResizeListener.current = null;
}
}, []);

View File

@ -49,14 +49,6 @@ const StyledModal = styled.div<{ modalSwipeOffset?: number; blur?: number }>`
.loader-wrapper {
padding: 0 16px 16px;
}
.modal-backdrop-active {
${(props) =>
props.blur &&
css`
backdrop-filter: blur(${props.blur}px) !important;
`};
}
`;
const Dialog = styled.div`

View File

@ -31,17 +31,6 @@ import { TTheme } from "@docspace/shared/themes";
import { mobile } from "../../../utils";
import { ModalDialogBackdropProps } from "../ModalDialog.types";
const backdropFilter = (props: {
theme: TTheme;
modalSwipeOffset?: number;
}) => {
const blur = props.theme.modalDialog.backdrop.blur;
const swipeOffset = props.modalSwipeOffset;
if (!swipeOffset) return `blur(${blur}px)`;
return `blur(${blur + swipeOffset * (blur / 120)}px)`;
};
const backdropBackground = (props: {
theme: TTheme;
modalSwipeOffset?: number;
@ -56,8 +45,6 @@ const backdropBackground = (props: {
const StyledModalBackdrop = styled.div.attrs(
(props: { theme: TTheme; modalSwipeOffset?: number; zIndex?: number }) => ({
style: {
backdropFilter: backdropFilter(props),
WebkitBackdropFilter: backdropFilter(props),
background: backdropBackground(props),
},
}),

View File

@ -0,0 +1,72 @@
import styled, { css } from "styled-components";
import { Base } from "../../themes";
export const StyledIcon = styled.div<{
size: string;
radius: string;
isArchive?: boolean;
color?: string;
wrongImage: boolean;
}>`
display: flex;
justify-content: center;
align-items: center;
height: ${(props) => props.size};
width: ${(props) => props.size};
.room-background {
height: ${(props) => props.size};
width: ${(props) => props.size};
border-radius: ${(props) => props.radius};
vertical-align: middle;
background: ${(props) =>
props.isArchive
? props.theme.roomIcon.backgroundArchive
: `#${props.color}`};
position: absolute;
opacity: ${(props) => props.theme.roomIcon.opacityBackground};
}
.room-title {
font-size: 14px;
font-weight: 700;
line-height: 16px;
color: ${(props) =>
props.wrongImage && props.theme.isBase ? "#333333" : "#ffffff"};
position: relative;
${(props) =>
!props.theme.isBase &&
!props.isArchive &&
css`
color: ${`#${props.color}`};
`};
}
.room-icon_badge {
position: absolute;
margin-block: 24px 0;
margin-inline: 24px 0;
.room-icon-button {
width: 12px;
height: 12px;
border: ${(props) => `1px solid ${props.theme.backgroundColor}`};
border-radius: 50%;
svg {
path {
fill: ${(props) => props.theme.backgroundColor};
}
rect {
stroke: ${(props) => props.theme.backgroundColor};
}
}
}
}
`;
StyledIcon.defaultProps = { theme: Base };

View File

@ -0,0 +1,29 @@
type RoomIconDefault = {
title: string;
isArchive?: boolean;
size?: string;
radius?: string;
showDefault: boolean;
imgClassName?: string;
className?: string;
};
type RoomIconColor = {
color: string;
imgSrc?: undefined;
imgClassName?: undefined;
};
type RoomIconImage = {
color?: string | undefined;
imgSrc: string;
imgClassName?: string;
};
type RoomIconBadge = { badgeUrl?: string; onBadgeClick?: () => void };
type RoomIconNonBadge = { badgeUrl?: undefined; onBadgeClick?: undefined };
export type RoomIconProps = RoomIconDefault &
(RoomIconColor | RoomIconImage) &
(RoomIconBadge | RoomIconNonBadge);

View File

@ -0,0 +1,30 @@
function Compare(...fns: Array<Function>) {
return (arg: string) => {
return fns.reduce((composed, fn) => fn(composed), arg);
};
}
function removeSpecialSymbol(text: string): string {
return text.replace(/[-_[\]{}()*+!?.,&\\^$|#@%]/g, "");
}
function trim(text: string): string {
return text.replace(/\s+/g, " ").trim();
}
function getFirstAndLastChar(text: string): string {
const [first, ...other] = text.split(" ");
return (first.at(0) ?? "") + (other.at(-1)?.at(0) ?? "");
}
function toUpperCase(text: string) {
return text.toUpperCase();
}
export const getRoomTitle = Compare(
removeSpecialSymbol,
trim,
getFirstAndLastChar,
toUpperCase,
);

View File

@ -24,128 +24,17 @@
// content are licensed under the terms of the Creative Commons Attribution-ShareAlike 4.0
// International. See the License terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
import React from "react";
import React, { useMemo } from "react";
import styled, { css } from "styled-components";
import { Base, globalColors } from "../../themes";
import { Text } from "../text";
import { IconButton } from "../icon-button";
import { classNames } from "../../utils";
const StyledIcon = styled.div<{
size: string;
radius: string;
isArchive?: boolean;
color?: string;
wrongImage: boolean;
}>`
display: flex;
justify-content: center;
align-items: center;
import { getRoomTitle } from "./RoomIcon.utils";
import { StyledIcon } from "./RoomIcon.styled";
height: ${(props) => props.size};
width: ${(props) => props.size};
.room-background {
height: ${(props) => props.size};
width: ${(props) => props.size};
border-radius: ${(props) => props.radius};
vertical-align: middle;
background: ${(props) =>
props.isArchive
? props.theme.roomIcon.backgroundArchive
: `#${props.color}`};
position: absolute;
opacity: ${(props) => props.theme.roomIcon.opacityBackground};
}
.room-title {
font-size: 14px;
font-weight: 700;
line-height: 16px;
color: ${(props) =>
props.wrongImage && props.theme.isBase
? globalColors.black
: globalColors.white};
position: relative;
${(props) =>
!props.theme.isBase &&
!props.isArchive &&
css`
color: ${`#${props.color}`};
`};
}
.room-icon_badge {
position: absolute;
margin-block: 24px 0;
margin-inline: 24px 0;
.room-icon-button {
width: 12px;
height: 12px;
border: ${(props) => `1px solid ${props.theme.backgroundColor}`};
border-radius: 50%;
svg {
path {
fill: ${(props) => props.theme.backgroundColor};
}
rect {
stroke: ${(props) => props.theme.backgroundColor};
}
}
}
}
`;
StyledIcon.defaultProps = { theme: Base };
// interface RoomIconProps {
// title: string;
// isArchive?: boolean;
// color: string;
// size?: string;
// radius?: string;
// showDefault: boolean;
// imgClassName?: string;
// imgSrc?: string;
// }
type RoomIconDefault = {
title: string;
isArchive?: boolean;
size?: string;
radius?: string;
showDefault: boolean;
imgClassName?: string;
className?: string;
};
type RoomIconColor = {
color: string;
imgSrc?: undefined;
imgClassName?: undefined;
};
type RoomIconImage = {
color?: string | undefined;
imgSrc: string;
imgClassName?: string;
};
type RoomIconBadge = { badgeUrl?: string; onBadgeClick?: () => void };
type RoomIconNonBadge = { badgeUrl?: undefined; onBadgeClick?: undefined };
type RoomIconProps = RoomIconDefault &
(RoomIconColor | RoomIconImage) &
(RoomIconBadge | RoomIconNonBadge);
import type { RoomIconProps } from "./RoomIcon.types";
const RoomIcon = ({
title,
@ -162,17 +51,7 @@ const RoomIcon = ({
}: RoomIconProps) => {
const [correctImage, setCorrectImage] = React.useState(true);
const titleWithoutNumberDuplicate = title?.replace(/\(\d+\)/, "");
const titleWithoutSpaces = titleWithoutNumberDuplicate
?.replace(/\s+/g, " ")
?.trim();
const indexAfterLastSpace = titleWithoutSpaces?.lastIndexOf(" ");
const secondCharacter =
!titleWithoutSpaces || indexAfterLastSpace === -1
? ""
: titleWithoutSpaces[indexAfterLastSpace + 1];
const roomTitle = title && (title[0] + secondCharacter).toUpperCase();
const roomTitle = useMemo(() => getRoomTitle(title ?? ""), [title]);
const prefetchImage = React.useCallback(() => {
if (!imgSrc) return;

View File

@ -70,7 +70,6 @@ const StyledInfoPanelWrapper = styled.div.attrs(({ id }) => ({
height: auto;
width: auto;
background: ${(props) => props.theme.infoPanel.blurColor};
backdrop-filter: blur(3px);
z-index: 300;
@media ${tablet} {
z-index: 309;

View File

@ -0,0 +1,30 @@
// (c) Copyright Ascensio System SIA 2009-2024
//
// This program is a free software product.
// You can redistribute it and/or modify it under the terms
// of the GNU Affero General Public License (AGPL) version 3 as published by the Free Software
// Foundation. In accordance with Section 7(a) of the GNU AGPL its Section 15 shall be amended
// to the effect that Ascensio System SIA expressly excludes the warranty of non-infringement of
// any third-party rights.
//
// This program is distributed WITHOUT ANY WARRANTY, without even the implied warranty
// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. For details, see
// the GNU AGPL at: http://www.gnu.org/licenses/agpl-3.0.html
//
// You can contact Ascensio System SIA at Lubanas st. 125a-25, Riga, Latvia, EU, LV-1021.
//
// The interactive user interfaces in modified source and object code versions of the Program must
// display Appropriate Legal Notices, as required under Section 5 of the GNU AGPL version 3.
//
// Pursuant to Section 7(b) of the License you must retain the original Product logo when
// distributing the program. Pursuant to Section 7(e) we decline to grant you any rights under
// trademark law for use of our trademarks.
//
// All the Product's GUI elements, including illustrations and icon sets, as well as technical writing
// content are licensed under the terms of the Creative Commons Attribution-ShareAlike 4.0
// International. See the License terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
export const DEFAULT_MIN_COLUMN_SIZE = 110;
export const SETTINGS_SIZE = 24;
export const MIN_SIZE_FIRST_COLUMN = 210;
export const TABLE_HEADER_HEIGHT = 40;

View File

@ -24,10 +24,7 @@
// content are licensed under the terms of the Creative Commons Attribution-ShareAlike 4.0
// International. See the License terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
export const MIN_SIZE_FIRST_COLUMN = 210;
export const DEFAULT_MIN_COLUMN_SIZE = 110;
export const SETTINGS_SIZE = 24;
export const HANDLE_OFFSET = 8;
import { SETTINGS_SIZE } from "./Table.constants";
export const getSubstring = (str: string) => +str.substring(0, str.length - 2);

View File

@ -38,14 +38,12 @@ import {
import { TTableColumn, TableHeaderProps } from "./Table.types";
import { TableSettings } from "./sub-components/TableSettings";
import { TableHeaderCell } from "./sub-components/TableHeaderCell";
import { checkingForUnfixedSize, getSubstring } from "./Table.utils";
import {
DEFAULT_MIN_COLUMN_SIZE,
MIN_SIZE_FIRST_COLUMN,
SETTINGS_SIZE,
HANDLE_OFFSET,
checkingForUnfixedSize,
getSubstring,
} from "./Table.utils";
MIN_SIZE_FIRST_COLUMN,
} from "./Table.constants";
import { isDesktop } from "../../utils";
class TableHeaderComponent extends React.Component<

View File

@ -107,6 +107,8 @@ const {
lightScrollActive,
silver,
highlandGray,
blurLight,
} = globalColors;
export const getBaseTheme = () => {
@ -1279,7 +1281,7 @@ export const getBaseTheme = () => {
},
backdrop: {
backgroundColor: lightGrayBlackout,
backgroundColor: blurLight,
unsetBackgroundColor: "unset",
},
@ -1831,7 +1833,7 @@ export const getBaseTheme = () => {
sectionHeaderToggleBgActive: grayLight,
backgroundColor: white,
blurColor: lightGrayBlackout,
blurColor: blurLight,
borderColor: grayLightMid,
thumbnailBorderColor: grayLightMid,
textColor: black,

View File

@ -37,7 +37,6 @@ const {
black,
darkBlack,
darkGrayBlackout,
grayLight,
darkGrayLight,
lightGrayHover,
@ -104,6 +103,8 @@ const {
darkScrollActive,
silver,
highlandGray,
blurDark,
} = globalColors;
const Dark: TTheme = {
@ -609,7 +610,7 @@ const Dark: TTheme = {
r: 27,
g: 27,
b: 27,
a: 0.4,
a: 0.6,
},
blur: 9,
},
@ -1269,7 +1270,7 @@ const Dark: TTheme = {
},
backdrop: {
backgroundColor: darkGrayBlackout,
backgroundColor: blurDark,
unsetBackgroundColor: "unset",
},
@ -1823,7 +1824,7 @@ const Dark: TTheme = {
sectionHeaderToggleBgActive: black,
backgroundColor: black,
blurColor: darkGrayBlackout,
blurColor: blurDark,
borderColor: grayDarkStrong,
thumbnailBorderColor: grayLightMid,
textColor: white,

View File

@ -29,8 +29,6 @@ export const globalColors = {
black: "#333333",
darkBlack: "#000",
lightGrayBlackout: "rgba(6, 22, 38, 0.2)",
darkGrayBlackout: "rgba(27, 27, 27, 0.4)",
grayLight: "#F8F9F9",
darkGrayLight: "#282828",
lightGrayHover: "#F3F4F4",
@ -69,6 +67,9 @@ export const globalColors = {
secondBlue: "#11A3D4",
mainYellow: "#FFD30F",
blurLight: "rgba(6, 22, 38, 0.2)",
blurDark: "rgba(27, 27, 27, 0.6)",
lightErrorStatus: "#F24724",
darkErrorStatus: "#E06451",

View File

@ -25,7 +25,6 @@
// International. See the License terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
export const INFO_PANEL_WIDTH = 400;
export const TABLE_HEADER_HEIGHT = 40;
export const MAX_INFINITE_LOADER_SHIFT = 800;
export function checkIsSSR() {

View File

@ -533,5 +533,6 @@
"Website": "Website",
"Yes": "Yes",
"Yesterday": "Yesterday",
"You": "You"
"You": "You",
"EnableThirdPartyIntegration": "Please ask a DocSpace owner or administrator to enable the corresponding service in the Integration section of the DocSpace Settings."
}

View File

@ -489,7 +489,7 @@
path = `/doceditor/?fileId=${config.id}&editorType=${config.editorType}&editorGoBack=${goBack}&customization=${customization}`;
if (config.requestToken) {
path = `${path}&share=${config.requestToken}`;
path = `${path}&share=${config.requestToken}&is_file=true`;
}
break;
@ -515,7 +515,7 @@
path = `/doceditor/?fileId=${config.id}&editorType=${config.editorType}&action=view&editorGoBack=${goBack}&customization=${customization}`;
if (config.requestToken) {
path = `${path}&share=${config.requestToken}`;
path = `${path}&share=${config.requestToken}&is_file=true`;
}
break;