Merge branch 'develop' into feature/rewrite-error-boundary
This commit is contained in:
commit
3cb31f417a
5760
i18next/client.babel
5760
i18next/client.babel
File diff suppressed because it is too large
Load Diff
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "docspace",
|
||||
"version": "2.0.2",
|
||||
"version": "2.0.3",
|
||||
"private": true,
|
||||
"workspaces": {
|
||||
"packages": [
|
||||
|
15
packages/client/.eslintrc.cjs
Normal file
15
packages/client/.eslintrc.cjs
Normal file
@ -0,0 +1,15 @@
|
||||
module.exports = {
|
||||
extends: "../shared/.eslintrc.cjs",
|
||||
parserOptions: {
|
||||
project: "tsconfig.eslint.json",
|
||||
tsconfigRootDir: __dirname,
|
||||
sourceType: "module",
|
||||
},
|
||||
|
||||
ignorePatterns: [
|
||||
"./tsconfig.json",
|
||||
"coverage/**",
|
||||
"storybook-static/**",
|
||||
"*.js",
|
||||
],
|
||||
};
|
3
packages/client/.prettierrc.json
Normal file
3
packages/client/.prettierrc.json
Normal file
@ -0,0 +1,3 @@
|
||||
{
|
||||
"extends": "../shared/.prettierrc.json"
|
||||
}
|
2
packages/client/index.d.ts
vendored
2
packages/client/index.d.ts
vendored
@ -1,5 +1,5 @@
|
||||
interface Window {
|
||||
zESettings?: any;
|
||||
zESettings?: unknown;
|
||||
zE?: {
|
||||
apply: Function;
|
||||
};
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@docspace/client",
|
||||
"version": "2.0.2",
|
||||
"version": "2.0.3",
|
||||
"private": true,
|
||||
"homepage": "",
|
||||
"scripts": {
|
||||
@ -59,6 +59,7 @@
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/core": "^7.21.3",
|
||||
"@babel/eslint-parser": "^7.21.8",
|
||||
"@babel/plugin-proposal-class-properties": "^7.18.6",
|
||||
"@babel/plugin-proposal-export-default-from": "^7.18.10",
|
||||
"@babel/plugin-transform-runtime": "^7.21.0",
|
||||
@ -66,16 +67,30 @@
|
||||
"@babel/preset-react": "^7.18.6",
|
||||
"@babel/preset-typescript": "^7.21.0",
|
||||
"@svgr/webpack": "^5.5.0",
|
||||
"@types/eslint": "^8.44.7",
|
||||
"@typescript-eslint/eslint-plugin": "^6.12.0",
|
||||
"@typescript-eslint/parser": "^6.12.0",
|
||||
"babel-loader": "^8.3.0",
|
||||
"clean-webpack-plugin": "^4.0.0",
|
||||
"copy-webpack-plugin": "^9.1.0",
|
||||
"css-loader": "^6.7.3",
|
||||
"eslint": "^8.54.0",
|
||||
"eslint-config-airbnb": "^19.0.4",
|
||||
"eslint-config-airbnb-typescript": "^17.1.0",
|
||||
"eslint-config-prettier": "^9.0.0",
|
||||
"eslint-plugin-import": "^2.29.0",
|
||||
"eslint-plugin-jsx-a11y": "^6.8.0",
|
||||
"eslint-plugin-prettier": "^5.0.1",
|
||||
"eslint-plugin-react": "^7.33.2",
|
||||
"eslint-plugin-react-hooks": "^4.6.0",
|
||||
"eslint-plugin-storybook": "^0.6.15",
|
||||
"external-remotes-plugin": "^1.0.0",
|
||||
"file-loader": "^6.2.0",
|
||||
"html-loader": "^4.2.0",
|
||||
"html-webpack-plugin": "5.5.0",
|
||||
"json-loader": "^0.5.7",
|
||||
"playwright": "^1.32.0",
|
||||
"prettier": "^3.1.0",
|
||||
"sass": "^1.59.3",
|
||||
"sass-loader": "^12.6.0",
|
||||
"serve": "14.2.0",
|
||||
|
@ -35,7 +35,7 @@
|
||||
"MobileWin": "حمّل ONLYOFFICE Desktop Editors لنظام ويندوز",
|
||||
"MoveHere": "انقل إلى هنا",
|
||||
"MoveToOperation": "جارٍ النقل",
|
||||
"NewForm": "قوالب جاهزة",
|
||||
"NewForm": "نموذج PDF",
|
||||
"Other": "آخر",
|
||||
"OwnerChange": "تغيير المالك",
|
||||
"Presentations": "العروض التقديمية",
|
||||
|
@ -35,7 +35,7 @@
|
||||
"MobileWin": "Windows üçün ONLYOFFICE Masaüstü Redaktorları endirin",
|
||||
"MoveHere": "Bura köçürün",
|
||||
"MoveToOperation": "Yer dəyişdirmə",
|
||||
"NewForm": "Forma şablonu",
|
||||
"NewForm": "PDF forma",
|
||||
"Other": "Digər",
|
||||
"OwnerChange": "Sahibi dəyiş",
|
||||
"Presentations": "Təqdimatlar",
|
||||
|
@ -35,7 +35,7 @@
|
||||
"MobileWin": "Изтеглете ONLYOFFICE настолни редактори за Windows",
|
||||
"MoveHere": "Премести се тук",
|
||||
"MoveToOperation": "Преместване",
|
||||
"NewForm": "Шаблон на формуляр",
|
||||
"NewForm": "PDF формуляр",
|
||||
"Other": "Друг",
|
||||
"OwnerChange": "Смени собственик",
|
||||
"Presentations": "Презентации",
|
||||
|
@ -35,7 +35,7 @@
|
||||
"MobileWin": "Stáhnout ONLYOFFICE Desktop Editors pro Windows",
|
||||
"MoveHere": "Přesunout zde",
|
||||
"MoveToOperation": "Přesouvám",
|
||||
"NewForm": "Šablona formuláře",
|
||||
"NewForm": "PDF formulář",
|
||||
"Other": "Jiný",
|
||||
"OwnerChange": "Změnit vlastníka",
|
||||
"Presentations": "Prezentace",
|
||||
|
@ -35,7 +35,7 @@
|
||||
"MobileWin": "Download ONLYOFFICE Desktop Editors für Windows",
|
||||
"MoveHere": "Verschieben",
|
||||
"MoveToOperation": "Wird verschoben",
|
||||
"NewForm": "Formularvorlage",
|
||||
"NewForm": "PDF-Formular",
|
||||
"Other": "Sonstiges",
|
||||
"OwnerChange": "Besitzer ändern",
|
||||
"Presentations": "Präsentationen",
|
||||
|
@ -35,7 +35,7 @@
|
||||
"MobileWin": "Λήψη ONLYOFFICE Desktop Editors για Windows",
|
||||
"MoveHere": "Μετακίνηση εδώ",
|
||||
"MoveToOperation": "Μετακίνηση",
|
||||
"NewForm": "Πρότυπο φόρμας",
|
||||
"NewForm": "Φόρμα PDF",
|
||||
"Other": "Άλλο",
|
||||
"OwnerChange": "Αλλαγή κατόχου",
|
||||
"Presentations": "Παρουσιάσεις",
|
||||
|
@ -14,9 +14,9 @@
|
||||
"ArchiveEmptyScreenUser": "Rooms that have been archived will appear here.",
|
||||
"Archives": "Archives",
|
||||
"AssignOwner": "Assign Owner",
|
||||
"BackToParentFolderButton": "Back to parent folder",
|
||||
"BadgeAlertDescription": "Several roles are specified in this form. Forms with multiple roles are not available for filling in this type of room",
|
||||
"BadgeMyDraftTitle": "My draft",
|
||||
"BackToParentFolderButton": "Back to parent folder",
|
||||
"ByAuthor": "Author",
|
||||
"ByCreation": "Created",
|
||||
"ByErasure": "Erasure",
|
||||
@ -27,20 +27,20 @@
|
||||
"CollaborationRooms": "Collaboration",
|
||||
"ContainsSpecCharacter": "The title can't contain any of the following characters: *+:\"<>?|/",
|
||||
"Convert": "Convert",
|
||||
"CopySharedLink": "Copy shared link",
|
||||
"CopyItem": "<strong>{{title}}</strong> copied",
|
||||
"CopyItems": "<strong>{{qty}}</strong> elements copied",
|
||||
"CopyLink": "Copy link",
|
||||
"CopyLinkPassword": "Copy link password",
|
||||
"CopyPassword": "Copy password",
|
||||
"CopySharedLink": "Copy shared link",
|
||||
"CreateAndCopy": "Create and copy",
|
||||
"CreateNewLink": "Create new link",
|
||||
"CreateRoom": "Create room",
|
||||
"CustomRooms": "Custom",
|
||||
"DaysRemaining": "Days remaining: {{daysRemaining}}",
|
||||
"DeleteSharedLink": "The previous link will become unavailable. A new shared link will be created.",
|
||||
"DeleteLink": "Delete link",
|
||||
"DeleteLinkNote": "The link will be deleted permanently. You will not be able to undo this action.",
|
||||
"DeleteSharedLink": "The previous link will become unavailable. A new shared link will be created.",
|
||||
"DisableDownload": "Restrict file content copy, file download and printing",
|
||||
"DisableLink": "Disable link",
|
||||
"DisableNotifications": "Disable notifications",
|
||||
@ -48,9 +48,9 @@
|
||||
"DocumentEdited": "Cannot perform the action because the document is being edited.",
|
||||
"DownloadAll": "Download all",
|
||||
"EditAdditionalLink": "Edit additional link",
|
||||
"EditSharedLink": "Edit shared link",
|
||||
"EditLink": "Edit link",
|
||||
"EditRoom": "Edit room",
|
||||
"EditSharedLink": "Edit shared link",
|
||||
"EmbeddingSettings": "Embedding settings",
|
||||
"EmptyFile": "Empty file",
|
||||
"EmptyFilterDescriptionText": "No files or folders match this filter. Try a different one or clear filter to view all files. ",
|
||||
@ -58,12 +58,12 @@
|
||||
"EmptyFolderDecription": "Drop files here or create new ones",
|
||||
"EmptyFolderDescriptionUser": "Files and folders uploaded by admins will appear here.",
|
||||
"EmptyFolderHeader": "No files in this folder",
|
||||
"EmptyFormFolderDoneHeaderText": "No finished forms yet",
|
||||
"EmptyFormFolderDoneDescriptionText": "This section will display all forms that are complete.",
|
||||
"EmptyFormFolderProgressHeaderText": "Nothing here yet",
|
||||
"EmptyFormFolderDoneHeaderText": "No finished forms yet",
|
||||
"EmptyFormFolderProgressDescriptionText": "This section will display the forms in progress.",
|
||||
"EmptyFormSubFolderHeaderText": "No files in this folder yet",
|
||||
"EmptyFormFolderProgressHeaderText": "Nothing here yet",
|
||||
"EmptyFormSubFolderDoneDescriptionText": "Here you will find forms which have been completely filled out by other users.",
|
||||
"EmptyFormSubFolderHeaderText": "No files in this folder yet",
|
||||
"EmptyFormSubFolderProgressDescriptionText": "Here you will find forms in progress, i.e. forms which users have started to fill out but haven't completed. ",
|
||||
"EmptyRecycleBin": "Empty Trash",
|
||||
"EmptyRootRoomHeader": "Welcome to DocSpace",
|
||||
@ -73,8 +73,10 @@
|
||||
"ExcludeSubfolders": "Exclude subfolders",
|
||||
"FavoritesEmptyContainerDescription": "To mark files as favorites or remove them from this list, use the context menu.",
|
||||
"FileContents": "File contents",
|
||||
"FileDownloadingIsRestricted": "File downloading is restricted in this room.",
|
||||
"FileRemoved": "File moved to Trash",
|
||||
"FileRenamed": "The document '{{oldTitle}}' is renamed to '{{newTitle}}'",
|
||||
"FilesWillAppearHere": "Files and folders added to the room will appear here.",
|
||||
"FillingFormRooms": "Filling form",
|
||||
"Filter": "Filter",
|
||||
"FinalizeVersion": "Finalize version",
|
||||
@ -84,7 +86,6 @@
|
||||
"FormRoom": "Form room",
|
||||
"Forms": "Forms",
|
||||
"FormsTemplates": "Forms templates",
|
||||
"SharedLinks": "Shared links",
|
||||
"GeneralLinkDeletedSuccessfully": "New general link created successfully",
|
||||
"GoToMyRooms": "Go to rooms",
|
||||
"GoToPersonal": "Go to My Documents",
|
||||
@ -99,6 +100,7 @@
|
||||
"LinkEditedSuccessfully": "Link successfully edited and copied",
|
||||
"LinkEnabledSuccessfully": "Link enabled successfully",
|
||||
"LinkForPortalUsers": "Link for DocSpace users",
|
||||
"LinkSettings": "Link settings",
|
||||
"LinkSuccessfullyCopied": "Link successfully copied to clipboard",
|
||||
"LinkSuccessfullyCreatedAndCopied": "Link successfully created and copied to clipboard",
|
||||
"LinkValidUntil": "This link will be valid until",
|
||||
@ -139,8 +141,8 @@
|
||||
"PrivateRoomHeader": "Welcome to ONLYOFFICE private room where every symbol you type is encrypted",
|
||||
"PrivateRoomSupport": "Work in Private Room is available via {{organizationName}} desktop app. <3>Instructions</3>",
|
||||
"PublicRoom": "Public room",
|
||||
"RecentlyAccessible": "Recently accessible via link",
|
||||
"RecentEmptyContainerDescription": "Your last viewed or edited docs will be displayed in this section.",
|
||||
"RecentlyAccessible": "Recently accessible via link",
|
||||
"RecentViaLinkEmptyContainerDescription": "Here you will find a list of the recently opened files shared with you via an external link.",
|
||||
"RecycleBinAction": "Empty trash",
|
||||
"RemovedFromFavorites": "Removed from favorites",
|
||||
@ -150,6 +152,7 @@
|
||||
"RevokeLink": "Revoke link",
|
||||
"RoomAvailableViaExternalLink": "Room available via external link",
|
||||
"RoomCreated": "Room created",
|
||||
"RoomEmptyAtTheMoment": "This room is empty at the moment.",
|
||||
"RoomEmptyContainerDescription": "Please create the first room.",
|
||||
"RoomEmptyContainerDescriptionUser": "Rooms shared with you will appear here.",
|
||||
"RoomNotificationsDisabled": "Room notifications disabled",
|
||||
@ -165,6 +168,7 @@
|
||||
"SelectorEmptyScreenHeader": "No files and folders here yet",
|
||||
"SendByEmail": "Send by email",
|
||||
"Share": "Share",
|
||||
"SharedLinks": "Shared links",
|
||||
"ShareFolder": "Share folder",
|
||||
"ShareFolderDescription": "A new room will be created and all the contents of the selected folder will be copied there. Afterwards, you can invite other users to collaborate on the files within a room.",
|
||||
"ShareRoom": "Share room",
|
||||
@ -190,9 +194,5 @@
|
||||
"WantToRestoreTheRoom": "All shared links in this room will become active, and its contents will be available to everyone with the link. Do you want to restore the room?",
|
||||
"WantToRestoreTheRooms": "All shared links in restored rooms will become active, and their contents will be available to everyone with the room links. Do you want to restore the rooms?",
|
||||
"WithSubfolders": "With subfolders",
|
||||
"YouLeftTheRoom": "You have left the room",
|
||||
"LinkSettings": "Link settings",
|
||||
"FileDownloadingIsRestricted": "File downloading is restricted in this room.",
|
||||
"RoomEmptyAtTheMoment": "This room is empty at the moment.",
|
||||
"FilesWillAppearHere": "Files and folders added to the room will appear here."
|
||||
"YouLeftTheRoom": "You have left the room"
|
||||
}
|
||||
|
@ -12,5 +12,6 @@
|
||||
"InviteViaLinkDescriptionRoom": "Create a universal link for self-authorization in the room",
|
||||
"LinkCopySuccess": "Link has been copied",
|
||||
"ResetChange": "Reset change",
|
||||
"SendInvitation": "Send invitation"
|
||||
"SendInvitation": "Send invitation",
|
||||
"UsersAlreadyAdded": "Some users have already been added"
|
||||
}
|
||||
|
@ -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."
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
{
|
||||
"AddGroupsForSharingButton": "Add groups",
|
||||
"AddShareMessage": "Add message",
|
||||
"AdditionalLinkRemove": "Additional link remove",
|
||||
"AddShareMessage": "Add message",
|
||||
"AnyoneWithLink": "Anyone with the link",
|
||||
"Comment": "Comment",
|
||||
"CopyExternalLink": "Copy external link",
|
||||
@ -19,16 +19,16 @@
|
||||
"GeneralAccessLinkRemove": "General access link remove",
|
||||
"InternalLink": "Internal link",
|
||||
"LinkAccessDenied": "Access to the link has been denied",
|
||||
"LinkName": "Link name",
|
||||
"LinkExpireAfter": "The link will expire after <1>{{date}}</1>",
|
||||
"LinkExpired": "The link has expired.",
|
||||
"LinkIsValid": "The link is valid for <1>{{date}}</1>",
|
||||
"LinkName": "Link name",
|
||||
"Notify users": "Notify users",
|
||||
"ReadOnly": "Read only",
|
||||
"ShareEmailBody": "You have been granted access to the {{itemName}} document. Click the link below to open the document right now: {{shareLink}}.",
|
||||
"ShareEmailSubject": "You have been granted access to the {{itemName}} document",
|
||||
"ShareDocument": "Share this document",
|
||||
"ShareDocumentDescription": "Provide access to the document and set the permission levels.",
|
||||
"ShareEmailBody": "You have been granted access to the {{itemName}} document. Click the link below to open the document right now: {{shareLink}}.",
|
||||
"ShareEmailSubject": "You have been granted access to the {{itemName}} document",
|
||||
"ShareVia": "Share via",
|
||||
"SharingSettingsTitle": "Sharing settings"
|
||||
}
|
||||
|
@ -35,7 +35,7 @@
|
||||
"MobileWin": "Download ONLYOFFICE Desktop Editors for Windows",
|
||||
"MoveHere": "Move here",
|
||||
"MoveToOperation": "Moving",
|
||||
"NewForm": "Form template",
|
||||
"NewForm": "PDF Form",
|
||||
"Other": "Other",
|
||||
"OwnerChange": "Change owner",
|
||||
"Presentations": "Presentations",
|
||||
|
@ -35,7 +35,7 @@
|
||||
"MobileWin": "Descargar los editores de escritorio ONLYOFFICE para Windows",
|
||||
"MoveHere": "Mover aquí",
|
||||
"MoveToOperation": "Moviendo",
|
||||
"NewForm": "Plantilla de formulario",
|
||||
"NewForm": "Formulario PDF",
|
||||
"Other": "Otro",
|
||||
"OwnerChange": "Cambiar propietario",
|
||||
"Presentations": "Presentaciones",
|
||||
|
@ -35,7 +35,7 @@
|
||||
"MobileWin": "Lataa ONLYOFFICE Desktop Editors Windowsille",
|
||||
"MoveHere": "Siirrä tänne",
|
||||
"MoveToOperation": "Siirretään",
|
||||
"NewForm": "Lomakemalli",
|
||||
"NewForm": "PDF-lomake",
|
||||
"Other": "Muu",
|
||||
"OwnerChange": "Vaihda omistaja",
|
||||
"Presentations": "Esitykset",
|
||||
|
@ -35,7 +35,7 @@
|
||||
"MobileWin": "Télécharger les applications de bureau ONLYOFFICE pour Windows",
|
||||
"MoveHere": "Déplacer ici",
|
||||
"MoveToOperation": "Déplacement",
|
||||
"NewForm": "Modèle de formulaire",
|
||||
"NewForm": "Formulaire PDF",
|
||||
"Other": "Autre",
|
||||
"OwnerChange": "Changer le propriétaire",
|
||||
"Presentations": "Présentations",
|
||||
|
@ -35,7 +35,7 @@
|
||||
"MobileWin": "Ներբեռնել ONLYOFFICE Desktop Editors Windows-ի համար",
|
||||
"MoveHere": "Տեղափոխել այստեղ",
|
||||
"MoveToOperation": "Տեղափոխություն",
|
||||
"NewForm": "Ձևանմուշ",
|
||||
"NewForm": "PDF Ձև",
|
||||
"Other": "Այլ",
|
||||
"OwnerChange": "Փոխել տնօրինողին",
|
||||
"Presentations": "Ներկայացումներ",
|
||||
|
@ -35,7 +35,7 @@
|
||||
"MobileWin": "Scarica ONLYOFFICE Desktop Editors per Windows",
|
||||
"MoveHere": "Sposta qui",
|
||||
"MoveToOperation": "Sta spostando",
|
||||
"NewForm": "Modello di modulo",
|
||||
"NewForm": "Modulo PDF",
|
||||
"Other": "Altro",
|
||||
"OwnerChange": "Cambiare proprietario",
|
||||
"Presentations": "Presentazioni",
|
||||
|
@ -35,7 +35,7 @@
|
||||
"MobileWin": "Windows用のONLYOFFICEデスクトップエディタをダウンロードする",
|
||||
"MoveHere": "ここに移動",
|
||||
"MoveToOperation": "移動中",
|
||||
"NewForm": "フォーム テンプレート",
|
||||
"NewForm": "PDFフォーム",
|
||||
"Other": "その他",
|
||||
"OwnerChange": "オーナー変更",
|
||||
"Presentations": "プレゼンテーション",
|
||||
|
@ -35,7 +35,7 @@
|
||||
"MobileWin": "Windows용 ONLYOFFICE Desktop Editors를 다운로드 받으세요",
|
||||
"MoveHere": "여기로 이동",
|
||||
"MoveToOperation": "이동 중",
|
||||
"NewForm": "양식 템플릿",
|
||||
"NewForm": "PDF 양식",
|
||||
"Other": "기타",
|
||||
"OwnerChange": "소유자 변경",
|
||||
"Presentations": "프레젠테이션",
|
||||
|
@ -34,7 +34,7 @@
|
||||
"MobileWin": "ດາວໂຫລດ ONLYOFFICE Desktop Editors ສໍາລັບ Windows",
|
||||
"MoveHere": "ຍ້າຍ ນີ້",
|
||||
"MoveToOperation": "ກຳລັງເຄື່ອນຍ້າຍ",
|
||||
"NewForm": "ແບບຟອມ",
|
||||
"NewForm": "ແບບຟອມ PDF",
|
||||
"Other": "ອື່ນໆ",
|
||||
"OwnerChange": "ປ່ຽນເຈົ້າຂອງ",
|
||||
"Presentations": "ບົດສະເຫນີ",
|
||||
|
@ -35,7 +35,7 @@
|
||||
"MobileWin": "Lejupielādēt ONLYOFFICE darbvirsmas redaktorus operētājsistēmai Windows",
|
||||
"MoveHere": "Pārvietoties šeit",
|
||||
"MoveToOperation": "Pārvieto",
|
||||
"NewForm": "Veidlapas veidne",
|
||||
"NewForm": "PDF veidlapa",
|
||||
"Other": "Cits",
|
||||
"OwnerChange": "Mainīt īpašnieku",
|
||||
"Presentations": "Prezentācijas",
|
||||
|
@ -35,7 +35,7 @@
|
||||
"MobileWin": "Download ONLYOFFICE Desktop Editors voor Windows",
|
||||
"MoveHere": "Hierheen verplaatsen",
|
||||
"MoveToOperation": "Verplaatsen",
|
||||
"NewForm": "Formulier sjabloon",
|
||||
"NewForm": "PDF-formulier",
|
||||
"Other": "Overige",
|
||||
"OwnerChange": "Wijzig eigenaar",
|
||||
"Presentations": "Presentaties",
|
||||
|
@ -35,7 +35,7 @@
|
||||
"MobileWin": "Pobierz ONLYOFFICE Desktop Editors dla Windows",
|
||||
"MoveHere": "Przenieś tutaj",
|
||||
"MoveToOperation": "Przenoszenie",
|
||||
"NewForm": "Szablon formularza",
|
||||
"NewForm": "Formularz PDF",
|
||||
"Other": "Inny",
|
||||
"OwnerChange": "Zmień właściciela",
|
||||
"Presentations": "Prezentacje",
|
||||
|
@ -35,7 +35,7 @@
|
||||
"MobileWin": "Baixar ONLYOFFICE Desktop Editors para Windows",
|
||||
"MoveHere": "Mover aqui",
|
||||
"MoveToOperation": "Movendo",
|
||||
"NewForm": "Modelo de formulário",
|
||||
"NewForm": "Formulário PDF",
|
||||
"Other": "Outro",
|
||||
"OwnerChange": "Alterar proprietário",
|
||||
"Presentations": "Apresentações ",
|
||||
|
@ -35,7 +35,7 @@
|
||||
"MobileWin": "Faça o download do ONLYOFFICE Desktop Editors para Windows",
|
||||
"MoveHere": "Mover para aqui",
|
||||
"MoveToOperation": "A mover",
|
||||
"NewForm": "Modelo de Formulário",
|
||||
"NewForm": "Formulário PDF",
|
||||
"Other": "Outros",
|
||||
"OwnerChange": "Alterar dono",
|
||||
"Presentations": "Apresentações ",
|
||||
|
@ -35,7 +35,7 @@
|
||||
"MobileWin": "Descarcă ONLYOFFICE Desktop Editors pentru Windows",
|
||||
"MoveHere": "Mutare în acest loc",
|
||||
"MoveToOperation": "Mutare",
|
||||
"NewForm": "Șablon formă,",
|
||||
"NewForm": "Formular PDF",
|
||||
"Other": "Altă",
|
||||
"OwnerChange": "Schimbare proprietar",
|
||||
"Presentations": "Prezentări",
|
||||
|
@ -35,7 +35,7 @@
|
||||
"MobileWin": "Скачать десктопные редакторы ONLYOFFICE для Windows",
|
||||
"MoveHere": "Переместить сюда",
|
||||
"MoveToOperation": "Перемещение",
|
||||
"NewForm": "Шаблон формы",
|
||||
"NewForm": "PDF-форма",
|
||||
"Other": "Другой",
|
||||
"OwnerChange": "Сменить владельца",
|
||||
"Presentations": "Презентации",
|
||||
|
@ -35,7 +35,7 @@
|
||||
"MobileWin": "Stiahnite si ONLYOFFICE Desktop Editors pre Windows",
|
||||
"MoveHere": "Posunúť sem",
|
||||
"MoveToOperation": "Presúva sa",
|
||||
"NewForm": "Šablóna formulára",
|
||||
"NewForm": "Formulár PDF",
|
||||
"Other": "Iný",
|
||||
"OwnerChange": "Zmeniť vlastníka",
|
||||
"Presentations": "Prezentácie",
|
||||
|
@ -35,7 +35,7 @@
|
||||
"MobileWin": "Prenesi ONLYOFFICE namizne urejevalnike za Windows",
|
||||
"MoveHere": "Premakni sem",
|
||||
"MoveToOperation": "Premikanje",
|
||||
"NewForm": "Predloga obrazca",
|
||||
"NewForm": "PDF obrazec",
|
||||
"Other": "Drugo",
|
||||
"OwnerChange": "Spremeni lastnika",
|
||||
"Presentations": "Predstavitve",
|
||||
|
@ -35,7 +35,7 @@
|
||||
"MobileWin": "Windows için ONLYOFFICE Masaüstü Düzenleyicilerini İndirin",
|
||||
"MoveHere": "Buraya taşı",
|
||||
"MoveToOperation": "Taşınıyor",
|
||||
"NewForm": "Form şablonu",
|
||||
"NewForm": "PDF formu",
|
||||
"Other": "Diğer",
|
||||
"OwnerChange": "Sahibi değiştir",
|
||||
"Presentations": "Sunumlar",
|
||||
|
@ -35,7 +35,7 @@
|
||||
"MobileWin": "Завантажити настільні редактори ONLYOFFICE для Windows",
|
||||
"MoveHere": "Перемістити сюди",
|
||||
"MoveToOperation": "Переміщення",
|
||||
"NewForm": "Шаблон форми",
|
||||
"NewForm": "Форма PDF",
|
||||
"Other": "Інше",
|
||||
"OwnerChange": "Змінити власника",
|
||||
"Presentations": "Презентації",
|
||||
|
@ -35,7 +35,7 @@
|
||||
"MobileWin": "Tải xuống Trình chỉnh sửa ONLYOFFICE cho máy tính Windows",
|
||||
"MoveHere": "Chuyển vào đây",
|
||||
"MoveToOperation": "Đang di chuyển",
|
||||
"NewForm": "Mẫu biểu mẫu",
|
||||
"NewForm": "Mẫu PDF",
|
||||
"Other": "Khác",
|
||||
"OwnerChange": "Thay đổi chủ sở hữu",
|
||||
"Presentations": "Bản trình bày",
|
||||
|
@ -35,7 +35,7 @@
|
||||
"MobileWin": "下载适用于Windows的ONLYOFFICE桌面编辑器",
|
||||
"MoveHere": "移到这里",
|
||||
"MoveToOperation": "移动中",
|
||||
"NewForm": "表单模板",
|
||||
"NewForm": "PDF表格",
|
||||
"Other": "其他",
|
||||
"OwnerChange": "变更所有者",
|
||||
"Presentations": "演示文稿",
|
||||
|
@ -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 &&
|
||||
|
@ -142,6 +142,10 @@ export type FilesSelectorProps = {
|
||||
|
||||
onClose?: () => void;
|
||||
|
||||
withSearch: boolean;
|
||||
withBreadCrumbs: boolean;
|
||||
withSubtitle: boolean;
|
||||
|
||||
isMove?: boolean;
|
||||
isCopy?: boolean;
|
||||
isRestore: boolean;
|
||||
@ -226,6 +230,8 @@ export type FilesSelectorProps = {
|
||||
embedded: boolean;
|
||||
withHeader: boolean;
|
||||
withCancelButton: boolean;
|
||||
cancelButtonLabel: string;
|
||||
acceptButtonLabel: string;
|
||||
settings: any;
|
||||
|
||||
roomsFolderId?: number;
|
||||
|
@ -46,6 +46,10 @@ const FilesSelector = ({
|
||||
|
||||
onClose,
|
||||
|
||||
withSearch = true,
|
||||
withBreadCrumbs = true,
|
||||
withSubtitle = true,
|
||||
|
||||
isMove,
|
||||
isCopy,
|
||||
isRestore,
|
||||
@ -76,7 +80,7 @@ const FilesSelector = ({
|
||||
|
||||
onSelectFolder,
|
||||
onSetBaseFolderPath,
|
||||
//onSetNewFolderPath,
|
||||
// onSetNewFolderPath,
|
||||
setIsDataReady,
|
||||
onSelectTreeNode,
|
||||
onSave,
|
||||
@ -103,6 +107,8 @@ const FilesSelector = ({
|
||||
embedded,
|
||||
withHeader,
|
||||
withCancelButton = true,
|
||||
cancelButtonLabel,
|
||||
acceptButtonLabel,
|
||||
getIcon,
|
||||
isRoomBackup,
|
||||
|
||||
@ -162,8 +168,8 @@ const FilesSelector = ({
|
||||
} = useLoadersHelper({ items });
|
||||
|
||||
useEffect(() => {
|
||||
setIsDataReady && setIsDataReady(!showLoader);
|
||||
}, [showLoader]);
|
||||
setIsDataReady?.(!showLoader);
|
||||
}, [showLoader, setIsDataReady]);
|
||||
|
||||
const { isRoot, setIsRoot, getRootData } = useRootHelper({
|
||||
setIsBreadCrumbsLoading,
|
||||
@ -265,24 +271,31 @@ const FilesSelector = ({
|
||||
}, [selectedItemId, isRoot]);
|
||||
|
||||
React.useEffect(() => {
|
||||
const sessionPath = window.sessionStorage.getItem("filesSelectorPath");
|
||||
let folderId = currentFolderId
|
||||
? currentFolderId
|
||||
: sessionPath && (isMove || isCopy || isRestore || isRestoreAll)
|
||||
? +sessionPath
|
||||
: fromFolderId;
|
||||
|
||||
const getRoomSettings = () => {
|
||||
setSelectedItemType("rooms");
|
||||
getRoomList(0, true);
|
||||
};
|
||||
|
||||
const needRoomList = isRoomsOnly && !currentFolderId;
|
||||
const needRoomList = isRoomsOnly && !folderId;
|
||||
|
||||
if (needRoomList) {
|
||||
getRoomSettings();
|
||||
return;
|
||||
}
|
||||
|
||||
if (!currentFolderId) {
|
||||
if (!folderId) {
|
||||
getRootData();
|
||||
return;
|
||||
}
|
||||
|
||||
setSelectedItemId(currentFolderId);
|
||||
setSelectedItemId(folderId);
|
||||
|
||||
if (
|
||||
needRoomList ||
|
||||
@ -296,8 +309,8 @@ const FilesSelector = ({
|
||||
}
|
||||
|
||||
setSelectedItemType("files");
|
||||
getFileList(0, currentFolderId, true);
|
||||
}, []);
|
||||
getFileList(0, folderId, true);
|
||||
}, [currentFolderId]);
|
||||
|
||||
const onClickBreadCrumb = (item: BreadCrumb) => {
|
||||
if (!isFirstLoad) {
|
||||
@ -312,7 +325,7 @@ const FilesSelector = ({
|
||||
setItems(null);
|
||||
|
||||
const idx = breadCrumbs.findIndex(
|
||||
(value) => value.id.toString() === item.id.toString()
|
||||
(value) => value.id.toString() === item.id.toString(),
|
||||
);
|
||||
|
||||
const maxLength = breadCrumbs.length - 1;
|
||||
@ -321,7 +334,7 @@ const FilesSelector = ({
|
||||
const newBreadCrumbs = breadCrumbs.map((item, index) => {
|
||||
if (!foundParentId) {
|
||||
currentFolderIndex = disabledItems.findIndex(
|
||||
(id) => id === item?.id
|
||||
(id) => id === item?.id,
|
||||
);
|
||||
}
|
||||
|
||||
@ -405,7 +418,7 @@ const FilesSelector = ({
|
||||
items: any,
|
||||
accessRights: any,
|
||||
fileName: string,
|
||||
isChecked: boolean
|
||||
isChecked: boolean,
|
||||
) => {
|
||||
const isPublic =
|
||||
breadCrumbs.findIndex((f: any) => f.roomType === RoomsType.PublicRoom) >
|
||||
@ -502,10 +515,10 @@ const FilesSelector = ({
|
||||
isMove,
|
||||
isSelect,
|
||||
filterParam,
|
||||
isRestore
|
||||
isRestore,
|
||||
);
|
||||
|
||||
const acceptButtonLabel = getAcceptButtonLabel(
|
||||
const defaultAcceptButtonLabel = getAcceptButtonLabel(
|
||||
t,
|
||||
isEditorDialog,
|
||||
isCopy,
|
||||
@ -513,7 +526,7 @@ const FilesSelector = ({
|
||||
isMove,
|
||||
isSelect,
|
||||
filterParam,
|
||||
isRestore
|
||||
isRestore,
|
||||
);
|
||||
|
||||
const isDisabled = getIsDisabled(
|
||||
@ -530,7 +543,7 @@ const FilesSelector = ({
|
||||
filterParam,
|
||||
!!selectedFileInfo,
|
||||
includeFolder,
|
||||
isRestore
|
||||
isRestore,
|
||||
);
|
||||
|
||||
const SelectorBody = (
|
||||
@ -544,10 +557,10 @@ const FilesSelector = ({
|
||||
onClearSearch={onClearSearchAction}
|
||||
items={items ? items : []}
|
||||
onSelect={onSelectAction}
|
||||
acceptButtonLabel={acceptButtonLabel}
|
||||
acceptButtonLabel={acceptButtonLabel || defaultAcceptButtonLabel}
|
||||
onAccept={onAcceptAction}
|
||||
withCancelButton={withCancelButton}
|
||||
cancelButtonLabel={t("Common:CancelButton")}
|
||||
cancelButtonLabel={cancelButtonLabel || t("Common:CancelButton")}
|
||||
onCancel={onCloseAction}
|
||||
emptyScreenImage={
|
||||
theme.isBase ? EmptyScreenAltSvgUrl : EmptyScreenAltSvgDarkUrl
|
||||
@ -561,12 +574,12 @@ const FilesSelector = ({
|
||||
}
|
||||
searchEmptyScreenHeader={t("Common:NotFoundTitle")}
|
||||
searchEmptyScreenDescription={t("EmptyFilterDescriptionText")}
|
||||
withBreadCrumbs
|
||||
withBreadCrumbs={withBreadCrumbs}
|
||||
breadCrumbs={breadCrumbs}
|
||||
onSelectBreadCrumb={onClickBreadCrumb}
|
||||
isLoading={showLoader}
|
||||
isBreadCrumbsLoading={showBreadCrumbsLoader}
|
||||
withSearch={!isRoot && items ? items.length > 0 : !isRoot && isFirstLoad}
|
||||
withSearch={withSearch && !isRoot && items ? items.length > 0 : !isRoot && isFirstLoad}
|
||||
rowLoader={
|
||||
<RowLoader
|
||||
isMultiSelect={false}
|
||||
@ -590,7 +603,7 @@ const FilesSelector = ({
|
||||
currentFooterInputValue={currentFooterInputValue}
|
||||
footerCheckboxLabel={footerCheckboxLabel}
|
||||
descriptionText={
|
||||
!filterParam || filterParam === "ALL"
|
||||
!withSubtitle || !filterParam || filterParam === "ALL"
|
||||
? ""
|
||||
: descriptionText ?? t("Common:SelectDOCXFormat")
|
||||
}
|
||||
@ -644,7 +657,7 @@ export default inject(
|
||||
filesStore,
|
||||
infoPanelStore,
|
||||
}: any,
|
||||
{ isCopy, isRestoreAll, isMove, isRestore, isPanelVisible, id }: any
|
||||
{ isCopy, isRestoreAll, isMove, isRestore, isPanelVisible, id }: any,
|
||||
) => {
|
||||
const { id: selectedId, parentId, rootFolderType } = selectedFolderStore;
|
||||
|
||||
@ -652,8 +665,6 @@ export default inject(
|
||||
filesActionsStore;
|
||||
const { itemOperationToFolder, clearActiveOperations } = uploadDataStore;
|
||||
|
||||
const sessionPath = window.sessionStorage.getItem("filesSelectorPath");
|
||||
|
||||
const { treeFolders, roomsFolderId } = treeFoldersStore;
|
||||
|
||||
const {
|
||||
@ -727,13 +738,8 @@ export default inject(
|
||||
? parentId
|
||||
: selectedId;
|
||||
|
||||
const currentFolderId =
|
||||
sessionPath && (isMove || isCopy || isRestore || isRestoreAll)
|
||||
? +sessionPath
|
||||
: fromFolderId;
|
||||
|
||||
return {
|
||||
currentFolderId,
|
||||
fromFolderId,
|
||||
parentId,
|
||||
rootFolderType,
|
||||
@ -770,5 +776,5 @@ export default inject(
|
||||
|
||||
roomsFolderId,
|
||||
};
|
||||
}
|
||||
},
|
||||
)(observer(FilesSelector));
|
||||
|
@ -123,9 +123,9 @@ const ContactContainer = (props) => {
|
||||
);
|
||||
};
|
||||
|
||||
export default inject(({ authStore, settingsStore, payments }) => {
|
||||
export default inject(({ authStore, settingsStore, paymentStore }) => {
|
||||
const { isCommunity } = authStore;
|
||||
const { helpUrl, salesEmail } = payments;
|
||||
const { helpUrl, salesEmail } = paymentStore;
|
||||
const { theme } = settingsStore;
|
||||
return { helpUrl, salesEmail, theme, isCommunity };
|
||||
})(observer(ContactContainer));
|
||||
|
@ -43,7 +43,9 @@ const AvatarEditorDialog = (props) => {
|
||||
const { visible, onClose, profile, updateCreatedAvatar, setHasAvatar } =
|
||||
props;
|
||||
const [avatar, setAvatar] = useState({
|
||||
uploadedFile: profile.hasAvatar ? profile.avatarMax : DefaultUserAvatarMax,
|
||||
uploadedFile: profile.hasAvatar
|
||||
? profile.avatarOriginal
|
||||
: DefaultUserAvatarMax,
|
||||
x: 0.5,
|
||||
y: 0.5,
|
||||
zoom: 1,
|
||||
@ -63,7 +65,6 @@ const AvatarEditorDialog = (props) => {
|
||||
onClose();
|
||||
return;
|
||||
}
|
||||
|
||||
const file = await dataUrlToFile(preview);
|
||||
|
||||
const avatarData = new FormData();
|
||||
|
@ -106,8 +106,8 @@ ChangePricingPlanDialog.propTypes = {
|
||||
onClose: PropTypes.func.isRequired,
|
||||
};
|
||||
|
||||
export default inject(({ payments, currentQuotaStore }) => {
|
||||
const { managersCount, allowedStorageSizeByQuota } = payments;
|
||||
export default inject(({ paymentStore, currentQuotaStore }) => {
|
||||
const { managersCount, allowedStorageSizeByQuota } = paymentStore;
|
||||
|
||||
const { addedManagersCount, usedTotalStorageSizeCount } = currentQuotaStore;
|
||||
return {
|
||||
|
@ -7,7 +7,7 @@ import { Portal } from "@docspace/shared/components/portal";
|
||||
import { Base } from "@docspace/shared/themes";
|
||||
|
||||
import WrappedComponent from "SRC_DIR/helpers/plugins/WrappedComponent";
|
||||
import { PluginComponents } from "SRC_DIR/helpers/plugins/constants";
|
||||
import { PluginComponents } from "SRC_DIR/helpers/plugins/enums";
|
||||
import { messageActions } from "SRC_DIR/helpers/plugins/utils";
|
||||
|
||||
const StyledFullScreen = styled.div`
|
||||
@ -83,7 +83,7 @@ const PluginDialog = ({
|
||||
updateMainButtonItems,
|
||||
updateProfileMenuItems,
|
||||
updateEventListenerItems,
|
||||
updateFileItems
|
||||
updateFileItems,
|
||||
);
|
||||
};
|
||||
|
||||
@ -111,7 +111,7 @@ const PluginDialog = ({
|
||||
updateMainButtonItems,
|
||||
updateProfileMenuItems,
|
||||
updateEventListenerItems,
|
||||
updateFileItems
|
||||
updateFileItems,
|
||||
);
|
||||
};
|
||||
|
||||
|
@ -198,8 +198,8 @@ SalesDepartmentRequestDialog.propTypes = {
|
||||
onClose: PropTypes.func.isRequired,
|
||||
};
|
||||
|
||||
export default inject(({ payments }) => {
|
||||
const { sendPaymentRequest } = payments;
|
||||
export default inject(({ paymentStore }) => {
|
||||
const { sendPaymentRequest } = paymentStore;
|
||||
|
||||
return {
|
||||
sendPaymentRequest,
|
||||
|
@ -5,7 +5,7 @@ import { useTranslation } from "react-i18next";
|
||||
import { Button } from "@docspace/shared/components/button";
|
||||
import { ModalDialog } from "@docspace/shared/components/modal-dialog";
|
||||
|
||||
import { PluginComponents } from "SRC_DIR/helpers/plugins/constants";
|
||||
import { PluginComponents } from "SRC_DIR/helpers/plugins/enums";
|
||||
import WrappedComponent from "SRC_DIR/helpers/plugins/WrappedComponent";
|
||||
|
||||
import Header from "./sub-components/Header";
|
||||
|
@ -7,7 +7,7 @@ import { Text } from "@docspace/shared/components/text";
|
||||
import { Link } from "@docspace/shared/components/link";
|
||||
import { getCorrectDate, getCookie } from "@docspace/shared/utils";
|
||||
|
||||
import { PluginStatus } from "SRC_DIR/helpers/plugins/constants";
|
||||
import { PluginStatus } from "SRC_DIR/helpers/plugins/enums";
|
||||
import { Base } from "@docspace/shared/themes";
|
||||
|
||||
const StyledContainer = styled.div`
|
||||
@ -121,7 +121,7 @@ const Info = ({ t, plugin, withDelete, withSeparator }) => {
|
||||
lineHeight={"20px"}
|
||||
noSelect
|
||||
>
|
||||
{plugin.createBy}
|
||||
{plugin.createBy.displayName}
|
||||
</Text>
|
||||
</>
|
||||
)}
|
||||
|
@ -53,7 +53,7 @@ const AddUsersPanel = ({
|
||||
const onBackClick = () => onClose();
|
||||
const getFilterWithOutDisabledUser = useCallback(
|
||||
() => Filter.getFilterWithOutDisabledUser(),
|
||||
[]
|
||||
[],
|
||||
);
|
||||
|
||||
const onKeyPress = (e) => {
|
||||
@ -88,6 +88,8 @@ const AddUsersPanel = ({
|
||||
avatar: item.avatar,
|
||||
isOwner: item.isOwner,
|
||||
isAdmin: item.isAdmin,
|
||||
isVisitor: item.isVisitor,
|
||||
isCollaborator: item.isCollaborator,
|
||||
};
|
||||
items.push(newItem);
|
||||
}
|
||||
@ -100,7 +102,7 @@ const AddUsersPanel = ({
|
||||
};
|
||||
|
||||
const selectedAccess = accessOptions.filter(
|
||||
(access) => access.access === accessRight
|
||||
(access) => access.access === accessRight,
|
||||
)[0];
|
||||
|
||||
const [itemsList, setItemsList] = useState(null);
|
||||
@ -110,11 +112,11 @@ const AddUsersPanel = ({
|
||||
const [total, setTotal] = useState(0);
|
||||
const [isLoading, setIsLoading] = useLoadingWithTimeout(
|
||||
LOADER_TIMEOUT,
|
||||
false
|
||||
false,
|
||||
);
|
||||
const [isLoadingSearch, setIsLoadingSearch] = useLoadingWithTimeout(
|
||||
LOADER_TIMEOUT,
|
||||
false
|
||||
false,
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
@ -321,7 +323,7 @@ export default inject(({ settingsStore }) => {
|
||||
})(
|
||||
observer(
|
||||
withTranslation(["SharingPanel", "PeopleTranslations", "Common"])(
|
||||
withLoader(AddUsersPanel)(<Loaders.DialogAsideLoader isPanel />)
|
||||
)
|
||||
)
|
||||
withLoader(AddUsersPanel)(<Loaders.DialogAsideLoader isPanel />),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
@ -292,6 +292,28 @@ const StyledDropDown = styled(DropDown)`
|
||||
text-overflow: ellipsis;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.email-list_avatar {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.email-list_add-button {
|
||||
display: flex;
|
||||
margin-left: auto;
|
||||
align-items: center;
|
||||
gap: 4px;
|
||||
|
||||
p {
|
||||
color: #4781d1;
|
||||
}
|
||||
|
||||
svg path {
|
||||
fill: #4781d1;
|
||||
}
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
|
@ -8,7 +8,7 @@ import { Text } from "@docspace/shared/components/text";
|
||||
import { TextInput } from "@docspace/shared/components/text-input";
|
||||
import { DropDownItem } from "@docspace/shared/components/drop-down-item";
|
||||
import { toastr } from "@docspace/shared/components/toast";
|
||||
import { parseAddresses } from "@docspace/shared/utils";
|
||||
import { parseAddresses, getParts } from "@docspace/shared/utils";
|
||||
import { ComboBox } from "@docspace/shared/components/combobox";
|
||||
|
||||
import Filter from "@docspace/shared/api/people/filter";
|
||||
@ -34,6 +34,9 @@ import {
|
||||
ResetLink,
|
||||
} from "../StyledInvitePanel";
|
||||
|
||||
import AtReactSvgUrl from "PUBLIC_DIR/images/@.react.svg?url";
|
||||
import ArrowIcon from "PUBLIC_DIR/images/arrow.right.react.svg";
|
||||
|
||||
const minSearchValue = 2;
|
||||
|
||||
const InviteInput = ({
|
||||
@ -60,10 +63,10 @@ const InviteInput = ({
|
||||
const [inputValue, setInputValue] = useState("");
|
||||
const [usersList, setUsersList] = useState([]);
|
||||
const [isChangeLangMail, setIsChangeLangMail] = useState(false);
|
||||
const [searchPanelVisible, setSearchPanelVisible] = useState(false);
|
||||
const [isAddEmailPanelBlocked, setIsAddEmailPanelBlocked] = useState(true);
|
||||
|
||||
const [selectedAccess, setSelectedAccess] = useState(defaultAccess);
|
||||
const [dropDownWidth, setDropDownWidth] = useState(0);
|
||||
|
||||
const searchRef = useRef();
|
||||
|
||||
@ -74,6 +77,13 @@ const InviteInput = ({
|
||||
isBeta: isBetaLanguage(language),
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
setTimeout(() => {
|
||||
const width = searchRef?.current?.offsetWidth ?? 0;
|
||||
if (width !== dropDownWidth) setDropDownWidth(width);
|
||||
}, 0);
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
!culture.key &&
|
||||
setInviteLanguage({
|
||||
@ -95,6 +105,7 @@ const InviteInput = ({
|
||||
access: selectedAccess,
|
||||
displayName: address.email,
|
||||
errors: address.parseErrors,
|
||||
isEmailInvite: true,
|
||||
};
|
||||
});
|
||||
}
|
||||
@ -105,32 +116,34 @@ const InviteInput = ({
|
||||
access: selectedAccess,
|
||||
displayName: addresses[0].email,
|
||||
errors: addresses[0].parseErrors,
|
||||
isEmailInvite: true,
|
||||
};
|
||||
};
|
||||
|
||||
const searchByQuery = async (value) => {
|
||||
const query = value.trim();
|
||||
|
||||
if (query.length >= minSearchValue) {
|
||||
if (query.length > minSearchValue) {
|
||||
const filter = Filter.getFilterWithOutDisabledUser();
|
||||
filter.search = query;
|
||||
|
||||
const users = await getMembersList(roomId, filter);
|
||||
|
||||
setUsersList(users.items);
|
||||
setIsAddEmailPanelBlocked(false);
|
||||
|
||||
if (users.total) setIsAddEmailPanelBlocked(false);
|
||||
}
|
||||
|
||||
if (!query) {
|
||||
closeInviteInputPanel();
|
||||
setInputValue("");
|
||||
setUsersList([]);
|
||||
setIsAddEmailPanelBlocked(true);
|
||||
}
|
||||
};
|
||||
|
||||
const debouncedSearch = useCallback(
|
||||
debounce((value) => searchByQuery(value), 300),
|
||||
[]
|
||||
[],
|
||||
);
|
||||
|
||||
const onChange = (e) => {
|
||||
@ -145,20 +158,22 @@ const InviteInput = ({
|
||||
return;
|
||||
}
|
||||
|
||||
if (
|
||||
(!!usersList.length || clearValue.length >= minSearchValue) &&
|
||||
!searchPanelVisible
|
||||
) {
|
||||
openInviteInputPanel();
|
||||
}
|
||||
|
||||
if (roomId !== -1) {
|
||||
debouncedSearch(clearValue);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
setIsAddEmailPanelBlocked(false);
|
||||
const regex =
|
||||
/^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{0,}))$/g;
|
||||
|
||||
const parts = getParts(value);
|
||||
for (let i = 0; i < parts.length; i += 1) {
|
||||
if (regex.test(parts[i])) {
|
||||
setIsAddEmailPanelBlocked(false);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
setIsAddEmailPanelBlocked(true);
|
||||
};
|
||||
|
||||
const removeExist = (items) => {
|
||||
@ -167,8 +182,7 @@ const InviteInput = ({
|
||||
return unique;
|
||||
}, []);
|
||||
|
||||
if (items.length > filtered.length)
|
||||
toastr.warning("Some users have already been added");
|
||||
if (items.length > filtered.length) toastr.warning(t("UsersAlreadyAdded"));
|
||||
|
||||
return filtered;
|
||||
};
|
||||
@ -179,22 +193,25 @@ const InviteInput = ({
|
||||
item.access = selectedAccess;
|
||||
|
||||
const addUser = () => {
|
||||
if (item.isOwner || item.isAdmin)
|
||||
item.access = ShareAccessRights.RoomManager;
|
||||
if (shared) {
|
||||
toastr.warning(t("UsersAlreadyAdded"));
|
||||
} else {
|
||||
if (item.isOwner || item.isAdmin)
|
||||
item.access = ShareAccessRights.RoomManager;
|
||||
|
||||
const items = removeExist([item, ...inviteItems]);
|
||||
const items = removeExist([item, ...inviteItems]);
|
||||
setInviteItems(items);
|
||||
}
|
||||
|
||||
setInviteItems(items);
|
||||
closeInviteInputPanel();
|
||||
setInputValue("");
|
||||
setUsersList([]);
|
||||
setIsAddEmailPanelBlocked(true);
|
||||
};
|
||||
|
||||
return (
|
||||
<DropDownItem
|
||||
key={id}
|
||||
onClick={addUser}
|
||||
disabled={shared}
|
||||
height={48}
|
||||
heightTablet={48}
|
||||
className="list-item"
|
||||
@ -220,8 +237,8 @@ const InviteInput = ({
|
||||
const filtered = removeExist(newItems);
|
||||
|
||||
setInviteItems(filtered);
|
||||
closeInviteInputPanel();
|
||||
setInputValue("");
|
||||
setIsAddEmailPanelBlocked(true);
|
||||
setUsersList([]);
|
||||
};
|
||||
|
||||
@ -231,7 +248,6 @@ const InviteInput = ({
|
||||
const filtered = removeExist(items);
|
||||
|
||||
setInviteItems(filtered);
|
||||
closeInviteInputPanel();
|
||||
setInputValue("");
|
||||
setUsersList([]);
|
||||
};
|
||||
@ -241,33 +257,35 @@ const InviteInput = ({
|
||||
const openUsersPanel = () => {
|
||||
setInputValue("");
|
||||
setAddUsersPanelVisible(true);
|
||||
setIsAddEmailPanelBlocked(true);
|
||||
};
|
||||
|
||||
const closeUsersPanel = () => {
|
||||
setAddUsersPanelVisible(false);
|
||||
};
|
||||
|
||||
const openInviteInputPanel = (e) => {
|
||||
setSearchPanelVisible(true);
|
||||
};
|
||||
|
||||
const closeInviteInputPanel = (e) => {
|
||||
if (e?.target?.tagName?.toUpperCase() === "INPUT") return;
|
||||
|
||||
setSearchPanelVisible(false);
|
||||
};
|
||||
|
||||
const foundUsers = usersList.map((user) => getItemContent(user));
|
||||
|
||||
const addEmailPanel = (
|
||||
<DropDownItem
|
||||
className="add-item"
|
||||
className="list-item"
|
||||
style={{ width: "inherit" }}
|
||||
textOverflow
|
||||
onClick={addEmail}
|
||||
height={48}
|
||||
>
|
||||
{t("Common:AddButton")} «{inputValue}»
|
||||
<div className="email-list_avatar">
|
||||
<Avatar size="min" role="user" source={AtReactSvgUrl} />
|
||||
<Text truncate fontSize="14px" fontWeight={600}>
|
||||
{inputValue}
|
||||
</Text>
|
||||
</div>
|
||||
<div className="email-list_add-button">
|
||||
<Text fontSize="13px" fontWeight={600}>
|
||||
{t("Common:AddButton")}
|
||||
</Text>
|
||||
<ArrowIcon />
|
||||
</div>
|
||||
</DropDownItem>
|
||||
);
|
||||
|
||||
@ -278,7 +296,7 @@ const InviteInput = ({
|
||||
};
|
||||
|
||||
const onKeyPress = (e) => {
|
||||
if (e.key === "Enter" && !!!usersList.length && inputValue.length > 2) {
|
||||
if (e.key === "Enter") {
|
||||
addEmail();
|
||||
}
|
||||
};
|
||||
@ -401,28 +419,27 @@ const InviteInput = ({
|
||||
: t("InviteRoomSearchPlaceholder")
|
||||
}
|
||||
value={inputValue}
|
||||
onFocus={openInviteInputPanel}
|
||||
isAutoFocussed={true}
|
||||
onKeyDown={onKeyDown}
|
||||
/>
|
||||
</StyledInviteInput>
|
||||
{inputValue.length >= minSearchValue &&
|
||||
(isAddEmailPanelBlocked ? (
|
||||
<></>
|
||||
) : (
|
||||
<StyledDropDown
|
||||
width={searchRef?.current?.offsetWidth}
|
||||
isDefaultMode={false}
|
||||
open={searchPanelVisible}
|
||||
manualX="16px"
|
||||
showDisabledItems
|
||||
clickOutsideAction={closeInviteInputPanel}
|
||||
eventTypes="click"
|
||||
{...dropDownMaxHeight}
|
||||
>
|
||||
{!!usersList.length ? foundUsers : addEmailPanel}
|
||||
</StyledDropDown>
|
||||
))}
|
||||
{isAddEmailPanelBlocked ? (
|
||||
<></>
|
||||
) : (
|
||||
<StyledDropDown
|
||||
width={dropDownWidth}
|
||||
isDefaultMode={false}
|
||||
open
|
||||
manualX="16px"
|
||||
showDisabledItems
|
||||
eventTypes="click"
|
||||
withBackdrop={false}
|
||||
zIndex={399}
|
||||
{...dropDownMaxHeight}
|
||||
>
|
||||
{!!usersList.length ? foundUsers : addEmailPanel}
|
||||
</StyledDropDown>
|
||||
)}
|
||||
|
||||
<AccessSelector
|
||||
className="add-manually-access"
|
||||
|
@ -3,11 +3,10 @@ import AtReactSvgUrl from "PUBLIC_DIR/images/@.react.svg?url";
|
||||
import React, { useState, useEffect } from "react";
|
||||
import { Avatar } from "@docspace/shared/components/avatar";
|
||||
import { Text } from "@docspace/shared/components/text";
|
||||
import { capitalize } from "lodash";
|
||||
|
||||
import { parseAddresses } from "@docspace/shared/utils";
|
||||
import { getAccessOptions } from "../utils";
|
||||
import { getUserRole } from "@docspace/shared/utils/common";
|
||||
import { getUserRole, getUserTypeLabel } from "@docspace/shared/utils/common";
|
||||
|
||||
import {
|
||||
StyledEditInput,
|
||||
@ -33,25 +32,37 @@ const Item = ({
|
||||
inputsRef,
|
||||
setIsOpenItemAccess,
|
||||
isMobileView,
|
||||
standalone,
|
||||
}) => {
|
||||
const { avatar, displayName, email, id, errors, access } = item;
|
||||
|
||||
const name = !!avatar ? (displayName !== "" ? displayName : email) : email;
|
||||
const source = !!avatar ? avatar : AtReactSvgUrl;
|
||||
const role = getUserRole(item);
|
||||
|
||||
const [edit, setEdit] = useState(false);
|
||||
const [inputValue, setInputValue] = useState(name);
|
||||
const [parseErrors, setParseErrors] = useState(errors);
|
||||
|
||||
const accesses = getAccessOptions(t, roomType, true, true, isOwner);
|
||||
const accesses = getAccessOptions(
|
||||
t,
|
||||
roomType,
|
||||
true,
|
||||
true,
|
||||
isOwner,
|
||||
standalone,
|
||||
);
|
||||
|
||||
const filteredAccesses = filterUserRoleOptions(accesses, item, true);
|
||||
|
||||
const defaultAccess = filteredAccesses.find(
|
||||
(option) => option.access === +access
|
||||
(option) => option.access === +access,
|
||||
);
|
||||
|
||||
const role = getUserRole(item);
|
||||
const typeLabel = item?.isEmailInvite
|
||||
? getUserTypeLabel(defaultAccess.type, t)
|
||||
: getUserTypeLabel(role, t);
|
||||
|
||||
const errorsInList = () => {
|
||||
const hasErrors = inviteItems.some((item) => !!item.errors?.length);
|
||||
setHasErrors(hasErrors);
|
||||
@ -133,7 +144,7 @@ const Item = ({
|
||||
color="#A3A9AE"
|
||||
truncate
|
||||
>
|
||||
{`${capitalize(role)} | ${email}`}
|
||||
{item.userName ? `${typeLabel} | ${email}` : `${typeLabel}`}
|
||||
</Text>
|
||||
</StyledInviteUserBody>
|
||||
|
||||
@ -167,6 +178,7 @@ const Item = ({
|
||||
setIsOpenItemAccess={setIsOpenItemAccess}
|
||||
isMobileView={isMobileView}
|
||||
noBorder
|
||||
standalone={standalone}
|
||||
/>
|
||||
)}
|
||||
</>
|
||||
|
@ -22,6 +22,7 @@ const Row = memo(({ data, index, style }) => {
|
||||
inputsRef,
|
||||
setIsOpenItemAccess,
|
||||
isMobileView,
|
||||
standalone,
|
||||
} = data;
|
||||
|
||||
if (inviteItems === undefined) return;
|
||||
@ -42,6 +43,7 @@ const Row = memo(({ data, index, style }) => {
|
||||
inputsRef={inputsRef}
|
||||
setIsOpenItemAccess={setIsOpenItemAccess}
|
||||
isMobileView={isMobileView}
|
||||
standalone={standalone}
|
||||
/>
|
||||
</StyledRow>
|
||||
);
|
||||
@ -60,6 +62,7 @@ const ItemsList = ({
|
||||
inputsRef,
|
||||
invitePanelBodyRef,
|
||||
isMobileView,
|
||||
standalone,
|
||||
}) => {
|
||||
const [bodyHeight, setBodyHeight] = useState(0);
|
||||
const [offsetTop, setOffsetTop] = useState(0);
|
||||
@ -146,6 +149,7 @@ const ItemsList = ({
|
||||
setIsOpenItemAccess,
|
||||
isMobileView,
|
||||
t,
|
||||
standalone,
|
||||
}}
|
||||
outerElementType={!scrollAllPanelContent && CustomScrollbarsVirtualList}
|
||||
>
|
||||
@ -155,14 +159,16 @@ const ItemsList = ({
|
||||
);
|
||||
};
|
||||
|
||||
export default inject(({ userStore, dialogsStore }) => {
|
||||
export default inject(({ userStore, dialogsStore, settingsStore }) => {
|
||||
const { setInviteItems, inviteItems, changeInviteItem } = dialogsStore;
|
||||
const { isOwner } = userStore.user;
|
||||
const { standalone } = settingsStore;
|
||||
|
||||
return {
|
||||
setInviteItems,
|
||||
inviteItems,
|
||||
changeInviteItem,
|
||||
isOwner,
|
||||
standalone,
|
||||
};
|
||||
})(observer(ItemsList));
|
||||
|
@ -10,7 +10,7 @@ export const getAccessOptions = (
|
||||
withRemove = false,
|
||||
withSeparator = false,
|
||||
isOwner = false,
|
||||
standalone = false
|
||||
standalone = false,
|
||||
) => {
|
||||
let options = [];
|
||||
const accesses = {
|
||||
@ -22,6 +22,7 @@ export const getAccessOptions = (
|
||||
color: "#EDC409",
|
||||
access:
|
||||
roomType === -1 ? EmployeeType.Admin : ShareAccessRights.FullAccess,
|
||||
type: "admin",
|
||||
},
|
||||
roomAdmin: {
|
||||
key: "roomAdmin",
|
||||
@ -31,6 +32,7 @@ export const getAccessOptions = (
|
||||
color: "#EDC409",
|
||||
access:
|
||||
roomType === -1 ? EmployeeType.User : ShareAccessRights.RoomManager,
|
||||
type: "manager",
|
||||
},
|
||||
collaborator: {
|
||||
key: "collaborator",
|
||||
@ -42,42 +44,49 @@ export const getAccessOptions = (
|
||||
roomType === -1
|
||||
? EmployeeType.Collaborator
|
||||
: ShareAccessRights.Collaborator,
|
||||
type: "collaborator",
|
||||
},
|
||||
user: {
|
||||
key: "user",
|
||||
label: t("Common:User"),
|
||||
description: t("Translations:RoleUserDescription"),
|
||||
access: EmployeeType.Guest,
|
||||
type: "user",
|
||||
},
|
||||
editor: {
|
||||
key: "editor",
|
||||
label: t("Translations:RoleEditor"),
|
||||
description: t("Translations:RoleEditorDescription"),
|
||||
access: ShareAccessRights.Editing,
|
||||
type: "user",
|
||||
},
|
||||
formFiller: {
|
||||
key: "formFiller",
|
||||
label: t("Translations:RoleFormFiller"),
|
||||
description: t("Translations:RoleFormFillerDescription"),
|
||||
access: ShareAccessRights.FormFilling,
|
||||
type: "user",
|
||||
},
|
||||
reviewer: {
|
||||
key: "reviewer",
|
||||
label: t("Translations:RoleReviewer"),
|
||||
description: t("Translations:RoleReviewerDescription"),
|
||||
access: ShareAccessRights.Review,
|
||||
type: "user",
|
||||
},
|
||||
commentator: {
|
||||
key: "commentator",
|
||||
label: t("Translations:RoleCommentator"),
|
||||
description: t("Translations:RoleCommentatorDescription"),
|
||||
access: ShareAccessRights.Comment,
|
||||
type: "user",
|
||||
},
|
||||
viewer: {
|
||||
key: "viewer",
|
||||
label: t("Translations:RoleViewer"),
|
||||
description: t("Translations:RoleViewerDescription"),
|
||||
access: ShareAccessRights.ReadOnly,
|
||||
type: "user",
|
||||
},
|
||||
};
|
||||
|
||||
|
@ -93,7 +93,7 @@ const ConfirmRoute = ({
|
||||
window.location.href = combineUrl(
|
||||
window.DocSpaceConfig?.proxy?.url,
|
||||
path,
|
||||
"/error"
|
||||
"/error",
|
||||
);
|
||||
break;
|
||||
case ValidationResult.Expired:
|
||||
@ -104,7 +104,7 @@ const ConfirmRoute = ({
|
||||
window.location.href = combineUrl(
|
||||
window.DocSpaceConfig?.proxy?.url,
|
||||
path,
|
||||
"/error"
|
||||
"/error",
|
||||
);
|
||||
break;
|
||||
case ValidationResult.TariffLimit:
|
||||
@ -115,7 +115,7 @@ const ConfirmRoute = ({
|
||||
window.location.href = combineUrl(
|
||||
window.DocSpaceConfig?.proxy?.url,
|
||||
path,
|
||||
"/error?messageKey=20"
|
||||
"/error?messageKey=20",
|
||||
);
|
||||
break;
|
||||
default:
|
||||
@ -126,7 +126,7 @@ const ConfirmRoute = ({
|
||||
window.location.href = combineUrl(
|
||||
window.DocSpaceConfig?.proxy?.url,
|
||||
path,
|
||||
"/error"
|
||||
"/error",
|
||||
);
|
||||
break;
|
||||
}
|
||||
@ -145,7 +145,7 @@ const ConfirmRoute = ({
|
||||
window.location.href = combineUrl(
|
||||
window.DocSpaceConfig?.proxy?.url,
|
||||
path,
|
||||
"/error"
|
||||
"/error",
|
||||
);
|
||||
});
|
||||
}, [getData, doAuthenticated, isAuthenticated, storeIsLoaded, logout]);
|
||||
|
@ -13,7 +13,7 @@ import { Button } from "@docspace/shared/components/button";
|
||||
import { ToggleButton } from "@docspace/shared/components/toggle-button";
|
||||
import { ComboBox } from "@docspace/shared/components/combobox";
|
||||
|
||||
import { PluginComponents } from "./constants";
|
||||
import { PluginComponents } from "./enums";
|
||||
|
||||
import { messageActions } from "./utils";
|
||||
|
||||
@ -74,7 +74,7 @@ const ComponentPure = ({
|
||||
component={item}
|
||||
pluginName={pluginName}
|
||||
/>
|
||||
)
|
||||
),
|
||||
);
|
||||
|
||||
return <Box {...elementProps}>{childrenComponents}</Box>;
|
||||
@ -110,7 +110,7 @@ const ComponentPure = ({
|
||||
updateMainButtonItems,
|
||||
updateProfileMenuItems,
|
||||
updateEventListenerItems,
|
||||
updateFileItems
|
||||
updateFileItems,
|
||||
);
|
||||
};
|
||||
|
||||
@ -139,7 +139,7 @@ const ComponentPure = ({
|
||||
updateMainButtonItems,
|
||||
updateProfileMenuItems,
|
||||
updateEventListenerItems,
|
||||
updateFileItems
|
||||
updateFileItems,
|
||||
);
|
||||
};
|
||||
|
||||
@ -168,11 +168,11 @@ const ComponentPure = ({
|
||||
updateMainButtonItems,
|
||||
updateProfileMenuItems,
|
||||
updateEventListenerItems,
|
||||
updateFileItems
|
||||
updateFileItems,
|
||||
);
|
||||
};
|
||||
|
||||
return <TextArea {...elementProps} onChange={onChangeAction} />;
|
||||
return <Textarea {...elementProps} onChange={onChangeAction} />;
|
||||
}
|
||||
|
||||
case PluginComponents.input: {
|
||||
@ -197,7 +197,7 @@ const ComponentPure = ({
|
||||
updateMainButtonItems,
|
||||
updateProfileMenuItems,
|
||||
updateEventListenerItems,
|
||||
updateFileItems
|
||||
updateFileItems,
|
||||
);
|
||||
};
|
||||
|
||||
@ -247,7 +247,7 @@ const ComponentPure = ({
|
||||
updateEventListenerItems,
|
||||
updateFileItems,
|
||||
|
||||
updatePlugin
|
||||
updatePlugin,
|
||||
);
|
||||
|
||||
setIsRequestRunning && setIsRequestRunning(false);
|
||||
@ -306,7 +306,7 @@ const ComponentPure = ({
|
||||
updateMainButtonItems,
|
||||
updateProfileMenuItems,
|
||||
updateEventListenerItems,
|
||||
updateFileItems
|
||||
updateFileItems,
|
||||
);
|
||||
};
|
||||
|
||||
|
@ -5,7 +5,7 @@ import PluginHeader from "./PluginHeader";
|
||||
import PluginInfo from "./PluginInfo";
|
||||
import PluginSettings from "./PluginSettings";
|
||||
|
||||
import { PluginScopes } from "../constants";
|
||||
import { PluginScopes } from "../enums";
|
||||
|
||||
const StyledPlugin = styled.div`
|
||||
display: flex;
|
||||
@ -79,7 +79,7 @@ const Plugin = ({
|
||||
author={author}
|
||||
status={status}
|
||||
description={description}
|
||||
createBy={createBy}
|
||||
createBy={createBy.displayName}
|
||||
createOn={createOn}
|
||||
homePage={homePage}
|
||||
url={url}
|
||||
|
@ -4,7 +4,7 @@ import styled from "styled-components";
|
||||
import { Text } from "@docspace/shared/components/text";
|
||||
import { getCorrectDate } from "@docspace/shared/utils";
|
||||
|
||||
import { PluginStatus } from "SRC_DIR/helpers/plugins/constants";
|
||||
import { PluginStatus } from "SRC_DIR/helpers/plugins/enums";
|
||||
import { Link } from "@docspace/shared/components/link";
|
||||
|
||||
import { getPluginUrl } from "../utils";
|
||||
|
@ -3,7 +3,7 @@ import styled from "styled-components";
|
||||
|
||||
import WrappedComponent from "../WrappedComponent";
|
||||
|
||||
import { PluginComponents } from "../constants";
|
||||
import { PluginComponents } from "../enums";
|
||||
|
||||
const StyledPluginSettings = styled.div`
|
||||
.settings-header {
|
||||
|
@ -1,87 +0,0 @@
|
||||
export const PluginFileType = Object.freeze({
|
||||
Files: "file",
|
||||
Folders: "folder",
|
||||
Rooms: "room",
|
||||
Image: "image",
|
||||
Video: "video",
|
||||
});
|
||||
|
||||
export const PluginScopes = Object.freeze({
|
||||
API: "API",
|
||||
Settings: "Settings",
|
||||
ContextMenu: "ContextMenu",
|
||||
InfoPanel: "InfoPanel",
|
||||
MainButton: "MainButton",
|
||||
ProfileMenu: "ProfileMenu",
|
||||
EventListener: "EventListener",
|
||||
File: "File",
|
||||
});
|
||||
|
||||
export const PluginStatus = Object.freeze({
|
||||
active: "active",
|
||||
hide: "hide",
|
||||
});
|
||||
|
||||
export const PluginActions = Object.freeze({
|
||||
updateProps: "update-props",
|
||||
updateContext: "update-context",
|
||||
|
||||
updateStatus: "update-status",
|
||||
|
||||
showToast: "show-toast",
|
||||
|
||||
// showSettingsModal: "show-settings-modal",
|
||||
// closeSettingsModal: "close-settings-modal",
|
||||
|
||||
showCreateDialogModal: "show-create-dialog-modal",
|
||||
|
||||
showModal: "show-modal",
|
||||
closeModal: "close-modal",
|
||||
|
||||
updateContextMenuItems: "update-context-menu-items",
|
||||
updateInfoPanelItems: "update-info-panel-items",
|
||||
updateMainButtonItems: "update-main-button-items",
|
||||
updateProfileMenuItems: "update-profile-menu-items",
|
||||
updateFileItems: "update-file-items",
|
||||
updateEventListenerItems: "update-event-listener-items",
|
||||
|
||||
sendPostMessage: "send-post-message",
|
||||
|
||||
saveSettings: "save-settings",
|
||||
});
|
||||
|
||||
export const PluginToastType = Object.freeze({
|
||||
success: "success",
|
||||
error: "error",
|
||||
warning: "warning",
|
||||
info: "info",
|
||||
});
|
||||
|
||||
export const PluginComponents = Object.freeze({
|
||||
box: "box",
|
||||
button: "button",
|
||||
checkbox: "checkbox",
|
||||
input: "input",
|
||||
label: "label",
|
||||
text: "text",
|
||||
textArea: "textArea",
|
||||
toggleButton: "toggleButton",
|
||||
img: "img",
|
||||
iFrame: "iFrame",
|
||||
comboBox: "comboBox",
|
||||
skeleton: "skeleton",
|
||||
});
|
||||
|
||||
export const PluginUsersType = Object.freeze({
|
||||
owner: "Owner",
|
||||
docSpaceAdmin: "DocSpaceAdmin",
|
||||
roomAdmin: "RoomAdmin",
|
||||
collaborator: "Collaborator",
|
||||
user: "User",
|
||||
});
|
||||
|
||||
export const PluginDevices = Object.freeze({
|
||||
mobile: "mobile",
|
||||
tablet: "tablet",
|
||||
desktop: "desktop",
|
||||
});
|
97
packages/client/src/helpers/plugins/enums.ts
Normal file
97
packages/client/src/helpers/plugins/enums.ts
Normal file
@ -0,0 +1,97 @@
|
||||
export const enum PluginFileType {
|
||||
Files = "file",
|
||||
Folders = "folder",
|
||||
Rooms = "room",
|
||||
Image = "image",
|
||||
Video = "video",
|
||||
}
|
||||
|
||||
export const enum PluginEvents {
|
||||
CREATE = "create",
|
||||
RENAME = "rename",
|
||||
ROOM_CREATE = "create_room",
|
||||
ROOM_EDIT = "edit_room",
|
||||
CHANGE_COLUMN = "change_column",
|
||||
CHANGE_USER_TYPE = "change_user_type",
|
||||
CREATE_PLUGIN_FILE = "create_plugin_file",
|
||||
}
|
||||
|
||||
export const enum PluginScopes {
|
||||
API = "API",
|
||||
Settings = "Settings",
|
||||
ContextMenu = "ContextMenu",
|
||||
InfoPanel = "InfoPanel",
|
||||
MainButton = "MainButton",
|
||||
ProfileMenu = "ProfileMenu",
|
||||
EventListener = "EventListener",
|
||||
File = "File",
|
||||
}
|
||||
|
||||
export const enum PluginStatus {
|
||||
active = "active",
|
||||
hide = "hide",
|
||||
}
|
||||
|
||||
export const enum PluginActions {
|
||||
updateProps = "update-props",
|
||||
updateContext = "update-context",
|
||||
|
||||
updateStatus = "update-status",
|
||||
|
||||
showToast = "show-toast",
|
||||
|
||||
// showSettingsModal= "show-settings-modal",
|
||||
// closeSettingsModal= "close-settings-modal",
|
||||
|
||||
showCreateDialogModal = "show-create-dialog-modal",
|
||||
|
||||
showModal = "show-modal",
|
||||
closeModal = "close-modal",
|
||||
|
||||
updateContextMenuItems = "update-context-menu-items",
|
||||
updateInfoPanelItems = "update-info-panel-items",
|
||||
updateMainButtonItems = "update-main-button-items",
|
||||
updateProfileMenuItems = "update-profile-menu-items",
|
||||
updateFileItems = "update-file-items",
|
||||
updateEventListenerItems = "update-event-listener-items",
|
||||
|
||||
sendPostMessage = "send-post-message",
|
||||
|
||||
saveSettings = "save-settings",
|
||||
}
|
||||
|
||||
export const enum PluginToastType {
|
||||
success = "success",
|
||||
error = "error",
|
||||
warning = "warning",
|
||||
info = "info",
|
||||
}
|
||||
|
||||
export const enum PluginComponents {
|
||||
box = "box",
|
||||
button = "button",
|
||||
checkbox = "checkbox",
|
||||
input = "input",
|
||||
label = "label",
|
||||
text = "text",
|
||||
textArea = "textArea",
|
||||
toggleButton = "toggleButton",
|
||||
img = "img",
|
||||
iFrame = "iFrame",
|
||||
comboBox = "comboBox",
|
||||
skeleton = "skeleton",
|
||||
}
|
||||
|
||||
export const enum PluginUsersType {
|
||||
owner = "Owner",
|
||||
docSpaceAdmin = "DocSpaceAdmin",
|
||||
roomAdmin = "RoomAdmin",
|
||||
collaborator = "Collaborator",
|
||||
user = "User",
|
||||
}
|
||||
|
||||
export const enum PluginDevices {
|
||||
mobile = "mobile",
|
||||
tablet = "tablet",
|
||||
desktop = "desktop",
|
||||
}
|
275
packages/client/src/helpers/plugins/types.ts
Normal file
275
packages/client/src/helpers/plugins/types.ts
Normal file
@ -0,0 +1,275 @@
|
||||
import { TCreatedBy } from "@docspace/shared/types";
|
||||
import { ButtonProps } from "@docspace/shared/components/button/Button.types";
|
||||
import { BoxProps } from "@docspace/shared/components/box/Box.types";
|
||||
import { TextInputProps } from "@docspace/shared/components/text-input";
|
||||
import { CheckboxProps } from "@docspace/shared/components/checkbox/Checkbox.types";
|
||||
import { ToggleButtonProps } from "@docspace/shared/components/toggle-button/ToggleButton.types";
|
||||
import { TextareaProps } from "@docspace/shared/components/textarea/Textarea.types";
|
||||
import {
|
||||
ComboboxProps,
|
||||
TOption,
|
||||
} from "@docspace/shared/components/combobox/Combobox.types";
|
||||
import { ToastProps } from "@docspace/shared/components/toast/Toast.type";
|
||||
import { ModalDialogProps } from "@docspace/shared/components/modal-dialog/ModalDialog.types";
|
||||
import { TextProps } from "@docspace/shared/components/text/Text.types";
|
||||
import { RectangleSkeletonProps } from "@docspace/shared/skeletons";
|
||||
import { LabelProps } from "@docspace/shared/components/label/Label.types";
|
||||
import {
|
||||
TFile,
|
||||
TFileSecurity,
|
||||
TFolderSecurity,
|
||||
} from "@docspace/shared/api/files/types";
|
||||
import { TRoomSecurity } from "@docspace/shared/api/rooms/types";
|
||||
|
||||
import {
|
||||
PluginActions,
|
||||
PluginComponents,
|
||||
PluginDevices,
|
||||
PluginEvents,
|
||||
PluginFileType,
|
||||
PluginStatus,
|
||||
PluginUsersType,
|
||||
} from "./enums";
|
||||
|
||||
export interface IPostMessage {
|
||||
frameId: string;
|
||||
message: { [key: string]: unknown };
|
||||
}
|
||||
|
||||
export interface IFrame {
|
||||
src: string;
|
||||
width?: string;
|
||||
height?: string;
|
||||
name?: string;
|
||||
sandbox?: string;
|
||||
id?: string;
|
||||
style?: { [key: string]: string };
|
||||
}
|
||||
|
||||
export interface ICreateDialog {
|
||||
title: string;
|
||||
startValue: string;
|
||||
visible: boolean;
|
||||
options?: TOption[];
|
||||
selectedOption?: TOption;
|
||||
onSelect?: (option: TOption) => IMessage | void;
|
||||
onSave?: (
|
||||
e: unknown,
|
||||
value: string,
|
||||
) => Promise<IMessage> | Promise<void> | IMessage | void;
|
||||
onCancel?: (e: unknown) => void;
|
||||
onClose?: (e: unknown) => void;
|
||||
isCreateDialog: boolean;
|
||||
extension?: string;
|
||||
}
|
||||
|
||||
export interface IImage {
|
||||
src: string;
|
||||
alt: string;
|
||||
width?: string;
|
||||
height?: string;
|
||||
name?: string;
|
||||
id?: string;
|
||||
style?: { [key: string]: string };
|
||||
}
|
||||
|
||||
export interface IMessage {
|
||||
actions?: PluginActions[];
|
||||
newProps?:
|
||||
| TextInputProps
|
||||
| CheckboxProps
|
||||
| ToggleButtonProps
|
||||
| ButtonProps
|
||||
| TextareaProps
|
||||
| ComboboxProps;
|
||||
toastProps?: ToastProps[];
|
||||
contextProps?: {
|
||||
name: string;
|
||||
props:
|
||||
| BoxProps
|
||||
| ButtonProps
|
||||
| CheckboxProps
|
||||
| ComboboxProps
|
||||
| IFrame
|
||||
| IImage
|
||||
| TextInputProps
|
||||
| LabelProps
|
||||
| RectangleSkeletonProps
|
||||
| TextProps
|
||||
| TextareaProps
|
||||
| ToggleButtonProps;
|
||||
}[];
|
||||
createDialogProps?: ICreateDialog;
|
||||
modalDialogProps?: ModalDialogProps;
|
||||
postMessage?: IPostMessage;
|
||||
settings?: string;
|
||||
}
|
||||
|
||||
type TButtonGroup = {
|
||||
component: PluginComponents.button;
|
||||
props: ButtonProps;
|
||||
contextName?: string;
|
||||
};
|
||||
|
||||
export interface ISettings {
|
||||
settings: BoxProps;
|
||||
saveButton: TButtonGroup;
|
||||
isLoading?: boolean;
|
||||
onLoad?: () => Promise<{ settings: BoxProps; saveButton?: TButtonGroup }>;
|
||||
}
|
||||
|
||||
export interface IContextMenuItem {
|
||||
key: string;
|
||||
label: string;
|
||||
icon: string;
|
||||
onClick: (id: number) => Promise<IMessage> | Promise<void> | IMessage | void;
|
||||
withActiveItem?: boolean;
|
||||
fileExt?: string[];
|
||||
fileType?: PluginFileType[];
|
||||
usersTypes?: PluginUsersType[];
|
||||
devices?: PluginDevices[];
|
||||
security?: (
|
||||
| keyof TRoomSecurity
|
||||
| keyof TFileSecurity
|
||||
| keyof TFolderSecurity
|
||||
)[];
|
||||
pluginName?: string;
|
||||
}
|
||||
|
||||
export interface IEventListenerItem {
|
||||
key: string;
|
||||
eventType: PluginEvents;
|
||||
eventHandler: () => Promise<IMessage> | Promise<void> | IMessage | void;
|
||||
usersTypes?: PluginUsersType[];
|
||||
devices?: PluginDevices[];
|
||||
pluginName?: string;
|
||||
}
|
||||
|
||||
export interface IFileItem {
|
||||
extension: string;
|
||||
onClick: (item: TFile) => Promise<IMessage> | Promise<void> | IMessage | void;
|
||||
usersType?: PluginUsersType[];
|
||||
devices?: PluginDevices[];
|
||||
fileTypeName?: string;
|
||||
fileRowIcon?: string;
|
||||
fileTileIcon?: string;
|
||||
fileIcon?: string;
|
||||
fileIconTile?: string;
|
||||
pluginName?: string;
|
||||
}
|
||||
|
||||
export interface IInfoPanelSubMenu {
|
||||
name: string;
|
||||
onClick?: (id: number) => Promise<IMessage> | Promise<void> | IMessage | void;
|
||||
}
|
||||
|
||||
export interface IInfoPanelItem {
|
||||
key: string;
|
||||
subMenu: IInfoPanelSubMenu;
|
||||
body: BoxProps;
|
||||
onLoad: () => Promise<{ body: BoxProps }>;
|
||||
filesType?: PluginFileType[];
|
||||
filesExsts?: string[];
|
||||
usersTypes?: PluginUsersType[];
|
||||
devices?: PluginDevices[];
|
||||
pluginName?: string;
|
||||
}
|
||||
|
||||
export interface IMainButtonItem {
|
||||
key: string;
|
||||
label: string;
|
||||
icon: string;
|
||||
onClick?: (
|
||||
id: number | string,
|
||||
) => Promise<IMessage> | Promise<void> | IMessage | void;
|
||||
usersType?: PluginUsersType[];
|
||||
items?: IMainButtonItem[] | null;
|
||||
devices?: PluginDevices[];
|
||||
pluginName?: string;
|
||||
}
|
||||
|
||||
export interface IProfileMenuItem {
|
||||
key: string;
|
||||
label: string;
|
||||
icon: string;
|
||||
onClick: () => Promise<IMessage> | Promise<void> | IMessage | void;
|
||||
usersType?: PluginUsersType[];
|
||||
devices?: PluginDevices[];
|
||||
pluginName?: string;
|
||||
}
|
||||
|
||||
export interface IframeWindow extends Window {
|
||||
Plugins: { [key: string]: TPlugin };
|
||||
}
|
||||
|
||||
export type TPlugin = {
|
||||
name: string;
|
||||
version: string;
|
||||
description: string;
|
||||
license: string;
|
||||
author: string;
|
||||
homePage: string;
|
||||
pluginName: string;
|
||||
scopes: string | string[];
|
||||
image: string;
|
||||
createBy: TCreatedBy;
|
||||
createOn: Date;
|
||||
enabled: boolean;
|
||||
system: boolean;
|
||||
url: string;
|
||||
settings: string;
|
||||
iconUrl: string;
|
||||
|
||||
status: PluginStatus;
|
||||
onLoadCallback: () => Promise<void>;
|
||||
updateStatus: (status: PluginStatus) => void;
|
||||
getStatus: () => PluginStatus;
|
||||
setOnLoadCallback: (callback: () => Promise<void>) => void;
|
||||
|
||||
adminPluginSettings?: ISettings | null;
|
||||
setAdminPluginSettings?: (settings: ISettings | null) => void;
|
||||
setAdminPluginSettingsValue?: (settings: string | null) => void;
|
||||
getAdminPluginSettings?: () => ISettings | null;
|
||||
|
||||
origin?: string;
|
||||
proxy?: string;
|
||||
prefix?: string;
|
||||
setOrigin?: (origin: string) => void;
|
||||
setProxy?: (proxy: string) => void;
|
||||
setPrefix?: (prefix: string) => void;
|
||||
getOrigin?: () => string;
|
||||
getProxy?: () => string;
|
||||
getPrefix?: () => string;
|
||||
setAPI?: (origin: string, proxy: string, prefix: string) => void;
|
||||
getAPI?: () => { origin: string; proxy: string; prefix: string };
|
||||
|
||||
contextMenuItems: Map<string, IContextMenuItem>;
|
||||
addContextMenuItem(item: IContextMenuItem): void;
|
||||
getContextMenuItems(): Map<string, IContextMenuItem>;
|
||||
getContextMenuItemsKeys(): string[];
|
||||
updateContextMenuItem(item: IContextMenuItem): void;
|
||||
|
||||
eventListenerItems?: Map<string, IEventListenerItem>;
|
||||
addEventListenerItem?: (item: IEventListenerItem) => void;
|
||||
getEventListenerItems?: () => Map<string, IEventListenerItem>;
|
||||
|
||||
fileItems?: Map<string, IFileItem>;
|
||||
addFileItem?: (item: IFileItem) => void;
|
||||
getFileItems?: () => Map<string, IFileItem>;
|
||||
updateFileItem?: (item: IFileItem) => void;
|
||||
|
||||
infoPanelItems?: Map<string, IInfoPanelItem>;
|
||||
addInfoPanelItem?: (item: IInfoPanelItem) => void;
|
||||
getInfoPanelItems?: () => Map<string, IInfoPanelItem>;
|
||||
updateInfoPanelItem?: (item: IInfoPanelItem) => void;
|
||||
|
||||
mainButtonItems?: Map<string, IMainButtonItem>;
|
||||
addMainButtonItem?: (item: IMainButtonItem) => void;
|
||||
getMainButtonItems?: () => Map<string, IMainButtonItem>;
|
||||
updateMainButtonItem?: (item: IMainButtonItem) => void;
|
||||
|
||||
profileMenuItems?: Map<string, IProfileMenuItem>;
|
||||
addProfileMenuItem?: (item: IProfileMenuItem) => void;
|
||||
getProfileMenuItems?: () => Map<string, IProfileMenuItem>;
|
||||
updateProfileMenuItem?: (item: IProfileMenuItem) => void;
|
||||
};
|
@ -3,7 +3,7 @@ import { toastr } from "@docspace/shared/components/toast";
|
||||
|
||||
import config from "PACKAGE_FILE";
|
||||
|
||||
import { PluginActions, PluginToastType } from "./constants";
|
||||
import { PluginActions, PluginToastType } from "./enums";
|
||||
import { Events } from "@docspace/shared/enums";
|
||||
|
||||
export const messageActions = (
|
||||
@ -26,7 +26,7 @@ export const messageActions = (
|
||||
updateEventListenerItems,
|
||||
updateFileItems,
|
||||
|
||||
updatePlugin
|
||||
updatePlugin,
|
||||
) => {
|
||||
if (!message || !message.actions || message.actions.length === 0) return;
|
||||
|
||||
@ -152,7 +152,7 @@ export const messageActions = (
|
||||
if (frame) {
|
||||
frame.contentWindow.postMessage(
|
||||
JSON.stringify(postMessage.message),
|
||||
"*"
|
||||
"*",
|
||||
);
|
||||
}
|
||||
|
||||
@ -177,6 +177,6 @@ export const getPluginUrl = (url, file) => {
|
||||
window.DocSpaceConfig?.proxy?.url,
|
||||
config.homepage,
|
||||
path,
|
||||
file
|
||||
file,
|
||||
);
|
||||
};
|
||||
|
@ -7,7 +7,7 @@ import { FolderType, ShareAccessRights } from "@docspace/shared/enums";
|
||||
import { translations } from "./autoGeneratedTranslations";
|
||||
// import router from "SRC_DIR/router";
|
||||
|
||||
export const setDocumentTitle = (subTitle = null) => {
|
||||
export const setDocumentTitle = (subTitle = "") => {
|
||||
const { isAuthenticated, product: currentModule } = authStore;
|
||||
const { organizationName } = settingsStore;
|
||||
|
||||
|
@ -32,8 +32,8 @@ const Bonus = ({ standaloneInit, isInitPaymentPage }) => {
|
||||
);
|
||||
};
|
||||
|
||||
export default inject(({ payments }) => {
|
||||
const { standaloneInit, isInitPaymentPage } = payments;
|
||||
export default inject(({ paymentStore }) => {
|
||||
const { standaloneInit, isInitPaymentPage } = paymentStore;
|
||||
|
||||
return {
|
||||
standaloneInit,
|
||||
|
@ -35,28 +35,26 @@ export default function withLoader(WrappedComponent) {
|
||||
type === "EmpInvite") &&
|
||||
!passwordSettings
|
||||
) {
|
||||
axios
|
||||
.all([getSettings(), getPortalPasswordSettings(confirmHeader)])
|
||||
.catch((error) => {
|
||||
let errorMessage = "";
|
||||
if (typeof error === "object") {
|
||||
errorMessage =
|
||||
error?.response?.data?.error?.message ||
|
||||
error?.statusText ||
|
||||
error?.message ||
|
||||
"";
|
||||
} else {
|
||||
errorMessage = error;
|
||||
}
|
||||
getPortalPasswordSettings(confirmHeader).catch((error) => {
|
||||
let errorMessage = "";
|
||||
if (typeof error === "object") {
|
||||
errorMessage =
|
||||
error?.response?.data?.error?.message ||
|
||||
error?.statusText ||
|
||||
error?.message ||
|
||||
"";
|
||||
} else {
|
||||
errorMessage = error;
|
||||
}
|
||||
|
||||
console.error(errorMessage);
|
||||
navigate(
|
||||
combineUrl(
|
||||
window.DocSpaceConfig?.proxy?.url,
|
||||
`/login/error?message=${errorMessage}`
|
||||
)
|
||||
);
|
||||
});
|
||||
console.error(errorMessage);
|
||||
navigate(
|
||||
combineUrl(
|
||||
window.DocSpaceConfig?.proxy?.url,
|
||||
`/login/error?message=${errorMessage}`,
|
||||
),
|
||||
);
|
||||
});
|
||||
}
|
||||
}, [passwordSettings]);
|
||||
|
||||
@ -77,8 +75,8 @@ export default function withLoader(WrappedComponent) {
|
||||
navigate(
|
||||
combineUrl(
|
||||
window.DocSpaceConfig?.proxy?.url,
|
||||
`/login/error?message=${errorMessage}`
|
||||
)
|
||||
`/login/error?message=${errorMessage}`,
|
||||
),
|
||||
);
|
||||
});
|
||||
}
|
||||
|
@ -10,6 +10,7 @@ import { ComboBox } from "@docspace/shared/components/combobox";
|
||||
|
||||
import { getUserStatus } from "SRC_DIR/helpers/people-helpers";
|
||||
import { StyledAccountContent } from "../../styles/accounts";
|
||||
import { getUserTypeLabel } from "@docspace/shared/utils/common";
|
||||
|
||||
const Accounts = (props) => {
|
||||
const {
|
||||
@ -46,21 +47,6 @@ const Accounts = (props) => {
|
||||
}
|
||||
}, [infoPanelSelection]);
|
||||
|
||||
const getUserTypeLabel = React.useCallback((role) => {
|
||||
switch (role) {
|
||||
case "owner":
|
||||
return t("Common:Owner");
|
||||
case "admin":
|
||||
return t("Common:DocSpaceAdmin");
|
||||
case "manager":
|
||||
return t("Common:RoomAdmin");
|
||||
case "collaborator":
|
||||
return t("Common:PowerUser");
|
||||
case "user":
|
||||
return t("Common:User");
|
||||
}
|
||||
}, []);
|
||||
|
||||
const getTypesOptions = React.useCallback(() => {
|
||||
const options = [];
|
||||
|
||||
@ -128,10 +114,10 @@ const Accounts = (props) => {
|
||||
setIsLoading(false);
|
||||
}
|
||||
},
|
||||
[infoPanelSelection, changeUserType, t]
|
||||
[infoPanelSelection, changeUserType, t],
|
||||
);
|
||||
|
||||
const typeLabel = getUserTypeLabel(role);
|
||||
const typeLabel = React.useCallback(() => getUserTypeLabel(role, t), [])();
|
||||
|
||||
const renderTypeData = () => {
|
||||
const typesOptions = getTypesOptions();
|
||||
@ -248,7 +234,7 @@ export default inject(
|
||||
getPeopleListItem: usersStore.getPeopleListItem,
|
||||
setInfoPanelSelection,
|
||||
};
|
||||
}
|
||||
},
|
||||
)(
|
||||
withTranslation([
|
||||
"People",
|
||||
@ -263,7 +249,7 @@ export default inject(
|
||||
"Translations",
|
||||
])(
|
||||
withLoader(observer(Accounts))(
|
||||
<Loaders.InfoPanelViewLoader view="accounts" />
|
||||
)
|
||||
)
|
||||
<Loaders.InfoPanelViewLoader view="accounts" />,
|
||||
),
|
||||
),
|
||||
);
|
||||
|
@ -9,9 +9,8 @@ import { toastr } from "@docspace/shared/components/toast";
|
||||
import { isMobileOnly, isMobile } from "react-device-detect";
|
||||
import { decode } from "he";
|
||||
import { filterUserRoleOptions } from "SRC_DIR/helpers";
|
||||
import { capitalize } from "lodash";
|
||||
|
||||
import { getUserRole } from "@docspace/shared/utils/common";
|
||||
import { getUserRole, getUserTypeLabel } from "@docspace/shared/utils/common";
|
||||
import { Text } from "@docspace/shared/components/text";
|
||||
import EmailPlusReactSvgUrl from "PUBLIC_DIR/images/e-mail+.react.svg?url";
|
||||
import { StyledUserTypeHeader } from "../../styles/members";
|
||||
@ -48,7 +47,7 @@ const User = ({
|
||||
|
||||
const fullRoomRoleOptions = membersHelper.getOptionsByRoomType(
|
||||
infoPanelSelection.roomType,
|
||||
canChangeUserRole
|
||||
canChangeUserRole,
|
||||
);
|
||||
|
||||
const userRole = membersHelper.getOptionByUserAccess(user.access, user);
|
||||
@ -57,7 +56,7 @@ const User = ({
|
||||
const onRepeatInvitation = async () => {
|
||||
resendEmailInvitations(infoPanelSelection.id, true)
|
||||
.then(() =>
|
||||
toastr.success(t("PeopleTranslations:SuccessSentMultipleInvitatios"))
|
||||
toastr.success(t("PeopleTranslations:SuccessSentMultipleInvitatios")),
|
||||
)
|
||||
.catch((err) => toastr.error(err));
|
||||
};
|
||||
@ -77,10 +76,10 @@ const User = ({
|
||||
const newMembers = {
|
||||
users: infoPanelMembers.users?.filter((m) => m.id !== user.id),
|
||||
administrators: infoPanelMembers.administrators?.filter(
|
||||
(m) => m.id !== user.id
|
||||
(m) => m.id !== user.id,
|
||||
),
|
||||
expected: infoPanelMembers.expected?.filter(
|
||||
(m) => m.id !== user.id
|
||||
(m) => m.id !== user.id,
|
||||
),
|
||||
};
|
||||
|
||||
@ -129,13 +128,13 @@ const User = ({
|
||||
setInfoPanelMembers({
|
||||
roomId: infoPanelSelection.id,
|
||||
users: infoPanelMembers.users?.map((m) =>
|
||||
m.id === user.id ? { ...m, access: option.access } : m
|
||||
m.id === user.id ? { ...m, access: option.access } : m,
|
||||
),
|
||||
administrators: infoPanelMembers.administrators?.map((m) =>
|
||||
m.id === user.id ? { ...m, access: option.access } : m
|
||||
m.id === user.id ? { ...m, access: option.access } : m,
|
||||
),
|
||||
expected: infoPanelMembers.expected?.map((m) =>
|
||||
m.id === user.id ? { ...m, access: option.access } : m
|
||||
m.id === user.id ? { ...m, access: option.access } : m,
|
||||
),
|
||||
});
|
||||
}
|
||||
@ -182,6 +181,8 @@ const User = ({
|
||||
const onToggle = (e, isOpen) => {
|
||||
// setIsScrollLocked(isOpen);
|
||||
};
|
||||
const role = getUserRole(user);
|
||||
const typeLabel = getUserTypeLabel(role, t);
|
||||
|
||||
const getTooltipContent = () => (
|
||||
<div>
|
||||
@ -197,15 +198,13 @@ const User = ({
|
||||
color="#A3A9AE !important"
|
||||
dir="auto"
|
||||
>
|
||||
{`${capitalize(role)} | ${user.email}`}
|
||||
{`${typeLabel} | ${user.email}`}
|
||||
</Text>
|
||||
</div>
|
||||
);
|
||||
|
||||
const userAvatar = user.hasAvatar ? user.avatar : DefaultUserPhotoUrl;
|
||||
|
||||
const role = getUserRole(user);
|
||||
|
||||
const withTooltip = user.isOwner || user.isAdmin;
|
||||
|
||||
const uniqueTooltipId = `userTooltip_${Math.random()}`;
|
||||
@ -269,7 +268,7 @@ const User = ({
|
||||
color="#A3A9AE"
|
||||
dir="auto"
|
||||
>
|
||||
{`${capitalize(role)} | ${user.email}`}
|
||||
{`${typeLabel} | ${user.email}`}
|
||||
</Text>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -2,7 +2,7 @@ import React from "react";
|
||||
import { inject, observer } from "mobx-react";
|
||||
|
||||
import WrappedComponent from "SRC_DIR/helpers/plugins/WrappedComponent";
|
||||
import { PluginComponents } from "SRC_DIR/helpers/plugins/constants";
|
||||
import { PluginComponents } from "SRC_DIR/helpers/plugins/enums";
|
||||
|
||||
const Plugin = ({ boxProps, pluginName }) => {
|
||||
return (
|
||||
|
@ -15,7 +15,7 @@ import {
|
||||
|
||||
import { StyledInfoPanelHeader } from "./styles/common";
|
||||
|
||||
import { PluginFileType } from "SRC_DIR/helpers/plugins/constants";
|
||||
import { PluginFileType } from "SRC_DIR/helpers/plugins/enums";
|
||||
|
||||
const InfoPanelHeaderContent = (props) => {
|
||||
const {
|
||||
@ -245,12 +245,12 @@ export default inject(
|
||||
|
||||
enablePlugins,
|
||||
};
|
||||
}
|
||||
},
|
||||
)(
|
||||
withTranslation(["Common", "InfoPanel"])(
|
||||
InfoPanelHeaderContent
|
||||
InfoPanelHeaderContent,
|
||||
// withLoader(observer(InfoPanelHeaderContent))(
|
||||
// <Loaders.InfoPanelHeaderLoader />
|
||||
// )
|
||||
)
|
||||
),
|
||||
);
|
||||
|
@ -4,7 +4,7 @@ import { withTranslation } from "react-i18next";
|
||||
import { useNavigate, useLocation } from "react-router-dom";
|
||||
import queryString from "query-string";
|
||||
|
||||
import { PluginFileType } from "SRC_DIR/helpers/plugins/constants";
|
||||
import { PluginFileType } from "SRC_DIR/helpers/plugins/enums";
|
||||
import { MEDIA_VIEW_URL } from "@docspace/shared/constants";
|
||||
import { combineUrl } from "@docspace/shared/utils/combineUrl";
|
||||
|
||||
@ -118,7 +118,7 @@ const FilesMediaViewer = (props) => {
|
||||
setCurrentId(id);
|
||||
navigate(url);
|
||||
},
|
||||
[setCurrentId, navigate]
|
||||
[setCurrentId, navigate],
|
||||
);
|
||||
|
||||
const resetSelection = () => {
|
||||
@ -159,7 +159,7 @@ const FilesMediaViewer = (props) => {
|
||||
// try to fix with one check later (see deleteAction)
|
||||
const isActiveFile = activeFiles.find((elem) => elem.id === file.id);
|
||||
const isActiveFolder = activeFolders.find(
|
||||
(elem) => elem.id === file.id
|
||||
(elem) => elem.id === file.id,
|
||||
);
|
||||
|
||||
if (isActiveFile || isActiveFolder) return;
|
||||
@ -169,7 +169,14 @@ const FilesMediaViewer = (props) => {
|
||||
}
|
||||
}
|
||||
},
|
||||
[files, t, activeFiles, activeFolders, setRemoveMediaItem, deleteItemAction]
|
||||
[
|
||||
files,
|
||||
t,
|
||||
activeFiles,
|
||||
activeFolders,
|
||||
setRemoveMediaItem,
|
||||
deleteItemAction,
|
||||
],
|
||||
);
|
||||
|
||||
const onDownloadMediaFile = useCallback(
|
||||
@ -179,7 +186,7 @@ const FilesMediaViewer = (props) => {
|
||||
return window.open(viewUrlFile, "_self");
|
||||
}
|
||||
},
|
||||
[playlist]
|
||||
[playlist],
|
||||
);
|
||||
|
||||
const onMediaViewerClose = useCallback(
|
||||
@ -227,7 +234,7 @@ const FilesMediaViewer = (props) => {
|
||||
setToPreviewFile,
|
||||
setMediaViewerData,
|
||||
setBufferSelection,
|
||||
]
|
||||
],
|
||||
);
|
||||
useEffect(() => {
|
||||
if (playlist.length === 0 && isOpenMediaViewer) onMediaViewerClose();
|
||||
@ -422,5 +429,5 @@ export default inject(
|
||||
pluginContextMenuItems,
|
||||
currentDeviceType,
|
||||
};
|
||||
}
|
||||
},
|
||||
)(withTranslation(["Files", "Translations"])(observer(FilesMediaViewer)));
|
||||
|
@ -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,
|
||||
|
||||
};
|
||||
}
|
||||
)(
|
||||
|
@ -14,6 +14,7 @@ import withContent from "SRC_DIR/HOCs/withPeopleContent";
|
||||
|
||||
import Badges from "../Badges";
|
||||
import { Base } from "@docspace/shared/themes";
|
||||
import { getUserTypeLabel } from "@docspace/shared/utils/common";
|
||||
|
||||
const StyledWrapper = styled.div`
|
||||
display: contents;
|
||||
@ -229,6 +230,9 @@ const PeopleTableRow = (props) => {
|
||||
hideColumns,
|
||||
value,
|
||||
standalone,
|
||||
typeAccountsColumnIsEnabled,
|
||||
emailAccountsColumnIsEnabled,
|
||||
infoPanelVisible,
|
||||
} = props;
|
||||
|
||||
const {
|
||||
@ -308,7 +312,7 @@ const PeopleTableRow = (props) => {
|
||||
setIsLoading(false);
|
||||
}
|
||||
},
|
||||
[item, changeUserType]
|
||||
[item, changeUserType],
|
||||
);
|
||||
|
||||
// const getRoomsOptions = React.useCallback(() => {
|
||||
@ -328,22 +332,7 @@ const PeopleTableRow = (props) => {
|
||||
// return <>{options.map((option) => option)}</>;
|
||||
// }, []);
|
||||
|
||||
const getUserTypeLabel = React.useCallback((role) => {
|
||||
switch (role) {
|
||||
case "owner":
|
||||
return t("Common:Owner");
|
||||
case "admin":
|
||||
return t("Common:DocSpaceAdmin");
|
||||
case "manager":
|
||||
return t("Common:RoomAdmin");
|
||||
case "collaborator":
|
||||
return t("Common:PowerUser");
|
||||
case "user":
|
||||
return t("Common:User");
|
||||
}
|
||||
}, []);
|
||||
|
||||
const typeLabel = getUserTypeLabel(role);
|
||||
const typeLabel = React.useCallback(() => getUserTypeLabel(role, t), [])();
|
||||
|
||||
const isChecked = checkedProps.checked;
|
||||
|
||||
@ -466,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 ? (
|
||||
@ -512,25 +510,29 @@ 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>
|
||||
);
|
||||
};
|
||||
|
||||
export default withTranslation(["People", "Common", "Settings"])(
|
||||
withContent(PeopleTableRow)
|
||||
withContent(PeopleTableRow),
|
||||
);
|
||||
|
@ -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))
|
||||
)
|
||||
);
|
||||
|
@ -283,7 +283,7 @@ const AdditionalResources = (props) => {
|
||||
);
|
||||
};
|
||||
|
||||
export default inject(({ filesSettingsStore, common, currentQuotaStore }) => {
|
||||
export default inject(({ settingsStore, common, currentQuotaStore }) => {
|
||||
const { setIsLoadedAdditionalResources, isLoadedAdditionalResources } =
|
||||
common;
|
||||
|
||||
@ -292,7 +292,7 @@ export default inject(({ filesSettingsStore, common, currentQuotaStore }) => {
|
||||
|
||||
additionalResourcesData,
|
||||
additionalResourcesIsDefault,
|
||||
} = filesSettingsStore;
|
||||
} = settingsStore;
|
||||
|
||||
const { isBrandingAndCustomizationAvailable } = currentQuotaStore;
|
||||
|
||||
|
@ -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)),
|
||||
),
|
||||
);
|
||||
|
@ -148,7 +148,7 @@ const WhiteLabel = (props) => {
|
||||
|
||||
const onRestoreDefault = async () => {
|
||||
try {
|
||||
await restoreWhiteLabelSettings(true);
|
||||
await restoreWhiteLabelSettings();
|
||||
await onResetCompanyName();
|
||||
toastr.success(t("Settings:SuccessfullySaveSettingsMessage"));
|
||||
} catch (error) {
|
||||
|
@ -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))));
|
||||
|
@ -23,6 +23,7 @@ const SubmenuCommon = (props) => {
|
||||
isLoadedSubmenu,
|
||||
getWhiteLabelLogoUrls,
|
||||
currentDeviceType,
|
||||
isMobileView,
|
||||
} = props;
|
||||
const navigate = useNavigate();
|
||||
|
||||
@ -41,7 +42,10 @@ const SubmenuCommon = (props) => {
|
||||
}, [tReady, isLoadedSubmenu]);
|
||||
|
||||
const load = async () => {
|
||||
await loadBaseInfo();
|
||||
const currentTab = getCurrentTab();
|
||||
await loadBaseInfo(
|
||||
!isMobileView ? (currentTab === 0 ? "general" : "branding") : ""
|
||||
);
|
||||
};
|
||||
|
||||
const data = [
|
||||
@ -111,13 +115,14 @@ export default inject(({ settingsStore, common }) => {
|
||||
|
||||
const isMobileView = currentDeviceType === DeviceType.mobile;
|
||||
return {
|
||||
loadBaseInfo: async () => {
|
||||
await initSettings(!isMobileView ? "general" : "");
|
||||
loadBaseInfo: async (page) => {
|
||||
await initSettings(page);
|
||||
},
|
||||
isLoaded,
|
||||
setIsLoadedSubmenu,
|
||||
isLoadedSubmenu,
|
||||
getWhiteLabelLogoUrls,
|
||||
currentDeviceType,
|
||||
isMobileView,
|
||||
};
|
||||
})(withLoading(withTranslation("Settings")(observer(SubmenuCommon))));
|
||||
|
@ -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)),
|
||||
);
|
File diff suppressed because it is too large
Load Diff
@ -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 (
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user