Merge branch 'develop' into bugfix/selectors
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "docspace",
|
||||
"version": "2.0.2",
|
||||
"version": "2.0.3",
|
||||
"private": true,
|
||||
"workspaces": {
|
||||
"packages": [
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@docspace/client",
|
||||
"version": "2.0.2",
|
||||
"version": "2.0.3",
|
||||
"private": true,
|
||||
"homepage": "",
|
||||
"scripts": {
|
||||
|
@ -1,38 +1,100 @@
|
||||
{
|
||||
"ActionButton": "Action button",
|
||||
"ActionButtonDescription": "You can disable the Action and + buttons in the current section header to limit creation of files, folders, and rooms.",
|
||||
"AddWatermarks": "Add watermarks to documents",
|
||||
"AdvancedDisplay": "Advanced display settings",
|
||||
"APILink": "API library",
|
||||
"Ascending": "Ascending",
|
||||
"AllTypes": "All types",
|
||||
"ButtonColor": "Button color",
|
||||
"ButtonCustomization": "Button customization",
|
||||
"ButtonText": "Button text",
|
||||
"CancelButtonText": "Cancel button text",
|
||||
"Code": "Code to insert",
|
||||
"CopyWindowCode": "Copy window embed code",
|
||||
"CreateSampleHeader": "Create sample DocSpace embed",
|
||||
"Chat": "Chat",
|
||||
"CSPDescription": "To safely embed DocSpace as an iframe in a website, add its URL to your allow list.",
|
||||
"CSPHeader": "Embed DocSpace as iframe",
|
||||
"CSPHelp": "This setting is a security mechanism that can be used to protect against content injection attacks. The CSP describes secure resource download sources. Downloading from resources not included in the `white list` is blocked. Specify the domains (together with the protocol) with which it will work.",
|
||||
"CSPInputPlaceholder": "Enter URL like this: https://example.com",
|
||||
"CustomizingDisplay": "Customizing the display",
|
||||
"DefaultColumnsOption": "Default (Quantity depends on screen width)",
|
||||
"DataDisplay": "Data display settings",
|
||||
"Descending": "Descending",
|
||||
"DisplayColumns": "Displaying columns in a file row",
|
||||
"EmbedCodeSuccessfullyCopied": "Embed code successfully copied to clipboard",
|
||||
"Editor": "Editor",
|
||||
"EditorDescription": "Allows you to open the SDK as a document editor for editing by specifying the id parameter for a file.",
|
||||
"EditorPresetDescription": "This mode allows you to open the SDK as a document editor for editing by specifying the id parameter for a file.",
|
||||
"EnterCount": "Enter count",
|
||||
"EnterHeight": "Enter height",
|
||||
"EnterId": "Enter id",
|
||||
"EnterPage": "Enter page number",
|
||||
"EnterWidth": "Enter width",
|
||||
"ElementItself": "The element itself",
|
||||
"ElementCalledAfterClicking": "The element will be called after clicking",
|
||||
"FeedbackAndSupport": "Feedback&Support",
|
||||
"Filter": "Search, Filter and Sort",
|
||||
"FileSelector": "File selector",
|
||||
"FileSelectorDescription": "Opens the file selector and allows you to select a file from a list of available files.",
|
||||
"FileSelectorPresetDescription": "Use this mode to display the file selector. It allows selecting a file from the list of the available ones.",
|
||||
"FileTypeDisplay": "File type display",
|
||||
"FrameId": "Frame id",
|
||||
"FileId": "File ID",
|
||||
"GetCode": "Get code to insert",
|
||||
"Header": "Header",
|
||||
"HeaderDescription": "You can disable header in the mobile version to limit access to the DocSpace sections (just like disabling the left menu in the desktop version).",
|
||||
"InterfaceElements": "Interface elements",
|
||||
"InitializeSDK": "Initialize the SDK in the following modes",
|
||||
"InLeftPanel": "in the left panel",
|
||||
"ItemsCount": "Items count on one page",
|
||||
"ItemsCountDescription": "You can specify the number of files / folders displayed on one page, as well as specify which page to start displaying",
|
||||
"JavascriptSdk": "Javascript SDK",
|
||||
"Manager": "Manager",
|
||||
"ManagerDescription": "Displays a list of entities depending on the specified rootPath. It allows you to create rooms, folders, and files and work with them.",
|
||||
"ManagerPresetDescription": "Use this mode to display a list of entities depending on the specified rootPath. It allows creating and working with rooms, folders and files.",
|
||||
"MainElementParameter": "Main element parameter",
|
||||
"Menu": "Left menu",
|
||||
"MenuDescription": "You can disable the left menu if users don't need to navigate to other sections.",
|
||||
"MobileOnly": "only mobile devices",
|
||||
"Page": "Display page (number)",
|
||||
"RoomDescription": "You can select the room you want to display",
|
||||
"RoomOrFolder": "Room or Folder",
|
||||
"RoomOrFolderDescription": "You can select the section, room or folder you want to display",
|
||||
"SDKDescription": "Using JavaScript SDK, you can embed a room or a folder from ONLYOFFICE DocSpace into your web interface as an iframe. Here, you can find settings for creating a sample iframe and configuring CSP. To use the complete SDK, please refer to the ",
|
||||
"RoomSelector": "Room selector",
|
||||
"RoomSelectorDescription": "Opens the room selector and allows you to select a room from a list of the available rooms.",
|
||||
"RoomSelectorPresetDescription": "Use this mode to display the room selector. It allows selecting a room from the list of the available ones.",
|
||||
"RoomTypeDisplay": "Room type display",
|
||||
"Rotate": "Rotate",
|
||||
"RightPanelCollapsed": "Right panel collapsed",
|
||||
"Scale": "Scale",
|
||||
"SDKDescription": "Using JavaScript SDK, you can embed one of the available ONLYOFFICE DocSpace modes into your web interface as an iframe (file manager, room or file selector, editor and viewer). Here, you can find settings for creating a sample iframe using modes and configuring CSP. To use the complete SDK, please refer to the ",
|
||||
"SearchBlock": "Search block",
|
||||
"ManagerSearchBlockDescription": "You can disable the search, filter and sort options.",
|
||||
"FilesSearchDescription": "File search within the opened folder/room.",
|
||||
"SearchTerm": "Search term",
|
||||
"SelectToDocSpace": "Select to DocSpace",
|
||||
"SelectImage": "Select image",
|
||||
"SettingUpColumns": "Setting up Columns",
|
||||
"SettingUpColumnsDescription": "You can disable the ability for users to manage and customize file information columns in list view.",
|
||||
"SetItUp": "Set it up",
|
||||
"SelectButtonText": "Select Button text",
|
||||
"SelectFile": "Select a file",
|
||||
"SelectRoom": "Select a room",
|
||||
"SelectTypes": "Select types",
|
||||
"SelectorPreview": "Selector preview",
|
||||
"SortOrder": "Sort order",
|
||||
"Title": "Navigate and Title"
|
||||
"SetUp": "SET UP",
|
||||
"SimpleRoom": "Simple Room",
|
||||
"SimpleRoomDescription": "Opens the room selector and allows you to select a room from a list of the available rooms.",
|
||||
"SimpleRoomPresetDescription": "Use this mode to display a list of entities depending on the specified rootPath. It allows creating and working with rooms, folders and files.",
|
||||
"Subtitle": "Subtitle",
|
||||
"SubtitleDescription": "Subtitle with additional comments or descriptions for the current directory.",
|
||||
"TabPlugins": "Tab Plugins",
|
||||
"Title": "Navigate and Title",
|
||||
"ManagerTitleDescription": "You can disable the title of the current section/room/folder.",
|
||||
"Viewer": "Viewer",
|
||||
"ViewerDescription": "Allows you to open the SDK as a document editor for viewing by specifying the id parameter for a file.",
|
||||
"ViewerPresetDescription": "Allows you to open the SDK as a document editor for viewing by specifying the id parameter for a file."
|
||||
}
|
||||
|
@ -134,6 +134,9 @@ const ArticleMainButtonContent = (props) => {
|
||||
isGracePeriod,
|
||||
setInviteUsersWarningDialogVisible,
|
||||
currentDeviceType,
|
||||
|
||||
isFrame,
|
||||
disableActionButton,
|
||||
} = props;
|
||||
|
||||
const navigate = useNavigate();
|
||||
@ -492,7 +495,9 @@ const ArticleMainButtonContent = (props) => {
|
||||
? t("Common:Invite")
|
||||
: t("Common:Actions");
|
||||
|
||||
const isDisabled = isSettingsPage
|
||||
const isDisabled = isFrame
|
||||
? disableActionButton
|
||||
: isSettingsPage
|
||||
? isSettingsPage
|
||||
: isAccountsPage
|
||||
? !isAccountsPage
|
||||
@ -638,6 +643,8 @@ export default inject(
|
||||
const { setOformFromFolderId, oformsFilter } = oformsStore;
|
||||
const { mainButtonItemsList } = pluginStore;
|
||||
|
||||
const { frameConfig, isFrame } = settingsStore
|
||||
|
||||
return {
|
||||
isGracePeriod,
|
||||
setInviteUsersWarningDialogVisible,
|
||||
@ -680,6 +687,9 @@ export default inject(
|
||||
versionHistoryPanelVisible,
|
||||
security,
|
||||
currentDeviceType,
|
||||
|
||||
isFrame,
|
||||
disableActionButton: frameConfig?.disableActionButton,
|
||||
};
|
||||
}
|
||||
)(
|
||||
|
@ -130,7 +130,7 @@ const Badges = ({
|
||||
const iconForm =
|
||||
sizeBadge === "medium" ? FormFillRectSvgUrl : AccessEditFormReactSvgUrl;
|
||||
|
||||
const iconEdit = !isForm ? FileActionsConvertEditDocReactSvgUrl : iconForm;
|
||||
const iconEdit = !isPdf ? FileActionsConvertEditDocReactSvgUrl : iconForm;
|
||||
|
||||
const iconRefresh = desktopView ? Refresh12ReactSvgUrl : RefreshReactSvgUrl;
|
||||
|
||||
@ -206,7 +206,7 @@ const Badges = ({
|
||||
/>
|
||||
</BadgeWrapper>
|
||||
)}
|
||||
{isEditing && !isVisitor && !isPdf && !(isRecentTab && !canEditing) && (
|
||||
{isEditing && !isVisitor && !(isRecentTab && !canEditing) && (
|
||||
<ColorTheme
|
||||
themeId={ThemeId.IconButton}
|
||||
isEditing={isEditing}
|
||||
@ -215,7 +215,7 @@ const Badges = ({
|
||||
size={sizeBadge}
|
||||
onClick={onFilesClick}
|
||||
hoverColor={theme.filesBadges.hoverIconColor}
|
||||
title={isForm ? t("Common:FillFormButton") : t("Common:EditButton")}
|
||||
title={isPdf ? t("Common:FillFormButton") : t("Common:EditButton")}
|
||||
/>
|
||||
)}
|
||||
{item.viewAccessibility?.MustConvert &&
|
||||
|
@ -20,6 +20,10 @@ export type FilesSelectorProps = {
|
||||
onClose?: () => void;
|
||||
|
||||
id?: string | number;
|
||||
withSearch: boolean;
|
||||
withBreadCrumbs: boolean;
|
||||
withSubtitle: boolean;
|
||||
|
||||
isMove?: boolean;
|
||||
isCopy?: boolean;
|
||||
isRestore: boolean;
|
||||
@ -104,6 +108,8 @@ export type FilesSelectorProps = {
|
||||
embedded: boolean;
|
||||
withHeader: boolean;
|
||||
withCancelButton: boolean;
|
||||
cancelButtonLabel: string;
|
||||
acceptButtonLabel: string;
|
||||
settings: unknown;
|
||||
|
||||
roomsFolderId?: number;
|
||||
|
@ -41,6 +41,10 @@ const FilesSelectorWrapper = ({
|
||||
|
||||
onClose,
|
||||
|
||||
withSearch = true,
|
||||
withBreadCrumbs = true,
|
||||
withSubtitle = true,
|
||||
|
||||
isMove,
|
||||
isCopy,
|
||||
isRestore,
|
||||
@ -96,6 +100,8 @@ const FilesSelectorWrapper = ({
|
||||
embedded,
|
||||
withHeader = true,
|
||||
withCancelButton = true,
|
||||
cancelButtonLabel,
|
||||
acceptButtonLabel,
|
||||
getIcon,
|
||||
isRoomBackup,
|
||||
|
||||
@ -243,7 +249,7 @@ const FilesSelectorWrapper = ({
|
||||
isRestore,
|
||||
);
|
||||
|
||||
const acceptButtonLabel = getAcceptButtonLabel(
|
||||
const defaultAcceptButtonLabel = getAcceptButtonLabel(
|
||||
t,
|
||||
isEditorDialog,
|
||||
isCopy,
|
||||
@ -309,7 +315,7 @@ const FilesSelectorWrapper = ({
|
||||
getIsDisabled={getIsDisabledAction}
|
||||
withHeader={withHeader}
|
||||
headerLabel={headerLabel}
|
||||
submitButtonLabel={acceptButtonLabel}
|
||||
submitButtonLabel={acceptButtonLabel || defaultAcceptButtonLabel}
|
||||
withCancelButton={withCancelButton}
|
||||
isPanelVisible={isPanelVisible}
|
||||
embedded={embedded}
|
||||
@ -318,8 +324,12 @@ const FilesSelectorWrapper = ({
|
||||
footerInputHeader={footerInputHeader || ""}
|
||||
currentFooterInputValue={currentFooterInputValue || ""}
|
||||
footerCheckboxLabel={footerCheckboxLabel || ""}
|
||||
withoutBackButton
|
||||
cancelButtonLabel={cancelButtonLabel}
|
||||
withBreadCrumbs={withBreadCrumbs}
|
||||
withSearch={withSearch}
|
||||
descriptionText={
|
||||
!filterParam || filterParam === "ALL"
|
||||
!withSubtitle || !filterParam || filterParam === "ALL"
|
||||
? ""
|
||||
: descriptionText ?? t("Common:SelectDOCXFormat")
|
||||
}
|
||||
@ -362,6 +372,7 @@ export default inject(
|
||||
isRestore,
|
||||
isPanelVisible,
|
||||
id,
|
||||
currentFolderId,
|
||||
}: FilesSelectorProps,
|
||||
) => {
|
||||
const { id: selectedId, parentId, rootFolderType } = selectedFolderStore;
|
||||
@ -370,8 +381,6 @@ export default inject(
|
||||
filesActionsStore;
|
||||
const { itemOperationToFolder, clearActiveOperations } = uploadDataStore;
|
||||
|
||||
const sessionPath = window.sessionStorage.getItem("filesSelectorPath");
|
||||
|
||||
const { treeFolders, roomsFolderId } = treeFoldersStore;
|
||||
|
||||
const {
|
||||
@ -419,6 +428,8 @@ export default inject(
|
||||
: []
|
||||
: [];
|
||||
|
||||
const sessionPath = window.sessionStorage.getItem("filesSelectorPath");
|
||||
|
||||
const selectionsWithoutEditing = isRestoreAll
|
||||
? filesList
|
||||
: isCopy
|
||||
@ -445,13 +456,13 @@ export default inject(
|
||||
? parentId
|
||||
: selectedId);
|
||||
|
||||
const currentFolderId =
|
||||
sessionPath && (isMove || isCopy || isRestore || isRestoreAll)
|
||||
const folderId =
|
||||
currentFolderId ||
|
||||
(sessionPath && (isMove || isCopy || isRestore || isRestoreAll)
|
||||
? +sessionPath
|
||||
: fromFolderId;
|
||||
: fromFolderId);
|
||||
|
||||
return {
|
||||
currentFolderId,
|
||||
fromFolderId,
|
||||
parentId,
|
||||
rootFolderType,
|
||||
@ -487,6 +498,7 @@ export default inject(
|
||||
getIcon,
|
||||
|
||||
roomsFolderId,
|
||||
currentFolderId: folderId,
|
||||
};
|
||||
},
|
||||
)(observer(FilesSelectorWrapper));
|
||||
|
@ -20,6 +20,21 @@ const StyledBadgesContainer = styled.div`
|
||||
display: flex;
|
||||
|
||||
align-items: center;
|
||||
|
||||
${(props) =>
|
||||
props.infoPanelVisible &&
|
||||
css`
|
||||
.accounts-badge:last-child {
|
||||
${(props) =>
|
||||
props.theme.interfaceDirection === "rtl"
|
||||
? css`
|
||||
margin-left: 12px;
|
||||
`
|
||||
: css`
|
||||
margin-right: 12px;
|
||||
`}
|
||||
}
|
||||
`}
|
||||
`;
|
||||
|
||||
const StyledPaidBadge = styled(Badge)`
|
||||
@ -52,7 +67,7 @@ const Badges = ({
|
||||
withoutPaid,
|
||||
isPaid = false,
|
||||
filter,
|
||||
|
||||
infoPanelVisible,
|
||||
isSSO = false,
|
||||
}) => {
|
||||
const navigate = useNavigate();
|
||||
@ -74,9 +89,13 @@ const Badges = ({
|
||||
};
|
||||
|
||||
return (
|
||||
<StyledBadgesContainer className="badges additional-badges">
|
||||
<StyledBadgesContainer
|
||||
className="badges additional-badges"
|
||||
infoPanelVisible={infoPanelVisible}
|
||||
>
|
||||
{isSSO && (
|
||||
<Badge
|
||||
className="accounts-badge"
|
||||
label={SSO_LABEL}
|
||||
color={"#FFFFFF"}
|
||||
backgroundColor="#22C386"
|
||||
@ -89,7 +108,7 @@ const Badges = ({
|
||||
)}
|
||||
{!withoutPaid && isPaid && (
|
||||
<StyledPaidBadge
|
||||
className="paid-badge"
|
||||
className="paid-badge accounts-badge"
|
||||
label={t("Paid")}
|
||||
backgroundColor={"#EDC409"}
|
||||
fontSize={"9px"}
|
||||
@ -101,10 +120,16 @@ const Badges = ({
|
||||
/>
|
||||
)}
|
||||
{statusType === "pending" && (
|
||||
<StyledSendClockIcon className="pending-badge" size="small" />
|
||||
<StyledSendClockIcon
|
||||
className="pending-badge accounts-badge"
|
||||
size="small"
|
||||
/>
|
||||
)}
|
||||
{statusType === "disabled" && (
|
||||
<StyledCatalogSpamIcon className="disabled-badge" size="small" />
|
||||
<StyledCatalogSpamIcon
|
||||
className="disabled-badge accounts-badge"
|
||||
size="small"
|
||||
/>
|
||||
)}
|
||||
</StyledBadgesContainer>
|
||||
);
|
||||
|
@ -123,6 +123,8 @@ const Table = ({
|
||||
canChangeUserType,
|
||||
isFiltered,
|
||||
currentDeviceType,
|
||||
typeAccountsColumnIsEnabled,
|
||||
emailAccountsColumnIsEnabled,
|
||||
}) => {
|
||||
const ref = useRef(null);
|
||||
const [hideColumns, setHideColumns] = React.useState(false);
|
||||
@ -173,6 +175,9 @@ const Table = ({
|
||||
canChangeUserType={canChangeUserType}
|
||||
hideColumns={hideColumns}
|
||||
itemIndex={index}
|
||||
typeAccountsColumnIsEnabled={typeAccountsColumnIsEnabled}
|
||||
emailAccountsColumnIsEnabled={emailAccountsColumnIsEnabled}
|
||||
infoPanelVisible={infoPanelVisible}
|
||||
/>
|
||||
))}
|
||||
</TableBody>
|
||||
@ -189,6 +194,7 @@ export default inject(
|
||||
accessRightsStore,
|
||||
infoPanelStore,
|
||||
userStore,
|
||||
tableStore,
|
||||
}) => {
|
||||
const {
|
||||
usersStore,
|
||||
@ -205,6 +211,8 @@ export default inject(
|
||||
const { isAdmin, isOwner, id: userId } = userStore.user;
|
||||
|
||||
const { canChangeUserType } = accessRightsStore;
|
||||
const { typeAccountsColumnIsEnabled, emailAccountsColumnIsEnabled } =
|
||||
tableStore;
|
||||
|
||||
return {
|
||||
peopleList,
|
||||
@ -224,6 +232,8 @@ export default inject(
|
||||
canChangeUserType,
|
||||
isFiltered,
|
||||
currentDeviceType,
|
||||
typeAccountsColumnIsEnabled,
|
||||
emailAccountsColumnIsEnabled,
|
||||
};
|
||||
}
|
||||
},
|
||||
)(observer(Table));
|
||||
|
@ -28,7 +28,7 @@ class PeopleTableHeader extends React.Component {
|
||||
{
|
||||
key: "Type",
|
||||
title: t("Common:Type"),
|
||||
enable: true,
|
||||
enable: props.typeAccountsColumnIsEnabled,
|
||||
sortBy: "type",
|
||||
resizable: true,
|
||||
onChange: this.onColumnChange,
|
||||
@ -44,7 +44,7 @@ class PeopleTableHeader extends React.Component {
|
||||
{
|
||||
key: "Mail",
|
||||
title: t("Common:Email"),
|
||||
enable: true,
|
||||
enable: props.emailAccountsColumnIsEnabled,
|
||||
resizable: true,
|
||||
sortBy: "email",
|
||||
onChange: this.onColumnChange,
|
||||
@ -52,38 +52,19 @@ class PeopleTableHeader extends React.Component {
|
||||
},
|
||||
];
|
||||
|
||||
const columns = this.getColumns(defaultColumns);
|
||||
const columns = props.getColumns(defaultColumns);
|
||||
|
||||
this.state = { columns };
|
||||
}
|
||||
|
||||
getColumns = (defaultColumns) => {
|
||||
const storageColumns = localStorage.getItem(
|
||||
`${TABLE_COLUMNS}=${this.props.userId}`
|
||||
);
|
||||
const columns = [];
|
||||
|
||||
if (storageColumns) {
|
||||
const splitColumns = storageColumns.split(",");
|
||||
|
||||
for (let col of defaultColumns) {
|
||||
const column = splitColumns.find((key) => key === col.key);
|
||||
column ? (col.enable = true) : (col.enable = false);
|
||||
|
||||
columns.push(col);
|
||||
}
|
||||
return columns;
|
||||
} else {
|
||||
return defaultColumns;
|
||||
}
|
||||
};
|
||||
|
||||
onColumnChange = (key, e) => {
|
||||
const { columns } = this.state;
|
||||
const columnIndex = columns.findIndex((c) => c.key === key);
|
||||
|
||||
if (columnIndex === -1) return;
|
||||
|
||||
this.props.setColumnEnable(key);
|
||||
|
||||
columns[columnIndex].enable = !columns[columnIndex].enable;
|
||||
this.setState({ columns });
|
||||
|
||||
@ -179,6 +160,7 @@ export default inject(
|
||||
infoPanelStore,
|
||||
clientLoadingStore,
|
||||
userStore,
|
||||
tableStore
|
||||
}) => {
|
||||
const { filterStore } = peopleStore;
|
||||
|
||||
@ -186,14 +168,25 @@ export default inject(
|
||||
|
||||
const { isVisible: infoPanelVisible } = infoPanelStore;
|
||||
const { withPaging } = settingsStore;
|
||||
|
||||
const {
|
||||
getColumns,
|
||||
setColumnEnable,
|
||||
typeAccountsColumnIsEnabled,
|
||||
emailAccountsColumnIsEnabled,
|
||||
} = tableStore;
|
||||
|
||||
return {
|
||||
filter,
|
||||
|
||||
setIsLoading: clientLoadingStore.setIsSectionBodyLoading,
|
||||
userId: userStore.user?.id,
|
||||
infoPanelVisible,
|
||||
withPaging,
|
||||
getColumns,
|
||||
setColumnEnable,
|
||||
typeAccountsColumnIsEnabled,
|
||||
emailAccountsColumnIsEnabled,
|
||||
|
||||
};
|
||||
}
|
||||
)(
|
||||
|
@ -230,6 +230,9 @@ const PeopleTableRow = (props) => {
|
||||
hideColumns,
|
||||
value,
|
||||
standalone,
|
||||
typeAccountsColumnIsEnabled,
|
||||
emailAccountsColumnIsEnabled,
|
||||
infoPanelVisible,
|
||||
} = props;
|
||||
|
||||
const {
|
||||
@ -452,10 +455,19 @@ const PeopleTableRow = (props) => {
|
||||
? displayName
|
||||
: email}
|
||||
</Link>
|
||||
<Badges statusType={statusType} isPaid={isPaidUser} isSSO={isSSO} />
|
||||
<Badges
|
||||
statusType={statusType}
|
||||
isPaid={isPaidUser}
|
||||
isSSO={isSSO}
|
||||
infoPanelVisible={infoPanelVisible}
|
||||
/>
|
||||
</TableCell>
|
||||
|
||||
<TableCell className={"table-cell_type"}>{typeCell}</TableCell>
|
||||
{typeAccountsColumnIsEnabled ? (
|
||||
<TableCell className={"table-cell_type"}>{typeCell}</TableCell>
|
||||
) : (
|
||||
<div />
|
||||
)}
|
||||
|
||||
{/* <TableCell className="table-cell_room">
|
||||
{!rooms?.length ? (
|
||||
@ -498,20 +510,24 @@ const PeopleTableRow = (props) => {
|
||||
)}
|
||||
</TableCell> */}
|
||||
|
||||
<TableCell>
|
||||
<Link
|
||||
type="page"
|
||||
title={email}
|
||||
fontSize="13px"
|
||||
fontWeight={600}
|
||||
color={sideInfoColor}
|
||||
onClick={onEmailClick}
|
||||
isTextOverflow
|
||||
enableUserSelect
|
||||
>
|
||||
{email}
|
||||
</Link>
|
||||
</TableCell>
|
||||
{emailAccountsColumnIsEnabled ? (
|
||||
<TableCell>
|
||||
<Link
|
||||
type="page"
|
||||
title={email}
|
||||
fontSize="13px"
|
||||
fontWeight={600}
|
||||
color={sideInfoColor}
|
||||
onClick={onEmailClick}
|
||||
isTextOverflow
|
||||
enableUserSelect
|
||||
>
|
||||
{email}
|
||||
</Link>
|
||||
</TableCell>
|
||||
) : (
|
||||
<div />
|
||||
)}
|
||||
</StyledPeopleRow>
|
||||
</StyledWrapper>
|
||||
);
|
||||
|
@ -422,6 +422,7 @@ class FilesTableHeader extends React.Component {
|
||||
tagRef,
|
||||
setHideColumns,
|
||||
isFrame,
|
||||
showSettings,
|
||||
} = this.props;
|
||||
|
||||
const {
|
||||
@ -452,7 +453,7 @@ class FilesTableHeader extends React.Component {
|
||||
tagRef={tagRef}
|
||||
setHideColumns={setHideColumns}
|
||||
settingsTitle={t("Files:TableSettingsTitle")}
|
||||
showSettings={!isFrame}
|
||||
showSettings={isFrame ? showSettings : true}
|
||||
/>
|
||||
);
|
||||
}
|
||||
@ -573,6 +574,7 @@ export default inject(
|
||||
|
||||
isFrame,
|
||||
frameTableColumns: frameConfig?.viewTableColumns,
|
||||
showSettings: frameConfig?.showSettings,
|
||||
};
|
||||
}
|
||||
)(
|
||||
|
@ -247,6 +247,8 @@ const SectionHeaderContent = (props) => {
|
||||
moveToPublicRoom,
|
||||
currentDeviceType,
|
||||
isFrame,
|
||||
showTitle,
|
||||
hideInfoPanel,
|
||||
onClickArchive,
|
||||
setLeaveRoomDialogVisible,
|
||||
inRoom,
|
||||
@ -1126,7 +1128,7 @@ const SectionHeaderContent = (props) => {
|
||||
onPlusClick={onCreateRoom}
|
||||
isEmptyPage={isEmptyPage}
|
||||
isRoom={isCurrentRoom || isAccountsPage}
|
||||
hideInfoPanel={isSettingsPage || isPublicRoom}
|
||||
hideInfoPanel={hideInfoPanel || isSettingsPage || isPublicRoom}
|
||||
withLogo={isPublicRoom && logo}
|
||||
burgerLogo={isPublicRoom && burgerLogo}
|
||||
isPublicRoom={isPublicRoom}
|
||||
@ -1136,6 +1138,7 @@ const SectionHeaderContent = (props) => {
|
||||
showRootFolderTitle={insideTheRoom}
|
||||
currentDeviceType={currentDeviceType}
|
||||
isFrame={isFrame}
|
||||
showTitle={isFrame ? showTitle : true}
|
||||
navigationButtonLabel={navigationButtonLabel}
|
||||
onNavigationButtonClick={onNavigationButtonClick}
|
||||
tariffBar={<TariffBar />}
|
||||
@ -1271,6 +1274,7 @@ export default inject(
|
||||
enablePlugins,
|
||||
theme,
|
||||
whiteLabelLogoUrls,
|
||||
frameConfig,
|
||||
isFrame,
|
||||
currentDeviceType,
|
||||
} = settingsStore;
|
||||
@ -1324,9 +1328,10 @@ export default inject(
|
||||
folderPath = navigationPath.filter((item) => !item.isRootRoom);
|
||||
}
|
||||
|
||||
const isRoot = isFrame
|
||||
? pathParts?.length === 1 || pathParts?.length === 2
|
||||
: pathParts?.length === 1;
|
||||
const isRoot =
|
||||
isFrame && frameConfig?.id
|
||||
? pathParts?.length === 1 || pathParts?.length === 2
|
||||
: pathParts?.length === 1;
|
||||
|
||||
const haveLinksRight =
|
||||
access === ShareAccessRights.RoomManager ||
|
||||
@ -1456,6 +1461,8 @@ export default inject(
|
||||
theme,
|
||||
whiteLabelLogoUrls,
|
||||
isFrame,
|
||||
showTitle: frameConfig?.showTitle,
|
||||
hideInfoPanel: isFrame && !frameConfig?.infoPanelVisible,
|
||||
currentDeviceType,
|
||||
setLeaveRoomDialogVisible,
|
||||
inRoom,
|
||||
|
@ -293,11 +293,7 @@ const PureHome = (props) => {
|
||||
<SectionWrapper {...sectionProps}>
|
||||
{(!isErrorRoomNotAvailable || isAccountsPage || isSettingsPage) && (
|
||||
<Section.SectionHeader>
|
||||
{isFrame ? (
|
||||
showTitle && <SectionHeaderContent />
|
||||
) : (
|
||||
<SectionHeaderContent />
|
||||
)}
|
||||
<SectionHeaderContent />
|
||||
</Section.SectionHeader>
|
||||
)}
|
||||
|
||||
|
@ -320,6 +320,6 @@ export default inject(
|
||||
}
|
||||
)(
|
||||
withLoading(
|
||||
withTranslation(["Settings", "Common"])(observer(ArticleBodyContent))
|
||||
withTranslation(["Settings", "Common", "JavascriptSdk"])(observer(ArticleBodyContent))
|
||||
)
|
||||
);
|
||||
|
@ -66,6 +66,14 @@ const CompanyInfoSettings = (props) => {
|
||||
const navigate = useNavigate();
|
||||
const location = useLocation();
|
||||
|
||||
const defaultCompanySettingsData = {
|
||||
address: companyInfoSettingsData.address,
|
||||
companyName: companyInfoSettingsData.companyName,
|
||||
email: companyInfoSettingsData.email,
|
||||
phone: companyInfoSettingsData.phone,
|
||||
site: companyInfoSettingsData.site,
|
||||
};
|
||||
|
||||
const defaultCompanySettingsError = {
|
||||
hasErrorAddress: false,
|
||||
hasErrorCompanyName: false,
|
||||
@ -74,9 +82,11 @@ const CompanyInfoSettings = (props) => {
|
||||
hasErrorSite: false,
|
||||
};
|
||||
|
||||
const [companySettings, setCompanySettings] = useState({});
|
||||
const [companySettings, setCompanySettings] = useState(
|
||||
defaultCompanySettingsData,
|
||||
);
|
||||
const [companySettingsError, setCompanySettingsError] = useState(
|
||||
defaultCompanySettingsError
|
||||
defaultCompanySettingsError,
|
||||
);
|
||||
const [showReminder, setShowReminder] = useState(false);
|
||||
const [isLoading, setIsLoading] = useState(false);
|
||||
@ -114,18 +124,11 @@ const CompanyInfoSettings = (props) => {
|
||||
setIsLoadedCompanyInfoSettingsData(true);
|
||||
}, [companyInfoSettingsData, tReady]);
|
||||
|
||||
const getSettings = () => {
|
||||
const getSettings = async () => {
|
||||
await getCompanyInfoSettings();
|
||||
const companySettings = getFromSessionStorage("companySettings");
|
||||
|
||||
const defaultData = {
|
||||
address: companyInfoSettingsData?.address,
|
||||
companyName: companyInfoSettingsData?.companyName,
|
||||
email: companyInfoSettingsData?.email,
|
||||
phone: companyInfoSettingsData?.phone,
|
||||
site: companyInfoSettingsData?.site,
|
||||
};
|
||||
|
||||
saveToSessionStorage("defaultCompanySettings", defaultData);
|
||||
saveToSessionStorage("defaultCompanySettings", defaultCompanySettingsData);
|
||||
|
||||
if (companySettings) {
|
||||
setCompanySettings({
|
||||
@ -136,7 +139,7 @@ const CompanyInfoSettings = (props) => {
|
||||
site: companySettings?.site,
|
||||
});
|
||||
} else {
|
||||
setCompanySettings(defaultData);
|
||||
setCompanySettings(defaultCompanySettingsData);
|
||||
}
|
||||
};
|
||||
|
||||
@ -146,7 +149,7 @@ const CompanyInfoSettings = (props) => {
|
||||
|
||||
useEffect(() => {
|
||||
const defaultCompanySettings = getFromSessionStorage(
|
||||
"defaultCompanySettings"
|
||||
"defaultCompanySettings",
|
||||
);
|
||||
|
||||
const newSettings = {
|
||||
@ -182,7 +185,7 @@ const CompanyInfoSettings = (props) => {
|
||||
|
||||
const validateEmpty = (value, type) => {
|
||||
const hasError = value.trim() === "";
|
||||
const phoneRegex = /^[\d\(\)\-+]+$/;
|
||||
const phoneRegex = /^[\d\(\)\-\s+]+$/;
|
||||
const hasErrorPhone = !phoneRegex.test(value);
|
||||
|
||||
if (type === "companyName") {
|
||||
@ -318,6 +321,13 @@ const CompanyInfoSettings = (props) => {
|
||||
setShowModal(false);
|
||||
};
|
||||
|
||||
const isDisabled =
|
||||
hasErrorAddress ||
|
||||
hasErrorCompanyName ||
|
||||
hasErrorEmail ||
|
||||
hasErrorPhone ||
|
||||
hasErrorSite;
|
||||
|
||||
if (!isLoadedCompanyInfoSettingsData) return <LoaderCompanyInfoSettings />;
|
||||
|
||||
return (
|
||||
@ -327,7 +337,7 @@ const CompanyInfoSettings = (props) => {
|
||||
onClose={onCloseModal}
|
||||
buildVersionInfo={buildVersionInfo}
|
||||
personal={personal}
|
||||
previewData={companySettings}
|
||||
previewData={defaultCompanySettingsData}
|
||||
/>
|
||||
|
||||
<StyledComponent isSettingPaid={isSettingPaid}>
|
||||
@ -444,6 +454,7 @@ const CompanyInfoSettings = (props) => {
|
||||
cancelButtonLabel={t("Common:Restore")}
|
||||
reminderText={t("YouHaveUnsavedChanges")}
|
||||
displaySettings={true}
|
||||
saveButtonDisabled={isDisabled}
|
||||
hasScroll={true}
|
||||
hideBorder={true}
|
||||
showReminder={(isSettingPaid && showReminder) || isLoading}
|
||||
@ -488,6 +499,6 @@ export default inject(({ settingsStore, common, currentQuotaStore }) => {
|
||||
};
|
||||
})(
|
||||
withLoading(
|
||||
withTranslation(["Settings", "Common"])(observer(CompanyInfoSettings))
|
||||
)
|
||||
withTranslation(["Settings", "Common"])(observer(CompanyInfoSettings)),
|
||||
),
|
||||
);
|
||||
|
@ -16,7 +16,7 @@ import MobileView from "./Branding/MobileView";
|
||||
|
||||
import { UnavailableStyles } from "../../utils/commonSettingsStyles";
|
||||
import { resetSessionStorage } from "../../utils";
|
||||
import { useIsMobileView } from "../../utils/useIsMobileView";
|
||||
import { DeviceType } from "@docspace/shared/enums";
|
||||
|
||||
const StyledComponent = styled.div`
|
||||
max-width: 700px;
|
||||
@ -60,8 +60,9 @@ const Branding = ({
|
||||
isLoadedCompanyInfoSettingsData,
|
||||
isSettingPaid,
|
||||
standalone,
|
||||
currentDeviceType
|
||||
}) => {
|
||||
const isMobileView = useIsMobileView();
|
||||
const isMobileView = currentDeviceType === DeviceType.mobile;
|
||||
|
||||
useEffect(() => {
|
||||
setDocumentTitle(t("Branding"));
|
||||
@ -104,11 +105,12 @@ const Branding = ({
|
||||
export default inject(({ settingsStore, currentQuotaStore, common }) => {
|
||||
const { isBrandingAndCustomizationAvailable } = currentQuotaStore;
|
||||
const { isLoadedCompanyInfoSettingsData } = common;
|
||||
const { standalone } = settingsStore;
|
||||
const { standalone, currentDeviceType } = settingsStore;
|
||||
|
||||
return {
|
||||
isLoadedCompanyInfoSettingsData,
|
||||
isSettingPaid: isBrandingAndCustomizationAvailable,
|
||||
standalone,
|
||||
currentDeviceType
|
||||
};
|
||||
})(withLoading(withTranslation(["Settings", "Common"])(observer(Branding))));
|
||||
|
@ -49,7 +49,7 @@ const PortalDeletion = (props) => {
|
||||
try {
|
||||
await sendDeletePortalEmail();
|
||||
toastr.success(
|
||||
t("PortalDeletionEmailSended", { ownerEmail: owner.email })
|
||||
t("PortalDeletionEmailSended", { ownerEmail: owner.email }),
|
||||
);
|
||||
} catch (error) {
|
||||
toastr.error(error);
|
||||
@ -62,7 +62,7 @@ const PortalDeletion = (props) => {
|
||||
};
|
||||
|
||||
const notActivatedEmail =
|
||||
owner.activationStatus === EmployeeActivationStatus.NotActivated;
|
||||
owner?.activationStatus === EmployeeActivationStatus.NotActivated;
|
||||
|
||||
return (
|
||||
<MainContainer>
|
||||
@ -115,5 +115,5 @@ export default inject(({ settingsStore, userStore }) => {
|
||||
sendActivationLink,
|
||||
};
|
||||
})(
|
||||
withTranslation(["Settings", "MainBar", "People", "Common"])(PortalDeletion)
|
||||
withTranslation(["Settings", "MainBar", "People", "Common"])(PortalDeletion),
|
||||
);
|
||||
|
@ -1,29 +1,32 @@
|
||||
import { useState, useEffect } from "react";
|
||||
import React from "react";
|
||||
import { withTranslation } from "react-i18next";
|
||||
import debounce from "lodash.debounce";
|
||||
import styled, { css } from "styled-components";
|
||||
import { Box } from "@docspace/shared/components/box";
|
||||
import { TextInput } from "@docspace/shared/components/text-input";
|
||||
import { Textarea } from "@docspace/shared/components/textarea";
|
||||
import { Label } from "@docspace/shared/components/label";
|
||||
import { Text } from "@docspace/shared/components/text";
|
||||
import { Checkbox } from "@docspace/shared/components/checkbox";
|
||||
import { ComboBox } from "@docspace/shared/components/combobox";
|
||||
import { TabsContainer } from "@docspace/shared/components/tabs-container";
|
||||
import FilesSelectorInput from "SRC_DIR/components/FilesSelectorInput";
|
||||
import { mobile, tablet } from "@docspace/shared/utils";
|
||||
import { objectToGetParams, loadScript } from "@docspace/shared/utils/common";
|
||||
import { useNavigate } from "react-router-dom";
|
||||
import { RoomsType } from "@docspace/shared/constants";
|
||||
import { inject, observer } from "mobx-react";
|
||||
|
||||
import { mobile, tablet } from "@docspace/shared/utils/device";
|
||||
import { isMobile } from "react-device-detect";
|
||||
|
||||
import { HelpButton } from "@docspace/shared/components/help-button";
|
||||
import { Box } from "@docspace/shared/components/box";
|
||||
import { Link } from "@docspace/shared/components/link";
|
||||
import { Text } from "@docspace/shared/components/text";
|
||||
|
||||
import GetCodeDialog from "./sub-components/GetCodeDialog";
|
||||
import CSP from "./sub-components/csp";
|
||||
import { Button } from "@docspace/shared/components/button";
|
||||
import PresetTile from "./sub-components/PresetTile";
|
||||
|
||||
const showPreviewThreshold = 720;
|
||||
import SimpleRoomImg from "PUBLIC_DIR/images/sdk-presets_simple-room.react.svg?url";
|
||||
import ManagerImg from "PUBLIC_DIR/images/sdk-presets_manager.react.svg?url";
|
||||
import RoomSelectorImg from "PUBLIC_DIR/images/sdk-presets_room-selector.react.svg?url";
|
||||
import FileSelectorImg from "PUBLIC_DIR/images/sdk-presets_file-selector.react.svg?url";
|
||||
import EditorImg from "PUBLIC_DIR/images/sdk-presets_editor.react.svg?url";
|
||||
import ViewerImg from "PUBLIC_DIR/images/sdk-presets_viewer.react.svg?url";
|
||||
import SimpleRoomImgDark from "PUBLIC_DIR/images/sdk-presets_simple-room_dark.react.svg?url";
|
||||
import ManagerImgDark from "PUBLIC_DIR/images/sdk-presets_manager_dark.react.svg?url";
|
||||
import RoomSelectorImgDark from "PUBLIC_DIR/images/sdk-presets_room-selector_dark.react.svg?url";
|
||||
import FileSelectorImgDark from "PUBLIC_DIR/images/sdk-presets_file-selector_dark.react.svg?url";
|
||||
import EditorImgDark from "PUBLIC_DIR/images/sdk-presets_editor_dark.react.svg?url";
|
||||
import ViewerImgDark from "PUBLIC_DIR/images/sdk-presets_viewer_dark.react.svg?url";
|
||||
|
||||
const SDKContainer = styled(Box)`
|
||||
@media ${tablet} {
|
||||
@ -36,35 +39,9 @@ const SDKContainer = styled(Box)`
|
||||
`}
|
||||
`;
|
||||
|
||||
const Controls = styled(Box)`
|
||||
max-width: 350px;
|
||||
min-width: 350px;
|
||||
width: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 16px;
|
||||
|
||||
@media ${tablet} {
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
${isMobile &&
|
||||
css`
|
||||
min-width: 0;
|
||||
`}
|
||||
|
||||
.label {
|
||||
min-width: fit-content;
|
||||
}
|
||||
|
||||
.checkbox {
|
||||
max-width: fit-content;
|
||||
}
|
||||
`;
|
||||
|
||||
const CategoryHeader = styled.div`
|
||||
margin-top: 40px;
|
||||
margin-bottom: 24px;
|
||||
margin-bottom: 16px;
|
||||
font-size: ${(props) => props.theme.getCorrectFontSize("16px")};
|
||||
font-style: normal;
|
||||
font-weight: 700;
|
||||
@ -80,448 +57,81 @@ const CategoryHeader = styled.div`
|
||||
`}
|
||||
`;
|
||||
|
||||
const CategorySubHeader = styled.div`
|
||||
margin-top: 8px;
|
||||
margin-bottom: 8px;
|
||||
font-size: ${(props) => props.theme.getCorrectFontSize("15px")};
|
||||
font-style: normal;
|
||||
font-weight: 600;
|
||||
line-height: 16px;
|
||||
|
||||
@media ${tablet} {
|
||||
&:not(&.copy-window-code) {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
}
|
||||
|
||||
${isMobile &&
|
||||
css`
|
||||
&:not(&.copy-window-code) {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
`}
|
||||
|
||||
@media ${mobile} {
|
||||
&:first-of-type {
|
||||
margin-top: 0;
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
const CategoryDescription = styled(Box)`
|
||||
margin-top: 5px;
|
||||
margin-top: 2px;
|
||||
max-width: 700px;
|
||||
.sdk-description {
|
||||
display: inline;
|
||||
line-height: 20px;
|
||||
color: ${(props) => props.theme.client.settings.common.descriptionColor};
|
||||
}
|
||||
`;
|
||||
|
||||
const ControlsGroup = styled(Box)`
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 8px;
|
||||
|
||||
@media ${tablet} {
|
||||
gap: 4px;
|
||||
}
|
||||
|
||||
${isMobile &&
|
||||
css`
|
||||
gap: 4px;
|
||||
`}
|
||||
`;
|
||||
|
||||
const LabelGroup = styled(Box)`
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 4px;
|
||||
`;
|
||||
|
||||
const InterfaceElements = styled(Box)`
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
const PresetsContainer = styled.div`
|
||||
display: grid;
|
||||
grid-template-columns: repeat(2, minmax(min(200px, 100%), 1fr));
|
||||
gap: 16px;
|
||||
margin-top: 24px;
|
||||
`;
|
||||
|
||||
const Frame = styled(Box)`
|
||||
max-width: fit-content;
|
||||
|
||||
margin-top: 16px;
|
||||
position: relative;
|
||||
|
||||
border-radius: 6px;
|
||||
border: 1px solid #d0d5da;
|
||||
|
||||
width: ${(props) => (props.width ? props.width : "100%")};
|
||||
height: calc(${(props) => (props.height ? props.height : "400px")} + 2px);
|
||||
|
||||
@media ${tablet} {
|
||||
margin-top: 4px;
|
||||
}
|
||||
|
||||
${(props) =>
|
||||
props.targetId &&
|
||||
`
|
||||
#${props.targetId} {
|
||||
border-radius: 6px;
|
||||
}
|
||||
`}
|
||||
|
||||
${isMobile &&
|
||||
css`
|
||||
margin-top: 4px;
|
||||
`}
|
||||
`;
|
||||
|
||||
const Container = styled(Box)`
|
||||
width: 100%;
|
||||
display: flex;
|
||||
flex-direction: row-reverse;
|
||||
justify-content: flex-end;
|
||||
gap: 16px;
|
||||
|
||||
@media ${tablet} {
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
${isMobile &&
|
||||
css`
|
||||
flex-direction: column;
|
||||
`}
|
||||
`;
|
||||
|
||||
const RowContainer = styled(Box)`
|
||||
flex-direction: row;
|
||||
display: flex;
|
||||
gap: 8px;
|
||||
|
||||
${(props) =>
|
||||
props.combo &&
|
||||
`
|
||||
height: 32px;
|
||||
align-items: center;
|
||||
`}
|
||||
`;
|
||||
|
||||
const ColumnContainer = styled(Box)`
|
||||
flex-direction: column;
|
||||
display: flex;
|
||||
gap: 8px;
|
||||
`;
|
||||
|
||||
const Preview = styled(Box)`
|
||||
width: 100%;
|
||||
margin-top: 24px;
|
||||
min-width: 660px;
|
||||
flex-direction: row;
|
||||
|
||||
@media ${tablet} {
|
||||
margin-top: 0;
|
||||
min-width: 0;
|
||||
}
|
||||
${isMobile &&
|
||||
css`
|
||||
margin-top: 0;
|
||||
min-width: 0;
|
||||
`}
|
||||
`;
|
||||
|
||||
const GetCodeButtonWrapper = styled.div`
|
||||
padding-block: 30px;
|
||||
position: sticky;
|
||||
bottom: 0;
|
||||
margin-top: 32px;
|
||||
background-color: ${({ theme }) => theme.backgroundColor};
|
||||
|
||||
@media ${mobile} {
|
||||
position: fixed;
|
||||
padding-inline: 16px;
|
||||
inset-inline: 0;
|
||||
}
|
||||
`;
|
||||
|
||||
const FilesSelectorInputWrapper = styled.div`
|
||||
& > div {
|
||||
margin: 0;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
`;
|
||||
|
||||
const PortalIntegration = (props) => {
|
||||
const {
|
||||
t,
|
||||
setDocumentTitle,
|
||||
currentColorScheme,
|
||||
sdkLink,
|
||||
fetchExternalLinks,
|
||||
} = props;
|
||||
const { t, setDocumentTitle, currentColorScheme, sdkLink, theme } = props;
|
||||
|
||||
setDocumentTitle(t("JavascriptSdk"));
|
||||
|
||||
const scriptUrl = `${window.location.origin}/static/scripts/api.js`;
|
||||
const navigate = useNavigate();
|
||||
|
||||
const dataSortBy = [
|
||||
{ key: "DateAndTime", label: t("Common:LastModifiedDate"), default: true },
|
||||
{ key: "AZ", label: t("Common:Title") },
|
||||
{ key: "Type", label: t("Common:Type") },
|
||||
{ key: "Size", label: t("Common:Size") },
|
||||
{ key: "DateAndTimeCreation", label: t("Files:ByCreation") },
|
||||
{ key: "Author", label: t("Files:ByAuthor") },
|
||||
];
|
||||
const navigateToSimpleRoom = () => navigate("room");
|
||||
const navigateToManager = () => navigate("manager");
|
||||
const navigateToRoomSelector = () => navigate("room-selector");
|
||||
const navigateToFileSelector = () => navigate("file-selector");
|
||||
const navigateToEditor = () => navigate("editor");
|
||||
const navigateToViewer = () => navigate("viewer");
|
||||
|
||||
const dataSortOrder = [
|
||||
{ key: "descending", label: t("Descending"), default: true },
|
||||
{ key: "ascending", label: t("Ascending") },
|
||||
];
|
||||
|
||||
const dataDimensions = [
|
||||
{ key: "percent", label: "%", default: true },
|
||||
{ key: "pixel", label: "px" },
|
||||
];
|
||||
|
||||
const [sortBy, setSortBy] = useState(dataSortBy[0]);
|
||||
const [sortOrder, setSortOrder] = useState(dataSortOrder[0]);
|
||||
const [widthDimension, setWidthDimension] = useState(dataDimensions[0]);
|
||||
const [heightDimension, setHeightDimension] = useState(dataDimensions[1]);
|
||||
const [width, setWidth] = useState("100");
|
||||
const [height, setHeight] = useState("600");
|
||||
const [withSubfolders, setWithSubfolders] = useState(false);
|
||||
const [isGetCodeDialogOpened, setIsGetCodeDialogOpened] = useState(false);
|
||||
const [showPreview, setShowPreview] = useState(
|
||||
window.innerWidth > showPreviewThreshold
|
||||
);
|
||||
const [sharedLinks, setSharedLinks] = useState(null);
|
||||
|
||||
const [config, setConfig] = useState({
|
||||
width: `${width}${widthDimension.label}`,
|
||||
height: `${height}${heightDimension.label}`,
|
||||
frameId: "ds-frame",
|
||||
showHeader: true,
|
||||
showTitle: true,
|
||||
showMenu: true,
|
||||
showFilter: true,
|
||||
init: true,
|
||||
});
|
||||
|
||||
const params = objectToGetParams(config);
|
||||
|
||||
const frameId = config.frameId || "ds-frame";
|
||||
|
||||
const destroyFrame = () => {
|
||||
window.DocSpace?.SDK?.frames[frameId]?.destroyFrame();
|
||||
};
|
||||
|
||||
const loadFrame = debounce(() => {
|
||||
const script = document.getElementById("integration");
|
||||
|
||||
if (script) {
|
||||
script.remove();
|
||||
}
|
||||
|
||||
const params = objectToGetParams(config);
|
||||
|
||||
loadScript(`${scriptUrl}${params}`, "integration", () =>
|
||||
window.DocSpace.SDK.initFrame(config)
|
||||
);
|
||||
}, 500);
|
||||
|
||||
useEffect(() => {
|
||||
loadFrame();
|
||||
return () => destroyFrame();
|
||||
});
|
||||
|
||||
const onChangeTab = () => {
|
||||
loadFrame();
|
||||
};
|
||||
|
||||
const onChangeWidth = (e) => {
|
||||
setConfig((config) => {
|
||||
return { ...config, width: `${e.target.value}${widthDimension.label}` };
|
||||
});
|
||||
|
||||
setWidth(e.target.value);
|
||||
};
|
||||
|
||||
const onChangeHeight = (e) => {
|
||||
setConfig((config) => {
|
||||
return { ...config, height: `${e.target.value}${heightDimension.label}` };
|
||||
});
|
||||
|
||||
setHeight(e.target.value);
|
||||
};
|
||||
|
||||
const onChangeFolderId = async (id, publicInPath) => {
|
||||
let newConfig = { id, requestToken: null, rootPath: "/rooms/shared/" };
|
||||
|
||||
if (!!publicInPath) {
|
||||
const links = await fetchExternalLinks(publicInPath.id);
|
||||
|
||||
if (links.length > 1) {
|
||||
const linksOptions = links.map((link) => {
|
||||
const { id, title, requestToken } = link.sharedTo;
|
||||
|
||||
return {
|
||||
key: id,
|
||||
label: title,
|
||||
requestToken: requestToken,
|
||||
};
|
||||
});
|
||||
|
||||
setSharedLinks(linksOptions);
|
||||
}
|
||||
|
||||
newConfig.requestToken = links[0].sharedTo?.requestToken;
|
||||
newConfig.rootPath = "/rooms/share";
|
||||
} else {
|
||||
setSharedLinks(null);
|
||||
}
|
||||
|
||||
setConfig((config) => {
|
||||
return { ...config, ...newConfig };
|
||||
});
|
||||
};
|
||||
|
||||
const onChangeSharedLink = (link) => {
|
||||
setConfig((config) => {
|
||||
return { ...config, requestToken: link.requestToken };
|
||||
});
|
||||
};
|
||||
|
||||
const onChangeFrameId = (e) => {
|
||||
setConfig((config) => {
|
||||
return { ...config, frameId: e.target.value };
|
||||
});
|
||||
};
|
||||
|
||||
const onChangeWithSubfolders = (e) => {
|
||||
setConfig((config) => {
|
||||
return { ...config, withSubfolders: !withSubfolders };
|
||||
});
|
||||
|
||||
setWithSubfolders(!withSubfolders);
|
||||
};
|
||||
|
||||
const onChangeSortBy = (item) => {
|
||||
setConfig((config) => {
|
||||
return { ...config, sortby: item.key };
|
||||
});
|
||||
|
||||
setSortBy(item);
|
||||
};
|
||||
|
||||
const onChangeSortOrder = (item) => {
|
||||
setConfig((config) => {
|
||||
return { ...config, sortorder: item.key };
|
||||
});
|
||||
|
||||
setSortOrder(item);
|
||||
};
|
||||
|
||||
const onChangeWidthDimension = (item) => {
|
||||
setConfig((config) => {
|
||||
return { ...config, width: `${width}${item.label}` };
|
||||
});
|
||||
|
||||
setWidthDimension(item);
|
||||
};
|
||||
|
||||
const onChangeHeightDimension = (item) => {
|
||||
setConfig((config) => {
|
||||
return { ...config, height: `${height}${item.label}` };
|
||||
});
|
||||
|
||||
setHeightDimension(item);
|
||||
};
|
||||
|
||||
const onChangeShowHeader = (e) => {
|
||||
setConfig((config) => {
|
||||
return { ...config, showHeader: !config.showHeader };
|
||||
});
|
||||
};
|
||||
|
||||
const onChangeShowTitle = () => {
|
||||
setConfig((config) => {
|
||||
return { ...config, showTitle: !config.showTitle };
|
||||
});
|
||||
};
|
||||
|
||||
const onChangeShowMenu = (e) => {
|
||||
setConfig((config) => {
|
||||
return { ...config, showMenu: !config.showMenu };
|
||||
});
|
||||
};
|
||||
|
||||
const onChangeShowFilter = (e) => {
|
||||
setConfig((config) => {
|
||||
return { ...config, showFilter: !config.showFilter };
|
||||
});
|
||||
};
|
||||
|
||||
const onChangeCount = (e) => {
|
||||
setConfig((config) => {
|
||||
return { ...config, count: e.target.value };
|
||||
});
|
||||
};
|
||||
|
||||
const onChangePage = (e) => {
|
||||
setConfig((config) => {
|
||||
return { ...config, page: e.target.value };
|
||||
});
|
||||
};
|
||||
|
||||
const onChangeSearch = (e) => {
|
||||
setConfig((config) => {
|
||||
return { ...config, search: e.target.value };
|
||||
});
|
||||
};
|
||||
|
||||
const openGetCodeModal = () => setIsGetCodeDialogOpened(true);
|
||||
|
||||
const closeGetCodeModal = () => setIsGetCodeDialogOpened(false);
|
||||
|
||||
const onResize = () => {
|
||||
const isEnoughWidthForPreview = window.innerWidth > showPreviewThreshold;
|
||||
if (isEnoughWidthForPreview !== showPreview)
|
||||
setShowPreview(isEnoughWidthForPreview);
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
window.addEventListener("resize", onResize);
|
||||
return () => {
|
||||
window.removeEventListener("resize", onResize);
|
||||
};
|
||||
}, [showPreview]);
|
||||
|
||||
const codeBlock = `<div id="${frameId}">Fallback text</div>\n<script src="${scriptUrl}${params}"></script>`;
|
||||
|
||||
const preview = (
|
||||
<Frame
|
||||
width={width + widthDimension.label}
|
||||
height={height + heightDimension.label}
|
||||
targetId={frameId}
|
||||
>
|
||||
<Box id={frameId}></Box>
|
||||
</Frame>
|
||||
);
|
||||
|
||||
const code = (
|
||||
<>
|
||||
<CategorySubHeader className="copy-window-code">
|
||||
{t("CopyWindowCode")}
|
||||
</CategorySubHeader>
|
||||
<Textarea value={codeBlock} heightTextArea="153px" />
|
||||
</>
|
||||
);
|
||||
|
||||
const dataTabs = [
|
||||
const presetsData = [
|
||||
{
|
||||
key: "preview",
|
||||
title: t("Common:Preview"),
|
||||
content: preview,
|
||||
title: t("Common:Room"),
|
||||
description: t("SimpleRoomDescription"),
|
||||
image: theme.isBase ? SimpleRoomImg : SimpleRoomImgDark,
|
||||
handleOnClick: navigateToSimpleRoom,
|
||||
},
|
||||
{
|
||||
key: "code",
|
||||
title: t("Code"),
|
||||
content: code,
|
||||
title: t("Manager"),
|
||||
description: t("ManagerDescription"),
|
||||
image: theme.isBase ? ManagerImg : ManagerImgDark,
|
||||
handleOnClick: navigateToManager,
|
||||
},
|
||||
{
|
||||
title: t("Editor"),
|
||||
description: t("EditorDescription"),
|
||||
image: theme.isBase ? EditorImg : EditorImgDark,
|
||||
handleOnClick: navigateToEditor,
|
||||
},
|
||||
{
|
||||
title: t("Viewer"),
|
||||
description: t("ViewerDescription"),
|
||||
image: theme.isBase ? ViewerImg : ViewerImgDark,
|
||||
handleOnClick: navigateToViewer,
|
||||
},
|
||||
{
|
||||
title: t("RoomSelector"),
|
||||
description: t("RoomSelectorDescription"),
|
||||
image: theme.isBase ? RoomSelectorImg : RoomSelectorImgDark,
|
||||
handleOnClick: navigateToRoomSelector,
|
||||
},
|
||||
{
|
||||
title: t("FileSelector"),
|
||||
description: t("FileSelectorDescription"),
|
||||
image: theme.isBase ? FileSelectorImg : FileSelectorImgDark,
|
||||
handleOnClick: navigateToFileSelector,
|
||||
},
|
||||
];
|
||||
|
||||
@ -531,7 +141,7 @@ const PortalIntegration = (props) => {
|
||||
<Text className="sdk-description">{t("SDKDescription")}</Text>
|
||||
<Link
|
||||
color={currentColorScheme?.main?.accent}
|
||||
fontSize="12px"
|
||||
fontSize="13px"
|
||||
fontWeight="400"
|
||||
onClick={() => window.open(sdkLink, "_blank")}
|
||||
>
|
||||
@ -540,233 +150,21 @@ const PortalIntegration = (props) => {
|
||||
<CSP t={t} />
|
||||
</CategoryDescription>
|
||||
<CategoryHeader>{t("CreateSampleHeader")}</CategoryHeader>
|
||||
<Container>
|
||||
{showPreview && (
|
||||
<Preview>
|
||||
<TabsContainer onSelect={onChangeTab} elements={dataTabs} />
|
||||
</Preview>
|
||||
)}
|
||||
<Controls>
|
||||
<CategorySubHeader>{t("CustomizingDisplay")}</CategorySubHeader>
|
||||
<ControlsGroup>
|
||||
<Label className="label" text={t("EmbeddingPanel:Width")} />
|
||||
<RowContainer combo>
|
||||
<TextInput
|
||||
onChange={onChangeWidth}
|
||||
placeholder={t("EnterWidth")}
|
||||
value={width}
|
||||
tabIndex={2}
|
||||
/>
|
||||
<ComboBox
|
||||
size="content"
|
||||
scaled={false}
|
||||
scaledOptions={true}
|
||||
onSelect={onChangeWidthDimension}
|
||||
options={dataDimensions}
|
||||
selectedOption={widthDimension}
|
||||
displaySelectedOption
|
||||
directionY="bottom"
|
||||
/>
|
||||
</RowContainer>
|
||||
</ControlsGroup>
|
||||
<ControlsGroup>
|
||||
<Label className="label" text={t("EmbeddingPanel:Height")} />
|
||||
<RowContainer combo>
|
||||
<TextInput
|
||||
onChange={onChangeHeight}
|
||||
placeholder={t("EnterHeight")}
|
||||
value={height}
|
||||
tabIndex={3}
|
||||
/>
|
||||
<ComboBox
|
||||
size="content"
|
||||
scaled={false}
|
||||
scaledOptions={true}
|
||||
onSelect={onChangeHeightDimension}
|
||||
options={dataDimensions}
|
||||
selectedOption={heightDimension}
|
||||
displaySelectedOption
|
||||
directionY="bottom"
|
||||
/>
|
||||
</RowContainer>
|
||||
</ControlsGroup>
|
||||
<ControlsGroup>
|
||||
<Label className="label" text={t("FrameId")} />
|
||||
<TextInput
|
||||
scale={true}
|
||||
onChange={onChangeFrameId}
|
||||
placeholder={t("EnterId")}
|
||||
value={config.frameId}
|
||||
tabIndex={4}
|
||||
/>
|
||||
</ControlsGroup>
|
||||
<InterfaceElements>
|
||||
<Label className="label">{t("InterfaceElements")}</Label>
|
||||
<Checkbox
|
||||
className="checkbox"
|
||||
label={t("Menu")}
|
||||
onChange={onChangeShowMenu}
|
||||
isChecked={config.showMenu}
|
||||
/>
|
||||
<Checkbox
|
||||
className="checkbox"
|
||||
label={t("Header")}
|
||||
onChange={onChangeShowHeader}
|
||||
isChecked={config.showHeader}
|
||||
/>
|
||||
<Checkbox
|
||||
className="checkbox"
|
||||
label={t("Filter")}
|
||||
onChange={onChangeShowFilter}
|
||||
isChecked={config.showFilter}
|
||||
/>
|
||||
<RowContainer>
|
||||
<Checkbox
|
||||
label={t("Title")}
|
||||
onChange={onChangeShowTitle}
|
||||
isChecked={config.showTitle}
|
||||
/>
|
||||
<Text color="gray">{`(${t("MobileOnly")})`}</Text>
|
||||
</RowContainer>
|
||||
</InterfaceElements>
|
||||
<CategorySubHeader>{t("DataDisplay")}</CategorySubHeader>
|
||||
<ControlsGroup>
|
||||
<LabelGroup>
|
||||
<Label className="label" text={t("RoomOrFolder")} />
|
||||
<HelpButton
|
||||
offsetRight={0}
|
||||
size={12}
|
||||
tooltipContent={
|
||||
<Text fontSize="12px">{t("RoomOrFolderDescription")}</Text>
|
||||
}
|
||||
/>
|
||||
</LabelGroup>
|
||||
<FilesSelectorInputWrapper>
|
||||
<FilesSelectorInput onSelectFolder={onChangeFolderId} isSelect />
|
||||
</FilesSelectorInputWrapper>
|
||||
</ControlsGroup>
|
||||
{sharedLinks && (
|
||||
<ControlsGroup>
|
||||
<LabelGroup>
|
||||
<Label
|
||||
className="label"
|
||||
text={t("SharingPanel:ExternalLink")}
|
||||
/>
|
||||
<HelpButton
|
||||
offsetRight={0}
|
||||
size={12}
|
||||
tooltipContent={
|
||||
<Text fontSize="12px">
|
||||
{t("CreateEditRoomDialog:PublicRoomDescription")}
|
||||
</Text>
|
||||
}
|
||||
/>
|
||||
</LabelGroup>
|
||||
<ComboBox
|
||||
scaled={true}
|
||||
onSelect={onChangeSharedLink}
|
||||
options={sharedLinks}
|
||||
selectedOption={sharedLinks[0]}
|
||||
displaySelectedOption
|
||||
directionY="bottom"
|
||||
/>
|
||||
</ControlsGroup>
|
||||
)}
|
||||
<CategorySubHeader>{t("AdvancedDisplay")}</CategorySubHeader>
|
||||
<ControlsGroup>
|
||||
<Label className="label" text={t("SearchTerm")} />
|
||||
<ColumnContainer>
|
||||
<TextInput
|
||||
scale={true}
|
||||
onChange={onChangeSearch}
|
||||
placeholder={t("Common:Search")}
|
||||
value={config.search}
|
||||
tabIndex={5}
|
||||
/>
|
||||
<Checkbox
|
||||
className="checkbox"
|
||||
label={t("Files:WithSubfolders")}
|
||||
onChange={onChangeWithSubfolders}
|
||||
isChecked={withSubfolders}
|
||||
/>
|
||||
</ColumnContainer>
|
||||
</ControlsGroup>
|
||||
<ControlsGroup>
|
||||
<Label className="label" text={t("Common:SortBy")} />
|
||||
<ComboBox
|
||||
onSelect={onChangeSortBy}
|
||||
options={dataSortBy}
|
||||
scaled={true}
|
||||
selectedOption={sortBy}
|
||||
displaySelectedOption
|
||||
directionY="top"
|
||||
/>
|
||||
</ControlsGroup>
|
||||
<ControlsGroup>
|
||||
<Label className="label" text={t("SortOrder")} />
|
||||
<ComboBox
|
||||
onSelect={onChangeSortOrder}
|
||||
options={dataSortOrder}
|
||||
scaled={true}
|
||||
selectedOption={sortOrder}
|
||||
displaySelectedOption
|
||||
directionY="top"
|
||||
/>
|
||||
</ControlsGroup>
|
||||
<ControlsGroup>
|
||||
<LabelGroup>
|
||||
<Label className="label" text={t("ItemsCount")} />
|
||||
<HelpButton
|
||||
offsetRight={0}
|
||||
size={12}
|
||||
tooltipContent={
|
||||
<Text fontSize="12px">{t("ItemsCountDescription")}</Text>
|
||||
}
|
||||
/>
|
||||
</LabelGroup>
|
||||
<TextInput
|
||||
scale={true}
|
||||
onChange={onChangeCount}
|
||||
placeholder={t("EnterCount")}
|
||||
value={config.count}
|
||||
tabIndex={6}
|
||||
/>
|
||||
</ControlsGroup>
|
||||
<ControlsGroup>
|
||||
<Label className="label" text={t("Page")} />
|
||||
<TextInput
|
||||
scale={true}
|
||||
onChange={onChangePage}
|
||||
placeholder={t("EnterPage")}
|
||||
value={config.page}
|
||||
isDisabled={!config.count}
|
||||
tabIndex={7}
|
||||
/>
|
||||
</ControlsGroup>
|
||||
</Controls>
|
||||
</Container>
|
||||
|
||||
{!showPreview && (
|
||||
<>
|
||||
<GetCodeButtonWrapper>
|
||||
<Button
|
||||
id="get-sdk-code-button"
|
||||
primary
|
||||
size="normal"
|
||||
scale
|
||||
label={t("GetCode")}
|
||||
onClick={openGetCodeModal}
|
||||
/>
|
||||
</GetCodeButtonWrapper>
|
||||
|
||||
<GetCodeDialog
|
||||
<Text lineHeight="20px" color={theme.sdkPresets.secondaryColor}>
|
||||
{t("InitializeSDK")}
|
||||
</Text>
|
||||
<PresetsContainer>
|
||||
{presetsData.map((data) => (
|
||||
<PresetTile
|
||||
t={t}
|
||||
visible={isGetCodeDialogOpened}
|
||||
codeBlock={codeBlock}
|
||||
onClose={closeGetCodeModal}
|
||||
key={data.title}
|
||||
title={data.title}
|
||||
description={data.description}
|
||||
image={data.image}
|
||||
handleOnClick={data.handleOnClick}
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
))}
|
||||
</PresetsContainer>
|
||||
</SDKContainer>
|
||||
);
|
||||
};
|
||||
@ -774,14 +172,12 @@ const PortalIntegration = (props) => {
|
||||
export default inject(({ settingsStore, authStore, publicRoomStore }) => {
|
||||
const { setDocumentTitle } = authStore;
|
||||
const { theme, currentColorScheme, sdkLink } = settingsStore;
|
||||
const { fetchExternalLinks } = publicRoomStore;
|
||||
|
||||
return {
|
||||
theme,
|
||||
setDocumentTitle,
|
||||
currentColorScheme,
|
||||
sdkLink,
|
||||
fetchExternalLinks,
|
||||
};
|
||||
})(
|
||||
withTranslation([
|
||||
@ -791,5 +187,5 @@ export default inject(({ settingsStore, authStore, publicRoomStore }) => {
|
||||
"CreateEditRoomDialog",
|
||||
"SharingPanel",
|
||||
"Common",
|
||||
])(observer(PortalIntegration))
|
||||
])(observer(PortalIntegration)),
|
||||
);
|
||||
|
@ -0,0 +1,350 @@
|
||||
import { useState, useEffect } from "react";
|
||||
import { withTranslation } from "react-i18next";
|
||||
import debounce from "lodash.debounce";
|
||||
import { Box } from "@docspace/shared/components/box";
|
||||
import { TextInput } from "@docspace/shared/components/text-input";
|
||||
import { Textarea } from "@docspace/shared/components/textarea";
|
||||
import { Label } from "@docspace/shared/components/label";
|
||||
import { Text } from "@docspace/shared/components/text";
|
||||
import { Checkbox } from "@docspace/shared/components/checkbox";
|
||||
import { ComboBox } from "@docspace/shared/components/combobox";
|
||||
import { TabsContainer } from "@docspace/shared/components/tabs-container";
|
||||
import FilesSelectorInput from "SRC_DIR/components/FilesSelectorInput";
|
||||
import { objectToGetParams, loadScript } from "@docspace/shared/utils/common";
|
||||
import { inject, observer } from "mobx-react";
|
||||
import { FilesSelectorFilterTypes } from "@docspace/shared/enums";
|
||||
|
||||
import { isTablet, isMobile } from "@docspace/shared/utils/device";
|
||||
|
||||
import EmptyIframeContainer from "../sub-components/EmptyIframeContainer";
|
||||
|
||||
import GetCodeDialog from "../sub-components/GetCodeDialog";
|
||||
import { Button } from "@docspace/shared/components/button";
|
||||
|
||||
const showPreviewThreshold = 720;
|
||||
|
||||
import {
|
||||
SDKContainer,
|
||||
Controls,
|
||||
CategoryHeader,
|
||||
CategorySubHeader,
|
||||
CategoryDescription,
|
||||
ControlsGroup,
|
||||
LabelGroup,
|
||||
ControlsSection,
|
||||
Frame,
|
||||
Container,
|
||||
RowContainer,
|
||||
Preview,
|
||||
GetCodeButtonWrapper,
|
||||
FilesSelectorInputWrapper,
|
||||
CodeWrapper,
|
||||
} from "./StyledPresets";
|
||||
|
||||
const Editor = (props) => {
|
||||
const { t, setDocumentTitle } = props;
|
||||
|
||||
setDocumentTitle(t("JavascriptSdk"));
|
||||
|
||||
const scriptUrl = `${window.location.origin}/static/scripts/api.js`;
|
||||
|
||||
const dataDimensions = [
|
||||
{ key: "percent", label: "%", default: true },
|
||||
{ key: "pixel", label: "px" },
|
||||
];
|
||||
|
||||
const [widthDimension, setWidthDimension] = useState(dataDimensions[0]);
|
||||
const [heightDimension, setHeightDimension] = useState(dataDimensions[0]);
|
||||
const [width, setWidth] = useState("100");
|
||||
const [height, setHeight] = useState("100");
|
||||
const [isGetCodeDialogOpened, setIsGetCodeDialogOpened] = useState(false);
|
||||
const [showPreview, setShowPreview] = useState(window.innerWidth > showPreviewThreshold);
|
||||
|
||||
const [config, setConfig] = useState({
|
||||
mode: "editor",
|
||||
width: `${width}${widthDimension.label}`,
|
||||
height: `${height}${heightDimension.label}`,
|
||||
frameId: "ds-frame",
|
||||
init: false,
|
||||
});
|
||||
|
||||
const params = objectToGetParams(config);
|
||||
|
||||
const frameId = config.frameId || "ds-frame";
|
||||
|
||||
const destroyFrame = () => {
|
||||
window.DocSpace?.SDK?.frames[frameId]?.destroyFrame();
|
||||
};
|
||||
|
||||
const loadFrame = debounce(() => {
|
||||
const script = document.getElementById("integration");
|
||||
|
||||
if (script) {
|
||||
script.remove();
|
||||
}
|
||||
|
||||
const params = objectToGetParams(config);
|
||||
|
||||
loadScript(`${scriptUrl}${params}`, "integration", () => window.DocSpace.SDK.initFrame(config));
|
||||
}, 500);
|
||||
|
||||
useEffect(() => {
|
||||
loadFrame();
|
||||
return () => destroyFrame();
|
||||
});
|
||||
|
||||
const onChangeTab = () => {
|
||||
loadFrame();
|
||||
};
|
||||
|
||||
const onChangeWidth = (e) => {
|
||||
setConfig((config) => {
|
||||
return { ...config, width: `${e.target.value}${widthDimension.label}` };
|
||||
});
|
||||
|
||||
setWidth(e.target.value);
|
||||
};
|
||||
|
||||
const onChangeHeight = (e) => {
|
||||
setConfig((config) => {
|
||||
return { ...config, height: `${e.target.value}${heightDimension.label}` };
|
||||
});
|
||||
|
||||
setHeight(e.target.value);
|
||||
};
|
||||
|
||||
const onChangeFileId = (file) => {
|
||||
setConfig((config) => {
|
||||
return { ...config, id: file.id, init: true };
|
||||
});
|
||||
};
|
||||
|
||||
const onChangeFrameId = (e) => {
|
||||
setConfig((config) => {
|
||||
return { ...config, frameId: e.target.value };
|
||||
});
|
||||
};
|
||||
|
||||
const onChangeWidthDimension = (item) => {
|
||||
setConfig((config) => {
|
||||
return { ...config, width: `${width}${item.label}` };
|
||||
});
|
||||
|
||||
setWidthDimension(item);
|
||||
};
|
||||
|
||||
const onChangeHeightDimension = (item) => {
|
||||
setConfig((config) => {
|
||||
return { ...config, height: `${height}${item.label}` };
|
||||
});
|
||||
|
||||
setHeightDimension(item);
|
||||
};
|
||||
|
||||
const openGetCodeModal = () => setIsGetCodeDialogOpened(true);
|
||||
|
||||
const closeGetCodeModal = () => setIsGetCodeDialogOpened(false);
|
||||
|
||||
const onResize = () => {
|
||||
const isEnoughWidthForPreview = window.innerWidth > showPreviewThreshold;
|
||||
if (isEnoughWidthForPreview !== showPreview) setShowPreview(isEnoughWidthForPreview);
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
window.addEventListener("resize", onResize);
|
||||
return () => {
|
||||
window.removeEventListener("resize", onResize);
|
||||
};
|
||||
}, [showPreview]);
|
||||
|
||||
const codeBlock = `<div id="${frameId}">Fallback text</div>\n<script src="${scriptUrl}${params}"></script>`;
|
||||
|
||||
const preview = (
|
||||
<Frame
|
||||
width={width + widthDimension.label}
|
||||
height={height + heightDimension.label}
|
||||
targetId={frameId}
|
||||
>
|
||||
{config.id !== undefined ? (
|
||||
<>
|
||||
<Box id={frameId}></Box>
|
||||
</>
|
||||
) : (
|
||||
<EmptyIframeContainer
|
||||
text={t("SelectFile")}
|
||||
width={width + widthDimension.label}
|
||||
height={height + heightDimension.label}
|
||||
/>
|
||||
)}
|
||||
</Frame>
|
||||
);
|
||||
|
||||
const code = (
|
||||
<CodeWrapper>
|
||||
<CategorySubHeader className="copy-window-code">{t("CopyWindowCode")}</CategorySubHeader>
|
||||
<Textarea value={codeBlock} heightTextArea={153} />
|
||||
</CodeWrapper>
|
||||
);
|
||||
|
||||
const dataTabs = [
|
||||
{
|
||||
key: "preview",
|
||||
title: t("Common:Preview"),
|
||||
content: preview,
|
||||
},
|
||||
{
|
||||
key: "code",
|
||||
title: t("Code"),
|
||||
content: code,
|
||||
},
|
||||
];
|
||||
|
||||
return (
|
||||
<SDKContainer>
|
||||
<CategoryDescription>
|
||||
<Text className="sdk-description">{t("EditorPresetDescription")}</Text>
|
||||
</CategoryDescription>
|
||||
<CategoryHeader>{t("CreateSampleHeader")}</CategoryHeader>
|
||||
<Container>
|
||||
{showPreview && (
|
||||
<Preview>
|
||||
<TabsContainer
|
||||
isDisabled={config?.id === undefined}
|
||||
onSelect={onChangeTab}
|
||||
elements={dataTabs}
|
||||
/>
|
||||
</Preview>
|
||||
)}
|
||||
<Controls>
|
||||
<ControlsSection>
|
||||
<CategorySubHeader>{t("FileId")}</CategorySubHeader>
|
||||
<ControlsGroup>
|
||||
<LabelGroup>
|
||||
<Label className="label" text={t("Common:SelectFile")} />
|
||||
</LabelGroup>
|
||||
<FilesSelectorInputWrapper>
|
||||
<FilesSelectorInput
|
||||
onSelectFile={onChangeFileId}
|
||||
filterParam={FilesSelectorFilterTypes.ALL}
|
||||
isSelect
|
||||
/>
|
||||
</FilesSelectorInputWrapper>
|
||||
</ControlsGroup>
|
||||
</ControlsSection>
|
||||
|
||||
<ControlsSection>
|
||||
<CategorySubHeader>{t("CustomizingDisplay")}</CategorySubHeader>
|
||||
<ControlsGroup>
|
||||
<Label className="label" text={t("EmbeddingPanel:Width")} />
|
||||
<RowContainer combo>
|
||||
<TextInput
|
||||
onChange={onChangeWidth}
|
||||
placeholder={t("EnterWidth")}
|
||||
value={width}
|
||||
tabIndex={2}
|
||||
/>
|
||||
<ComboBox
|
||||
size="content"
|
||||
scaled={false}
|
||||
scaledOptions={true}
|
||||
onSelect={onChangeWidthDimension}
|
||||
options={dataDimensions}
|
||||
selectedOption={widthDimension}
|
||||
displaySelectedOption
|
||||
directionY="bottom"
|
||||
/>
|
||||
</RowContainer>
|
||||
</ControlsGroup>
|
||||
<ControlsGroup>
|
||||
<Label className="label" text={t("EmbeddingPanel:Height")} />
|
||||
<RowContainer combo>
|
||||
<TextInput
|
||||
onChange={onChangeHeight}
|
||||
placeholder={t("EnterHeight")}
|
||||
value={height}
|
||||
tabIndex={3}
|
||||
/>
|
||||
<ComboBox
|
||||
size="content"
|
||||
scaled={false}
|
||||
scaledOptions={true}
|
||||
onSelect={onChangeHeightDimension}
|
||||
options={dataDimensions}
|
||||
selectedOption={heightDimension}
|
||||
displaySelectedOption
|
||||
directionY="bottom"
|
||||
/>
|
||||
</RowContainer>
|
||||
</ControlsGroup>
|
||||
<ControlsGroup>
|
||||
<Label className="label" text={t("FrameId")} />
|
||||
<TextInput
|
||||
scale={true}
|
||||
onChange={onChangeFrameId}
|
||||
placeholder={t("EnterId")}
|
||||
value={config.frameId}
|
||||
tabIndex={4}
|
||||
/>
|
||||
</ControlsGroup>
|
||||
</ControlsSection>
|
||||
|
||||
{/* <InterfaceElements>
|
||||
<Label className="label">{t("InterfaceElements")}</Label>
|
||||
<Checkbox
|
||||
className="checkbox"
|
||||
label={t("RightPanelCollapsed")}
|
||||
onChange={() => {}}
|
||||
isChecked={true}
|
||||
/>
|
||||
<Checkbox
|
||||
className="checkbox"
|
||||
label={t("TabPlugins")}
|
||||
onChange={() => {}}
|
||||
isChecked={true}
|
||||
/>
|
||||
<RowContainer>
|
||||
<Checkbox label={t("Chat")} onChange={() => {}} isChecked={true} />
|
||||
<Text color="gray">({t("InLeftPanel")})</Text>
|
||||
</RowContainer>
|
||||
<RowContainer>
|
||||
<Checkbox label={t("FeedbackAndSupport")} onChange={() => {}} isChecked={true} />
|
||||
<Text color="gray">({t("InLeftPanel")})</Text>
|
||||
</RowContainer>
|
||||
</InterfaceElements> */}
|
||||
</Controls>
|
||||
</Container>
|
||||
|
||||
{!showPreview && (
|
||||
<>
|
||||
<GetCodeButtonWrapper>
|
||||
<Button
|
||||
id="get-sdk-code-button"
|
||||
primary
|
||||
size="normal"
|
||||
scale
|
||||
label={t("GetCode")}
|
||||
onClick={openGetCodeModal}
|
||||
/>
|
||||
</GetCodeButtonWrapper>
|
||||
|
||||
<GetCodeDialog
|
||||
t={t}
|
||||
visible={isGetCodeDialogOpened}
|
||||
codeBlock={codeBlock}
|
||||
onClose={closeGetCodeModal}
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
</SDKContainer>
|
||||
);
|
||||
};
|
||||
|
||||
export default inject(({ authStore, settingsStore }) => {
|
||||
const { setDocumentTitle } = authStore;
|
||||
const { theme } = settingsStore;
|
||||
|
||||
return {
|
||||
theme,
|
||||
setDocumentTitle,
|
||||
};
|
||||
})(withTranslation(["JavascriptSdk", "Files", "EmbeddingPanel", "Common"])(observer(Editor)));
|
@ -0,0 +1,693 @@
|
||||
import { useState, useEffect } from "react";
|
||||
import { withTranslation } from "react-i18next";
|
||||
import debounce from "lodash.debounce";
|
||||
import { Box } from "@docspace/shared/components/box";
|
||||
import { TextInput } from "@docspace/shared/components/text-input";
|
||||
import { Textarea } from "@docspace/shared/components/textarea";
|
||||
import { Label } from "@docspace/shared/components/label";
|
||||
import { Text } from "@docspace/shared/components/text";
|
||||
import { Checkbox } from "@docspace/shared/components/checkbox";
|
||||
import { ComboBox } from "@docspace/shared/components/combobox";
|
||||
import { TabsContainer } from "@docspace/shared/components/tabs-container";
|
||||
import FilesSelectorInput from "SRC_DIR/components/FilesSelectorInput";
|
||||
import { RadioButtonGroup } from "@docspace/shared/components/radio-button-group";
|
||||
import { SelectedItem } from "@docspace/shared/components/selected-item";
|
||||
import { ColorInput } from "@docspace/shared/components/color-input";
|
||||
import { objectToGetParams, loadScript } from "@docspace/shared/utils/common";
|
||||
import { inject, observer } from "mobx-react";
|
||||
|
||||
import { isTablet, isMobile } from "@docspace/shared/utils/device";
|
||||
|
||||
import { HelpButton } from "@docspace/shared/components/help-button";
|
||||
import { Button } from "@docspace/shared/components/button";
|
||||
|
||||
import GetCodeDialog from "../sub-components/GetCodeDialog";
|
||||
|
||||
import { FilesSelectorFilterTypes } from "@docspace/shared/enums";
|
||||
import { TooltipContent } from "../sub-components/TooltipContent";
|
||||
|
||||
import SubtitleUrl from "PUBLIC_DIR/images/sdk-presets_subtitle.react.svg?url";
|
||||
import SearchUrl from "PUBLIC_DIR/images/sdk-presets_files-search.react.svg?url";
|
||||
|
||||
import { toastr } from "@docspace/shared/components/toast";
|
||||
|
||||
const showPreviewThreshold = 720;
|
||||
|
||||
import {
|
||||
SDKContainer,
|
||||
Controls,
|
||||
CategoryHeader,
|
||||
CategorySubHeader,
|
||||
CategoryDescription,
|
||||
ControlsGroup,
|
||||
LabelGroup,
|
||||
ControlsSection,
|
||||
Frame,
|
||||
Container,
|
||||
RowContainer,
|
||||
Preview,
|
||||
GetCodeButtonWrapper,
|
||||
FilesSelectorInputWrapper,
|
||||
SelectedItemsContainer,
|
||||
CodeWrapper,
|
||||
} from "./StyledPresets";
|
||||
|
||||
const FileSelector = (props) => {
|
||||
const { t, setDocumentTitle, fetchExternalLinks } = props;
|
||||
|
||||
setDocumentTitle(t("JavascriptSdk"));
|
||||
|
||||
const scriptUrl = `${window.location.origin}/static/scripts/api.js`;
|
||||
|
||||
const dataDimensions = [
|
||||
{ key: "percent", label: "%", default: true },
|
||||
{ key: "pixel", label: "px" },
|
||||
];
|
||||
|
||||
const elementDisplayOptions = [
|
||||
{ value: "element", label: t("ElementItself") },
|
||||
{
|
||||
value: "button",
|
||||
label: (
|
||||
<RowContainer>
|
||||
{t("Common:Button")}
|
||||
<Text color="gray">{`(${t("ElementCalledAfterClicking")})`}</Text>
|
||||
</RowContainer>
|
||||
),
|
||||
},
|
||||
];
|
||||
|
||||
const fileTypeDisplay = [
|
||||
{ value: FilesSelectorFilterTypes.ALL, label: t("AllTypes") },
|
||||
{ value: "custom-types", label: t("SelectTypes") },
|
||||
];
|
||||
|
||||
const [fileOptions, setFileOptions] = useState([
|
||||
{ key: FilesSelectorFilterTypes.DOCX, label: FilesSelectorFilterTypes.DOCX },
|
||||
{ key: FilesSelectorFilterTypes.IMG, label: FilesSelectorFilterTypes.IMG },
|
||||
{ key: FilesSelectorFilterTypes.BackupOnly, label: FilesSelectorFilterTypes.BackupOnly },
|
||||
{ key: FilesSelectorFilterTypes.DOCXF, label: FilesSelectorFilterTypes.DOCXF },
|
||||
{ key: FilesSelectorFilterTypes.XLSX, label: FilesSelectorFilterTypes.XLSX },
|
||||
]);
|
||||
|
||||
const [widthDimension, setWidthDimension] = useState(dataDimensions[1]);
|
||||
const [heightDimension, setHeightDimension] = useState(dataDimensions[0]);
|
||||
const [width, setWidth] = useState("600");
|
||||
const [height, setHeight] = useState("100");
|
||||
const [isGetCodeDialogOpened, setIsGetCodeDialogOpened] = useState(false);
|
||||
const [showPreview, setShowPreview] = useState(window.innerWidth > showPreviewThreshold);
|
||||
const [sharedLinks, setSharedLinks] = useState(null);
|
||||
const [selectedElementType, setSelectedElementType] = useState(elementDisplayOptions[1].value);
|
||||
const [typeDisplay, setTypeDisplay] = useState(fileTypeDisplay[0].value);
|
||||
const [selectedType, setSelectedType] = useState(fileOptions[0]);
|
||||
const [selectedFileTypes, setSelectedFileTypes] = useState([
|
||||
{ key: "file-type-documents", label: t("Common:Documents") },
|
||||
{ key: "file-type-folders", label: t("Translations:Folders") },
|
||||
{ key: "file-type-spreadsheets", label: t("Translations:Spreadsheets") },
|
||||
{ key: "file-type-archives", label: t("Files:Archives") },
|
||||
{ key: "file-type-presentations", label: t("Translations:Presentations") },
|
||||
{ key: "file-type-images", label: t("Filse:Images") },
|
||||
{ key: "file-type-media", label: t("Files:Media") },
|
||||
{ key: "file-type-forms-templates", label: t("Files:FormsTemplates") },
|
||||
{ key: "file-type-forms", label: t("Files:Forms") },
|
||||
]);
|
||||
|
||||
const [config, setConfig] = useState({
|
||||
mode: "file-selector",
|
||||
width: `${width}${widthDimension.label}`,
|
||||
height: `${height}${heightDimension.label}`,
|
||||
frameId: "ds-frame",
|
||||
init: true,
|
||||
showSelectorCancel: true,
|
||||
showSelectorHeader: true,
|
||||
withSearch: true,
|
||||
acceptButtonLabel: t("Common:SelectAction"),
|
||||
cancelButtonLabel: t("Common:CancelButton"),
|
||||
// withBreadCrumbs: true,
|
||||
withSubtitle: true,
|
||||
filterParam: FilesSelectorFilterTypes.ALL,
|
||||
isButtonMode: false,
|
||||
buttonWithLogo: true,
|
||||
events: {
|
||||
onSelectCallback: (items) => {
|
||||
toastr.success(items[0].label);
|
||||
},
|
||||
onCloseCallback: null,
|
||||
onAppReady: null,
|
||||
onAppError: (e) => console.log("onAppError", e),
|
||||
onEditorCloseCallback: null,
|
||||
onAuthSuccess: null,
|
||||
onSignOut: null,
|
||||
},
|
||||
});
|
||||
|
||||
const params = objectToGetParams(config);
|
||||
|
||||
const frameId = config.frameId || "ds-frame";
|
||||
|
||||
const destroyFrame = () => {
|
||||
window.DocSpace?.SDK?.frames[frameId]?.destroyFrame();
|
||||
};
|
||||
|
||||
const loadFrame = debounce(() => {
|
||||
const script = document.getElementById("integration");
|
||||
|
||||
if (script) {
|
||||
script.remove();
|
||||
}
|
||||
|
||||
const params = objectToGetParams(config);
|
||||
|
||||
loadScript(`${scriptUrl}${params}`, "integration", () => window.DocSpace.SDK.initFrame(config));
|
||||
}, 500);
|
||||
|
||||
useEffect(() => {
|
||||
loadFrame();
|
||||
return () => destroyFrame();
|
||||
});
|
||||
|
||||
const toggleButtonMode = (e) => {
|
||||
setSelectedElementType(e.target.value);
|
||||
setConfig((config) => ({ ...config, isButtonMode: e.target.value === "button" }));
|
||||
};
|
||||
|
||||
const onChangeTab = (tab) => {
|
||||
if (tab.key === "preview" && selectedElementType === "button") {
|
||||
setConfig((config) => ({ ...config, isButtonMode: true }));
|
||||
} else if (tab.key === "selector-preview") {
|
||||
setConfig((config) => ({ ...config, isButtonMode: false }));
|
||||
} else if (tab.key === "code") {
|
||||
setConfig((config) => ({ ...config, isButtonMode: selectedElementType === "button" }));
|
||||
}
|
||||
};
|
||||
|
||||
const onChangeWidth = (e) => {
|
||||
setConfig((config) => {
|
||||
return { ...config, width: `${e.target.value}${widthDimension.label}` };
|
||||
});
|
||||
|
||||
setWidth(e.target.value);
|
||||
};
|
||||
|
||||
const onChangeHeight = (e) => {
|
||||
setConfig((config) => {
|
||||
return { ...config, height: `${e.target.value}${heightDimension.label}` };
|
||||
});
|
||||
|
||||
setHeight(e.target.value);
|
||||
};
|
||||
|
||||
const onChangeFolderId = async (id, publicInPath) => {
|
||||
let newConfig = { id, requestToken: null, rootPath: "/rooms/shared/" };
|
||||
|
||||
if (!!publicInPath) {
|
||||
const links = await fetchExternalLinks(publicInPath.id);
|
||||
|
||||
if (links.length > 1) {
|
||||
const linksOptions = links.map((link) => {
|
||||
const { id, title, requestToken } = link.sharedTo;
|
||||
|
||||
return {
|
||||
key: id,
|
||||
label: title,
|
||||
requestToken: requestToken,
|
||||
};
|
||||
});
|
||||
|
||||
setSharedLinks(linksOptions);
|
||||
}
|
||||
|
||||
newConfig.requestToken = links[0].sharedTo?.requestToken;
|
||||
newConfig.rootPath = "/rooms/share";
|
||||
} else {
|
||||
setSharedLinks(null);
|
||||
}
|
||||
|
||||
setConfig((config) => {
|
||||
return { ...config, ...newConfig };
|
||||
});
|
||||
};
|
||||
|
||||
const onChangeSharedLink = (link) => {
|
||||
setConfig((config) => {
|
||||
return { ...config, requestToken: link.requestToken };
|
||||
});
|
||||
};
|
||||
|
||||
const onChangeFrameId = (e) => {
|
||||
setConfig((config) => {
|
||||
return { ...config, frameId: e.target.value };
|
||||
});
|
||||
};
|
||||
|
||||
const changeColumnsOption = (e) => {
|
||||
setTypeDisplay(e.target.value);
|
||||
setConfig((config) => {
|
||||
return {
|
||||
...config,
|
||||
filterParam:
|
||||
e.target.value === FilesSelectorFilterTypes.ALL
|
||||
? FilesSelectorFilterTypes.ALL
|
||||
: selectedType,
|
||||
};
|
||||
});
|
||||
};
|
||||
|
||||
const onChangeWidthDimension = (item) => {
|
||||
setConfig((config) => {
|
||||
return { ...config, width: `${width}${item.label}` };
|
||||
});
|
||||
|
||||
setWidthDimension(item);
|
||||
};
|
||||
|
||||
const onChangeHeightDimension = (item) => {
|
||||
setConfig((config) => {
|
||||
return { ...config, height: `${height}${item.label}` };
|
||||
});
|
||||
|
||||
setHeightDimension(item);
|
||||
};
|
||||
|
||||
const openGetCodeModal = () => setIsGetCodeDialogOpened(true);
|
||||
|
||||
const closeGetCodeModal = () => setIsGetCodeDialogOpened(false);
|
||||
|
||||
const onTypeSelect = (option) => {
|
||||
// setFileOptions((prevFileOptions) => prevFileOptions.filter((file) => file.key !== option.key));
|
||||
setSelectedType(option);
|
||||
setConfig((config) => {
|
||||
return { ...config, filterParam: option.key };
|
||||
});
|
||||
|
||||
// if (!selectedFileTypes.find((type) => type.key === option.key)) {
|
||||
// setSelectedFileTypes((prevFileTypes) => [...prevFileTypes, option]);
|
||||
// }
|
||||
};
|
||||
|
||||
const deleteSelectedType = (option) => {
|
||||
setFileOptions((prevFileOptions) => [option, ...prevFileOptions]);
|
||||
const filteredTypes = selectedFileTypes.filter((type) => type.key !== option.key);
|
||||
setSelectedFileTypes(filteredTypes);
|
||||
};
|
||||
|
||||
const toggleWithSearch = () => {
|
||||
setConfig((config) => ({ ...config, withSearch: !config.withSearch }));
|
||||
};
|
||||
|
||||
// const toggleBreadCrumbs = () => {
|
||||
// setConfig((config) => ({ ...config, withBreadCrumbs: !config.withBreadCrumbs }));
|
||||
// };
|
||||
|
||||
const toggleWithSubtitle = () => {
|
||||
setConfig((config) => ({ ...config, withSubtitle: !config.withSubtitle }));
|
||||
};
|
||||
|
||||
const onChangeAcceptLabel = (e) => {
|
||||
setConfig((config) => {
|
||||
return { ...config, acceptButtonLabel: e.target.value };
|
||||
});
|
||||
};
|
||||
|
||||
const onChangeCancelLabel = (e) => {
|
||||
setConfig((config) => {
|
||||
return { ...config, cancelButtonLabel: e.target.value };
|
||||
});
|
||||
};
|
||||
|
||||
const onResize = () => {
|
||||
const isEnoughWidthForPreview = window.innerWidth > showPreviewThreshold;
|
||||
if (isEnoughWidthForPreview !== showPreview) setShowPreview(isEnoughWidthForPreview);
|
||||
};
|
||||
|
||||
const setButtonColor = (color) => {
|
||||
setConfig((config) => ({ ...config, buttonColor: color }));
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
window.addEventListener("resize", onResize);
|
||||
return () => {
|
||||
window.removeEventListener("resize", onResize);
|
||||
};
|
||||
}, [showPreview]);
|
||||
|
||||
const codeBlock = `<div id="${frameId}">Fallback text</div>\n<script src="${scriptUrl}${params}"></script>`;
|
||||
|
||||
const preview = (
|
||||
<Frame
|
||||
width={width + widthDimension.label}
|
||||
height={height + heightDimension.label}
|
||||
targetId={frameId}
|
||||
>
|
||||
<Box id={frameId}></Box>
|
||||
</Frame>
|
||||
);
|
||||
|
||||
const code = (
|
||||
<CodeWrapper width={width + widthDimension.label} height={height + heightDimension.label}>
|
||||
<CategorySubHeader className="copy-window-code">{t("CopyWindowCode")}</CategorySubHeader>
|
||||
<Textarea value={codeBlock} heightTextArea={153} />
|
||||
</CodeWrapper>
|
||||
);
|
||||
|
||||
const dataTabs =
|
||||
selectedElementType === "element"
|
||||
? [
|
||||
{
|
||||
key: "preview",
|
||||
title: t("Common:Preview"),
|
||||
content: preview,
|
||||
},
|
||||
{
|
||||
key: "code",
|
||||
title: t("Code"),
|
||||
content: code,
|
||||
},
|
||||
]
|
||||
: [
|
||||
{
|
||||
key: "preview",
|
||||
title: t("Common:Preview"),
|
||||
content: preview,
|
||||
},
|
||||
{
|
||||
key: "selector-preview",
|
||||
title: t("SelectorPreview"),
|
||||
content: preview,
|
||||
},
|
||||
{
|
||||
key: "code",
|
||||
title: t("Code"),
|
||||
content: code,
|
||||
},
|
||||
];
|
||||
|
||||
return (
|
||||
<SDKContainer>
|
||||
<CategoryDescription>
|
||||
<Text className="sdk-description">{t("FileSelectorPresetDescription")}</Text>
|
||||
</CategoryDescription>
|
||||
<CategoryHeader>{t("CreateSampleHeader")}</CategoryHeader>
|
||||
<Container>
|
||||
{showPreview && (
|
||||
<Preview>
|
||||
<TabsContainer onSelect={onChangeTab} elements={dataTabs} />
|
||||
</Preview>
|
||||
)}
|
||||
<Controls>
|
||||
<ControlsSection>
|
||||
<CategorySubHeader>{t("MainElementParameter")}</CategorySubHeader>
|
||||
<RadioButtonGroup
|
||||
orientation="vertical"
|
||||
options={elementDisplayOptions}
|
||||
name="elementDisplayInput"
|
||||
selected={selectedElementType}
|
||||
onClick={toggleButtonMode}
|
||||
spacing="8px"
|
||||
/>
|
||||
{config.isButtonMode && (
|
||||
<>
|
||||
<CategorySubHeader>{t("ButtonCustomization")}</CategorySubHeader>
|
||||
<ControlsGroup>
|
||||
<Label className="label" text={t("ButtonColor")} />
|
||||
<ColorInput scale handleChange={setButtonColor} defaultColor={"#5299E0"} />
|
||||
</ControlsGroup>
|
||||
<ControlsGroup>
|
||||
<Label className="label" text={t("ButtonText")} />
|
||||
<TextInput
|
||||
scale
|
||||
onChange={(e) => {
|
||||
setConfig((config) => ({ ...config, buttonText: e.target.value }));
|
||||
}}
|
||||
placeholder={t("SelectToDocSpace")}
|
||||
value={config.buttonText}
|
||||
tabIndex={3}
|
||||
/>
|
||||
<Checkbox
|
||||
className="checkbox"
|
||||
label={"Logo"}
|
||||
onChange={() => {
|
||||
setConfig((config) => ({
|
||||
...config,
|
||||
buttonWithLogo: !config.buttonWithLogo,
|
||||
}));
|
||||
}}
|
||||
isChecked={config.buttonWithLogo}
|
||||
/>
|
||||
</ControlsGroup>
|
||||
</>
|
||||
)}
|
||||
</ControlsSection>
|
||||
|
||||
<ControlsSection>
|
||||
<CategorySubHeader>{t("CustomizingDisplay")}</CategorySubHeader>
|
||||
<ControlsGroup>
|
||||
<Label className="label" text={t("EmbeddingPanel:Width")} />
|
||||
<RowContainer combo>
|
||||
<TextInput
|
||||
onChange={onChangeWidth}
|
||||
placeholder={t("EnterWidth")}
|
||||
value={width}
|
||||
tabIndex={2}
|
||||
/>
|
||||
<ComboBox
|
||||
size="content"
|
||||
scaled={false}
|
||||
scaledOptions={true}
|
||||
onSelect={onChangeWidthDimension}
|
||||
options={dataDimensions}
|
||||
selectedOption={widthDimension}
|
||||
displaySelectedOption
|
||||
directionY="bottom"
|
||||
/>
|
||||
</RowContainer>
|
||||
</ControlsGroup>
|
||||
<ControlsGroup>
|
||||
<Label className="label" text={t("EmbeddingPanel:Height")} />
|
||||
<RowContainer combo>
|
||||
<TextInput
|
||||
onChange={onChangeHeight}
|
||||
placeholder={t("EnterHeight")}
|
||||
value={height}
|
||||
tabIndex={3}
|
||||
/>
|
||||
<ComboBox
|
||||
size="content"
|
||||
scaled={false}
|
||||
scaledOptions={true}
|
||||
onSelect={onChangeHeightDimension}
|
||||
options={dataDimensions}
|
||||
selectedOption={heightDimension}
|
||||
displaySelectedOption
|
||||
directionY="bottom"
|
||||
/>
|
||||
</RowContainer>
|
||||
</ControlsGroup>
|
||||
<ControlsGroup>
|
||||
<Label className="label" text={t("FrameId")} />
|
||||
<TextInput
|
||||
scale={true}
|
||||
onChange={onChangeFrameId}
|
||||
placeholder={t("EnterId")}
|
||||
value={config.frameId}
|
||||
tabIndex={4}
|
||||
/>
|
||||
</ControlsGroup>
|
||||
</ControlsSection>
|
||||
|
||||
<ControlsSection>
|
||||
<Label className="label">{t("InterfaceElements")}</Label>
|
||||
{/* <Checkbox
|
||||
className="checkbox"
|
||||
label={t("Common:Title")}
|
||||
onChange={toggleBreadCrumbs}
|
||||
isChecked={config.withBreadCrumbs}
|
||||
/> */}
|
||||
|
||||
<LabelGroup>
|
||||
<Checkbox
|
||||
className="checkbox"
|
||||
label={t("Subtitle")}
|
||||
onChange={toggleWithSubtitle}
|
||||
isChecked={config.withSubtitle}
|
||||
/>
|
||||
<HelpButton
|
||||
place="right"
|
||||
offsetRight={4}
|
||||
size={12}
|
||||
tooltipContent={
|
||||
<TooltipContent
|
||||
title={t("Subtitle")}
|
||||
description={t("SubtitleDescription")}
|
||||
img={SubtitleUrl}
|
||||
/>
|
||||
}
|
||||
/>
|
||||
</LabelGroup>
|
||||
<LabelGroup>
|
||||
<Checkbox
|
||||
className="checkbox"
|
||||
label={t("Common:Search")}
|
||||
onChange={toggleWithSearch}
|
||||
isChecked={config.withSearch}
|
||||
/>
|
||||
<HelpButton
|
||||
place="right"
|
||||
offsetRight={4}
|
||||
size={12}
|
||||
tooltipContent={
|
||||
<TooltipContent
|
||||
title={t("Common:Search")}
|
||||
description={t("FilesSearchDescription")}
|
||||
img={SearchUrl}
|
||||
/>
|
||||
}
|
||||
/>
|
||||
</LabelGroup>
|
||||
<Label className="label" text={t("SelectButtonText")} />
|
||||
<TextInput
|
||||
scale={true}
|
||||
onChange={onChangeAcceptLabel}
|
||||
placeholder={t("Common:SelectAction")}
|
||||
value={config.acceptButtonLabel}
|
||||
tabIndex={4}
|
||||
/>
|
||||
<Label className="label" text={t("CancelButtonText")} />
|
||||
<TextInput
|
||||
scale={true}
|
||||
onChange={onChangeCancelLabel}
|
||||
placeholder={t("Common:CancelButton")}
|
||||
value={config.cancelButtonLabel}
|
||||
tabIndex={4}
|
||||
/>
|
||||
</ControlsSection>
|
||||
|
||||
<ControlsSection>
|
||||
<CategorySubHeader>{t("DataDisplay")}</CategorySubHeader>
|
||||
<ControlsGroup>
|
||||
<LabelGroup>
|
||||
<Label className="label" text={t("RoomOrFolder")} />
|
||||
<HelpButton
|
||||
offsetRight={0}
|
||||
size={12}
|
||||
tooltipContent={<Text fontSize="12px">{t("RoomOrFolderDescription")}</Text>}
|
||||
/>
|
||||
</LabelGroup>
|
||||
<FilesSelectorInputWrapper>
|
||||
<FilesSelectorInput onSelectFolder={onChangeFolderId} isSelect />
|
||||
</FilesSelectorInputWrapper>
|
||||
</ControlsGroup>
|
||||
{sharedLinks && (
|
||||
<ControlsGroup>
|
||||
<LabelGroup>
|
||||
<Label className="label" text={t("SharingPanel:ExternalLink")} />
|
||||
<HelpButton
|
||||
offsetRight={0}
|
||||
size={12}
|
||||
tooltipContent={
|
||||
<Text fontSize="12px">{t("CreateEditRoomDialog:PublicRoomDescription")}</Text>
|
||||
}
|
||||
/>
|
||||
</LabelGroup>
|
||||
<ComboBox
|
||||
scaled={true}
|
||||
onSelect={onChangeSharedLink}
|
||||
options={sharedLinks}
|
||||
selectedOption={sharedLinks[0]}
|
||||
displaySelectedOption
|
||||
directionY="bottom"
|
||||
/>
|
||||
</ControlsGroup>
|
||||
)}
|
||||
</ControlsSection>
|
||||
|
||||
<ControlsSection>
|
||||
<CategorySubHeader>{t("AdvancedDisplay")}</CategorySubHeader>
|
||||
<Label className="label" text={t("FileTypeDisplay")} />
|
||||
<RadioButtonGroup
|
||||
orientation="vertical"
|
||||
options={fileTypeDisplay}
|
||||
name="columnsDisplayOptions"
|
||||
selected={typeDisplay}
|
||||
onClick={changeColumnsOption}
|
||||
spacing="8px"
|
||||
/>
|
||||
{typeDisplay === "custom-types" && (
|
||||
<>
|
||||
<ComboBox
|
||||
onSelect={onTypeSelect}
|
||||
options={
|
||||
fileOptions || {
|
||||
key: "Select",
|
||||
label: t("Common:SelectAction"),
|
||||
}
|
||||
}
|
||||
scaled={true}
|
||||
directionY="top"
|
||||
selectedOption={selectedType}
|
||||
// selectedOption={{
|
||||
// key: "Select",
|
||||
// label: t("Common:SelectAction"),
|
||||
// }}
|
||||
/>
|
||||
|
||||
{/* <SelectedItemsContainer>
|
||||
{selectedFileTypes.map((type) => (
|
||||
<SelectedItem
|
||||
key={type.key}
|
||||
onClick={() => deleteSelectedType(type)}
|
||||
label={type.label}
|
||||
/>
|
||||
))}
|
||||
</SelectedItemsContainer> */}
|
||||
</>
|
||||
)}
|
||||
</ControlsSection>
|
||||
</Controls>
|
||||
</Container>
|
||||
|
||||
{!showPreview && (
|
||||
<>
|
||||
<GetCodeButtonWrapper>
|
||||
<Button
|
||||
id="get-sdk-code-button"
|
||||
primary
|
||||
size="normal"
|
||||
scale
|
||||
label={t("GetCode")}
|
||||
onClick={openGetCodeModal}
|
||||
/>
|
||||
</GetCodeButtonWrapper>
|
||||
|
||||
<GetCodeDialog
|
||||
t={t}
|
||||
visible={isGetCodeDialogOpened}
|
||||
codeBlock={codeBlock}
|
||||
onClose={closeGetCodeModal}
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
</SDKContainer>
|
||||
);
|
||||
};
|
||||
|
||||
export default inject(({ authStore, settingsStore, publicRoomStore }) => {
|
||||
const { setDocumentTitle } = authStore;
|
||||
const { theme } = settingsStore;
|
||||
const { fetchExternalLinks } = publicRoomStore;
|
||||
|
||||
return {
|
||||
theme,
|
||||
setDocumentTitle,
|
||||
fetchExternalLinks,
|
||||
};
|
||||
})(
|
||||
withTranslation([
|
||||
"JavascriptSdk",
|
||||
"Files",
|
||||
"EmbeddingPanel",
|
||||
"Common",
|
||||
"Translations",
|
||||
"SharingPanel",
|
||||
])(observer(FileSelector)),
|
||||
);
|
@ -0,0 +1,483 @@
|
||||
import { useState, useEffect } from "react";
|
||||
import { withTranslation } from "react-i18next";
|
||||
import debounce from "lodash.debounce";
|
||||
import { Box } from "@docspace/shared/components/box";
|
||||
import { TextInput } from "@docspace/shared/components/text-input";
|
||||
import { Textarea } from "@docspace/shared/components/textarea";
|
||||
import { Label } from "@docspace/shared/components/label";
|
||||
import { Text } from "@docspace/shared/components/text";
|
||||
import { Checkbox } from "@docspace/shared/components/checkbox";
|
||||
import { ComboBox } from "@docspace/shared/components/combobox";
|
||||
import { TabsContainer } from "@docspace/shared/components/tabs-container";
|
||||
import { RadioButtonGroup } from "@docspace/shared/components/radio-button-group";
|
||||
import { ColorInput } from "@docspace/shared/components/color-input";
|
||||
import { objectToGetParams, loadScript } from "@docspace/shared/utils/common";
|
||||
import { inject, observer } from "mobx-react";
|
||||
|
||||
import { isTablet, isMobile } from "@docspace/shared/utils/device";
|
||||
|
||||
import GetCodeDialog from "../sub-components/GetCodeDialog";
|
||||
import { Button } from "@docspace/shared/components/button";
|
||||
|
||||
import { RoomsType } from "@docspace/shared/enums";
|
||||
|
||||
import { toastr } from "@docspace/shared/components/toast";
|
||||
|
||||
const showPreviewThreshold = 720;
|
||||
|
||||
import {
|
||||
SDKContainer,
|
||||
Controls,
|
||||
CategoryHeader,
|
||||
CategorySubHeader,
|
||||
CategoryDescription,
|
||||
ControlsGroup,
|
||||
ControlsSection,
|
||||
Frame,
|
||||
Container,
|
||||
RowContainer,
|
||||
Preview,
|
||||
GetCodeButtonWrapper,
|
||||
CodeWrapper,
|
||||
} from "./StyledPresets";
|
||||
|
||||
const RoomSelector = (props) => {
|
||||
const { t, setDocumentTitle } = props;
|
||||
|
||||
setDocumentTitle(t("JavascriptSdk"));
|
||||
|
||||
const scriptUrl = `${window.location.origin}/static/scripts/api.js`;
|
||||
|
||||
const dataDimensions = [
|
||||
{ key: "percent", label: "%", default: true },
|
||||
{ key: "pixel", label: "px" },
|
||||
];
|
||||
|
||||
const elementDisplayOptions = [
|
||||
{ value: "element", label: t("ElementItself") },
|
||||
{
|
||||
value: "button",
|
||||
label: (
|
||||
<RowContainer>
|
||||
{t("Common:Button")}
|
||||
<Text color="gray">{`(${t("ElementCalledAfterClicking")})`}</Text>
|
||||
</RowContainer>
|
||||
),
|
||||
},
|
||||
];
|
||||
|
||||
const roomTypeOptions = [
|
||||
{ key: "room-type-all", label: t("AllTypes"), roomType: undefined, default: true },
|
||||
{
|
||||
key: "room-type-collaboration",
|
||||
label: t("CreateEditRoomDialog:CollaborationRoomTitle"),
|
||||
roomType: RoomsType.EditingRoom,
|
||||
},
|
||||
{ key: "room-type-public", label: t("Files:PublicRoom"), roomType: RoomsType.PublicRoom },
|
||||
{
|
||||
key: "room-type-custom",
|
||||
label: t("CreateEditRoomDialog:CustomRoomTitle"),
|
||||
roomType: RoomsType.CustomRoom,
|
||||
},
|
||||
];
|
||||
|
||||
const [widthDimension, setWidthDimension] = useState(dataDimensions[1]);
|
||||
const [heightDimension, setHeightDimension] = useState(dataDimensions[0]);
|
||||
const [width, setWidth] = useState("600");
|
||||
const [height, setHeight] = useState("100");
|
||||
const [isGetCodeDialogOpened, setIsGetCodeDialogOpened] = useState(false);
|
||||
const [showPreview, setShowPreview] = useState(window.innerWidth > showPreviewThreshold);
|
||||
const [selectedElementType, setSelectedElementType] = useState(elementDisplayOptions[0].value);
|
||||
const [roomType, setRoomType] = useState(roomTypeOptions[0]);
|
||||
|
||||
const debouncedOnSelect = debounce((items) => {
|
||||
toastr.success(items[0].label);
|
||||
}, 0);
|
||||
|
||||
const [config, setConfig] = useState({
|
||||
mode: "room-selector",
|
||||
width: `${width}${widthDimension.label}`,
|
||||
height: `${height}${heightDimension.label}`,
|
||||
frameId: "ds-frame",
|
||||
init: true,
|
||||
showSelectorCancel: true,
|
||||
showSelectorHeader: true,
|
||||
withSearch: true,
|
||||
acceptButtonLabel: t("Common:SelectAction"),
|
||||
cancelButtonLabel: t("Common:CancelButton"),
|
||||
isButtonMode: false,
|
||||
buttonWithLogo: true,
|
||||
events: {
|
||||
onSelectCallback: debouncedOnSelect,
|
||||
onCloseCallback: null,
|
||||
onAppReady: null,
|
||||
onAppError: (e) => console.log("onAppError", e),
|
||||
onEditorCloseCallback: null,
|
||||
onAuthSuccess: null,
|
||||
onSignOut: null,
|
||||
},
|
||||
});
|
||||
|
||||
const params = objectToGetParams(config);
|
||||
|
||||
const frameId = config.frameId || "ds-frame";
|
||||
|
||||
const destroyFrame = () => {
|
||||
window.DocSpace?.SDK?.frames[frameId]?.destroyFrame();
|
||||
};
|
||||
|
||||
const loadFrame = debounce(() => {
|
||||
const script = document.getElementById("integration");
|
||||
|
||||
if (script) {
|
||||
script.remove();
|
||||
}
|
||||
|
||||
const params = objectToGetParams(config);
|
||||
|
||||
loadScript(`${scriptUrl}${params}`, "integration", () => window.DocSpace.SDK.initFrame(config));
|
||||
}, 500);
|
||||
|
||||
useEffect(() => {
|
||||
loadFrame();
|
||||
return destroyFrame;
|
||||
});
|
||||
|
||||
const toggleButtonMode = (e) => {
|
||||
setSelectedElementType(e.target.value);
|
||||
setConfig((config) => ({ ...config, isButtonMode: e.target.value === "button" }));
|
||||
};
|
||||
|
||||
const changeRoomType = (option) => {
|
||||
setRoomType(option);
|
||||
setConfig((config) => ({ ...config, roomType: option.roomType }));
|
||||
};
|
||||
|
||||
const onChangeTab = (tab) => {
|
||||
if (tab.key === "preview" && selectedElementType === "button") {
|
||||
setConfig((config) => ({ ...config, isButtonMode: true }));
|
||||
} else if (tab.key === "selector-preview") {
|
||||
setConfig((config) => ({ ...config, isButtonMode: false }));
|
||||
} else if (tab.key === "code") {
|
||||
setConfig((config) => ({ ...config, isButtonMode: selectedElementType === "button" }));
|
||||
}
|
||||
};
|
||||
|
||||
const onChangeWidth = (e) => {
|
||||
setConfig((config) => {
|
||||
return { ...config, width: `${e.target.value}${widthDimension.label}` };
|
||||
});
|
||||
|
||||
setWidth(e.target.value);
|
||||
};
|
||||
|
||||
const onChangeHeight = (e) => {
|
||||
setConfig((config) => {
|
||||
return { ...config, height: `${e.target.value}${heightDimension.label}` };
|
||||
});
|
||||
|
||||
setHeight(e.target.value);
|
||||
};
|
||||
|
||||
const onChangeFrameId = (e) => {
|
||||
setConfig((config) => {
|
||||
return { ...config, frameId: e.target.value };
|
||||
});
|
||||
};
|
||||
|
||||
const onChangeWidthDimension = (item) => {
|
||||
setConfig((config) => {
|
||||
return { ...config, width: `${width}${item.label}` };
|
||||
});
|
||||
|
||||
setWidthDimension(item);
|
||||
};
|
||||
|
||||
const onChangeHeightDimension = (item) => {
|
||||
setConfig((config) => {
|
||||
return { ...config, height: `${height}${item.label}` };
|
||||
});
|
||||
|
||||
setHeightDimension(item);
|
||||
};
|
||||
|
||||
const toggleWithSearch = () => {
|
||||
setConfig((config) => ({ ...config, withSearch: !config.withSearch }));
|
||||
};
|
||||
|
||||
const onChangeAcceptLabel = (e) => {
|
||||
setConfig((config) => {
|
||||
return { ...config, acceptButtonLabel: e.target.value };
|
||||
});
|
||||
};
|
||||
|
||||
const onChangeCancelLabel = (e) => {
|
||||
setConfig((config) => {
|
||||
return { ...config, cancelButtonLabel: e.target.value };
|
||||
});
|
||||
};
|
||||
|
||||
const openGetCodeModal = () => setIsGetCodeDialogOpened(true);
|
||||
|
||||
const closeGetCodeModal = () => setIsGetCodeDialogOpened(false);
|
||||
|
||||
const onResize = () => {
|
||||
const isEnoughWidthForPreview = window.innerWidth > showPreviewThreshold;
|
||||
if (isEnoughWidthForPreview !== showPreview) setShowPreview(isEnoughWidthForPreview);
|
||||
};
|
||||
|
||||
const setButtonColor = (color) => {
|
||||
setConfig((config) => ({ ...config, buttonColor: color }));
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
window.addEventListener("resize", onResize);
|
||||
return () => {
|
||||
window.removeEventListener("resize", onResize);
|
||||
};
|
||||
}, [showPreview]);
|
||||
|
||||
const codeBlock = `<div id="${frameId}">Fallback text</div>\n<script src="${scriptUrl}${params}"></script>`;
|
||||
|
||||
const preview = (
|
||||
<Frame
|
||||
width={width + widthDimension.label}
|
||||
height={height + heightDimension.label}
|
||||
targetId={frameId}
|
||||
>
|
||||
<Box id={frameId}></Box>
|
||||
</Frame>
|
||||
);
|
||||
|
||||
const code = (
|
||||
<CodeWrapper width={width + widthDimension.label} height={height + heightDimension.label}>
|
||||
<CategorySubHeader className="copy-window-code">{t("CopyWindowCode")}</CategorySubHeader>
|
||||
<Textarea value={codeBlock} heightTextArea={153} />
|
||||
</CodeWrapper>
|
||||
);
|
||||
|
||||
const dataTabs =
|
||||
selectedElementType === "element"
|
||||
? [
|
||||
{
|
||||
key: "preview",
|
||||
title: t("Common:Preview"),
|
||||
content: preview,
|
||||
},
|
||||
{
|
||||
key: "code",
|
||||
title: t("Code"),
|
||||
content: code,
|
||||
},
|
||||
]
|
||||
: [
|
||||
{
|
||||
key: "preview",
|
||||
title: t("Common:Preview"),
|
||||
content: preview,
|
||||
},
|
||||
{
|
||||
key: "selector-preview",
|
||||
title: t("SelectorPreview"),
|
||||
content: preview,
|
||||
},
|
||||
{
|
||||
key: "code",
|
||||
title: t("Code"),
|
||||
content: code,
|
||||
},
|
||||
];
|
||||
|
||||
return (
|
||||
<SDKContainer>
|
||||
<CategoryDescription>
|
||||
<Text className="sdk-description">{t("RoomSelectorPresetDescription")}</Text>
|
||||
</CategoryDescription>
|
||||
<CategoryHeader>{t("CreateSampleHeader")}</CategoryHeader>
|
||||
<Container>
|
||||
{showPreview && (
|
||||
<Preview>
|
||||
<TabsContainer onSelect={onChangeTab} elements={dataTabs} />
|
||||
</Preview>
|
||||
)}
|
||||
<Controls>
|
||||
<ControlsSection>
|
||||
<CategorySubHeader>{t("MainElementParameter")}</CategorySubHeader>
|
||||
<RadioButtonGroup
|
||||
orientation="vertical"
|
||||
options={elementDisplayOptions}
|
||||
name="elementDisplayInput"
|
||||
selected={selectedElementType}
|
||||
onClick={toggleButtonMode}
|
||||
spacing="8px"
|
||||
/>
|
||||
{config.isButtonMode && (
|
||||
<>
|
||||
<CategorySubHeader>{t("ButtonCustomization")}</CategorySubHeader>
|
||||
<ControlsGroup>
|
||||
<Label className="label" text={t("ButtonColor")} />
|
||||
<ColorInput scale handleChange={setButtonColor} defaultColor={"#5299E0"} />
|
||||
</ControlsGroup>
|
||||
<ControlsGroup>
|
||||
<Label className="label" text={t("ButtonText")} />
|
||||
<TextInput
|
||||
scale
|
||||
onChange={(e) => {
|
||||
setConfig((config) => ({ ...config, buttonText: e.target.value }));
|
||||
}}
|
||||
placeholder={t("SelectToDocSpace")}
|
||||
value={config.buttonText}
|
||||
tabIndex={3}
|
||||
/>
|
||||
<Checkbox
|
||||
className="checkbox"
|
||||
label={"Logo"}
|
||||
onChange={() => {
|
||||
setConfig((config) => ({
|
||||
...config,
|
||||
buttonWithLogo: !config.buttonWithLogo,
|
||||
}));
|
||||
}}
|
||||
isChecked={config.buttonWithLogo}
|
||||
/>
|
||||
</ControlsGroup>
|
||||
</>
|
||||
)}
|
||||
</ControlsSection>
|
||||
|
||||
<ControlsSection>
|
||||
<CategorySubHeader>{t("CustomizingDisplay")}</CategorySubHeader>
|
||||
<ControlsGroup>
|
||||
<Label className="label" text={t("EmbeddingPanel:Width")} />
|
||||
<RowContainer combo>
|
||||
<TextInput
|
||||
onChange={onChangeWidth}
|
||||
placeholder={t("EnterWidth")}
|
||||
value={width}
|
||||
tabIndex={4}
|
||||
/>
|
||||
<ComboBox
|
||||
size="content"
|
||||
scaled={false}
|
||||
scaledOptions={true}
|
||||
onSelect={onChangeWidthDimension}
|
||||
options={dataDimensions}
|
||||
selectedOption={widthDimension}
|
||||
displaySelectedOption
|
||||
directionY="bottom"
|
||||
/>
|
||||
</RowContainer>
|
||||
</ControlsGroup>
|
||||
<ControlsGroup>
|
||||
<Label className="label" text={t("EmbeddingPanel:Height")} />
|
||||
<RowContainer combo>
|
||||
<TextInput
|
||||
onChange={onChangeHeight}
|
||||
placeholder={t("EnterHeight")}
|
||||
value={height}
|
||||
tabIndex={5}
|
||||
/>
|
||||
<ComboBox
|
||||
size="content"
|
||||
scaled={false}
|
||||
scaledOptions={true}
|
||||
onSelect={onChangeHeightDimension}
|
||||
options={dataDimensions}
|
||||
selectedOption={heightDimension}
|
||||
displaySelectedOption
|
||||
directionY="bottom"
|
||||
/>
|
||||
</RowContainer>
|
||||
</ControlsGroup>
|
||||
<ControlsGroup>
|
||||
<Label className="label" text={t("FrameId")} />
|
||||
<TextInput
|
||||
scale={true}
|
||||
onChange={onChangeFrameId}
|
||||
placeholder={t("EnterId")}
|
||||
value={config.frameId}
|
||||
tabIndex={6}
|
||||
/>
|
||||
</ControlsGroup>
|
||||
</ControlsSection>
|
||||
|
||||
<ControlsSection>
|
||||
<Label className="label">{t("InterfaceElements")}</Label>
|
||||
<Checkbox
|
||||
className="checkbox"
|
||||
label={t("Common:Search")}
|
||||
onChange={toggleWithSearch}
|
||||
isChecked={config.withSearch}
|
||||
/>
|
||||
<Label className="label" text={t("SelectButtonText")} />
|
||||
<TextInput
|
||||
scale={true}
|
||||
onChange={onChangeAcceptLabel}
|
||||
placeholder={t("Common:SelectAction")}
|
||||
value={config.acceptButtonLabel}
|
||||
tabIndex={7}
|
||||
/>
|
||||
<Label className="label" text={t("CancelButtonText")} />
|
||||
<TextInput
|
||||
scale={true}
|
||||
onChange={onChangeCancelLabel}
|
||||
placeholder={t("Common:CancelButton")}
|
||||
value={config.cancelButtonLabel}
|
||||
tabIndex={8}
|
||||
/>
|
||||
</ControlsSection>
|
||||
|
||||
<ControlsSection>
|
||||
<CategorySubHeader>{t("AdvancedDisplay")}</CategorySubHeader>
|
||||
|
||||
<Label className="label" text={t("RoomTypeDisplay")} />
|
||||
<ComboBox
|
||||
onSelect={changeRoomType}
|
||||
options={roomTypeOptions}
|
||||
scaled={true}
|
||||
selectedOption={roomType}
|
||||
displaySelectedOption
|
||||
directionY="top"
|
||||
/>
|
||||
</ControlsSection>
|
||||
</Controls>
|
||||
</Container>
|
||||
|
||||
{!showPreview && (
|
||||
<>
|
||||
<GetCodeButtonWrapper>
|
||||
<Button
|
||||
id="get-sdk-code-button"
|
||||
primary
|
||||
size="normal"
|
||||
scale
|
||||
label={t("GetCode")}
|
||||
onClick={openGetCodeModal}
|
||||
/>
|
||||
</GetCodeButtonWrapper>
|
||||
|
||||
<GetCodeDialog
|
||||
t={t}
|
||||
visible={isGetCodeDialogOpened}
|
||||
codeBlock={codeBlock}
|
||||
onClose={closeGetCodeModal}
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
</SDKContainer>
|
||||
);
|
||||
};
|
||||
|
||||
export default inject(({ authStore, settingsStore }) => {
|
||||
const { setDocumentTitle } = authStore;
|
||||
const { theme } = settingsStore;
|
||||
|
||||
return {
|
||||
theme,
|
||||
setDocumentTitle,
|
||||
};
|
||||
})(
|
||||
withTranslation(["JavascriptSdk", "Files", "EmbeddingPanel", "Common", "CreateEditRoomDialog"])(
|
||||
observer(RoomSelector),
|
||||
),
|
||||
);
|
@ -0,0 +1,407 @@
|
||||
import { useState, useEffect } from "react";
|
||||
import { withTranslation } from "react-i18next";
|
||||
import debounce from "lodash.debounce";
|
||||
import { Box } from "@docspace/shared/components/box";
|
||||
import { TextInput } from "@docspace/shared/components/text-input";
|
||||
import { Textarea } from "@docspace/shared/components/textarea";
|
||||
import { Label } from "@docspace/shared/components/label";
|
||||
import { Text } from "@docspace/shared/components/text";
|
||||
import { ComboBox } from "@docspace/shared/components/combobox";
|
||||
import { TabsContainer } from "@docspace/shared/components/tabs-container";
|
||||
import FilesSelectorInput from "SRC_DIR/components/FilesSelectorInput";
|
||||
import { objectToGetParams, loadScript } from "@docspace/shared/utils/common";
|
||||
import { inject, observer } from "mobx-react";
|
||||
|
||||
import { isTablet, isMobile } from "@docspace/shared/utils/device";
|
||||
|
||||
import { HelpButton } from "@docspace/shared/components/help-button";
|
||||
|
||||
import GetCodeDialog from "../sub-components/GetCodeDialog";
|
||||
import { Button } from "@docspace/shared/components/button";
|
||||
|
||||
import EmptyIframeContainer from "../sub-components/EmptyIframeContainer";
|
||||
|
||||
const showPreviewThreshold = 720;
|
||||
|
||||
import {
|
||||
SDKContainer,
|
||||
Controls,
|
||||
CategoryHeader,
|
||||
CategorySubHeader,
|
||||
CategoryDescription,
|
||||
ControlsGroup,
|
||||
LabelGroup,
|
||||
Frame,
|
||||
Container,
|
||||
RowContainer,
|
||||
Preview,
|
||||
GetCodeButtonWrapper,
|
||||
FilesSelectorInputWrapper,
|
||||
ControlsSection,
|
||||
CodeWrapper,
|
||||
} from "./StyledPresets";
|
||||
|
||||
const SimpleRoom = (props) => {
|
||||
const { t, setDocumentTitle, fetchExternalLinks } = props;
|
||||
|
||||
setDocumentTitle(t("JavascriptSdk"));
|
||||
|
||||
const scriptUrl = `${window.location.origin}/static/scripts/api.js`;
|
||||
|
||||
const dataDimensions = [
|
||||
{ key: "percent", label: "%", default: true },
|
||||
{ key: "pixel", label: "px" },
|
||||
];
|
||||
|
||||
const [widthDimension, setWidthDimension] = useState(dataDimensions[0]);
|
||||
const [heightDimension, setHeightDimension] = useState(dataDimensions[1]);
|
||||
const [width, setWidth] = useState("100");
|
||||
const [height, setHeight] = useState(isTablet() ? "400" : isMobile() ? "206" : "600");
|
||||
const [isGetCodeDialogOpened, setIsGetCodeDialogOpened] = useState(false);
|
||||
const [showPreview, setShowPreview] = useState(window.innerWidth > showPreviewThreshold);
|
||||
const [sharedLinks, setSharedLinks] = useState(null);
|
||||
|
||||
const [config, setConfig] = useState({
|
||||
mode: "manager",
|
||||
width: `${width}${widthDimension.label}`,
|
||||
height: `${height}${heightDimension.label}`,
|
||||
frameId: "ds-frame",
|
||||
showHeader: false,
|
||||
showTitle: true,
|
||||
showMenu: false,
|
||||
showFilter: true,
|
||||
disableActionButton: false,
|
||||
infoPanelVisible: false,
|
||||
init: false,
|
||||
filter: {
|
||||
count: 100,
|
||||
page: 1,
|
||||
sortorder: "descending",
|
||||
sortby: "DateAndTime",
|
||||
search: "",
|
||||
withSubfolders: false,
|
||||
},
|
||||
});
|
||||
|
||||
const params = objectToGetParams(config);
|
||||
|
||||
const frameId = config.frameId || "ds-frame";
|
||||
|
||||
const destroyFrame = () => {
|
||||
window.DocSpace?.SDK?.frames[frameId]?.destroyFrame();
|
||||
};
|
||||
|
||||
const loadFrame = debounce(() => {
|
||||
const script = document.getElementById("integration");
|
||||
|
||||
if (script) {
|
||||
script.remove();
|
||||
}
|
||||
|
||||
const params = objectToGetParams(config);
|
||||
|
||||
loadScript(`${scriptUrl}${params}`, "integration", () => window.DocSpace.SDK.initFrame(config));
|
||||
}, 500);
|
||||
|
||||
useEffect(() => {
|
||||
loadFrame();
|
||||
return () => destroyFrame();
|
||||
});
|
||||
|
||||
const onChangeTab = () => {
|
||||
loadFrame();
|
||||
};
|
||||
|
||||
const onChangeWidth = (e) => {
|
||||
setConfig((config) => {
|
||||
return { ...config, width: `${e.target.value}${widthDimension.label}` };
|
||||
});
|
||||
|
||||
setWidth(e.target.value);
|
||||
};
|
||||
|
||||
const onChangeHeight = (e) => {
|
||||
setConfig((config) => {
|
||||
return { ...config, height: `${e.target.value}${heightDimension.label}` };
|
||||
});
|
||||
|
||||
setHeight(e.target.value);
|
||||
};
|
||||
|
||||
const onChangeFolderId = async (id, publicInPath) => {
|
||||
let newConfig = { id, requestToken: null, rootPath: "/rooms/shared/" };
|
||||
|
||||
if (!!publicInPath) {
|
||||
const links = await fetchExternalLinks(publicInPath.id);
|
||||
|
||||
if (links.length > 1) {
|
||||
const linksOptions = links.map((link) => {
|
||||
const { id, title, requestToken } = link.sharedTo;
|
||||
|
||||
return {
|
||||
key: id,
|
||||
label: title,
|
||||
requestToken: requestToken,
|
||||
};
|
||||
});
|
||||
|
||||
setSharedLinks(linksOptions);
|
||||
}
|
||||
|
||||
newConfig.requestToken = links[0].sharedTo?.requestToken;
|
||||
newConfig.rootPath = "/rooms/share";
|
||||
} else {
|
||||
setSharedLinks(null);
|
||||
}
|
||||
|
||||
setConfig((config) => {
|
||||
return { ...config, ...newConfig, init: true };
|
||||
});
|
||||
};
|
||||
|
||||
const onChangeSharedLink = (link) => {
|
||||
setConfig((config) => {
|
||||
return { ...config, requestToken: link.requestToken };
|
||||
});
|
||||
};
|
||||
|
||||
const onChangeFrameId = (e) => {
|
||||
setConfig((config) => {
|
||||
return { ...config, frameId: e.target.value };
|
||||
});
|
||||
};
|
||||
|
||||
const onChangeWidthDimension = (item) => {
|
||||
setConfig((config) => {
|
||||
return { ...config, width: `${width}${item.label}` };
|
||||
});
|
||||
|
||||
setWidthDimension(item);
|
||||
};
|
||||
|
||||
const onChangeHeightDimension = (item) => {
|
||||
setConfig((config) => {
|
||||
return { ...config, height: `${height}${item.label}` };
|
||||
});
|
||||
|
||||
setHeightDimension(item);
|
||||
};
|
||||
|
||||
const openGetCodeModal = () => setIsGetCodeDialogOpened(true);
|
||||
|
||||
const closeGetCodeModal = () => setIsGetCodeDialogOpened(false);
|
||||
|
||||
const onResize = () => {
|
||||
const isEnoughWidthForPreview = window.innerWidth > showPreviewThreshold;
|
||||
if (isEnoughWidthForPreview !== showPreview) setShowPreview(isEnoughWidthForPreview);
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
window.addEventListener("resize", onResize);
|
||||
return () => {
|
||||
window.removeEventListener("resize", onResize);
|
||||
};
|
||||
}, [showPreview]);
|
||||
|
||||
const codeBlock = `<div id="${frameId}">Fallback text</div>\n<script src="${scriptUrl}${params}"></script>`;
|
||||
|
||||
const preview = (
|
||||
<Frame
|
||||
width={width + widthDimension.label}
|
||||
height={height + heightDimension.label}
|
||||
targetId={frameId}
|
||||
>
|
||||
{config.id !== undefined ? (
|
||||
<>
|
||||
<Box id={frameId}></Box>
|
||||
</>
|
||||
) : (
|
||||
<EmptyIframeContainer
|
||||
text={t("SelectRoom")}
|
||||
width={width + widthDimension.label}
|
||||
height={height + heightDimension.label}
|
||||
/>
|
||||
)}
|
||||
</Frame>
|
||||
);
|
||||
|
||||
const code = (
|
||||
<CodeWrapper>
|
||||
<CategorySubHeader className="copy-window-code">{t("CopyWindowCode")}</CategorySubHeader>
|
||||
<Textarea value={codeBlock} heightTextArea={153} />
|
||||
</CodeWrapper>
|
||||
);
|
||||
|
||||
const dataTabs = [
|
||||
{
|
||||
key: "preview",
|
||||
title: t("Common:Preview"),
|
||||
content: preview,
|
||||
},
|
||||
{
|
||||
key: "code",
|
||||
title: t("Code"),
|
||||
content: code,
|
||||
},
|
||||
];
|
||||
|
||||
return (
|
||||
<SDKContainer>
|
||||
<CategoryDescription>
|
||||
<Text className="sdk-description">{t("SimpleRoomPresetDescription")}</Text>
|
||||
</CategoryDescription>
|
||||
<CategoryHeader>{t("CreateSampleHeader")}</CategoryHeader>
|
||||
<Container>
|
||||
{showPreview && (
|
||||
<Preview>
|
||||
<TabsContainer
|
||||
isDisabled={config?.id === undefined}
|
||||
onSelect={onChangeTab}
|
||||
elements={dataTabs}
|
||||
/>
|
||||
</Preview>
|
||||
)}
|
||||
<Controls>
|
||||
<ControlsSection>
|
||||
<CategorySubHeader>{t("DataDisplay")}</CategorySubHeader>
|
||||
<ControlsGroup>
|
||||
<LabelGroup>
|
||||
<Label className="label" text={t("Common:Room")} />
|
||||
<HelpButton
|
||||
offsetRight={0}
|
||||
size={12}
|
||||
tooltipContent={<Text fontSize="12px">{t("RoomOrFolderDescription")}</Text>}
|
||||
/>
|
||||
</LabelGroup>
|
||||
<FilesSelectorInputWrapper>
|
||||
<FilesSelectorInput onSelectFolder={onChangeFolderId} isSelect isRoomsOnly />
|
||||
</FilesSelectorInputWrapper>
|
||||
</ControlsGroup>
|
||||
{sharedLinks && (
|
||||
<ControlsGroup>
|
||||
<LabelGroup>
|
||||
<Label className="label" text={t("SharingPanel:ExternalLink")} />
|
||||
<HelpButton
|
||||
offsetRight={0}
|
||||
size={12}
|
||||
tooltipContent={
|
||||
<Text fontSize="12px">{t("CreateEditRoomDialog:PublicRoomDescription")}</Text>
|
||||
}
|
||||
/>
|
||||
</LabelGroup>
|
||||
<ComboBox
|
||||
scaled={true}
|
||||
onSelect={onChangeSharedLink}
|
||||
options={sharedLinks}
|
||||
selectedOption={sharedLinks[0]}
|
||||
displaySelectedOption
|
||||
directionY="bottom"
|
||||
/>
|
||||
</ControlsGroup>
|
||||
)}
|
||||
</ControlsSection>
|
||||
|
||||
<ControlsSection>
|
||||
<CategorySubHeader>{t("CustomizingDisplay")}</CategorySubHeader>
|
||||
<ControlsGroup>
|
||||
<Label className="label" text={t("EmbeddingPanel:Width")} />
|
||||
<RowContainer combo>
|
||||
<TextInput
|
||||
onChange={onChangeWidth}
|
||||
placeholder={t("EnterWidth")}
|
||||
value={width}
|
||||
tabIndex={2}
|
||||
/>
|
||||
<ComboBox
|
||||
size="content"
|
||||
scaled={false}
|
||||
scaledOptions={true}
|
||||
onSelect={onChangeWidthDimension}
|
||||
options={dataDimensions}
|
||||
selectedOption={widthDimension}
|
||||
displaySelectedOption
|
||||
directionY="bottom"
|
||||
/>
|
||||
</RowContainer>
|
||||
</ControlsGroup>
|
||||
<ControlsGroup>
|
||||
<Label className="label" text={t("EmbeddingPanel:Height")} />
|
||||
<RowContainer combo>
|
||||
<TextInput
|
||||
onChange={onChangeHeight}
|
||||
placeholder={t("EnterHeight")}
|
||||
value={height}
|
||||
tabIndex={3}
|
||||
/>
|
||||
<ComboBox
|
||||
size="content"
|
||||
scaled={false}
|
||||
scaledOptions={true}
|
||||
onSelect={onChangeHeightDimension}
|
||||
options={dataDimensions}
|
||||
selectedOption={heightDimension}
|
||||
displaySelectedOption
|
||||
directionY="bottom"
|
||||
/>
|
||||
</RowContainer>
|
||||
</ControlsGroup>
|
||||
<ControlsGroup>
|
||||
<Label className="label" text={t("FrameId")} />
|
||||
<TextInput
|
||||
scale={true}
|
||||
onChange={onChangeFrameId}
|
||||
placeholder={t("EnterId")}
|
||||
value={config.frameId}
|
||||
tabIndex={4}
|
||||
/>
|
||||
</ControlsGroup>
|
||||
</ControlsSection>
|
||||
</Controls>
|
||||
</Container>
|
||||
|
||||
{!showPreview && (
|
||||
<>
|
||||
<GetCodeButtonWrapper>
|
||||
<Button
|
||||
id="get-sdk-code-button"
|
||||
primary
|
||||
size="normal"
|
||||
scale
|
||||
label={t("GetCode")}
|
||||
onClick={openGetCodeModal}
|
||||
/>
|
||||
</GetCodeButtonWrapper>
|
||||
|
||||
<GetCodeDialog
|
||||
t={t}
|
||||
visible={isGetCodeDialogOpened}
|
||||
codeBlock={codeBlock}
|
||||
onClose={closeGetCodeModal}
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
</SDKContainer>
|
||||
);
|
||||
};
|
||||
|
||||
export default inject(({ authStore, settingsStore, publicRoomStore }) => {
|
||||
const { setDocumentTitle } = authStore;
|
||||
const { theme } = settingsStore;
|
||||
const { fetchExternalLinks } = publicRoomStore;
|
||||
|
||||
return {
|
||||
theme,
|
||||
setDocumentTitle,
|
||||
fetchExternalLinks,
|
||||
};
|
||||
})(
|
||||
withTranslation([
|
||||
"JavascriptSdk",
|
||||
"Files",
|
||||
"EmbeddingPanel",
|
||||
"Common",
|
||||
"Files",
|
||||
"Translations",
|
||||
"SharingPanel",
|
||||
])(observer(SimpleRoom)),
|
||||
);
|
@ -0,0 +1,264 @@
|
||||
import styled, { css } from "styled-components";
|
||||
import { isMobile, mobile, tablet } from "@docspace/shared/utils/device";
|
||||
import { Box } from "@docspace/shared/components/box";
|
||||
import Base from "@docspace/shared/themes/base";
|
||||
|
||||
export const SDKContainer = styled(Box)`
|
||||
@media ${tablet} {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
${isMobile() &&
|
||||
css`
|
||||
width: 100%;
|
||||
`}
|
||||
|
||||
.tabs_body {
|
||||
height: calc(100lvh - 260px);
|
||||
}
|
||||
`;
|
||||
|
||||
export const Controls = styled(Box)`
|
||||
max-width: 350px;
|
||||
min-width: 350px;
|
||||
width: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 32px;
|
||||
margin-top: 16px;
|
||||
|
||||
@media ${tablet} {
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
${isMobile() &&
|
||||
css`
|
||||
min-width: 0;
|
||||
`}
|
||||
|
||||
.label {
|
||||
min-width: fit-content;
|
||||
}
|
||||
|
||||
.checkbox {
|
||||
max-width: fit-content;
|
||||
}
|
||||
`;
|
||||
|
||||
export const CategoryHeader = styled.div`
|
||||
margin-top: 24px;
|
||||
margin-bottom: 24px;
|
||||
font-size: ${(props) => props.theme.getCorrectFontSize("16px")};
|
||||
font-style: normal;
|
||||
font-weight: 700;
|
||||
line-height: 22px;
|
||||
|
||||
@media ${tablet} {
|
||||
margin-top: 24px;
|
||||
}
|
||||
|
||||
${isMobile() &&
|
||||
css`
|
||||
margin-top: 24px;
|
||||
`}
|
||||
`;
|
||||
|
||||
export const CategorySubHeader = styled.div`
|
||||
font-size: ${(props) => props.theme.getCorrectFontSize("15px")};
|
||||
font-style: normal;
|
||||
font-weight: 600;
|
||||
line-height: 16px;
|
||||
|
||||
@media ${tablet} {
|
||||
&:not(&.copy-window-code) {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
}
|
||||
|
||||
${isMobile() &&
|
||||
css`
|
||||
&:not(&.copy-window-code) {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
`}
|
||||
|
||||
@media ${mobile} {
|
||||
&:first-of-type {
|
||||
margin-top: 0;
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
export const CategoryDescription = styled(Box)`
|
||||
max-width: 700px;
|
||||
.sdk-description {
|
||||
line-height: 20px;
|
||||
color: ${(props) => props.theme.client.settings.common.descriptionColor};
|
||||
}
|
||||
`;
|
||||
|
||||
export const ControlsGroup = styled(Box)`
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 4px;
|
||||
|
||||
.toggle {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
@media ${tablet} {
|
||||
gap: 4px;
|
||||
}
|
||||
|
||||
${isMobile() &&
|
||||
css`
|
||||
gap: 4px;
|
||||
`}
|
||||
`;
|
||||
|
||||
export const CheckboxGroup = styled(Box)`
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 10px;
|
||||
`;
|
||||
|
||||
export const LabelGroup = styled(Box)`
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 4px;
|
||||
`;
|
||||
|
||||
export const ControlsSection = styled(Box)`
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 16px;
|
||||
`;
|
||||
|
||||
export const Frame = styled(Box)`
|
||||
margin-top: 16px;
|
||||
position: relative;
|
||||
|
||||
border-radius: 6px;
|
||||
border: 1px solid ${(props) => props.theme.sdkPresets.borderColor};
|
||||
|
||||
width: calc(${(props) => (props.width ? props.width : "100%")} + 2px);
|
||||
height: calc(${(props) => (props.height ? props.height : "400px")} + 2px);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
|
||||
@media ${tablet} {
|
||||
margin-top: 4px;
|
||||
}
|
||||
|
||||
${(props) =>
|
||||
props.targetId &&
|
||||
`
|
||||
#${props.targetId} {
|
||||
border-radius: 6px;
|
||||
}
|
||||
`}
|
||||
|
||||
${isMobile() &&
|
||||
css`
|
||||
margin-top: 4px;
|
||||
`}
|
||||
|
||||
.frame-container {
|
||||
height: 100% !important;
|
||||
|
||||
& > iframe {
|
||||
height: 100% !important;
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
Frame.defaultProps = { theme: Base };
|
||||
|
||||
export const Container = styled(Box)`
|
||||
width: 100%;
|
||||
display: flex;
|
||||
flex-direction: row-reverse;
|
||||
justify-content: flex-end;
|
||||
gap: 48px;
|
||||
|
||||
@media ${tablet} {
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
${isMobile() &&
|
||||
css`
|
||||
flex-direction: column;
|
||||
`}
|
||||
`;
|
||||
|
||||
export const RowContainer = styled(Box)`
|
||||
flex-direction: row;
|
||||
display: flex;
|
||||
gap: 8px;
|
||||
|
||||
${(props) =>
|
||||
props.combo &&
|
||||
`
|
||||
height: 32px;
|
||||
align-items: center;
|
||||
`}
|
||||
`;
|
||||
|
||||
export const ColumnContainer = styled(Box)`
|
||||
flex-direction: column;
|
||||
display: flex;
|
||||
gap: 8px;
|
||||
`;
|
||||
|
||||
export const Preview = styled(Box)`
|
||||
width: 100%;
|
||||
min-width: 660px;
|
||||
flex-direction: row;
|
||||
|
||||
@media ${tablet} {
|
||||
margin-top: 0;
|
||||
min-width: 0;
|
||||
}
|
||||
${isMobile() &&
|
||||
css`
|
||||
margin-top: 0;
|
||||
min-width: 0;
|
||||
`}
|
||||
`;
|
||||
|
||||
export const GetCodeButtonWrapper = styled.div`
|
||||
padding-block: 30px;
|
||||
position: sticky;
|
||||
bottom: 0;
|
||||
margin-top: 32px;
|
||||
background-color: ${({ theme }) => theme.backgroundColor};
|
||||
|
||||
@media ${mobile} {
|
||||
position: fixed;
|
||||
padding-inline: 16px;
|
||||
inset-inline: 0;
|
||||
}
|
||||
`;
|
||||
|
||||
export const FilesSelectorInputWrapper = styled.div`
|
||||
& > div {
|
||||
margin: 0;
|
||||
}
|
||||
`;
|
||||
|
||||
export const SelectedItemsContainer = styled.div`
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
`;
|
||||
|
||||
export const CodeWrapper = styled.div`
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 16px;
|
||||
|
||||
margin-top: 16px;
|
||||
|
||||
width: calc(${(props) => (props.width ? props.width : "100%")} + 2px);
|
||||
height: calc(${(props) => (props.height ? props.height : "400px")} + 2px);
|
||||
`;
|
@ -0,0 +1,395 @@
|
||||
import { useState, useEffect } from "react";
|
||||
import { withTranslation } from "react-i18next";
|
||||
import debounce from "lodash.debounce";
|
||||
import { Box } from "@docspace/shared/components/box";
|
||||
import { TextInput } from "@docspace/shared/components/text-input";
|
||||
import { Textarea } from "@docspace/shared/components/textarea";
|
||||
import { Label } from "@docspace/shared/components/label";
|
||||
import { Text } from "@docspace/shared/components/text";
|
||||
import { Checkbox } from "@docspace/shared/components/checkbox";
|
||||
import { ComboBox } from "@docspace/shared/components/combobox";
|
||||
import { TabsContainer } from "@docspace/shared/components/tabs-container";
|
||||
import FilesSelectorInput from "SRC_DIR/components/FilesSelectorInput";
|
||||
import { objectToGetParams, loadScript } from "@docspace/shared/utils/common";
|
||||
import { inject, observer } from "mobx-react";
|
||||
import { ImageEditor } from "@docspace/shared/components/image-editor";
|
||||
import { FilesSelectorFilterTypes } from "@docspace/shared/enums";
|
||||
|
||||
import { isTablet, isMobile } from "@docspace/shared/utils/device";
|
||||
|
||||
import EmptyIframeContainer from "../sub-components/EmptyIframeContainer";
|
||||
|
||||
import GetCodeDialog from "../sub-components/GetCodeDialog";
|
||||
import { Button } from "@docspace/shared/components/button";
|
||||
|
||||
const showPreviewThreshold = 720;
|
||||
|
||||
import {
|
||||
SDKContainer,
|
||||
Controls,
|
||||
CategoryHeader,
|
||||
CategorySubHeader,
|
||||
CategoryDescription,
|
||||
ControlsGroup,
|
||||
LabelGroup,
|
||||
ControlsSection,
|
||||
Frame,
|
||||
Container,
|
||||
RowContainer,
|
||||
ColumnContainer,
|
||||
Preview,
|
||||
GetCodeButtonWrapper,
|
||||
FilesSelectorInputWrapper,
|
||||
CodeWrapper,
|
||||
} from "./StyledPresets";
|
||||
|
||||
const Viewer = (props) => {
|
||||
const { t, setDocumentTitle } = props;
|
||||
|
||||
setDocumentTitle(t("JavascriptSdk"));
|
||||
|
||||
const scriptUrl = `${window.location.origin}/static/scripts/api.js`;
|
||||
|
||||
const dataDimensions = [
|
||||
{ key: "percent", label: "%", default: true },
|
||||
{ key: "pixel", label: "px" },
|
||||
];
|
||||
|
||||
const [widthDimension, setWidthDimension] = useState(dataDimensions[0]);
|
||||
const [heightDimension, setHeightDimension] = useState(dataDimensions[0]);
|
||||
const [width, setWidth] = useState("100");
|
||||
const [height, setHeight] = useState("100");
|
||||
const [isGetCodeDialogOpened, setIsGetCodeDialogOpened] = useState(false);
|
||||
const [showPreview, setShowPreview] = useState(window.innerWidth > showPreviewThreshold);
|
||||
|
||||
const [config, setConfig] = useState({
|
||||
mode: "viewer",
|
||||
width: `${width}${widthDimension.label}`,
|
||||
height: `${height}${heightDimension.label}`,
|
||||
frameId: "ds-frame",
|
||||
init: false,
|
||||
});
|
||||
|
||||
const params = objectToGetParams(config);
|
||||
|
||||
const frameId = config.frameId || "ds-frame";
|
||||
|
||||
const destroyFrame = () => {
|
||||
window.DocSpace?.SDK?.frames[frameId]?.destroyFrame();
|
||||
};
|
||||
|
||||
const loadFrame = debounce(() => {
|
||||
const script = document.getElementById("integration");
|
||||
|
||||
if (script) {
|
||||
script.remove();
|
||||
}
|
||||
|
||||
const params = objectToGetParams(config);
|
||||
|
||||
loadScript(`${scriptUrl}${params}`, "integration", () => window.DocSpace.SDK.initFrame(config));
|
||||
}, 500);
|
||||
|
||||
useEffect(() => {
|
||||
loadFrame();
|
||||
return () => destroyFrame();
|
||||
});
|
||||
|
||||
const onChangeTab = () => {
|
||||
loadFrame();
|
||||
};
|
||||
|
||||
const onChangeWidth = (e) => {
|
||||
setConfig((config) => {
|
||||
return { ...config, width: `${e.target.value}${widthDimension.label}` };
|
||||
});
|
||||
|
||||
setWidth(e.target.value);
|
||||
};
|
||||
|
||||
const onChangeHeight = (e) => {
|
||||
setConfig((config) => {
|
||||
return { ...config, height: `${e.target.value}${heightDimension.label}` };
|
||||
});
|
||||
|
||||
setHeight(e.target.value);
|
||||
};
|
||||
|
||||
const onChangeFileId = (file) => {
|
||||
setConfig((config) => {
|
||||
return { ...config, id: file.id };
|
||||
});
|
||||
};
|
||||
|
||||
const onChangeFrameId = (e) => {
|
||||
setConfig((config) => {
|
||||
return { ...config, frameId: e.target.value, init: true };
|
||||
});
|
||||
};
|
||||
|
||||
const onChangeWidthDimension = (item) => {
|
||||
setConfig((config) => {
|
||||
return { ...config, width: `${width}${item.label}` };
|
||||
});
|
||||
|
||||
setWidthDimension(item);
|
||||
};
|
||||
|
||||
const onChangeHeightDimension = (item) => {
|
||||
setConfig((config) => {
|
||||
return { ...config, height: `${height}${item.label}` };
|
||||
});
|
||||
|
||||
setHeightDimension(item);
|
||||
};
|
||||
|
||||
const openGetCodeModal = () => setIsGetCodeDialogOpened(true);
|
||||
|
||||
const closeGetCodeModal = () => setIsGetCodeDialogOpened(false);
|
||||
|
||||
const onResize = () => {
|
||||
const isEnoughWidthForPreview = window.innerWidth > showPreviewThreshold;
|
||||
if (isEnoughWidthForPreview !== showPreview) setShowPreview(isEnoughWidthForPreview);
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
window.addEventListener("resize", onResize);
|
||||
return () => {
|
||||
window.removeEventListener("resize", onResize);
|
||||
};
|
||||
}, [showPreview]);
|
||||
|
||||
const codeBlock = `<div id="${frameId}">Fallback text</div>\n<script src="${scriptUrl}${params}"></script>`;
|
||||
|
||||
const preview = (
|
||||
<Frame
|
||||
width={width + widthDimension.label}
|
||||
height={height + heightDimension.label}
|
||||
targetId={frameId}
|
||||
>
|
||||
{config.id !== undefined ? (
|
||||
<>
|
||||
<Box id={frameId}></Box>
|
||||
</>
|
||||
) : (
|
||||
<EmptyIframeContainer
|
||||
text={t("SelectFile")}
|
||||
width={width + widthDimension.label}
|
||||
height={height + heightDimension.label}
|
||||
/>
|
||||
)}
|
||||
</Frame>
|
||||
);
|
||||
|
||||
const code = (
|
||||
<CodeWrapper>
|
||||
<CategorySubHeader className="copy-window-code">{t("CopyWindowCode")}</CategorySubHeader>
|
||||
<Textarea value={codeBlock} heightTextArea={153} />
|
||||
</CodeWrapper>
|
||||
);
|
||||
|
||||
const dataTabs = [
|
||||
{
|
||||
key: "preview",
|
||||
title: t("Common:Preview"),
|
||||
content: preview,
|
||||
},
|
||||
{
|
||||
key: "code",
|
||||
title: t("Code"),
|
||||
content: code,
|
||||
},
|
||||
];
|
||||
|
||||
return (
|
||||
<SDKContainer>
|
||||
<CategoryDescription>
|
||||
<Text className="sdk-description">{t("ViewerPresetDescription")}</Text>
|
||||
</CategoryDescription>
|
||||
<CategoryHeader>{t("CreateSampleHeader")}</CategoryHeader>
|
||||
<Container>
|
||||
{showPreview && (
|
||||
<Preview>
|
||||
<TabsContainer
|
||||
isDisabled={config?.id === undefined}
|
||||
onSelect={onChangeTab}
|
||||
elements={dataTabs}
|
||||
/>
|
||||
</Preview>
|
||||
)}
|
||||
<Controls>
|
||||
<ControlsSection>
|
||||
<CategorySubHeader>{t("FileId")}</CategorySubHeader>
|
||||
<ControlsGroup>
|
||||
<LabelGroup>
|
||||
<Label className="label" text={t("Common:SelectFile")} />
|
||||
</LabelGroup>
|
||||
<FilesSelectorInputWrapper>
|
||||
<FilesSelectorInput
|
||||
onSelectFile={onChangeFileId}
|
||||
filterParam={FilesSelectorFilterTypes.ALL}
|
||||
isSelect
|
||||
/>
|
||||
</FilesSelectorInputWrapper>
|
||||
</ControlsGroup>
|
||||
</ControlsSection>
|
||||
|
||||
<ControlsSection>
|
||||
<CategorySubHeader>{t("CustomizingDisplay")}</CategorySubHeader>
|
||||
<ControlsGroup>
|
||||
<Label className="label" text={t("EmbeddingPanel:Width")} />
|
||||
<RowContainer combo>
|
||||
<TextInput
|
||||
onChange={onChangeWidth}
|
||||
placeholder={t("EnterWidth")}
|
||||
value={width}
|
||||
tabIndex={2}
|
||||
/>
|
||||
<ComboBox
|
||||
size="content"
|
||||
scaled={false}
|
||||
scaledOptions={true}
|
||||
onSelect={onChangeWidthDimension}
|
||||
options={dataDimensions}
|
||||
selectedOption={widthDimension}
|
||||
displaySelectedOption
|
||||
directionY="bottom"
|
||||
/>
|
||||
</RowContainer>
|
||||
</ControlsGroup>
|
||||
<ControlsGroup>
|
||||
<Label className="label" text={t("EmbeddingPanel:Height")} />
|
||||
<RowContainer combo>
|
||||
<TextInput
|
||||
onChange={onChangeHeight}
|
||||
placeholder={t("EnterHeight")}
|
||||
value={height}
|
||||
tabIndex={3}
|
||||
/>
|
||||
<ComboBox
|
||||
size="content"
|
||||
scaled={false}
|
||||
scaledOptions={true}
|
||||
onSelect={onChangeHeightDimension}
|
||||
options={dataDimensions}
|
||||
selectedOption={heightDimension}
|
||||
displaySelectedOption
|
||||
directionY="bottom"
|
||||
/>
|
||||
</RowContainer>
|
||||
</ControlsGroup>
|
||||
<ControlsGroup>
|
||||
<Label className="label" text={t("FrameId")} />
|
||||
<TextInput
|
||||
scale={true}
|
||||
onChange={onChangeFrameId}
|
||||
placeholder={t("EnterId")}
|
||||
value={config.frameId}
|
||||
tabIndex={4}
|
||||
/>
|
||||
</ControlsGroup>
|
||||
</ControlsSection>
|
||||
|
||||
{/* <InterfaceElements>
|
||||
<Label className="label">{t("InterfaceElements")}</Label>
|
||||
<Checkbox
|
||||
className="checkbox"
|
||||
label={t("TabPlugins")}
|
||||
onChange={() => {}}
|
||||
isChecked={true}
|
||||
/>
|
||||
<RowContainer>
|
||||
<Checkbox label={t("Chat")} onChange={() => {}} isChecked={true} />
|
||||
<Text color="gray">({t("InLeftPanel")})</Text>
|
||||
</RowContainer>
|
||||
<RowContainer>
|
||||
<Checkbox label={t("FeedbackAndSupport")} onChange={() => {}} isChecked={true} />
|
||||
<Text color="gray">({t("InLeftPanel")})</Text>
|
||||
</RowContainer>
|
||||
</InterfaceElements>
|
||||
<CategorySubHeader>{t("AddWatermarks")}</CategorySubHeader>
|
||||
<ControlsGroup>
|
||||
<LabelGroup>
|
||||
<Label className="label" text={t("SelectImage")} />
|
||||
</LabelGroup>
|
||||
<FilesSelectorInputWrapper>
|
||||
<FilesSelectorInput onSelectFolder={onChangeFileId} isSelect />
|
||||
</FilesSelectorInputWrapper>
|
||||
</ControlsGroup>
|
||||
<Label className="label" text={t("Scale")} />
|
||||
<ComboBox
|
||||
onSelect={() => {}}
|
||||
options={[
|
||||
{ key: "1", label: "100%", default: true },
|
||||
{ key: "2", label: "50%" },
|
||||
{ key: "3", label: "25%" },
|
||||
]}
|
||||
scaled={true}
|
||||
selectedOption={{ key: "1", label: "100%", default: true }}
|
||||
displaySelectedOption
|
||||
directionY="top"
|
||||
/>
|
||||
<Label className="label" text={t("Rotate")} />
|
||||
<ComboBox
|
||||
onSelect={() => {}}
|
||||
options={[
|
||||
{ key: "1", label: "45%", default: true },
|
||||
{ key: "2", label: "75%" },
|
||||
{ key: "3", label: "90%" },
|
||||
{ key: "4", label: "180%" },
|
||||
]}
|
||||
scaled={true}
|
||||
selectedOption={{ key: "1", label: "45%", default: true }}
|
||||
displaySelectedOption
|
||||
directionY="top"
|
||||
/>
|
||||
<Label className="label" text={t("CreateEditRoomDialog:Icon")} />
|
||||
<ImageEditor
|
||||
t={t}
|
||||
className="wrapper-image-editor"
|
||||
classNameWrapperImageCropper="avatar-editor"
|
||||
image={{}}
|
||||
setPreview={() => {}}
|
||||
onChangeImage={() => {}}
|
||||
/> */}
|
||||
</Controls>
|
||||
</Container>
|
||||
|
||||
{!showPreview && (
|
||||
<>
|
||||
<GetCodeButtonWrapper>
|
||||
<Button
|
||||
id="get-sdk-code-button"
|
||||
primary
|
||||
size="normal"
|
||||
scale
|
||||
label={t("GetCode")}
|
||||
onClick={openGetCodeModal}
|
||||
/>
|
||||
</GetCodeButtonWrapper>
|
||||
|
||||
<GetCodeDialog
|
||||
t={t}
|
||||
visible={isGetCodeDialogOpened}
|
||||
codeBlock={codeBlock}
|
||||
onClose={closeGetCodeModal}
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
</SDKContainer>
|
||||
);
|
||||
};
|
||||
|
||||
export default inject(({ authStore, settingsStore }) => {
|
||||
const { setDocumentTitle } = authStore;
|
||||
const { theme } = settingsStore;
|
||||
|
||||
return {
|
||||
theme,
|
||||
setDocumentTitle,
|
||||
};
|
||||
})(
|
||||
withTranslation(["JavascriptSdk", "Files", "EmbeddingPanel", "Common", "CreateEditRoomDialog"])(
|
||||
observer(Viewer),
|
||||
),
|
||||
);
|
@ -0,0 +1,39 @@
|
||||
import React from "react";
|
||||
import styled from "styled-components";
|
||||
|
||||
import { RectangleSkeleton } from "@docspace/shared/skeletons/rectangle";
|
||||
import { Base } from "@docspace/shared/themes";
|
||||
|
||||
const StyledContainer = styled.div`
|
||||
width: ${(props) => props.width};
|
||||
height: ${(props) => props.height};
|
||||
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
|
||||
border: 1px solid ${(props) => props.theme.plugins.borderColor};
|
||||
border-radius: 6px;
|
||||
|
||||
overflow: hidden;
|
||||
|
||||
.emptyIframeText {
|
||||
position: absolute;
|
||||
font-size: 44px;
|
||||
font-weight: 700;
|
||||
line-height: 59.92px;
|
||||
color: ${(props) => props.theme.text.emailColor};
|
||||
}
|
||||
`;
|
||||
StyledContainer.defaultProps = { theme: Base };
|
||||
|
||||
const EmptyIframeContainer = ({ text, width, height }) => {
|
||||
return (
|
||||
<StyledContainer width={width} height={height}>
|
||||
<RectangleSkeleton width="100%" height="100%" borderRadius="6px" />
|
||||
<span className="emptyIframeText">{text}</span>
|
||||
</StyledContainer>
|
||||
);
|
||||
};
|
||||
|
||||
export default EmptyIframeContainer;
|
@ -0,0 +1,82 @@
|
||||
import React from "react";
|
||||
import styled, { css } from "styled-components";
|
||||
|
||||
import { Base } from "@docspace/shared/themes";
|
||||
|
||||
import { Text } from "@docspace/shared/components/text";
|
||||
import { Button } from "@docspace/shared/components/button";
|
||||
|
||||
import ArrowIcon from "PUBLIC_DIR/images/arrow-left.react.svg";
|
||||
|
||||
const TileContainer = styled.div`
|
||||
box-sizing: border-box;
|
||||
|
||||
width: 100%;
|
||||
max-width: 342px;
|
||||
height: 354px;
|
||||
|
||||
padding: 12px 16px;
|
||||
|
||||
border-radius: 6px;
|
||||
border: 1px solid ${(props) => props.theme.sdkPresets.borderColor};
|
||||
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-between;
|
||||
gap: 12px;
|
||||
|
||||
.tileContent {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
.navigationButton {
|
||||
border: none;
|
||||
|
||||
.button-content {
|
||||
flex-direction: row-reverse;
|
||||
}
|
||||
|
||||
.icon {
|
||||
transform: scale(-1, 1);
|
||||
}
|
||||
|
||||
:hover {
|
||||
${() =>
|
||||
css`
|
||||
border: ${(props) => props.theme.button.border.baseHover};
|
||||
box-sizing: ${(props) => props.theme.button.boxSizing};
|
||||
`}
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
TileContainer.defaultProps = { theme: Base };
|
||||
|
||||
const PresetTile = (props) => {
|
||||
const { t, title, description, image, handleOnClick } = props;
|
||||
|
||||
return (
|
||||
<TileContainer>
|
||||
<div className="tileContent">
|
||||
<Text fontSize="16px" lineHeight="22px" fontWeight={700}>
|
||||
{title}
|
||||
</Text>
|
||||
<img src={image} alt={title} />
|
||||
<Text lineHeight="20px">{description}</Text>
|
||||
</div>
|
||||
<Button
|
||||
className="navigationButton"
|
||||
label={t("SetUp")}
|
||||
icon={<ArrowIcon />}
|
||||
scale
|
||||
isClicked
|
||||
size="small"
|
||||
onClick={handleOnClick}
|
||||
/>
|
||||
</TileContainer>
|
||||
);
|
||||
};
|
||||
|
||||
export default PresetTile;
|
@ -0,0 +1,49 @@
|
||||
import React from "react";
|
||||
import { Text } from "@docspace/shared/components/text";
|
||||
import styled from "styled-components";
|
||||
|
||||
import XImg from "PUBLIC_DIR/images/x.react.svg";
|
||||
|
||||
const Wrapper = styled.div`
|
||||
box-sizing: border-box;
|
||||
|
||||
max-width: 216px;
|
||||
width: 100%;
|
||||
padding: 8px 4px 16px;
|
||||
`;
|
||||
|
||||
const HeaderContainer = styled.header`
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: flex-start;
|
||||
|
||||
margin-bottom: 8px;
|
||||
|
||||
svg {
|
||||
cursor: pointer;
|
||||
path {
|
||||
fill: #333;
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
const ImgWrapper = styled.div`
|
||||
margin-top: 16px;
|
||||
`;
|
||||
|
||||
export const TooltipContent = ({ title, description, img }) => {
|
||||
return (
|
||||
<Wrapper>
|
||||
<HeaderContainer>
|
||||
<Text fontSize="16px" fontWeight={700} lineHeight="22px">
|
||||
{title}
|
||||
</Text>
|
||||
{/* <XImg /> */}
|
||||
</HeaderContainer>
|
||||
<Text>{description}</Text>
|
||||
<ImgWrapper>
|
||||
<img src={img} alt={title} />
|
||||
</ImgWrapper>
|
||||
</Wrapper>
|
||||
);
|
||||
};
|
@ -8,6 +8,7 @@ import { Text } from "@docspace/shared/components/text";
|
||||
import { SelectorAddButton } from "@docspace/shared/components/selector-add-button";
|
||||
import { SelectedItem } from "@docspace/shared/components/selected-item";
|
||||
import { tablet } from "@docspace/shared/utils";
|
||||
import Base from "@docspace/shared/themes/base";
|
||||
|
||||
const CategoryHeader = styled.div`
|
||||
margin-top: 24px;
|
||||
@ -23,6 +24,7 @@ const Container = styled.div`
|
||||
|
||||
&.description-holder {
|
||||
display: block;
|
||||
color: ${(props) => props.theme.sdkPresets.secondaryColor};
|
||||
}
|
||||
|
||||
&.description-holder > div {
|
||||
@ -41,6 +43,8 @@ const Container = styled.div`
|
||||
}
|
||||
`;
|
||||
|
||||
Container.defaultProps = { theme: Base };
|
||||
|
||||
const ChipsContainer = styled.div`
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
@ -129,7 +129,9 @@ const DeliveryDatePicker = ({
|
||||
const SelectedDateTime = () => {
|
||||
const formattedTime = isTimeEqual
|
||||
? ""
|
||||
: ` ${filters.deliveryFrom.format("HH:mm")} - ${moment(filters.deliveryTo)
|
||||
: ` ${moment(filters.deliveryFrom).tz(window.timezone).format("HH:mm")} - ${moment(
|
||||
filters.deliveryTo,
|
||||
)
|
||||
.tz(window.timezone)
|
||||
.format("HH:mm")}`;
|
||||
|
||||
@ -210,6 +212,7 @@ const DeliveryDatePicker = ({
|
||||
hasError={!isTimeValid}
|
||||
tabIndex={1}
|
||||
locale={i18n.language}
|
||||
initialTime={filters.deliveryFrom}
|
||||
/>
|
||||
</span>
|
||||
|
||||
@ -219,10 +222,11 @@ const DeliveryDatePicker = ({
|
||||
<TimePicker
|
||||
classNameInput="before-time"
|
||||
date={filters.deliveryTo}
|
||||
setDate={setDeliveryTo}
|
||||
onChange={setDeliveryTo}
|
||||
hasError={!isTimeValid}
|
||||
tabIndex={2}
|
||||
locale={i18n.language}
|
||||
initialTime={filters.deliveryTo}
|
||||
/>
|
||||
</TimePickerCell>
|
||||
) : (
|
||||
|
@ -37,6 +37,7 @@ const StatusBadgeSelector = ({
|
||||
label={label}
|
||||
onClick={handleOnClick}
|
||||
primary={isStatusSelected(statusCode)}
|
||||
size="extraSmall"
|
||||
/>
|
||||
);
|
||||
};
|
||||
@ -77,7 +78,7 @@ const StatusPicker = ({ filters, setFilters }) => {
|
||||
handleStatusClick={handleStatusClick}
|
||||
key={code}
|
||||
/>
|
||||
)
|
||||
),
|
||||
);
|
||||
|
||||
return (
|
||||
|
@ -178,6 +178,7 @@ const FilterDialog = (props) => {
|
||||
size="normal"
|
||||
primary={true}
|
||||
onClick={handleApplyFilters}
|
||||
isDisabled={filters.deliveryTo <= filters.deliveryFrom}
|
||||
/>
|
||||
<Button
|
||||
className="cancel-button"
|
||||
|
@ -43,16 +43,14 @@ const StatusBar = (props) => {
|
||||
<SelectedItem
|
||||
label={
|
||||
moment(historyFilters.deliveryDate)
|
||||
.format("DD MMM YYYY")
|
||||
.tz(window.timezone) +
|
||||
.tz(window.timezone)
|
||||
.format("DD MMM YYYY") +
|
||||
" " +
|
||||
moment(historyFilters.deliveryFrom)
|
||||
.format("HH:mm")
|
||||
.tz(window.timezone) +
|
||||
" - " +
|
||||
moment(historyFilters.deliveryTo)
|
||||
.format("HH:mm")
|
||||
.tz(window.timezone)
|
||||
.format("HH:mm") +
|
||||
" - " +
|
||||
moment(historyFilters.deliveryTo).tz(window.timezone).format("HH:mm")
|
||||
}
|
||||
onClose={clearDate}
|
||||
onClick={clearDate}
|
||||
|
@ -51,6 +51,7 @@ const StatusBadge = (props) => {
|
||||
maxWidth="80px"
|
||||
fontWeight={700}
|
||||
noHover
|
||||
isVersionBadge
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
@ -15,7 +15,6 @@ import {
|
||||
sloBindingOptions,
|
||||
nameIdOptions,
|
||||
} from "./sub-components/constants";
|
||||
import { useIsMobileView } from "../../../utils/useIsMobileView";
|
||||
import { DeviceType } from "@docspace/shared/enums";
|
||||
|
||||
const PROVIDER_URL = "https://idpservice/idp";
|
||||
|
@ -8,9 +8,9 @@ import { Text } from "@docspace/shared/components/text";
|
||||
import { Button } from "@docspace/shared/components/button";
|
||||
|
||||
import { mobile, size } from "@docspace/shared/utils";
|
||||
import { DeviceType } from "@docspace/shared/enums";
|
||||
|
||||
import MetadataUrlField from "./sub-components/MetadataUrlField";
|
||||
import { useIsMobileView } from "../../../utils/useIsMobileView";
|
||||
|
||||
const StyledWrapper = styled.div`
|
||||
.button-wrapper {
|
||||
@ -30,11 +30,11 @@ const StyledWrapper = styled.div`
|
||||
|
||||
const ProviderMetadata = (props) => {
|
||||
const { t } = useTranslation("SingleSignOn");
|
||||
const isMobileView = useIsMobileView();
|
||||
const navigate = useNavigate();
|
||||
const location = useLocation();
|
||||
const { downloadMetadata, currentDeviceType } = props;
|
||||
|
||||
const { downloadMetadata } = props;
|
||||
const isMobileView = currentDeviceType === DeviceType.mobile;
|
||||
|
||||
const url = window.location.origin;
|
||||
|
||||
@ -95,10 +95,12 @@ const ProviderMetadata = (props) => {
|
||||
);
|
||||
};
|
||||
|
||||
export default inject(({ ssoStore }) => {
|
||||
export default inject(({ ssoStore, settingsStore }) => {
|
||||
const { downloadMetadata } = ssoStore;
|
||||
const { currentDeviceType } = settingsStore;
|
||||
|
||||
return {
|
||||
downloadMetadata,
|
||||
currentDeviceType
|
||||
};
|
||||
})(observer(ProviderMetadata));
|
||||
|
@ -18,6 +18,7 @@ const SubmitResetButtons = (props) => {
|
||||
hasErrors,
|
||||
hasChanges,
|
||||
isLoadingXml,
|
||||
enableSso,
|
||||
} = props;
|
||||
|
||||
return (
|
||||
@ -32,7 +33,9 @@ const SubmitResetButtons = (props) => {
|
||||
displaySettings={true}
|
||||
hasScroll={true}
|
||||
isSaving={isSubmitLoading}
|
||||
saveButtonDisabled={hasErrors || !hasChanges || isLoadingXml}
|
||||
saveButtonDisabled={
|
||||
!enableSso || hasErrors || !hasChanges || isLoadingXml
|
||||
}
|
||||
cancelEnable={!(isSubmitLoading || isLoadingXml)}
|
||||
additionalClassSaveButton="save-button"
|
||||
additionalClassCancelButton="restore-button"
|
||||
@ -53,6 +56,7 @@ export default inject(({ ssoStore }) => {
|
||||
hasErrors,
|
||||
hasChanges,
|
||||
isLoadingXml,
|
||||
enableSso,
|
||||
} = ssoStore;
|
||||
|
||||
return {
|
||||
@ -65,5 +69,6 @@ export default inject(({ ssoStore }) => {
|
||||
hasErrors,
|
||||
hasChanges,
|
||||
isLoadingXml,
|
||||
enableSso,
|
||||
};
|
||||
})(observer(SubmitResetButtons));
|
||||
|
@ -13,7 +13,6 @@ import ToggleSSO from "./sub-components/ToggleSSO";
|
||||
import SSOLoader from "./sub-components/ssoLoader";
|
||||
|
||||
import MobileView from "./MobileView";
|
||||
import { useIsMobileView } from "../../../utils/useIsMobileView";
|
||||
import { DeviceType } from "@docspace/shared/enums";
|
||||
|
||||
const SERVICE_PROVIDER_SETTINGS = "serviceProviderSettings";
|
||||
|
@ -1,66 +0,0 @@
|
||||
import React from "react";
|
||||
import { inject, observer } from "mobx-react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
|
||||
import { Box } from "@docspace/shared/components/box";
|
||||
import { Button } from "@docspace/shared/components/button";
|
||||
import { ModalDialog } from "@docspace/shared/components/modal-dialog";
|
||||
import { Text } from "@docspace/shared/components/text";
|
||||
|
||||
import StyledModalDialog from "../styled-containers/StyledModalDialog";
|
||||
|
||||
const DisableSsoConfirmationModal = (props) => {
|
||||
const { t } = useTranslation(["SingleSignOn", "Common"]);
|
||||
const {
|
||||
closeConfirmationDisableModal,
|
||||
confirmationDisableModal,
|
||||
confirmDisable,
|
||||
} = props;
|
||||
|
||||
return (
|
||||
<StyledModalDialog
|
||||
contentHeight="100%"
|
||||
displayType="modal"
|
||||
onClose={closeConfirmationDisableModal}
|
||||
visible={confirmationDisableModal}
|
||||
>
|
||||
<ModalDialog.Header>{t("Common:Confirmation")}</ModalDialog.Header>
|
||||
|
||||
<ModalDialog.Body>
|
||||
<Text noSelect>{t("ConfirmationText")}</Text>
|
||||
</ModalDialog.Body>
|
||||
|
||||
<ModalDialog.Footer>
|
||||
<Button
|
||||
id="ok-button"
|
||||
label={t("Common:OKButton")}
|
||||
onClick={confirmDisable}
|
||||
primary
|
||||
scale
|
||||
size="normal"
|
||||
/>
|
||||
<Button
|
||||
id="cancel-button"
|
||||
label={t("Common:CancelButton")}
|
||||
onClick={closeConfirmationDisableModal}
|
||||
scale
|
||||
size="normal"
|
||||
/>
|
||||
</ModalDialog.Footer>
|
||||
</StyledModalDialog>
|
||||
);
|
||||
};
|
||||
|
||||
export default inject(({ ssoStore }) => {
|
||||
const {
|
||||
closeConfirmationDisableModal,
|
||||
confirmationDisableModal,
|
||||
confirmDisable,
|
||||
} = ssoStore;
|
||||
|
||||
return {
|
||||
closeConfirmationDisableModal,
|
||||
confirmationDisableModal,
|
||||
confirmDisable,
|
||||
};
|
||||
})(observer(DisableSsoConfirmationModal));
|
@ -6,21 +6,11 @@ import { Box } from "@docspace/shared/components/box";
|
||||
import { Text } from "@docspace/shared/components/text";
|
||||
import { ToggleButton } from "@docspace/shared/components/toggle-button";
|
||||
import { Badge } from "@docspace/shared/components/badge";
|
||||
import DisableSsoConfirmationModal from "./DisableSsoConfirmationModal";
|
||||
|
||||
const borderProp = { radius: "6px" };
|
||||
|
||||
const ToggleSSO = (props) => {
|
||||
const {
|
||||
theme,
|
||||
enableSso,
|
||||
isSsoEnabled,
|
||||
openConfirmationDisableModal,
|
||||
ssoToggle,
|
||||
confirmationDisableModal,
|
||||
isSSOAvailable,
|
||||
t,
|
||||
} = props;
|
||||
const { theme, enableSso, ssoToggle, isSSOAvailable, t } = props;
|
||||
|
||||
return (
|
||||
<>
|
||||
@ -40,9 +30,7 @@ const ToggleSSO = (props) => {
|
||||
<ToggleButton
|
||||
className="enable-sso toggle"
|
||||
isChecked={enableSso}
|
||||
onChange={
|
||||
isSsoEnabled && enableSso ? openConfirmationDisableModal : ssoToggle
|
||||
}
|
||||
onChange={() => ssoToggle(t)}
|
||||
isDisabled={!isSSOAvailable}
|
||||
/>
|
||||
|
||||
@ -77,28 +65,17 @@ const ToggleSSO = (props) => {
|
||||
</Text>
|
||||
</div>
|
||||
</Box>
|
||||
|
||||
{confirmationDisableModal && <DisableSsoConfirmationModal />}
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default inject(({ settingsStore, ssoStore }) => {
|
||||
const { theme } = settingsStore;
|
||||
const {
|
||||
enableSso,
|
||||
isSsoEnabled,
|
||||
openConfirmationDisableModal,
|
||||
ssoToggle,
|
||||
confirmationDisableModal,
|
||||
} = ssoStore;
|
||||
const { enableSso, ssoToggle } = ssoStore;
|
||||
|
||||
return {
|
||||
theme,
|
||||
enableSso,
|
||||
isSsoEnabled,
|
||||
openConfirmationDisableModal,
|
||||
ssoToggle,
|
||||
confirmationDisableModal,
|
||||
};
|
||||
})(withTranslation(["SingleSignOn"])(observer(ToggleSSO)));
|
||||
|
@ -334,6 +334,50 @@ export const settingsTree = [
|
||||
link: "javascript-sdk",
|
||||
tKey: "DeveloperTools",
|
||||
isCategory: true,
|
||||
children: [
|
||||
{
|
||||
id: "portal-settings_catalog-javascript-sdk_simple-room",
|
||||
key: "5-1-0",
|
||||
icon: "",
|
||||
link: "room",
|
||||
tKey: "Common:Room",
|
||||
},
|
||||
{
|
||||
id: "portal-settings_catalog-javascript-sdk_manager",
|
||||
key: "5-1-1",
|
||||
icon: "",
|
||||
link: "manager",
|
||||
tKey: "JavascriptSdk:Manager",
|
||||
},
|
||||
{
|
||||
id: "portal-settings_catalog-javascript-sdk_room-selector",
|
||||
key: "5-1-2",
|
||||
icon: "",
|
||||
link: "room-selector",
|
||||
tKey: "JavascriptSdk:RoomSelector",
|
||||
},
|
||||
{
|
||||
id: "portal-settings_catalog-javascript-sdk_file-selector",
|
||||
key: "5-1-3",
|
||||
icon: "",
|
||||
link: "file-selector",
|
||||
tKey: "JavascriptSdk:FileSelector",
|
||||
},
|
||||
{
|
||||
id: "portal-settings_catalog-javascript-sdk_editor",
|
||||
key: "5-1-4",
|
||||
icon: "",
|
||||
link: "editor",
|
||||
tKey: "JavascriptSdk:Editor",
|
||||
},
|
||||
{
|
||||
id: "portal-settings_catalog-javascript-sdk_viewer",
|
||||
key: "5-1-5",
|
||||
icon: "",
|
||||
link: "viewer",
|
||||
tKey: "JavascriptSdk:Viewer",
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
id: "portal-settings_catalog-plugin-sdk",
|
||||
|
@ -1,22 +0,0 @@
|
||||
import { useState, useLayoutEffect } from "react";
|
||||
import { size } from "@docspace/shared/utils";
|
||||
|
||||
export const useIsMobileView = () => {
|
||||
const [isMobileView, setIsMobileView] = useState(false);
|
||||
|
||||
const onCheckView = () => {
|
||||
window.innerWidth <= size.mobile
|
||||
? setIsMobileView(true)
|
||||
: setIsMobileView(false);
|
||||
};
|
||||
|
||||
useLayoutEffect(() => {
|
||||
onCheckView();
|
||||
|
||||
window.addEventListener("resize", onCheckView);
|
||||
|
||||
return () => window.removeEventListener("resize", onCheckView);
|
||||
}, []);
|
||||
|
||||
return isMobileView;
|
||||
};
|
@ -145,6 +145,13 @@ const PreparationPortal = (props) => {
|
||||
returnToPortal();
|
||||
}
|
||||
} catch (error) {
|
||||
const status = err?.response?.status;
|
||||
const needCreationTableTime = status === 404;
|
||||
|
||||
if (needCreationTableTime) {
|
||||
return;
|
||||
}
|
||||
|
||||
clearAllIntervals();
|
||||
setErrorMessage(error);
|
||||
}
|
||||
@ -249,7 +256,7 @@ const PreparationPortalWrapper = inject(({ backup }) => {
|
||||
multiplicationFactor,
|
||||
};
|
||||
})(
|
||||
withTranslation(["PreparationPortal", "Common"])(observer(PreparationPortal))
|
||||
withTranslation(["PreparationPortal", "Common"])(observer(PreparationPortal)),
|
||||
);
|
||||
|
||||
PreparationPortal.propTypes = {
|
||||
|
@ -1,4 +1,5 @@
|
||||
import { useEffect, useState, useCallback } from "react";
|
||||
import { useState, useEffect, useCallback, useRef } from "react";
|
||||
import { withTranslation } from "react-i18next";
|
||||
import { inject, observer } from "mobx-react";
|
||||
import { useParams } from "react-router-dom";
|
||||
import AppLoader from "@docspace/common/components/AppLoader";
|
||||
@ -13,6 +14,7 @@ import {
|
||||
import { RoomsType } from "@docspace/shared/enums";
|
||||
|
||||
const Sdk = ({
|
||||
t,
|
||||
frameConfig,
|
||||
match,
|
||||
setFrameConfig,
|
||||
@ -30,6 +32,14 @@ const Sdk = ({
|
||||
}) => {
|
||||
const [isDataReady, setIsDataReady] = useState(false);
|
||||
|
||||
const formatsDescription = {
|
||||
DOCX: t("Common:SelectDOCXFormat"),
|
||||
DOCXF: t("Common:SelectDOCXFFormat"),
|
||||
BackupOnly: t("Common:SelectBackupOnlyFormat"),
|
||||
IMG: t("Common:SelectIMGFormat"),
|
||||
XLSX: t("Common:SelectXLSXFormat"),
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
window.addEventListener("message", handleMessage, false);
|
||||
return () => {
|
||||
@ -134,8 +144,8 @@ const Sdk = ({
|
||||
|
||||
const onSelectRoom = useCallback(
|
||||
async (data) => {
|
||||
if (data[0].logo.large !== "") {
|
||||
data[0].icon = toRelativeUrl(data[0].logo.large);
|
||||
if (data[0].logo?.large !== "") {
|
||||
data[0].icon = toRelativeUrl(data[0].logo?.large);
|
||||
} else {
|
||||
data[0].icon = await getRoomsIcon(data[0].roomType, false, 32);
|
||||
}
|
||||
@ -193,17 +203,30 @@ const Sdk = ({
|
||||
: {};
|
||||
|
||||
let component;
|
||||
|
||||
switch (mode) {
|
||||
case "room-selector":
|
||||
const cancelButtonProps = frameConfig?.showSelectorCancel
|
||||
? { withCancelButton: true, cancelButtonLabel: "", onCancel: onClose }
|
||||
? {
|
||||
withCancelButton: true,
|
||||
cancelButtonLabel: frameConfig?.cancelButtonLabel,
|
||||
onCancel: onClose,
|
||||
}
|
||||
: {};
|
||||
|
||||
const headerProps = frameConfig?.showSelectorHeader
|
||||
? { withHeader: true, headerProps: { headerLabel: "" } }
|
||||
: {};
|
||||
|
||||
component = (
|
||||
<RoomSelector
|
||||
{...cancelButtonProps}
|
||||
withHeader={frameConfig?.showSelectorHeader}
|
||||
{...headerProps}
|
||||
onSubmit={onSelectRoom}
|
||||
withSearch={frameConfig?.withSearch}
|
||||
submitButtonLabel={frameConfig?.acceptButtonLabel}
|
||||
roomType={frameConfig?.roomType}
|
||||
onSelect={() => {}}
|
||||
setIsDataReady={setIsDataReady}
|
||||
isMultiSelect={false}
|
||||
/>
|
||||
@ -219,10 +242,19 @@ const Sdk = ({
|
||||
setIsDataReady={setIsDataReady}
|
||||
onSelectFile={onSelectFile}
|
||||
onClose={onClose}
|
||||
filterParam={"ALL"}
|
||||
withBreadCrumbs={frameConfig?.withBreadCrumbs}
|
||||
withSubtitle={frameConfig?.withSubtitle}
|
||||
filterParam={frameConfig?.filterParam}
|
||||
isUserOnly={selectorType === "userFolderOnly"}
|
||||
isRoomsOnly={selectorType === "roomsOnly"}
|
||||
withCancelButton={frameConfig?.showSelectorCancel}
|
||||
withSearch={frameConfig?.withSearch}
|
||||
acceptButtonLabel={frameConfig?.acceptButtonLabel}
|
||||
cancelButtonLabel={frameConfig?.cancelButtonLabel}
|
||||
currentFolderId={frameConfig?.id}
|
||||
descriptionText={
|
||||
formatsDescription[frameConfig?.filterParam || "DOCX"]
|
||||
}
|
||||
/>
|
||||
);
|
||||
break;
|
||||
@ -268,4 +300,4 @@ export default inject(
|
||||
getFilePrimaryLink,
|
||||
};
|
||||
},
|
||||
)(observer(Sdk));
|
||||
)(withTranslation(["JavascriptSdk", "Common"])(observer(Sdk)));
|
||||
|
@ -135,6 +135,25 @@ const RestoreBackup = loadable(() =>
|
||||
);
|
||||
const Bonus = loadable(() => import("../pages/Bonus"));
|
||||
|
||||
const SimpleRoom = loadable(() =>
|
||||
import("../pages/PortalSettings/categories/developer-tools/JavascriptSDK/presets/SimpleRoom")
|
||||
);
|
||||
const Manager = loadable(() =>
|
||||
import("../pages/PortalSettings/categories/developer-tools/JavascriptSDK/presets/Manager")
|
||||
);
|
||||
const RoomSelector = loadable(() =>
|
||||
import("../pages/PortalSettings/categories/developer-tools/JavascriptSDK/presets/RoomSelector")
|
||||
);
|
||||
const FileSelector = loadable(() =>
|
||||
import("../pages/PortalSettings/categories/developer-tools/JavascriptSDK/presets/FileSelector")
|
||||
);
|
||||
const Editor = loadable(() =>
|
||||
import("../pages/PortalSettings/categories/developer-tools/JavascriptSDK/presets/Editor")
|
||||
);
|
||||
const Viewer = loadable(() =>
|
||||
import("../pages/PortalSettings/categories/developer-tools/JavascriptSDK/presets/Viewer")
|
||||
);
|
||||
|
||||
const PortalSettingsRoutes = {
|
||||
path: "portal-settings/",
|
||||
element: (
|
||||
@ -290,6 +309,30 @@ const PortalSettingsRoutes = {
|
||||
path: "developer-tools/javascript-sdk",
|
||||
element: <DeveloperTools />,
|
||||
},
|
||||
{
|
||||
path: "developer-tools/javascript-sdk/room",
|
||||
element: <SimpleRoom />,
|
||||
},
|
||||
{
|
||||
path: "developer-tools/javascript-sdk/manager",
|
||||
element: <Manager />,
|
||||
},
|
||||
{
|
||||
path: "developer-tools/javascript-sdk/room-selector",
|
||||
element: <RoomSelector />,
|
||||
},
|
||||
{
|
||||
path: "developer-tools/javascript-sdk/file-selector",
|
||||
element: <FileSelector />,
|
||||
},
|
||||
{
|
||||
path: "developer-tools/javascript-sdk/editor",
|
||||
element: <Editor />,
|
||||
},
|
||||
{
|
||||
path: "developer-tools/javascript-sdk/viewer",
|
||||
element: <Viewer />,
|
||||
},
|
||||
{
|
||||
path: "developer-tools/plugin-sdk",
|
||||
element: <DeveloperTools />,
|
||||
|
@ -98,7 +98,6 @@ class SsoFormStore {
|
||||
spMetadata = false;
|
||||
idpIsModalVisible = false;
|
||||
spIsModalVisible = false;
|
||||
confirmationDisableModal = false;
|
||||
confirmationResetModal = false;
|
||||
|
||||
// errors
|
||||
@ -155,12 +154,13 @@ class SsoFormStore {
|
||||
}
|
||||
};
|
||||
|
||||
ssoToggle = () => {
|
||||
ssoToggle = (t) => {
|
||||
if (!this.enableSso) {
|
||||
this.enableSso = true;
|
||||
this.serviceProviderSettings = true;
|
||||
} else {
|
||||
this.enableSso = false;
|
||||
!this.hasErrors && this.saveSsoSettings(t);
|
||||
}
|
||||
|
||||
for (let key in this) {
|
||||
@ -224,14 +224,6 @@ class SsoFormStore {
|
||||
this.defaultSettings = defaultSettings;
|
||||
};
|
||||
|
||||
openConfirmationDisableModal = () => {
|
||||
this.confirmationDisableModal = true;
|
||||
};
|
||||
|
||||
closeConfirmationDisableModal = () => {
|
||||
this.confirmationDisableModal = false;
|
||||
};
|
||||
|
||||
openResetModal = () => {
|
||||
this.confirmationResetModal = true;
|
||||
};
|
||||
@ -240,13 +232,6 @@ class SsoFormStore {
|
||||
this.confirmationResetModal = false;
|
||||
};
|
||||
|
||||
confirmDisable = () => {
|
||||
this.resetForm();
|
||||
this.setIsSsoEnabled(false);
|
||||
this.ssoToggle();
|
||||
this.confirmationDisableModal = false;
|
||||
};
|
||||
|
||||
confirmReset = () => {
|
||||
this.resetForm();
|
||||
this.setIsSsoEnabled(false);
|
||||
@ -552,12 +537,12 @@ class SsoFormStore {
|
||||
if (meta.singleSignOnService) {
|
||||
this.ssoUrlPost = this.getPropValue(
|
||||
meta.singleSignOnService,
|
||||
BINDING_POST
|
||||
BINDING_POST,
|
||||
);
|
||||
|
||||
this.ssoUrlRedirect = this.getPropValue(
|
||||
meta.singleSignOnService,
|
||||
BINDING_REDIRECT
|
||||
BINDING_REDIRECT,
|
||||
);
|
||||
}
|
||||
|
||||
@ -568,12 +553,12 @@ class SsoFormStore {
|
||||
|
||||
this.sloUrlRedirect = this.getPropValue(
|
||||
meta.singleLogoutService,
|
||||
BINDING_REDIRECT
|
||||
BINDING_REDIRECT,
|
||||
);
|
||||
|
||||
this.sloUrlPost = this.getPropValue(
|
||||
meta.singleLogoutService,
|
||||
BINDING_POST
|
||||
BINDING_POST,
|
||||
);
|
||||
}
|
||||
|
||||
@ -598,7 +583,7 @@ class SsoFormStore {
|
||||
if (meta.certificate.signing) {
|
||||
if (Array.isArray(meta.certificate.signing)) {
|
||||
meta.certificate.signing = this.getUniqueItems(
|
||||
meta.certificate.signing
|
||||
meta.certificate.signing,
|
||||
).reverse();
|
||||
meta.certificate.signing.forEach((signingCrt) => {
|
||||
data.push({
|
||||
@ -690,14 +675,14 @@ class SsoFormStore {
|
||||
delSpCertificate = (action) => {
|
||||
this.resetSpCheckboxes(action);
|
||||
this.spCertificates = this.spCertificates.filter(
|
||||
(certificate) => certificate.action !== action
|
||||
(certificate) => certificate.action !== action,
|
||||
);
|
||||
};
|
||||
|
||||
delIdpCertificate = (cert) => {
|
||||
this.resetIdpCheckboxes();
|
||||
this.idpCertificates = this.idpCertificates.filter(
|
||||
(certificate) => certificate.crt !== cert
|
||||
(certificate) => certificate.crt !== cert,
|
||||
);
|
||||
};
|
||||
|
||||
@ -713,7 +698,7 @@ class SsoFormStore {
|
||||
(item) =>
|
||||
(item.action === this.spAction ||
|
||||
item.action === SSO_SIGNING_ENCRYPT) &&
|
||||
!this.isEdit
|
||||
!this.isEdit,
|
||||
);
|
||||
};
|
||||
|
||||
@ -785,7 +770,7 @@ class SsoFormStore {
|
||||
|
||||
if (
|
||||
this.idpCertificates.find(
|
||||
(item) => item.crt === this.idpCertificate && !this.isEdit
|
||||
(item) => item.crt === this.idpCertificate && !this.isEdit,
|
||||
)
|
||||
) {
|
||||
toastr.error(t("CertificateExist"));
|
||||
@ -896,7 +881,7 @@ class SsoFormStore {
|
||||
if (!this.enableSso || this.isLoadingXml) return true;
|
||||
return !this.spCertificates.some(
|
||||
(cert) =>
|
||||
cert.action === SSO_SIGNING || cert.action === SSO_SIGNING_ENCRYPT
|
||||
cert.action === SSO_SIGNING || cert.action === SSO_SIGNING_ENCRYPT,
|
||||
);
|
||||
}
|
||||
|
||||
@ -904,7 +889,7 @@ class SsoFormStore {
|
||||
if (!this.enableSso || this.isLoadingXml) return true;
|
||||
return !this.spCertificates.some(
|
||||
(cert) =>
|
||||
cert.action === SSO_ENCRYPT || cert.action === SSO_SIGNING_ENCRYPT
|
||||
cert.action === SSO_ENCRYPT || cert.action === SSO_SIGNING_ENCRYPT,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -2,6 +2,7 @@ import { makeAutoObservable } from "mobx";
|
||||
import { TableVersions } from "SRC_DIR/helpers/constants";
|
||||
|
||||
const TABLE_COLUMNS = `filesTableColumns_ver-${TableVersions.Files}`;
|
||||
const TABLE_ACCOUNTS_COLUMNS = `peopleTableColumns_ver-${TableVersions.Accounts}`;
|
||||
const TABLE_ROOMS_COLUMNS = `roomsTableColumns_ver-${TableVersions.Rooms}`;
|
||||
const TABLE_TRASH_COLUMNS = `trashTableColumns_ver-${TableVersions.Trash}`;
|
||||
const TABLE_SDK_COLUMNS = `filesSDKTableColumns_ver-${TableVersions.Files}`;
|
||||
@ -43,7 +44,9 @@ class TableStore {
|
||||
createdTrashColumnIsEnabled = false;
|
||||
sizeTrashColumnIsEnabled = false;
|
||||
typeTrashColumnIsEnabled = false;
|
||||
|
||||
typeAccountsColumnIsEnabled = true;
|
||||
emailAccountsColumnIsEnabled = true;
|
||||
|
||||
constructor(authStore, treeFoldersStore, userStore, settingsStore) {
|
||||
makeAutoObservable(this);
|
||||
|
||||
@ -107,12 +110,17 @@ class TableStore {
|
||||
setSizeTrashColumn = (enable) => (this.sizeTrashColumnIsEnabled = enable);
|
||||
setTypeTrashColumn = (enable) => (this.typeTrashColumnIsEnabled = enable);
|
||||
|
||||
setAccountsColumnType = (enable) =>
|
||||
(this.typeAccountsColumnIsEnabled = enable);
|
||||
setAccountsColumnEmail = (enable) =>
|
||||
(this.emailAccountsColumnIsEnabled = enable);
|
||||
|
||||
setColumnsEnable = () => {
|
||||
const storageColumns = localStorage.getItem(this.tableStorageName);
|
||||
const splitColumns = storageColumns && storageColumns.split(",");
|
||||
|
||||
if (splitColumns) {
|
||||
const { isRoomsFolder, isArchiveFolder, isTrashFolder } =
|
||||
const { isRoomsFolder, isArchiveFolder, isTrashFolder, isAccounts } =
|
||||
this.treeFoldersStore;
|
||||
const isRooms = isRoomsFolder || isArchiveFolder;
|
||||
|
||||
@ -124,6 +132,12 @@ class TableStore {
|
||||
return;
|
||||
}
|
||||
|
||||
if (isAccounts) {
|
||||
this.setAccountsColumnType(splitColumns.includes("Type"));
|
||||
this.setAccountsColumnEmail(splitColumns.includes("Mail"));
|
||||
return;
|
||||
}
|
||||
|
||||
if (isTrashFolder) {
|
||||
this.setRoomColumn(splitColumns.includes("Room"));
|
||||
this.setAuthorTrashColumn(splitColumns.includes("AuthorTrash"));
|
||||
@ -145,7 +159,7 @@ class TableStore {
|
||||
};
|
||||
|
||||
setColumnEnable = (key) => {
|
||||
const { isRoomsFolder, isArchiveFolder, isTrashFolder } =
|
||||
const { isRoomsFolder, isArchiveFolder, isTrashFolder, isAccounts } =
|
||||
this.treeFoldersStore;
|
||||
const isRooms = isRoomsFolder || isArchiveFolder;
|
||||
|
||||
@ -186,7 +200,9 @@ class TableStore {
|
||||
case "Type":
|
||||
isRooms
|
||||
? this.setRoomColumnType(!this.roomColumnTypeIsEnabled)
|
||||
: this.setTypeColumn(!this.typeColumnIsEnabled);
|
||||
: isAccounts
|
||||
? this.setAccountsColumnType(!this.typeAccountsColumnIsEnabled)
|
||||
: this.setTypeColumn(!this.typeColumnIsEnabled);
|
||||
return;
|
||||
case "TypeTrash":
|
||||
this.setTypeTrashColumn(!this.typeTrashColumnIsEnabled);
|
||||
@ -208,6 +224,10 @@ class TableStore {
|
||||
this.setRoomColumnActivity(!this.roomColumnActivityIsEnabled);
|
||||
return;
|
||||
|
||||
case "Mail":
|
||||
this.setAccountsColumnEmail(!this.emailAccountsColumnIsEnabled);
|
||||
return;
|
||||
|
||||
default:
|
||||
return;
|
||||
}
|
||||
@ -235,7 +255,7 @@ class TableStore {
|
||||
};
|
||||
|
||||
get tableStorageName() {
|
||||
const { isRoomsFolder, isArchiveFolder, isTrashFolder } =
|
||||
const { isRoomsFolder, isArchiveFolder, isTrashFolder, isAccounts } =
|
||||
this.treeFoldersStore;
|
||||
const isRooms = isRoomsFolder || isArchiveFolder;
|
||||
const userId = this.userStore.user?.id;
|
||||
@ -245,9 +265,11 @@ class TableStore {
|
||||
|
||||
return isRooms
|
||||
? `${TABLE_ROOMS_COLUMNS}=${userId}`
|
||||
: isTrashFolder
|
||||
? `${TABLE_TRASH_COLUMNS}=${userId}`
|
||||
: `${TABLE_COLUMNS}=${userId}`;
|
||||
: isAccounts
|
||||
? `${TABLE_ACCOUNTS_COLUMNS}=${userId}`
|
||||
: isTrashFolder
|
||||
? `${TABLE_TRASH_COLUMNS}=${userId}`
|
||||
: `${TABLE_COLUMNS}=${userId}`;
|
||||
}
|
||||
|
||||
get columnStorageName() {
|
||||
|
@ -215,6 +215,10 @@ class TreeFoldersStore {
|
||||
return this.recycleBinFolder ? this.recycleBinFolder.id : null;
|
||||
}
|
||||
|
||||
get isAccounts() {
|
||||
return window.location.pathname.includes("accounts/filter");
|
||||
}
|
||||
|
||||
get isPersonalRoom() {
|
||||
return (
|
||||
this.myFolder &&
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@docspace/common",
|
||||
"version": "2.0.2",
|
||||
"version": "2.0.3",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"build": "echo 'skip it'",
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@docspace/editor",
|
||||
"version": "2.0.2",
|
||||
"version": "2.0.3",
|
||||
"private": true,
|
||||
"homepage": "/doceditor",
|
||||
"scripts": {
|
||||
|
@ -2,7 +2,7 @@ import React, { useEffect } from "react";
|
||||
import Editor from "./components/Editor.js";
|
||||
import { useSSR } from "react-i18next";
|
||||
import useMfScripts from "./helpers/useMfScripts";
|
||||
import { isRetina } from "@docspace/shared/utils/common";
|
||||
import { isRetina, frameCallCommand } from "@docspace/shared/utils/common";
|
||||
import { combineUrl } from "@docspace/shared/utils/combineUrl";
|
||||
import { getCookie, setCookie } from "@docspace/shared/utils/cookie";
|
||||
|
||||
@ -40,7 +40,8 @@ const App = ({
|
||||
|
||||
switch (rest?.config?.documentType) {
|
||||
case "word":
|
||||
icon = rest?.config?.document?.fileType === "pdf" ? PDFIcoUrl : TextIcoUrl;
|
||||
icon =
|
||||
rest?.config?.document?.fileType === "pdf" ? PDFIcoUrl : TextIcoUrl;
|
||||
break;
|
||||
case "slide":
|
||||
icon = PresentationIcoUrl;
|
||||
@ -80,6 +81,8 @@ const App = ({
|
||||
(isLoadingDocumentError || isLoadedDocument)
|
||||
)
|
||||
tempElm.outerHTML = "";
|
||||
|
||||
if (isLoadingDocumentError) frameCallCommand("setIsLoaded");
|
||||
}
|
||||
|
||||
if (isRetina() && getCookie("is_retina") == null) {
|
||||
|
@ -23,7 +23,11 @@ import {
|
||||
import { EditorWrapper } from "../components/StyledEditor";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import withDialogs from "../helpers/withDialogs";
|
||||
import { assign, frameCallEvent, frameCallCommand } from "@docspace/shared/utils/common";
|
||||
import {
|
||||
assign,
|
||||
frameCallEvent,
|
||||
frameCallCommand,
|
||||
} from "@docspace/shared/utils/common";
|
||||
import { getEditorTheme } from "@docspace/shared/utils";
|
||||
import { toastr } from "@docspace/shared/components/toast";
|
||||
import { DocumentEditor } from "@onlyoffice/document-editor-react";
|
||||
@ -40,6 +44,7 @@ const onSDKInfo = (event) => {
|
||||
};
|
||||
|
||||
const onSDKWarning = (event) => {
|
||||
frameCallCommand("setIsLoaded");
|
||||
console.log(
|
||||
"ONLYOFFICE Document Editor reports a warning: code " +
|
||||
event.data.warningCode +
|
||||
@ -49,6 +54,7 @@ const onSDKWarning = (event) => {
|
||||
};
|
||||
|
||||
const onSDKError = (event) => {
|
||||
frameCallCommand("setIsLoaded");
|
||||
console.log(
|
||||
"ONLYOFFICE Document Editor reports an error: code " +
|
||||
event.data.errorCode +
|
||||
@ -272,10 +278,10 @@ function Editor({
|
||||
documentType === "word"
|
||||
? "docx"
|
||||
: documentType === "slide"
|
||||
? "pptx"
|
||||
: documentType === "cell"
|
||||
? "xlsx"
|
||||
: "docxf";
|
||||
? "pptx"
|
||||
: documentType === "cell"
|
||||
? "xlsx"
|
||||
: "docxf";
|
||||
|
||||
let fileName = t("Common:NewDocument");
|
||||
|
||||
@ -565,14 +571,14 @@ function Editor({
|
||||
console.log("onDocumentReady", arguments, { docEditor });
|
||||
documentIsReady = true;
|
||||
|
||||
frameCallCommand("setIsLoaded");
|
||||
|
||||
config?.errorMessage && docEditor?.showMessage(config.errorMessage);
|
||||
|
||||
if (isSharingAccess) {
|
||||
loadUsersRightsList(docEditor);
|
||||
}
|
||||
|
||||
frameCallCommand("setIsLoaded");
|
||||
|
||||
assign(window, ["ASC", "Files", "Editor", "docEditor"], docEditor); //Do not remove: it's for Back button on Mobile App
|
||||
};
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@docspace/login",
|
||||
"version": "2.0.2",
|
||||
"version": "2.0.3",
|
||||
"private": true,
|
||||
"homepage": "/login",
|
||||
"scripts": {
|
||||
|
@ -3,6 +3,7 @@ import { commonInputStyles } from "../../utils";
|
||||
import { Base } from "../../themes";
|
||||
|
||||
export const Wrapper = styled.div`
|
||||
position: relative;
|
||||
.hex-value {
|
||||
${commonInputStyles}
|
||||
box-sizing: border-box;
|
||||
@ -28,8 +29,14 @@ export const InputWrapper = styled.div<{ scale?: boolean }>`
|
||||
align-items: center;
|
||||
|
||||
width: ${(props) => (props.scale ? "100%" : "fit-content")};
|
||||
|
||||
input {
|
||||
font-family: ${(props) => props.theme.fontFamily};
|
||||
}
|
||||
`;
|
||||
|
||||
InputWrapper.defaultProps = { theme: Base };
|
||||
|
||||
export const ColorBlock = styled.span<{ isDisabled?: boolean }>`
|
||||
position: absolute;
|
||||
right: 8px;
|
||||
|
@ -258,15 +258,19 @@ const StyledInfoPanelToggleColorThemeWrapper = styled(ColorTheme) <{
|
||||
`;
|
||||
StyledInfoPanelToggleColorThemeWrapper.defaultProps = { theme: Base };
|
||||
|
||||
const StyledControlButtonContainer = styled.div<{ isFrame?: boolean }>`
|
||||
const StyledControlButtonContainer = styled.div<{
|
||||
isFrame?: boolean;
|
||||
showTitle?: boolean;
|
||||
}>`
|
||||
${(props) =>
|
||||
props.theme.interfaceDirection === "rtl"
|
||||
props.showTitle &&
|
||||
(props.theme.interfaceDirection === "rtl"
|
||||
? css`
|
||||
margin-right: 16px;
|
||||
`
|
||||
: css`
|
||||
margin-left: 16px;
|
||||
`}
|
||||
`)}
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 16px;
|
||||
|
@ -51,6 +51,7 @@ const Navigation = ({
|
||||
titleIcon,
|
||||
currentDeviceType,
|
||||
rootRoomTitle,
|
||||
showTitle,
|
||||
navigationButtonLabel,
|
||||
onNavigationButtonClick,
|
||||
tariffBar,
|
||||
@ -167,6 +168,7 @@ const Navigation = ({
|
||||
isRootFolderTitle
|
||||
onClick={onTextClick}
|
||||
/>
|
||||
|
||||
{navigationTitleNode}
|
||||
</div>
|
||||
) : (
|
||||
@ -234,7 +236,7 @@ const Navigation = ({
|
||||
onBackToParentFolder={onBackToParentFolder}
|
||||
/>
|
||||
|
||||
{navigationTitleContainerNode}
|
||||
{showTitle && navigationTitleContainerNode}
|
||||
|
||||
<ControlButtons
|
||||
isRootFolder={isRootFolder}
|
||||
@ -251,6 +253,7 @@ const Navigation = ({
|
||||
isFrame={isFrame}
|
||||
isPublicRoom={isPublicRoom}
|
||||
isTrashFolder={isTrashFolder}
|
||||
showTitle={showTitle}
|
||||
navigationButtonLabel={navigationButtonLabel}
|
||||
onNavigationButtonClick={onNavigationButtonClick}
|
||||
tariffBar={tariffBar}
|
||||
|
@ -60,6 +60,7 @@ export interface IControlButtonProps {
|
||||
isPublicRoom?: boolean;
|
||||
isTrashFolder?: boolean;
|
||||
isMobile?: boolean;
|
||||
showTitle?: boolean;
|
||||
navigationButtonLabel?: string;
|
||||
onNavigationButtonClick?: () => void;
|
||||
tariffBar?: React.ReactNode;
|
||||
@ -165,6 +166,7 @@ export interface INavigationProps {
|
||||
titleIcon: string;
|
||||
currentDeviceType: DeviceType;
|
||||
rootRoomTitle: string;
|
||||
showTitle: boolean;
|
||||
navigationButtonLabel?: string;
|
||||
onNavigationButtonClick?: () => void;
|
||||
tariffBar: React.ReactNode;
|
||||
|
@ -30,6 +30,7 @@ const ControlButtons = ({
|
||||
isPublicRoom,
|
||||
isTrashFolder,
|
||||
isMobile,
|
||||
showTitle,
|
||||
navigationButtonLabel,
|
||||
onNavigationButtonClick,
|
||||
tariffBar,
|
||||
@ -53,7 +54,7 @@ const ControlButtons = ({
|
||||
const isTabletView = isTablet();
|
||||
|
||||
return (
|
||||
<StyledControlButtonContainer isFrame={isFrame}>
|
||||
<StyledControlButtonContainer isFrame={isFrame} showTitle={showTitle}>
|
||||
{!isRootFolder || (isTrashFolder && !isEmptyFilesList) ? (
|
||||
<>
|
||||
{!isMobile && canCreate && (
|
||||
|
@ -169,7 +169,7 @@ const TabsContainer = ({
|
||||
))}
|
||||
</NavItem>
|
||||
</StyledScrollbar>
|
||||
<div>{elements[state.activeTab].content}</div>
|
||||
<div className="tabs_body">{elements[state.activeTab].content}</div>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@docspace/shared",
|
||||
"version": "2.0.2",
|
||||
"version": "2.0.3",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"build": "echo 'skip it'",
|
||||
|
@ -102,6 +102,10 @@ export interface FilesSelectorProps {
|
||||
socketSubscribers: Set<string>;
|
||||
disabledItems: string[] | number[];
|
||||
filterParam?: string;
|
||||
withoutBackButton: boolean;
|
||||
withBreadCrumbs: boolean;
|
||||
withSearch: boolean;
|
||||
cancelButtonLabel: string;
|
||||
getIcon?: (size: number, fileExst: string) => string;
|
||||
treeFolders?: TFolder[];
|
||||
onSetBaseFolderPath?: (
|
||||
|
@ -3,7 +3,7 @@ import {
|
||||
TSelectorHeader,
|
||||
TSelectorItem,
|
||||
} from "../../components/selector/Selector.types";
|
||||
import { TLogo } from "../../api/rooms/types";
|
||||
|
||||
import { RoomsType } from "../../enums";
|
||||
|
||||
export type RoomSelectorProps = TSelectorHeader &
|
||||
@ -15,16 +15,9 @@ export type RoomSelectorProps = TSelectorHeader &
|
||||
isMultiSelect: boolean;
|
||||
|
||||
onSubmit: (items: TSelectorItem[]) => void;
|
||||
|
||||
roomType?: RoomsType;
|
||||
excludeItems?: number[];
|
||||
setIsDataReady?: (value: boolean) => void;
|
||||
submitButtonLabel?: string;
|
||||
withSearch?: boolean;
|
||||
};
|
||||
|
||||
export type TItem = {
|
||||
id: number;
|
||||
label: string;
|
||||
icon: string;
|
||||
color: string | undefined;
|
||||
logo: TLogo;
|
||||
roomType: RoomsType;
|
||||
};
|
||||
|
@ -25,6 +25,13 @@ const RoomSelector = ({
|
||||
className,
|
||||
style,
|
||||
|
||||
excludeItems,
|
||||
|
||||
withSearch,
|
||||
|
||||
isMultiSelect,
|
||||
|
||||
submitButtonLabel,
|
||||
onSubmit,
|
||||
|
||||
withHeader,
|
||||
@ -33,9 +40,10 @@ const RoomSelector = ({
|
||||
setIsDataReady,
|
||||
|
||||
withCancelButton,
|
||||
isMultiSelect,
|
||||
|
||||
cancelButtonLabel,
|
||||
onCancel,
|
||||
|
||||
roomType,
|
||||
}: RoomSelectorProps) => {
|
||||
const { t }: { t: TTranslation } = useTranslation(["RoomSelector", "Common"]);
|
||||
|
||||
@ -84,7 +92,7 @@ const RoomSelector = ({
|
||||
|
||||
filter.page = page;
|
||||
filter.pageCount = PAGE_COUNT;
|
||||
|
||||
filter.type = roomType;
|
||||
filter.filterValue = searchValue || null;
|
||||
|
||||
const {
|
||||
@ -93,7 +101,9 @@ const RoomSelector = ({
|
||||
count,
|
||||
} = await api.rooms.getRooms(filter);
|
||||
|
||||
const rooms = convertToItems(folders);
|
||||
const rooms = convertToItems(folders).filter((x) =>
|
||||
excludeItems ? !excludeItems.includes(x.id) : true,
|
||||
);
|
||||
|
||||
setHasNextPage(count === PAGE_COUNT);
|
||||
|
||||
@ -113,7 +123,7 @@ const RoomSelector = ({
|
||||
|
||||
setIsNextPageLoading(false);
|
||||
},
|
||||
[searchValue],
|
||||
[excludeItems, roomType, searchValue],
|
||||
);
|
||||
|
||||
const headerSelectorProps: TSelectorHeader = withHeader
|
||||
@ -124,25 +134,27 @@ const RoomSelector = ({
|
||||
headerLabel: headerProps.headerLabel || t("RoomList"),
|
||||
},
|
||||
}
|
||||
: ({} as TSelectorHeader);
|
||||
: {};
|
||||
|
||||
const cancelButtonSelectorProps: TSelectorCancelButton = withCancelButton
|
||||
? {
|
||||
withCancelButton,
|
||||
cancelButtonLabel: t("Common:CancelButton"),
|
||||
withCancelButton: true,
|
||||
cancelButtonLabel: cancelButtonLabel || t("Common:CancelButton"),
|
||||
onCancel,
|
||||
}
|
||||
: ({} as TSelectorCancelButton);
|
||||
: {};
|
||||
|
||||
const searchSelectorProps: TSelectorSearch = {
|
||||
withSearch: true,
|
||||
searchPlaceholder: t("Common:Search"),
|
||||
searchValue,
|
||||
onSearch: onSearchAction,
|
||||
onClearSearch: onClearSearchAction,
|
||||
searchLoader: <SearchLoader />,
|
||||
isSearchLoading: isFirstLoad.current,
|
||||
};
|
||||
const searchSelectorProps: TSelectorSearch = withSearch
|
||||
? {
|
||||
withSearch: true,
|
||||
searchPlaceholder: t("Common:Search"),
|
||||
searchValue,
|
||||
onSearch: onSearchAction,
|
||||
onClearSearch: onClearSearchAction,
|
||||
searchLoader: <SearchLoader />,
|
||||
isSearchLoading: isFirstLoad.current,
|
||||
}
|
||||
: {};
|
||||
|
||||
return (
|
||||
<Selector
|
||||
@ -154,7 +166,7 @@ const RoomSelector = ({
|
||||
{...searchSelectorProps}
|
||||
onSelect={(item) => setSelectedItem(item)}
|
||||
items={items}
|
||||
submitButtonLabel={t("Common:SelectAction")}
|
||||
submitButtonLabel={submitButtonLabel || t("Common:SelectAction")}
|
||||
onSubmit={onSubmit}
|
||||
isMultiSelect={isMultiSelect}
|
||||
emptyScreenImage={EmptyScreenCorporateSvgUrl}
|
||||
|
@ -13,7 +13,7 @@ import { getCookie, setCookie } from "../utils/cookie";
|
||||
import { TTenantExtraRes } from "../api/portal/types";
|
||||
import { TenantStatus } from "../enums";
|
||||
import { COOKIE_EXPIRATION_YEAR, LANGUAGE } from "../constants";
|
||||
import { TI18n } from "../types";
|
||||
import { Nullable, TI18n } from "../types";
|
||||
import { UserStore } from "./UserStore";
|
||||
|
||||
import { CurrentTariffStatusStore } from "./CurrentTariffStatusStore";
|
||||
@ -36,7 +36,7 @@ class AuthStore {
|
||||
|
||||
providers: TThirdPartyProvider[] = [];
|
||||
|
||||
capabilities: TCapabilities = {} as TCapabilities;
|
||||
capabilities: Nullable<TCapabilities> = null;
|
||||
|
||||
isInit = false;
|
||||
|
||||
@ -44,7 +44,7 @@ class AuthStore {
|
||||
|
||||
isUpdatingTariff = false;
|
||||
|
||||
tenantExtra: TTenantExtraRes = {} as TTenantExtraRes;
|
||||
tenantExtra: Nullable<TTenantExtraRes> = null;
|
||||
|
||||
skipRequest = false;
|
||||
|
||||
@ -159,12 +159,14 @@ class AuthStore {
|
||||
};
|
||||
|
||||
get isEnterprise() {
|
||||
this.currentTariffStatusStore?.setIsEnterprise(this.tenantExtra.enterprise);
|
||||
return this.tenantExtra.enterprise;
|
||||
this.currentTariffStatusStore?.setIsEnterprise(
|
||||
this.tenantExtra?.enterprise || false,
|
||||
);
|
||||
return this.tenantExtra?.enterprise;
|
||||
}
|
||||
|
||||
get isCommunity() {
|
||||
return this.tenantExtra.opensource;
|
||||
return this.tenantExtra?.opensource;
|
||||
}
|
||||
|
||||
getTenantExtra = async () => {
|
||||
|
@ -15,9 +15,10 @@ import {
|
||||
COUNT_FOR_SHOWING_BAR,
|
||||
PERCENTAGE_FOR_SHOWING_BAR,
|
||||
} from "../constants";
|
||||
import { Nullable } from "../types";
|
||||
|
||||
class CurrentQuotasStore {
|
||||
currentPortalQuota: TPaymentQuota = {} as TPaymentQuota;
|
||||
currentPortalQuota: Nullable<TPaymentQuota> = null;
|
||||
|
||||
currentPortalQuotaFeatures: TPaymentFeature[] = [];
|
||||
|
||||
@ -32,15 +33,15 @@ class CurrentQuotasStore {
|
||||
};
|
||||
|
||||
get isFreeTariff() {
|
||||
return this.currentPortalQuota.free;
|
||||
return this.currentPortalQuota?.free;
|
||||
}
|
||||
|
||||
get isTrial() {
|
||||
return this.currentPortalQuota.trial;
|
||||
return this.currentPortalQuota?.trial;
|
||||
}
|
||||
|
||||
get currentPlanCost() {
|
||||
if (this.currentPortalQuota.price) return this.currentPortalQuota.price;
|
||||
if (this.currentPortalQuota?.price) return this.currentPortalQuota.price;
|
||||
|
||||
return { value: 0, currencySymbol: "" };
|
||||
}
|
||||
@ -159,7 +160,7 @@ class CurrentQuotasStore {
|
||||
}
|
||||
|
||||
get currentTariffPlanTitle() {
|
||||
return this.currentPortalQuota.title;
|
||||
return this.currentPortalQuota?.title;
|
||||
}
|
||||
|
||||
get quotaCharacteristics() {
|
||||
|
@ -9,9 +9,10 @@ import { TPortalTariff } from "../api/portal/types";
|
||||
import { TUser } from "../api/people/types";
|
||||
import { isValidDate } from "../utils";
|
||||
import { getDaysLeft, getDaysRemaining } from "../utils/common";
|
||||
import { Nullable } from "../types";
|
||||
|
||||
class CurrentTariffStatusStore {
|
||||
portalTariffStatus: TPortalTariff = {} as TPortalTariff;
|
||||
portalTariffStatus: Nullable<TPortalTariff> = null;
|
||||
|
||||
isLoaded = false;
|
||||
|
||||
@ -38,35 +39,37 @@ class CurrentTariffStatusStore {
|
||||
};
|
||||
|
||||
get isGracePeriod() {
|
||||
return this.portalTariffStatus.state === TariffState.Delay;
|
||||
return this.portalTariffStatus?.state === TariffState.Delay;
|
||||
}
|
||||
|
||||
get isPaidPeriod() {
|
||||
return this.portalTariffStatus.state === TariffState.Paid;
|
||||
return this.portalTariffStatus?.state === TariffState.Paid;
|
||||
}
|
||||
|
||||
get isNotPaidPeriod() {
|
||||
return this.portalTariffStatus.state === TariffState.NotPaid;
|
||||
return this.portalTariffStatus?.state === TariffState.NotPaid;
|
||||
}
|
||||
|
||||
get dueDate() {
|
||||
return this.portalTariffStatus.dueDate;
|
||||
return this.portalTariffStatus ? this.portalTariffStatus.dueDate : null;
|
||||
}
|
||||
|
||||
get delayDueDate() {
|
||||
return this.portalTariffStatus.delayDueDate;
|
||||
return this.portalTariffStatus
|
||||
? this.portalTariffStatus.delayDueDate
|
||||
: null;
|
||||
}
|
||||
|
||||
get customerId() {
|
||||
return this.portalTariffStatus.customerId;
|
||||
return this.portalTariffStatus?.customerId;
|
||||
}
|
||||
|
||||
get portalStatus() {
|
||||
return this.portalTariffStatus.portalStatus;
|
||||
return this.portalTariffStatus?.portalStatus;
|
||||
}
|
||||
|
||||
get licenseDate() {
|
||||
return this.portalTariffStatus.licenseDate;
|
||||
return this.portalTariffStatus?.licenseDate;
|
||||
}
|
||||
|
||||
setPayerInfo = async () => {
|
||||
@ -97,7 +100,6 @@ class CurrentTariffStatusStore {
|
||||
|
||||
get isPaymentDateValid() {
|
||||
if (this.dueDate === null) return false;
|
||||
|
||||
return isValidDate(this.dueDate);
|
||||
}
|
||||
|
||||
|
@ -2,9 +2,10 @@ import { makeAutoObservable, runInAction } from "mobx";
|
||||
import api from "../api";
|
||||
import { TPaymentFeature, TPaymentQuota } from "../api/portal/types";
|
||||
import { MANAGER, TOTAL_SIZE } from "../constants";
|
||||
import { Nullable } from "../types";
|
||||
|
||||
class PaymentQuotasStore {
|
||||
portalPaymentQuotas: TPaymentQuota = {} as TPaymentQuota;
|
||||
portalPaymentQuotas: Nullable<TPaymentQuota> = null;
|
||||
|
||||
portalPaymentQuotasFeatures: TPaymentFeature[] = [];
|
||||
|
||||
@ -19,7 +20,7 @@ class PaymentQuotasStore {
|
||||
};
|
||||
|
||||
get planCost() {
|
||||
if (this.portalPaymentQuotas.price) return this.portalPaymentQuotas.price;
|
||||
if (this.portalPaymentQuotas?.price) return this.portalPaymentQuotas.price;
|
||||
return { value: 0, currencySymbol: "" };
|
||||
}
|
||||
|
||||
@ -56,7 +57,7 @@ class PaymentQuotasStore {
|
||||
}
|
||||
|
||||
get tariffPlanTitle() {
|
||||
return this.portalPaymentQuotas.title;
|
||||
return this.portalPaymentQuotas?.title;
|
||||
}
|
||||
|
||||
setPortalPaymentQuotas = async () => {
|
||||
|
@ -45,6 +45,7 @@ import { Dark, Base, TColorScheme } from "../themes";
|
||||
import { toastr } from "../components/toast";
|
||||
import { TData } from "../components/toast/Toast.type";
|
||||
import { version } from "../package.json";
|
||||
import { Nullable } from "../types";
|
||||
|
||||
// import { getFromLocalStorage } from "@docspace/client/src/pages/PortalSettings/utils";
|
||||
|
||||
@ -143,7 +144,7 @@ class SettingsStore {
|
||||
uploadDashboard: "",
|
||||
};
|
||||
|
||||
logoUrl: TWhiteLabel = {} as TWhiteLabel;
|
||||
logoUrl: Nullable<TWhiteLabel> = null;
|
||||
|
||||
isDesktopClient = isDesktopEditors;
|
||||
|
||||
@ -172,7 +173,7 @@ class SettingsStore {
|
||||
|
||||
folderPath: TFolder[] = [];
|
||||
|
||||
hashSettings: TPasswordHash = {} as TPasswordHash;
|
||||
hashSettings: Nullable<TPasswordHash> = null;
|
||||
|
||||
title = "";
|
||||
|
||||
@ -180,7 +181,7 @@ class SettingsStore {
|
||||
|
||||
nameSchemaId = null;
|
||||
|
||||
owner: TUser = {} as TUser;
|
||||
owner: Nullable<TUser> = null;
|
||||
|
||||
wizardToken = null;
|
||||
|
||||
@ -234,7 +235,7 @@ class SettingsStore {
|
||||
|
||||
selectedThemeId: number | null = null;
|
||||
|
||||
currentColorScheme: TColorScheme = {} as TColorScheme;
|
||||
currentColorScheme: Nullable<TColorScheme> = null;
|
||||
|
||||
enablePlugins = false;
|
||||
|
||||
@ -242,11 +243,11 @@ class SettingsStore {
|
||||
|
||||
domainValidator: TDomainValidator | null = null;
|
||||
|
||||
additionalResourcesData: TAdditionalResources = {} as TAdditionalResources;
|
||||
additionalResourcesData: Nullable<TAdditionalResources> = null;
|
||||
|
||||
additionalResourcesIsDefault = true;
|
||||
|
||||
companyInfoSettingsData: TCompanyInfo = {} as TCompanyInfo;
|
||||
companyInfoSettingsData: Nullable<TCompanyInfo> = null;
|
||||
|
||||
companyInfoSettingsIsDefault = true;
|
||||
|
||||
@ -499,7 +500,7 @@ class SettingsStore {
|
||||
};
|
||||
|
||||
getSettings = async () => {
|
||||
let newSettings: TSettings = {} as TSettings;
|
||||
let newSettings: Nullable<TSettings> = null;
|
||||
|
||||
if (window?.__ASC_INITIAL_EDITOR_STATE__?.portalSettings)
|
||||
newSettings = window.__ASC_INITIAL_EDITOR_STATE__.portalSettings;
|
||||
@ -514,7 +515,7 @@ class SettingsStore {
|
||||
|
||||
Object.keys(newSettings).forEach((forEachKey) => {
|
||||
const key = forEachKey as keyof TSettings;
|
||||
if (key in this) {
|
||||
if (key in this && newSettings) {
|
||||
this.setValue(
|
||||
key as keyof SettingsStore,
|
||||
key === "defaultPage"
|
||||
@ -530,7 +531,7 @@ class SettingsStore {
|
||||
});
|
||||
}
|
||||
}
|
||||
} else if (key === "passwordHash") {
|
||||
} else if (key === "passwordHash" && newSettings) {
|
||||
this.setValue("hashSettings", newSettings[key]);
|
||||
}
|
||||
});
|
||||
@ -748,6 +749,7 @@ class SettingsStore {
|
||||
|
||||
getPortalOwner = async () => {
|
||||
const owner = await api.people.getUserById(this.ownerId);
|
||||
|
||||
this.setPortalOwner(owner);
|
||||
return owner;
|
||||
};
|
||||
@ -965,7 +967,7 @@ class SettingsStore {
|
||||
this.frameConfig = frameConfig;
|
||||
});
|
||||
|
||||
if (!!frameConfig) {
|
||||
if (frameConfig) {
|
||||
frameCallEvent({
|
||||
event: "onAppReady",
|
||||
data: { frameId: frameConfig.frameId },
|
||||
@ -992,13 +994,13 @@ class SettingsStore {
|
||||
};
|
||||
|
||||
getAppearanceTheme = async () => {
|
||||
let res: TGetColorTheme = {} as TGetColorTheme;
|
||||
let res: Nullable<TGetColorTheme> = null;
|
||||
if (window?.__ASC_INITIAL_EDITOR_STATE__?.appearanceTheme)
|
||||
res = window.__ASC_INITIAL_EDITOR_STATE__.appearanceTheme;
|
||||
else res = await api.settings.getAppearanceTheme();
|
||||
|
||||
const currentColorScheme = res.themes.find((theme) => {
|
||||
return res.selected === theme.id;
|
||||
return res && res.selected === theme.id;
|
||||
});
|
||||
|
||||
this.setAppearanceTheme(res.themes);
|
||||
@ -1100,4 +1102,3 @@ class SettingsStore {
|
||||
}
|
||||
|
||||
export { SettingsStore };
|
||||
|
||||
|
@ -3209,6 +3209,11 @@ export const getBaseTheme = () => {
|
||||
pluginName: "#5C5C5C",
|
||||
descriptionColor: "#657077",
|
||||
},
|
||||
|
||||
sdkPresets: {
|
||||
borderColor: "#d0d5da",
|
||||
secondaryColor: "#657077",
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
|
@ -3184,6 +3184,11 @@ const Dark: TTheme = {
|
||||
pluginName: "#A3A9AE",
|
||||
descriptionColor: "#ADADAD",
|
||||
},
|
||||
|
||||
sdkPresets: {
|
||||
borderColor: "#474747",
|
||||
secondaryColor: "#ADADAD",
|
||||
},
|
||||
};
|
||||
|
||||
export default Dark;
|
||||
|
@ -15,6 +15,8 @@ export type TViewAs = "tile" | "table" | "row" | "settings" | "profile";
|
||||
|
||||
export type TTranslation = (key: string, prop?: unknown) => string;
|
||||
|
||||
export type Nullable<T> = T | null;
|
||||
|
||||
export type NonFunctionPropertyNames<T, ExcludeTypes> = {
|
||||
[K in keyof T]: T[K] extends ExcludeTypes ? never : K;
|
||||
}[keyof T];
|
||||
|
5
public/images/light_small_logo.react.svg
Normal file
@ -0,0 +1,5 @@
|
||||
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M7.02215 15.2038L0.421696 12.1631C-0.140565 11.8977 -0.140565 11.4874 0.421696 11.2461L2.71963 10.1843L6.99771 12.1631C7.55997 12.4286 8.46448 12.4286 9.00229 12.1631L13.2804 10.1843L15.5783 11.2461C16.1406 11.5116 16.1406 11.9218 15.5783 12.1631L8.97785 15.2038C8.46448 15.4451 7.55997 15.4451 7.02215 15.2038Z" fill="white"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M7.00076 11.441L0.420411 8.39689C-0.140137 8.13114 -0.140137 7.72042 0.420411 7.47882L2.6626 6.43994L7.00076 8.44521C7.56131 8.71097 8.46306 8.71097 8.99924 8.44521L13.3374 6.43994L15.5796 7.47882C16.1401 7.74458 16.1401 8.1553 15.5796 8.39689L8.99924 11.441C8.43869 11.7068 7.53694 11.7068 7.00076 11.441Z" fill="white"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M7.00076 7.71748L0.420411 4.71714C-0.140137 4.45521 -0.140137 4.0504 0.420411 3.81227L7.00076 0.81193C7.56131 0.549995 8.46306 0.549995 8.99924 0.81193L15.5796 3.81227C16.1401 4.07421 16.1401 4.47902 15.5796 4.71714L8.99924 7.71748C8.43869 7.95561 7.53694 7.95561 7.00076 7.71748Z" fill="white"/>
|
||||
</svg>
|
After Width: | Height: | Size: 1.2 KiB |
12
public/images/sdk-presets_action-button.react.svg
Normal file
After Width: | Height: | Size: 22 KiB |
11
public/images/sdk-presets_action-button_dark.react.svg
Normal file
After Width: | Height: | Size: 20 KiB |
10
public/images/sdk-presets_columns.react.svg
Normal file
After Width: | Height: | Size: 9.1 KiB |
9
public/images/sdk-presets_columns_dark.react.svg
Normal file
After Width: | Height: | Size: 7.6 KiB |
9
public/images/sdk-presets_editor.react.svg
Normal file
@ -0,0 +1,9 @@
|
||||
<svg width="310" height="180" viewBox="0 0 310 180" fill="none" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<rect width="310" height="180" fill="url(#pattern0)"/>
|
||||
<defs>
|
||||
<pattern id="pattern0" patternContentUnits="objectBoundingBox" width="1" height="1">
|
||||
<use xlink:href="#image0_986_510" transform="scale(0.0016129 0.00277778)"/>
|
||||
</pattern>
|
||||
<image id="image0_986_510" width="620" height="360" xlink:href="data:image/png;base64,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"/>
|
||||
</defs>
|
||||
</svg>
|
After Width: | Height: | Size: 4.6 KiB |
9
public/images/sdk-presets_editor_dark.react.svg
Normal file
@ -0,0 +1,9 @@
|
||||
<svg width="310" height="180" viewBox="0 0 310 180" fill="none" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<rect width="310" height="180" fill="url(#pattern0)"/>
|
||||
<defs>
|
||||
<pattern id="pattern0" patternContentUnits="objectBoundingBox" width="1" height="1">
|
||||
<use xlink:href="#image0_986_9271" transform="scale(0.0016129 0.00277778)"/>
|
||||
</pattern>
|
||||
<image id="image0_986_9271" width="620" height="360" xlink:href="data:image/png;base64,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"/>
|
||||
</defs>
|
||||
</svg>
|
After Width: | Height: | Size: 4.5 KiB |
9
public/images/sdk-presets_file-selector.react.svg
Normal file
After Width: | Height: | Size: 16 KiB |
9
public/images/sdk-presets_file-selector_dark.react.svg
Normal file
After Width: | Height: | Size: 14 KiB |
10
public/images/sdk-presets_files-search.react.svg
Normal file
After Width: | Height: | Size: 8.8 KiB |
10
public/images/sdk-presets_header.react.svg
Normal file
After Width: | Height: | Size: 26 KiB |
9
public/images/sdk-presets_header_dark.react.svg
Normal file
After Width: | Height: | Size: 26 KiB |
10
public/images/sdk-presets_left-menu.react.svg
Normal file
After Width: | Height: | Size: 104 KiB |
9
public/images/sdk-presets_left-menu_dark.react.svg
Normal file
After Width: | Height: | Size: 94 KiB |
9
public/images/sdk-presets_manager.react.svg
Normal file
After Width: | Height: | Size: 24 KiB |
9
public/images/sdk-presets_manager_dark.react.svg
Normal file
After Width: | Height: | Size: 22 KiB |
9
public/images/sdk-presets_room-selector.react.svg
Normal file
After Width: | Height: | Size: 16 KiB |
9
public/images/sdk-presets_room-selector_dark.react.svg
Normal file
After Width: | Height: | Size: 14 KiB |
11
public/images/sdk-presets_search.react.svg
Normal file
After Width: | Height: | Size: 9.7 KiB |
10
public/images/sdk-presets_search_dark.react.svg
Normal file
After Width: | Height: | Size: 9.0 KiB |
9
public/images/sdk-presets_simple-room.react.svg
Normal file
After Width: | Height: | Size: 125 KiB |
9
public/images/sdk-presets_simple-room_dark.react.svg
Normal file
After Width: | Height: | Size: 110 KiB |
10
public/images/sdk-presets_subtitle.react.svg
Normal file
After Width: | Height: | Size: 28 KiB |
14
public/images/sdk-presets_title.react.svg
Normal file
After Width: | Height: | Size: 19 KiB |
13
public/images/sdk-presets_title_dark.react.svg
Normal file
After Width: | Height: | Size: 17 KiB |
9
public/images/sdk-presets_viewer.react.svg
Normal file
@ -0,0 +1,9 @@
|
||||
<svg width="310" height="180" viewBox="0 0 310 180" fill="none" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<rect width="310" height="180" fill="url(#pattern0)"/>
|
||||
<defs>
|
||||
<pattern id="pattern0" patternContentUnits="objectBoundingBox" width="1" height="1">
|
||||
<use xlink:href="#image0_986_950" transform="scale(0.0016129 0.00277778)"/>
|
||||
</pattern>
|
||||
<image id="image0_986_950" width="620" height="360" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAmwAAAFoCAYAAADq7KeuAAAACXBIWXMAABYlAAAWJQFJUiTwAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAptSURBVHgB7d3RauPoGcfhz47MsjCTWGnKUAql0DLbm+hBYW5mb2ivptCDHs4V7NCWUtjCQDBOYmiXCM3GOV12P2ljjf+2nuckJ0J+LRx9P4SQFu++/uZTAQAg1rIAABBNsAEAhBNsAADhBBsAQDjBBgAQTrABAIQTbAAA4ZraBr+5eV3+9Ltfl6YZ1nb/+/6x/Ou7Tfnv7cNB93topzLnUOnf59yO96Gd6vEZOjcAL1M96//ht78atTh8+cWqfPW0oBx6v4d2KnMOlf59zu14H9qpHp+hcwPwMtUz/5dfVC/C/ciQBeWX7PfQTmXOodK/z7kd70M71eMzx8AG+NycaQEAwgk2AIBwgo0CAGQTbAAA4QQbAEA4wQYAEE6wAQCEE2wAAOEEGwBAuGqwdV1fxvr/94/VbX7Jfg/tVOYcKv37nNvxPrRTPT5D5gbgZarB9u1/bp9OyF0Zar+g/PO7TXW7sfs9tFOZc6j073Nux/vQTvX4DJ0bgJdZvPv6m08FAIBY7mEDAAgn2AAAwgk2AIBwgg0AIJxgAwAIJ9gAAMIJNgCAcIu7u7vP+hy2Dx8+PP998+ZNAQA4JR8/fnz++/bt2/I5ucIGABBOsAEAhBNsAADhBBsAQDjBBgAQTrABAIQTbAAA4QQbAEA4wQYAEE6wAQCEE2wAAOGa2gYPu1253WxL3/dliFXTlHZ9WV6/elUAAOZkqm6qXmHbbO8Hf+jeY9c9DwoAMDdTdVM12LqnHY01ZlAAgHMxVTe5hw0AIJxgAwAIJ9gAAMIJNgCAcIINACBc9Tlsc/XtP/5dAIDP66s//r7wY66wAQCEc4Wt4t1f/lwAgGn99W9/L/w0V9gAAMJVg225XJSxVs1FAQCYm6m6qRpsN9dtaUYE2H7Qdn1VAADmZqpuqt7Dtn97fO0N8gAATNdN7mEDAAgn2AAAwgk2AIBwgg0AIJxgAwAIJ9gAAMIJNgCAcNXnsD3sduV2sy1935chVk1T2vWlZ7cBALMzVTdVr7BttveDP3TvseueBwUAmJupuqkabN3TjsYaMygAwLmYqpvcwwYAEE6wAQCEE2wAAOEEGwBAOMEGABBOsAEAhBNsAADhBBsAQDjBBgAQrhpsy+WijLVqLgoAwNxM1U3VYLu5bkszIsD2g7brqwIAMDdTdVNT22D/9vjaG+QBAJium9zDBgAQTrABAIQTbAAA4QQbAEA4wQYAEE6wAQCEE2wAAOGqz2F72O3K7WZb+r4vQ6yaprTrS89uAwBmZ6puql5h22zvB3/o3mPXPQ8KADA3U3VTNdi6px2NNWZQAIBzMVU3uYcNACCcYAMACCfYAADCCTYAgHCCDQAgnGADAAgn2AAAwgk2AIBwgg0AIFw12JbLRRlr1VwUAIC5maqbqsF2c92WZkSA7Qdt11cFAGBupuqmprbB/u3xtTfIAwAwXTe5hw0AIJxgAwAIJ9gAAMIJNgCAcIINACCcYAMACCfYAADCVZ/D9rDbldvNtvR9X4ZYNU1p15ee3QYAzM5U3VS9wrbZ3g/+0L3HrnseFABgbqbqpmqwdU87GmvMoAAA52KqbnIPGwBAOMEGABBOsAEAhBNsAADhBBsAQDjBBgAQTrABAIQTbAAA4QQbAEC4arAtl4sy1qq5KAAAczNVN1WD7ea6Lc2IANsP2q6vCgDA3EzVTU1tg/3b42tvkAcAYLpucg8bAEA4wQYAEE6wAQCEE2wAAOEEGwBAOMEGABBOsAEAhKs+h+1htyu3m23p+74MsWqa0q4vPbsNAJidqbqpeoVts70f/KF7j133PCgAwNxM1U3VYOuedjTWmEEBAM7FVN3kHjYAgHCCDQAgnGADAAgn2AAAwgk2AIBwgg0AIJxgAwAIJ9gAAMIJNgCAcNVgWy4XZaxVc1EAAOZmqm6qBtvNdVuaEQG2H7RdXxUAgLmZqpua2gb7t8fX3iAPAMB03eQeNgCAcIINACCcYAMACCfYAADCCTYAgHCCDQAgnGADAAgn2AAAwgk2AIBwgg0AIJxgAwAIJ9gAAMIJNgCAcIINACCcYAMACCfYAADCCTYAgHCCDQAgnGADAAgn2AAAwgk2AIBwgg0AIJxgAwAIJ9gAAMIJNgCAcIINACCcYAMACCfYAADCCTYAgHCCDQAgnGADAAgn2AAAwgk2AIBwgg0AIJxgAwAIJ9gAAMIJNgCAcIINACCcYAMACCfYAADCCTYAgHCCDQAgnGADAAgn2AAAwgk2AIBwgg0AIJxgAwAIJ9gAAMIJNgCAcIINACCcYAMACCfYAADCCTYAgHCCDQAgnGADAAgn2AAAwgk2AIBwgg0AIJxgAwAIJ9gAAMIJNgCAcIINACCcYAMACCfYAADCCTYAgHCCDQAgnGADAAgn2AAAwgk2AIBwgg0AIJxgAwAIJ9gAAMIJNgCAcIINACCcYAMACCfYAADCCTYAgHCCDQAgnGADAAgn2AAAwgk2AIBwgg0AIJxgAwAIJ9gAAMIJNgCAcIINACCcYAMACCfYAADCCTYAgHCCDQAgnGADAAgn2AAAwgk2AIBwgg0AIJxgAwAIJ9gAAMIJNgCAcIINACCcYAMACCfYAADCCTYAgHCCDQAgnGADAAgn2AAAwgk2AIBwgg0AIJxgAwAIJ9gAAMIJNgCAcIINACCcYAMACCfYAADCCTYAgHCCDQAgnGADAAgn2AAAwgk2AIBwgg0AIJxgAwAIJ9gAAMIJNgCAcIINACCcYAMACCfYAADCCTYAgHCCDQAgnGADAAgn2AAAwgk2AIBwgg0AIJxgAwAIJ9gAAMIJNgCAcIINACCcYAMACCfYAADCCTYAgHCCDQAgnGADAAgn2AAAwgk2AIBwgg0AIJxgAwAIJ9gAAMIJNgCAcIINACCcYAMACCfYAADCCTYAgHCCDQAgnGADAAgn2AAAwgk2AIBwgg0AIJxgAwAIJ9gAAMIJNgCAcIINACCcYAMACCfYAADCCTYAgHCCDQAgnGADAAgn2AAAwgk2AIBwgg0AIJxgAwAIJ9gAAMIJNgCAcIINACCcYAMACCfYAADCCTYAgHCCDQAgnGADAAgn2AAAwgk2AIBwgg0AIJxgAwAIJ9gAAMIJNgCAcIINACCcYAMACCfYAADCCTYAgHCCDQAgnGADAAgn2AAAwgk2AIBwgg0AIJxgAwAIJ9gAAMIJNgCAcIINACCcYAMACCfYAADCCTYAgHCL9+/ffyoAAMRyhQ0AINzi7u7OFTYAgGCusAEAhBNsAADhBBsAQLimHMnDblduN9vS931Jsmqa0q4vy+tXr352u9T5j23o8QOGc77JcOrrg/XtZY69vh3tCttmex/5Y3jsuucfak3q/Mc29PgBwznfZDj19cH69jLHXt+OFmzd0xdPNeSHmjz/sflHh8Nyvslx6uuD9e1ljrm+uYcNACCcYAMACCfYAADCHS3YlstFSbVqLqrbJM9/bEOOHzCc802OU18frG8vc8z17WjBdnPdliZwYd//UNv1VXW71PmPbejxA4Zzvslw6uuD9e1ljr2+eZcoAEA497ABAIQTbAAA4QQbAEC4HwCa6lwu6k4UIAAAAABJRU5ErkJggg=="/>
|
||||
</defs>
|
||||
</svg>
|
After Width: | Height: | Size: 4.1 KiB |
9
public/images/sdk-presets_viewer_dark.react.svg
Normal file
@ -0,0 +1,9 @@
|
||||
<svg width="310" height="180" viewBox="0 0 310 180" fill="none" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<rect width="310" height="180" fill="url(#pattern0)"/>
|
||||
<defs>
|
||||
<pattern id="pattern0" patternContentUnits="objectBoundingBox" width="1" height="1">
|
||||
<use xlink:href="#image0_986_9286" transform="scale(0.0016129 0.00277778)"/>
|
||||
</pattern>
|
||||
<image id="image0_986_9286" width="620" height="360" xlink:href="data:image/png;base64,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"/>
|
||||
</defs>
|
||||
</svg>
|
After Width: | Height: | Size: 4.0 KiB |
@ -31,6 +31,7 @@
|
||||
"ByFirstNameSorting": "First name",
|
||||
"ByLastNameSorting": "Last name",
|
||||
"Bytes": "bytes",
|
||||
"Button": "Button",
|
||||
"CancelButton": "Cancel",
|
||||
"ChangeButton": "Change",
|
||||
"ChangesSavedSuccessfully": "Changes saved successfully",
|
||||
@ -131,6 +132,7 @@
|
||||
"ExpiredLink": "Expired link",
|
||||
"FeedbackAndSupport": "Feedback & Support",
|
||||
"FillFormButton": "Fill in the form",
|
||||
"Filter": "Filter",
|
||||
"FirstName": "First name",
|
||||
"Free": "Free",
|
||||
"FreeProFeatures": "Free access to pro features",
|
||||
@ -261,8 +263,11 @@
|
||||
"SearchEmptyRoomsDescription": "No rooms match this filter. Try a different one or clear filter to view all rooms.",
|
||||
"SelectAction": "Select",
|
||||
"SelectAll": "Select all",
|
||||
"SelectBackupOnlyFormat": "Select backup only file",
|
||||
"SelectDOCXFFormat": "Select .DOCXF file",
|
||||
"SelectDOCXFormat": "Select .DOCX file",
|
||||
"SelectIMGFormat": "Select IMG file",
|
||||
"SelectXLSXFormat": "Select .XLSX file",
|
||||
"SelectFile": "Select file",
|
||||
"SendButton": "Send",
|
||||
"SendReport": "Send report",
|
||||
|