Merge branch 'hotfix/v2.6.1' into feature/translations-quotas
This commit is contained in:
commit
3cae2e01ae
@ -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 -->
|
||||
|
@ -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";
|
||||
|
@ -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") ||
|
||||
|
@ -169,6 +169,10 @@ const withHotkeys = (Component) => {
|
||||
};
|
||||
|
||||
const onPaste = async (e) => {
|
||||
const someDialogIsOpen = checkDialogsOpen();
|
||||
|
||||
if (someDialogIsOpen) return;
|
||||
|
||||
uploadClipboardFiles(t, e);
|
||||
};
|
||||
|
||||
|
@ -170,7 +170,7 @@ const PureConnectDialogContainer = (props) => {
|
||||
provider_id,
|
||||
)
|
||||
.then(async () => {
|
||||
await setThirdPartyAccountsInfo();
|
||||
await setThirdPartyAccountsInfo(t);
|
||||
})
|
||||
.catch((err) => {
|
||||
toastr.error(err);
|
||||
|
@ -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"
|
||||
|
@ -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,
|
||||
};
|
||||
},
|
||||
|
@ -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;
|
||||
top: 0;
|
||||
|
@ -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",
|
||||
});
|
||||
|
@ -54,11 +54,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} {
|
||||
|
@ -485,7 +485,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}
|
||||
|
@ -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"])(
|
||||
|
@ -45,6 +45,7 @@ const GroupsTableItem = ({
|
||||
getGroupContextOptions,
|
||||
getModel,
|
||||
openGroupAction,
|
||||
peopleAccountsGroupsColumnIsEnabled,
|
||||
managerAccountsGroupsColumnIsEnabled,
|
||||
|
||||
changeGroupSelection,
|
||||
@ -139,6 +140,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
|
||||
|
@ -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,
|
||||
};
|
||||
},
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -625,6 +625,12 @@ const StyledBackup = styled.div`
|
||||
}
|
||||
.backup_third-party-context {
|
||||
margin-top: 4px;
|
||||
|
||||
svg {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
padding: 7px;
|
||||
}
|
||||
}
|
||||
`;
|
||||
const StyledBackupList = styled.div`
|
||||
@ -764,6 +770,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,
|
||||
@ -774,4 +805,5 @@ export {
|
||||
StyledAutoBackup,
|
||||
StyledStoragesModule,
|
||||
StyledSettingsHeader,
|
||||
StyledComboBoxItem,
|
||||
};
|
||||
|
@ -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}
|
||||
/>
|
||||
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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;
|
||||
};
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
};
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -80,6 +80,7 @@ class TableStore {
|
||||
emailAccountsColumnIsEnabled = true;
|
||||
storageAccountsColumnIsEnabled = true;
|
||||
|
||||
peopleAccountsGroupsColumnIsEnabled = true;
|
||||
managerAccountsGroupsColumnIsEnabled = true;
|
||||
|
||||
typeAccountsInsideGroupColumnIsEnabled = true;
|
||||
@ -163,6 +164,8 @@ class TableStore {
|
||||
setAccountsColumnStorage = (enable) =>
|
||||
(this.storageAccountsColumnIsEnabled = enable);
|
||||
|
||||
setAccountsGroupsColumnPeople = (enable) =>
|
||||
(this.peopleAccountsGroupsColumnIsEnabled = enable);
|
||||
setAccountsGroupsColumnManager = (enable) =>
|
||||
(this.managerAccountsGroupsColumnIsEnabled = enable);
|
||||
|
||||
@ -210,6 +213,7 @@ class TableStore {
|
||||
}
|
||||
|
||||
if (getIsAccountsGroups()) {
|
||||
this.setAccountsGroupsColumnPeople(splitColumns.includes("People"));
|
||||
this.setAccountsGroupsColumnManager(
|
||||
splitColumns.includes("Head of Group"),
|
||||
);
|
||||
@ -349,6 +353,12 @@ class TableStore {
|
||||
: this.setRoomColumnQuota(!this.roomQuotaColumnIsEnable);
|
||||
return;
|
||||
|
||||
case "People":
|
||||
this.setAccountsGroupsColumnPeople(
|
||||
!this.peopleAccountsGroupsColumnIsEnabled,
|
||||
);
|
||||
return;
|
||||
|
||||
case "Head of Group":
|
||||
this.setAccountsGroupsColumnManager(
|
||||
!this.managerAccountsGroupsColumnIsEnabled,
|
||||
|
@ -84,7 +84,10 @@ class ThirdPartyStore {
|
||||
oauthHref: storage.redirectUrl,
|
||||
category: storage.name,
|
||||
requiredConnectionUrl: storage.requiredConnectionUrl,
|
||||
clientId: storage.clientId,
|
||||
}));
|
||||
|
||||
return res;
|
||||
};
|
||||
|
||||
saveThirdParty = (
|
||||
|
@ -98,7 +98,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();
|
||||
|
@ -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",
|
||||
|
@ -110,6 +110,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"
|
||||
|
@ -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" /> -->
|
||||
|
@ -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;
|
||||
|
@ -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" && (
|
||||
|
@ -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 {
|
||||
|
@ -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"}`;
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
}, []);
|
||||
|
@ -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`
|
||||
|
@ -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),
|
||||
},
|
||||
}),
|
||||
|
72
packages/shared/components/room-icon/RoomIcon.styled.ts
Normal file
72
packages/shared/components/room-icon/RoomIcon.styled.ts
Normal 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 };
|
29
packages/shared/components/room-icon/RoomIcon.types.ts
Normal file
29
packages/shared/components/room-icon/RoomIcon.types.ts
Normal 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);
|
30
packages/shared/components/room-icon/RoomIcon.utils.ts
Normal file
30
packages/shared/components/room-icon/RoomIcon.utils.ts
Normal 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,
|
||||
);
|
@ -24,126 +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 } 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 { Text } from "../text";
|
||||
import { IconButton } from "../icon-button";
|
||||
|
||||
height: ${(props) => props.size};
|
||||
import { getRoomTitle } from "./RoomIcon.utils";
|
||||
import { StyledIcon } from "./RoomIcon.styled";
|
||||
|
||||
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 };
|
||||
|
||||
// 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,
|
||||
@ -160,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;
|
||||
|
@ -85,7 +85,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;
|
||||
|
30
packages/shared/components/table/Table.constants.ts
Normal file
30
packages/shared/components/table/Table.constants.ts
Normal 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;
|
@ -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);
|
||||
|
||||
|
@ -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<
|
||||
|
@ -29,7 +29,6 @@ import AvatarBaseReactSvgUrl from "PUBLIC_DIR/images/avatar.base.react.svg?url";
|
||||
import { globalColors } from "./globalColors";
|
||||
import { CommonTheme } from "./commonTheme";
|
||||
import { DEFAULT_FONT_FAMILY } from "../constants";
|
||||
import { color } from "storybook-static/sb-manager/chunk-INSKDKQB";
|
||||
|
||||
export type TColorScheme = {
|
||||
id: number;
|
||||
@ -92,6 +91,8 @@ const {
|
||||
darkRed,
|
||||
|
||||
lightErrorStatus,
|
||||
|
||||
blurLight,
|
||||
} = globalColors;
|
||||
|
||||
export const getBaseTheme = () => {
|
||||
@ -1337,7 +1338,7 @@ export const getBaseTheme = () => {
|
||||
},
|
||||
|
||||
backdrop: {
|
||||
backgroundColor: "rgba(6, 22, 38, 0.2)",
|
||||
backgroundColor: blurLight,
|
||||
unsetBackgroundColor: "unset",
|
||||
},
|
||||
|
||||
@ -2069,7 +2070,7 @@ export const getBaseTheme = () => {
|
||||
sectionHeaderToggleBgActive: grayLight,
|
||||
|
||||
backgroundColor: white,
|
||||
blurColor: "rgba(6, 22, 38, 0.2)",
|
||||
blurColor: blurLight,
|
||||
borderColor: grayLightMid,
|
||||
thumbnailBorderColor: grayLightMid,
|
||||
textColor: black,
|
||||
@ -2097,7 +2098,7 @@ export const getBaseTheme = () => {
|
||||
roleSelectorColor: "#a3a9ae",
|
||||
disabledRoleSelectorColor: "#a3a9ae",
|
||||
roleSelectorArrowColor: "#a3a9ae",
|
||||
createLink: "#a3a9ae",
|
||||
createLink: black,
|
||||
linkAccessComboboxExpired: "#a3a9ae",
|
||||
},
|
||||
|
||||
|
@ -65,6 +65,8 @@ const {
|
||||
darkErrorStatus,
|
||||
charlestonGreen,
|
||||
outerSpace,
|
||||
|
||||
blurDark,
|
||||
} = globalColors;
|
||||
|
||||
const Dark: TTheme = {
|
||||
@ -635,7 +637,7 @@ const Dark: TTheme = {
|
||||
r: 27,
|
||||
g: 27,
|
||||
b: 27,
|
||||
a: 0.4,
|
||||
a: 0.6,
|
||||
},
|
||||
blur: 9,
|
||||
},
|
||||
@ -1305,7 +1307,7 @@ const Dark: TTheme = {
|
||||
},
|
||||
|
||||
backdrop: {
|
||||
backgroundColor: "rgba(20, 20, 20, 0.8)",
|
||||
backgroundColor: blurDark,
|
||||
unsetBackgroundColor: "unset",
|
||||
},
|
||||
|
||||
@ -2041,7 +2043,7 @@ const Dark: TTheme = {
|
||||
sectionHeaderToggleBgActive: "#292929",
|
||||
|
||||
backgroundColor: black,
|
||||
blurColor: "rgba(20, 20, 20, 0.8)",
|
||||
blurColor: blurDark,
|
||||
borderColor: "#474747",
|
||||
thumbnailBorderColor: grayLightMid,
|
||||
textColor: white,
|
||||
|
@ -47,6 +47,9 @@ export const globalColors = {
|
||||
lightHover: "#F3F4F4",
|
||||
veryDarkGrey: "#3D3D3D",
|
||||
|
||||
blurLight: "rgba(6, 22, 38, 0.2)",
|
||||
blurDark: "rgba(27, 27, 27, 0.6)",
|
||||
|
||||
blueMain: "#2DA7DB",
|
||||
blueHover: "#3DB8EC",
|
||||
blueActive: "#1F97CA",
|
||||
|
@ -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() {
|
||||
|
@ -513,5 +513,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."
|
||||
}
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user