diff --git a/DNN Platform/Modules/ResourceManager/App_LocalResources/ResourceManager.resx b/DNN Platform/Modules/ResourceManager/App_LocalResources/ResourceManager.resx index 1406766b1ec..37757c05408 100644 --- a/DNN Platform/Modules/ResourceManager/App_LocalResources/ResourceManager.resx +++ b/DNN Platform/Modules/ResourceManager/App_LocalResources/ResourceManager.resx @@ -342,4 +342,22 @@ Mapped Path + + Edit + + + Role Permissions + + + User Permissions + + + Folder ID + + + General + + + Permissions + \ No newline at end of file diff --git a/DNN Platform/Modules/ResourceManager/Components/ItemsManager.cs b/DNN Platform/Modules/ResourceManager/Components/ItemsManager.cs index 495703a4ef2..f116cdd1ac7 100644 --- a/DNN Platform/Modules/ResourceManager/Components/ItemsManager.cs +++ b/DNN Platform/Modules/ResourceManager/Components/ItemsManager.cs @@ -133,7 +133,7 @@ public void SaveFileDetails(IFileInfo file, FileDetailsRequest fileDetails) public void SaveFolderDetails(IFolderInfo folder, FolderDetailsRequest folderDetails) { this.assetManager.RenameFolder(folderDetails.FolderId, folderDetails.FolderName); - folder.FolderPermissions.Clear(); + folder.FolderPermissions.Clear(); folder.FolderPermissions.AddRange(folderDetails.Permissions.RolePermissions.ToPermissionInfos(folderDetails.FolderId)); folder.FolderPermissions.AddRange(folderDetails.Permissions.UserPermissions.ToPermissionInfos(folderDetails.FolderId)); FolderManager.Instance.UpdateFolder(folder); diff --git a/DNN Platform/Modules/ResourceManager/Components/PermissionHelper.cs b/DNN Platform/Modules/ResourceManager/Components/PermissionHelper.cs index 805a45e126b..cb9335c4d9e 100644 --- a/DNN Platform/Modules/ResourceManager/Components/PermissionHelper.cs +++ b/DNN Platform/Modules/ResourceManager/Components/PermissionHelper.cs @@ -229,7 +229,7 @@ public static ArrayList ToPermissionInfos(this IList permissions AllowAccess = p.AllowAccess, FolderID = folderId, PermissionID = p.PermissionId, - RoleID = Null.NullInteger, + RoleID = int.Parse(Globals.glbRoleNothing), UserID = permission.UserId, }); } diff --git a/DNN Platform/Modules/ResourceManager/Dnn.Modules.ResourceManager.csproj b/DNN Platform/Modules/ResourceManager/Dnn.Modules.ResourceManager.csproj index fff7f81f8bb..239d710b475 100644 --- a/DNN Platform/Modules/ResourceManager/Dnn.Modules.ResourceManager.csproj +++ b/DNN Platform/Modules/ResourceManager/Dnn.Modules.ResourceManager.csproj @@ -133,6 +133,7 @@ + diff --git a/DNN Platform/Modules/ResourceManager/ResourceManager.Web/package-lock.json b/DNN Platform/Modules/ResourceManager/ResourceManager.Web/package-lock.json new file mode 100644 index 00000000000..1ddac12eb8c --- /dev/null +++ b/DNN Platform/Modules/ResourceManager/ResourceManager.Web/package-lock.json @@ -0,0 +1,31 @@ +{ + "name": "dnn-resource-manager", + "version": "9.10.2", + "lockfileVersion": 1, + "requires": true, + "dependencies": { + "@dnncommunity/dnn-elements": { + "version": "0.15.0-beta.21", + "resolved": "https://registry.npmjs.org/@dnncommunity/dnn-elements/-/dnn-elements-0.15.0-beta.21.tgz", + "integrity": "sha512-d5wcJBy8cnkHpMF05723+wtoBEAWuSUQGkEdmdHUEVgwjqmJNlqKBNQ34Gp4rydp3NxFseGTL2KIIcp94TbCQQ==", + "dev": true + }, + "@stencil/core": { + "version": "2.14.2", + "resolved": "https://registry.npmjs.org/@stencil/core/-/core-2.14.2.tgz", + "integrity": "sha512-NMC5Xi8sPFJxaO4rz6CbMHuD6PteE/RJWtjrbkusmpjKRtMXkfZJPIgOrleZ4xO+vXcNyL535Ru7vUADqEsTiQ==" + }, + "@stencil/sass": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/@stencil/sass/-/sass-1.5.2.tgz", + "integrity": "sha512-nJ93pUSylsGsMX0eLmhxh1oEljcUjj5mYjhB9ziCdoaydAdjukrUoqDCC7tdVbOcBo2hKptQyWqCtETnBGYsXQ==", + "dev": true + }, + "@stencil/store": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@stencil/store/-/store-1.5.0.tgz", + "integrity": "sha512-fe5fCF6dgVlDM1iLRkkJUyUh0Tfx305asVGgMAJjIs7Q+x/b1pGgTLROm9Ibr53PZuFwr5Kg+4h9p4FLbYqHgA==", + "dev": true + } + } +} diff --git a/DNN Platform/Modules/ResourceManager/ResourceManager.Web/package.json b/DNN Platform/Modules/ResourceManager/ResourceManager.Web/package.json index eb7e3fa222f..fd9426ba9e0 100644 --- a/DNN Platform/Modules/ResourceManager/ResourceManager.Web/package.json +++ b/DNN Platform/Modules/ResourceManager/ResourceManager.Web/package.json @@ -29,7 +29,7 @@ }, "license": "MIT", "devDependencies": { - "@dnncommunity/dnn-elements": "0.14.1", + "@dnncommunity/dnn-elements": "^0.15.0-beta.21", "@stencil/sass": "^1.5.2", "@stencil/store": "^1.5.0" } diff --git a/DNN Platform/Modules/ResourceManager/ResourceManager.Web/src/components.d.ts b/DNN Platform/Modules/ResourceManager/ResourceManager.Web/src/components.d.ts index b3018e14bcc..0d994bc36a8 100644 --- a/DNN Platform/Modules/ResourceManager/ResourceManager.Web/src/components.d.ts +++ b/DNN Platform/Modules/ResourceManager/ResourceManager.Web/src/components.d.ts @@ -5,12 +5,15 @@ * It contains typing information for all components that exist in this project. */ import { HTMLStencilElement, JSXBase } from "@stencil/core/internal"; +import { GetFolderContentResponse, Item } from "./services/ItemsClient"; import { FolderTreeItem } from "./services/InternalServicesClient"; -import { GetFolderContentResponse } from "./services/ItemsClient"; export namespace Components { interface DnnActionCreateFolder { "parentFolderId": number; } + interface DnnActionEditItem { + "item": Item; + } interface DnnResourceManager { /** * The ID of the module. @@ -19,7 +22,13 @@ export namespace Components { } interface DnnRmActionsBar { } + interface DnnRmCreateFolder { + } interface DnnRmEditFolder { + /** + * The ID of the folder to edit. + */ + "folderId": number; } interface DnnRmFilesPane { /** @@ -29,9 +38,9 @@ export namespace Components { } interface DnnRmFolderContextMenu { /** - * The ID of the folder onto which the context menu was triggered on. + * The item that triggered this menu. */ - "clickedFolderId": number; + "item": Item; } interface DnnRmFolderList { } @@ -44,6 +53,10 @@ export namespace Components { * The basic information about the folder */ "folder": FolderTreeItem; + /** + * The ID of the parent folder. + */ + "parentFolderId": number; } interface DnnRmItemsCardview { /** @@ -73,6 +86,12 @@ declare global { prototype: HTMLDnnActionCreateFolderElement; new (): HTMLDnnActionCreateFolderElement; }; + interface HTMLDnnActionEditItemElement extends Components.DnnActionEditItem, HTMLStencilElement { + } + var HTMLDnnActionEditItemElement: { + prototype: HTMLDnnActionEditItemElement; + new (): HTMLDnnActionEditItemElement; + }; interface HTMLDnnResourceManagerElement extends Components.DnnResourceManager, HTMLStencilElement { } var HTMLDnnResourceManagerElement: { @@ -85,6 +104,12 @@ declare global { prototype: HTMLDnnRmActionsBarElement; new (): HTMLDnnRmActionsBarElement; }; + interface HTMLDnnRmCreateFolderElement extends Components.DnnRmCreateFolder, HTMLStencilElement { + } + var HTMLDnnRmCreateFolderElement: { + prototype: HTMLDnnRmCreateFolderElement; + new (): HTMLDnnRmCreateFolderElement; + }; interface HTMLDnnRmEditFolderElement extends Components.DnnRmEditFolder, HTMLStencilElement { } var HTMLDnnRmEditFolderElement: { @@ -153,8 +178,10 @@ declare global { }; interface HTMLElementTagNameMap { "dnn-action-create-folder": HTMLDnnActionCreateFolderElement; + "dnn-action-edit-item": HTMLDnnActionEditItemElement; "dnn-resource-manager": HTMLDnnResourceManagerElement; "dnn-rm-actions-bar": HTMLDnnRmActionsBarElement; + "dnn-rm-create-folder": HTMLDnnRmCreateFolderElement; "dnn-rm-edit-folder": HTMLDnnRmEditFolderElement; "dnn-rm-files-pane": HTMLDnnRmFilesPaneElement; "dnn-rm-folder-context-menu": HTMLDnnRmFolderContextMenuElement; @@ -172,6 +199,9 @@ declare namespace LocalJSX { interface DnnActionCreateFolder { "parentFolderId"?: number; } + interface DnnActionEditItem { + "item": Item; + } interface DnnResourceManager { /** * The ID of the module. @@ -180,7 +210,17 @@ declare namespace LocalJSX { } interface DnnRmActionsBar { } + interface DnnRmCreateFolder { + /** + * Fires when there is a possibility that some folders have changed. Can be used to force parts of the UI to refresh. + */ + "onDnnRmFoldersChanged"?: (event: CustomEvent) => void; + } interface DnnRmEditFolder { + /** + * The ID of the folder to edit. + */ + "folderId": number; /** * Fires when there is a possibility that some folders have changed. Can be used to force parts of the UI to refresh. */ @@ -194,9 +234,9 @@ declare namespace LocalJSX { } interface DnnRmFolderContextMenu { /** - * The ID of the folder onto which the context menu was triggered on. + * The item that triggered this menu. */ - "clickedFolderId": number; + "item": Item; } interface DnnRmFolderList { } @@ -213,6 +253,10 @@ declare namespace LocalJSX { * Fires when a context menu is opened for this item. Emits the folder ID. */ "onDnnRmcontextMenuOpened"?: (event: CustomEvent) => void; + /** + * The ID of the parent folder. + */ + "parentFolderId": number; } interface DnnRmItemsCardview { /** @@ -236,8 +280,10 @@ declare namespace LocalJSX { } interface IntrinsicElements { "dnn-action-create-folder": DnnActionCreateFolder; + "dnn-action-edit-item": DnnActionEditItem; "dnn-resource-manager": DnnResourceManager; "dnn-rm-actions-bar": DnnRmActionsBar; + "dnn-rm-create-folder": DnnRmCreateFolder; "dnn-rm-edit-folder": DnnRmEditFolder; "dnn-rm-files-pane": DnnRmFilesPane; "dnn-rm-folder-context-menu": DnnRmFolderContextMenu; @@ -256,8 +302,10 @@ declare module "@stencil/core" { export namespace JSX { interface IntrinsicElements { "dnn-action-create-folder": LocalJSX.DnnActionCreateFolder & JSXBase.HTMLAttributes; + "dnn-action-edit-item": LocalJSX.DnnActionEditItem & JSXBase.HTMLAttributes; "dnn-resource-manager": LocalJSX.DnnResourceManager & JSXBase.HTMLAttributes; "dnn-rm-actions-bar": LocalJSX.DnnRmActionsBar & JSXBase.HTMLAttributes; + "dnn-rm-create-folder": LocalJSX.DnnRmCreateFolder & JSXBase.HTMLAttributes; "dnn-rm-edit-folder": LocalJSX.DnnRmEditFolder & JSXBase.HTMLAttributes; "dnn-rm-files-pane": LocalJSX.DnnRmFilesPane & JSXBase.HTMLAttributes; "dnn-rm-folder-context-menu": LocalJSX.DnnRmFolderContextMenu & JSXBase.HTMLAttributes; diff --git a/DNN Platform/Modules/ResourceManager/ResourceManager.Web/src/components/actions/dnn-action-create-folder/dnn-action-create-folder.tsx b/DNN Platform/Modules/ResourceManager/ResourceManager.Web/src/components/actions/dnn-action-create-folder/dnn-action-create-folder.tsx index 23e6b1a9978..956cae8d6bd 100644 --- a/DNN Platform/Modules/ResourceManager/ResourceManager.Web/src/components/actions/dnn-action-create-folder/dnn-action-create-folder.tsx +++ b/DNN Platform/Modules/ResourceManager/ResourceManager.Web/src/components/actions/dnn-action-create-folder/dnn-action-create-folder.tsx @@ -35,7 +35,7 @@ export class DnnActionCreateFolder { const modal = document.createElement("dnn-modal"); modal.backdropDismiss = false; modal.showCloseButton = false; - const editor = document.createElement("dnn-rm-edit-folder"); + const editor = document.createElement("dnn-rm-create-folder"); modal.appendChild(editor); document.body.appendChild(modal); modal.show(); diff --git a/DNN Platform/Modules/ResourceManager/ResourceManager.Web/src/components/actions/dnn-action-create-folder/readme.md b/DNN Platform/Modules/ResourceManager/ResourceManager.Web/src/components/actions/dnn-action-create-folder/readme.md index 58351e39c3f..46970721d7f 100644 --- a/DNN Platform/Modules/ResourceManager/ResourceManager.Web/src/components/actions/dnn-action-create-folder/readme.md +++ b/DNN Platform/Modules/ResourceManager/ResourceManager.Web/src/components/actions/dnn-action-create-folder/readme.md @@ -22,14 +22,14 @@ ### Depends on - dnn-modal -- [dnn-rm-edit-folder](../../dnn-rm-edit-folder) +- [dnn-rm-create-folder](../../dnn-rm-create-folder) ### Graph ```mermaid graph TD; dnn-action-create-folder --> dnn-modal - dnn-action-create-folder --> dnn-rm-edit-folder - dnn-rm-edit-folder --> dnn-button + dnn-action-create-folder --> dnn-rm-create-folder + dnn-rm-create-folder --> dnn-button dnn-button --> dnn-modal dnn-button --> dnn-button dnn-rm-actions-bar --> dnn-action-create-folder diff --git a/DNN Platform/Modules/ResourceManager/ResourceManager.Web/src/components/actions/dnn-action-edit-item/dnn-action-edit-item.tsx b/DNN Platform/Modules/ResourceManager/ResourceManager.Web/src/components/actions/dnn-action-edit-item/dnn-action-edit-item.tsx new file mode 100644 index 00000000000..a8fc1f4942c --- /dev/null +++ b/DNN Platform/Modules/ResourceManager/ResourceManager.Web/src/components/actions/dnn-action-edit-item/dnn-action-edit-item.tsx @@ -0,0 +1,42 @@ +import { Component, Host, h, Prop } from '@stencil/core'; +import { Item } from '../../../services/ItemsClient'; +import state from "../../../store/store"; + +@Component({ + tag: 'dnn-action-edit-item', + styleUrl: '../dnn-action.scss', + shadow: true, +}) +export class DnnActionEditItem { + + @Prop() item!: Item; + + private handleClick(): void { + this.showModal(); + } + + private showModal(){ + const modal = document.createElement("dnn-modal"); + modal.backdropDismiss = false; + modal.showCloseButton = false; + // We also need to show a different model depending if we have a file or folder + if (this.item.isFolder){ + const editor = document.createElement("dnn-rm-edit-folder") as HTMLDnnRmEditFolderElement; + editor.folderId = this.item.itemId; + modal.appendChild(editor); + } + document.body.appendChild(modal); + modal.show(); + } + + render() { + return ( + + + + ); + } +} diff --git a/DNN Platform/Modules/ResourceManager/ResourceManager.Web/src/components/actions/dnn-action-edit-item/readme.md b/DNN Platform/Modules/ResourceManager/ResourceManager.Web/src/components/actions/dnn-action-edit-item/readme.md new file mode 100644 index 00000000000..350031263b8 --- /dev/null +++ b/DNN Platform/Modules/ResourceManager/ResourceManager.Web/src/components/actions/dnn-action-edit-item/readme.md @@ -0,0 +1,49 @@ +# dnn-action-edit-item + + + + + + +## Properties + +| Property | Attribute | Description | Type | Default | +| ------------------- | --------- | ----------- | ------ | ----------- | +| `item` _(required)_ | -- | | `Item` | `undefined` | + + +## Dependencies + +### Used by + + - [dnn-rm-actions-bar](../../dnn-rm-actions-bar) + - [dnn-rm-folder-context-menu](../../context-menus/dnn-rm-folder-context-menu) + +### Depends on + +- dnn-modal +- [dnn-rm-edit-folder](../../dnn-rm-edit-folder) + +### Graph +```mermaid +graph TD; + dnn-action-edit-item --> dnn-modal + dnn-action-edit-item --> dnn-rm-edit-folder + dnn-rm-edit-folder --> dnn-tabs + dnn-rm-edit-folder --> dnn-tab + dnn-rm-edit-folder --> dnn-permissions-grid + dnn-rm-edit-folder --> dnn-button + dnn-permissions-grid --> dnn-checkbox + dnn-permissions-grid --> dnn-button + dnn-permissions-grid --> dnn-searchbox + dnn-permissions-grid --> dnn-collapsible + dnn-button --> dnn-modal + dnn-button --> dnn-button + dnn-rm-actions-bar --> dnn-action-edit-item + dnn-rm-folder-context-menu --> dnn-action-edit-item + style dnn-action-edit-item fill:#f9f,stroke:#333,stroke-width:4px +``` + +---------------------------------------------- + +*Built with [StencilJS](https://stenciljs.com/)* diff --git a/DNN Platform/Modules/ResourceManager/ResourceManager.Web/src/components/context-menus/dnn-rm-folder-context-menu/dnn-rm-folder-context-menu.tsx b/DNN Platform/Modules/ResourceManager/ResourceManager.Web/src/components/context-menus/dnn-rm-folder-context-menu/dnn-rm-folder-context-menu.tsx index ccd3b93ea8b..38f9c19754e 100644 --- a/DNN Platform/Modules/ResourceManager/ResourceManager.Web/src/components/context-menus/dnn-rm-folder-context-menu/dnn-rm-folder-context-menu.tsx +++ b/DNN Platform/Modules/ResourceManager/ResourceManager.Web/src/components/context-menus/dnn-rm-folder-context-menu/dnn-rm-folder-context-menu.tsx @@ -1,4 +1,5 @@ import { Component, Host, h, Prop } from '@stencil/core'; +import { Item } from '../../../services/ItemsClient'; import state from '../../../store/store'; @Component({ @@ -8,14 +9,17 @@ import state from '../../../store/store'; }) export class DnnRmFolderContextMenu { - /** The ID of the folder onto which the context menu was triggered on. */ - @Prop() clickedFolderId!: number; + /** The item that triggered this menu. */ + @Prop() item!: Item; render() { return ( {state.currentItems?.hasAddFoldersPermission && - + + } + {state.currentItems?.hasManagePermission && + } ); diff --git a/DNN Platform/Modules/ResourceManager/ResourceManager.Web/src/components/context-menus/dnn-rm-folder-context-menu/readme.md b/DNN Platform/Modules/ResourceManager/ResourceManager.Web/src/components/context-menus/dnn-rm-folder-context-menu/readme.md index 54c13e38d6b..42f41b1c17b 100644 --- a/DNN Platform/Modules/ResourceManager/ResourceManager.Web/src/components/context-menus/dnn-rm-folder-context-menu/readme.md +++ b/DNN Platform/Modules/ResourceManager/ResourceManager.Web/src/components/context-menus/dnn-rm-folder-context-menu/readme.md @@ -7,9 +7,9 @@ ## Properties -| Property | Attribute | Description | Type | Default | -| ------------------------------ | ------------------- | ------------------------------------------------------------------ | -------- | ----------- | -| `clickedFolderId` _(required)_ | `clicked-folder-id` | The ID of the folder onto which the context menu was triggered on. | `number` | `undefined` | +| Property | Attribute | Description | Type | Default | +| ------------------- | --------- | ---------------------------------- | ------ | ----------- | +| `item` _(required)_ | -- | The item that triggered this menu. | `Item` | `undefined` | ## Dependencies @@ -23,16 +23,28 @@ ### Depends on - [dnn-action-create-folder](../../actions/dnn-action-create-folder) +- [dnn-action-edit-item](../../actions/dnn-action-edit-item) ### Graph ```mermaid graph TD; dnn-rm-folder-context-menu --> dnn-action-create-folder + dnn-rm-folder-context-menu --> dnn-action-edit-item dnn-action-create-folder --> dnn-modal - dnn-action-create-folder --> dnn-rm-edit-folder - dnn-rm-edit-folder --> dnn-button + dnn-action-create-folder --> dnn-rm-create-folder + dnn-rm-create-folder --> dnn-button dnn-button --> dnn-modal dnn-button --> dnn-button + dnn-action-edit-item --> dnn-modal + dnn-action-edit-item --> dnn-rm-edit-folder + dnn-rm-edit-folder --> dnn-tabs + dnn-rm-edit-folder --> dnn-tab + dnn-rm-edit-folder --> dnn-permissions-grid + dnn-rm-edit-folder --> dnn-button + dnn-permissions-grid --> dnn-checkbox + dnn-permissions-grid --> dnn-button + dnn-permissions-grid --> dnn-searchbox + dnn-permissions-grid --> dnn-collapsible dnn-rm-folder-list-item --> dnn-rm-folder-context-menu dnn-rm-items-cardview --> dnn-rm-folder-context-menu dnn-rm-items-listview --> dnn-rm-folder-context-menu diff --git a/DNN Platform/Modules/ResourceManager/ResourceManager.Web/src/components/dnn-resource-manager/readme.md b/DNN Platform/Modules/ResourceManager/ResourceManager.Web/src/components/dnn-resource-manager/readme.md index 49813ae5d3b..9622d7dc7cd 100644 --- a/DNN Platform/Modules/ResourceManager/ResourceManager.Web/src/components/dnn-resource-manager/readme.md +++ b/DNN Platform/Modules/ResourceManager/ResourceManager.Web/src/components/dnn-resource-manager/readme.md @@ -31,22 +31,34 @@ graph TD; dnn-rm-top-bar --> dnn-searchbox dnn-rm-left-pane --> dnn-rm-folder-list dnn-rm-folder-list --> dnn-rm-folder-list-item - dnn-rm-folder-list-item --> dnn-treeview-item - dnn-rm-folder-list-item --> dnn-rm-folder-list-item dnn-rm-folder-list-item --> dnn-collapsible dnn-rm-folder-list-item --> dnn-rm-folder-context-menu - dnn-treeview-item --> dnn-collapsible + dnn-rm-folder-list-item --> dnn-treeview-item + dnn-rm-folder-list-item --> dnn-rm-folder-list-item dnn-rm-folder-context-menu --> dnn-action-create-folder + dnn-rm-folder-context-menu --> dnn-action-edit-item dnn-action-create-folder --> dnn-modal - dnn-action-create-folder --> dnn-rm-edit-folder - dnn-rm-edit-folder --> dnn-button + dnn-action-create-folder --> dnn-rm-create-folder + dnn-rm-create-folder --> dnn-button dnn-button --> dnn-modal dnn-button --> dnn-button + dnn-action-edit-item --> dnn-modal + dnn-action-edit-item --> dnn-rm-edit-folder + dnn-rm-edit-folder --> dnn-tabs + dnn-rm-edit-folder --> dnn-tab + dnn-rm-edit-folder --> dnn-permissions-grid + dnn-rm-edit-folder --> dnn-button + dnn-permissions-grid --> dnn-checkbox + dnn-permissions-grid --> dnn-button + dnn-permissions-grid --> dnn-searchbox + dnn-permissions-grid --> dnn-collapsible + dnn-treeview-item --> dnn-collapsible dnn-rm-right-pane --> dnn-rm-actions-bar dnn-rm-right-pane --> dnn-rm-files-pane dnn-rm-right-pane --> dnn-rm-status-bar dnn-rm-actions-bar --> dnn-vertical-overflow-menu dnn-rm-actions-bar --> dnn-action-create-folder + dnn-rm-actions-bar --> dnn-action-edit-item dnn-rm-actions-bar --> dnn-collapsible dnn-rm-files-pane --> dnn-rm-items-listview dnn-rm-files-pane --> dnn-rm-items-cardview diff --git a/DNN Platform/Modules/ResourceManager/ResourceManager.Web/src/components/dnn-rm-actions-bar/dnn-rm-actions-bar.tsx b/DNN Platform/Modules/ResourceManager/ResourceManager.Web/src/components/dnn-rm-actions-bar/dnn-rm-actions-bar.tsx index 6c484731ad8..94702bf61b5 100644 --- a/DNN Platform/Modules/ResourceManager/ResourceManager.Web/src/components/dnn-rm-actions-bar/dnn-rm-actions-bar.tsx +++ b/DNN Platform/Modules/ResourceManager/ResourceManager.Web/src/components/dnn-rm-actions-bar/dnn-rm-actions-bar.tsx @@ -51,6 +51,11 @@ export class DnnRmActionsBar { {state.selectedItems && state.selectedItems.length == 0 && state.currentItems && state.currentItems.hasAddFilesPermission && } + { + state.selectedItems.length == 1 && + state.currentItems.hasManagePermission && + + }
{state.selectedItems.length > 0 && diff --git a/DNN Platform/Modules/ResourceManager/ResourceManager.Web/src/components/dnn-rm-actions-bar/readme.md b/DNN Platform/Modules/ResourceManager/ResourceManager.Web/src/components/dnn-rm-actions-bar/readme.md index a0e66126c2b..182fa0271e1 100644 --- a/DNN Platform/Modules/ResourceManager/ResourceManager.Web/src/components/dnn-rm-actions-bar/readme.md +++ b/DNN Platform/Modules/ResourceManager/ResourceManager.Web/src/components/dnn-rm-actions-bar/readme.md @@ -15,6 +15,7 @@ - dnn-vertical-overflow-menu - [dnn-action-create-folder](../actions/dnn-action-create-folder) +- [dnn-action-edit-item](../actions/dnn-action-edit-item) - dnn-collapsible ### Graph @@ -22,12 +23,23 @@ graph TD; dnn-rm-actions-bar --> dnn-vertical-overflow-menu dnn-rm-actions-bar --> dnn-action-create-folder + dnn-rm-actions-bar --> dnn-action-edit-item dnn-rm-actions-bar --> dnn-collapsible dnn-action-create-folder --> dnn-modal - dnn-action-create-folder --> dnn-rm-edit-folder - dnn-rm-edit-folder --> dnn-button + dnn-action-create-folder --> dnn-rm-create-folder + dnn-rm-create-folder --> dnn-button dnn-button --> dnn-modal dnn-button --> dnn-button + dnn-action-edit-item --> dnn-modal + dnn-action-edit-item --> dnn-rm-edit-folder + dnn-rm-edit-folder --> dnn-tabs + dnn-rm-edit-folder --> dnn-tab + dnn-rm-edit-folder --> dnn-permissions-grid + dnn-rm-edit-folder --> dnn-button + dnn-permissions-grid --> dnn-checkbox + dnn-permissions-grid --> dnn-button + dnn-permissions-grid --> dnn-searchbox + dnn-permissions-grid --> dnn-collapsible dnn-rm-right-pane --> dnn-rm-actions-bar style dnn-rm-actions-bar fill:#f9f,stroke:#333,stroke-width:4px ``` diff --git a/DNN Platform/Modules/ResourceManager/ResourceManager.Web/src/components/dnn-rm-create-folder/dnn-rm-create-folder.scss b/DNN Platform/Modules/ResourceManager/ResourceManager.Web/src/components/dnn-rm-create-folder/dnn-rm-create-folder.scss new file mode 100644 index 00000000000..898f5863232 --- /dev/null +++ b/DNN Platform/Modules/ResourceManager/ResourceManager.Web/src/components/dnn-rm-create-folder/dnn-rm-create-folder.scss @@ -0,0 +1,19 @@ +:host { + display: block; +} + +.form{ + label{ + font-weight: bold; + margin-top: 0.5em; + } + display: grid; + grid-template-columns: 1fr; +} + +.controls{ + margin-top: 2em; + display: flex; + justify-content: flex-end; + gap: 1em; +} \ No newline at end of file diff --git a/DNN Platform/Modules/ResourceManager/ResourceManager.Web/src/components/dnn-rm-create-folder/dnn-rm-create-folder.tsx b/DNN Platform/Modules/ResourceManager/ResourceManager.Web/src/components/dnn-rm-create-folder/dnn-rm-create-folder.tsx new file mode 100644 index 00000000000..6df3fca6c12 --- /dev/null +++ b/DNN Platform/Modules/ResourceManager/ResourceManager.Web/src/components/dnn-rm-create-folder/dnn-rm-create-folder.tsx @@ -0,0 +1,166 @@ +import { Component, Host, h, Element, State, Event, EventEmitter } from '@stencil/core'; +import { CreateNewFolderRequest, FolderMappingInfo, ItemsClient } from '../../services/ItemsClient'; +import state from '../../store/store'; + +@Component({ + tag: 'dnn-rm-create-folder', + styleUrl: 'dnn-rm-create-folder.scss', + shadow: true, +}) +export class DnnRmCreateFolder { + + /** + * Fires when there is a possibility that some folders have changed. + * Can be used to force parts of the UI to refresh. + */ + @Event() dnnRmFoldersChanged: EventEmitter; + + @Element() el : HTMLDnnRmCreateFolderElement + + @State() folderMappings: FolderMappingInfo[]; + + @State() newFolderRequest: CreateNewFolderRequest = { + FolderMappingId: -1, + FolderName: "", + ParentFolderId: state.currentItems.folder.folderId, + } + + private readonly itemsClient: ItemsClient; + private nameField: HTMLInputElement; + + constructor(){ + this.itemsClient = new ItemsClient(state.moduleId); + } + + componentWillLoad() { + this.itemsClient.getFolderMappings() + .then(data => { + this.folderMappings = data.sort((a, b) => a.FolderMappingID - b.FolderMappingID); + this.newFolderRequest = { + ...this.newFolderRequest, + FolderMappingId: this.folderMappings[0].FolderMappingID, + ParentFolderId: state.currentItems.folder.folderId, + }; + }) + .catch(reason => console.error(reason)); + } + + componentDidLoad() { + setTimeout(() => { + this.nameField.focus(); + }, 350); + } + + private handleCancel(): void { + const modal = this.el.parentElement as HTMLDnnModalElement; + modal.hide().then(() => { + setTimeout(() => { + document.body.removeChild(modal); + }, 300); + }); + } + + private handleTypeChanged(e: Event): void { + const select = e.target as HTMLSelectElement; + const option = select.options[select.selectedIndex] as HTMLOptionElement; + const newValue = Number.parseInt(option.value); + this.newFolderRequest = { + ...this.newFolderRequest, + FolderMappingId: newValue, + }; + } + + private handleSave(): void { + this.itemsClient.createNewFolder(this.newFolderRequest) + .then(() => { + this.dnnRmFoldersChanged.emit(); + state.currentItems = { + ...state.currentItems, + items: [], + }; + const modal = this.el.parentElement as HTMLDnnModalElement; + modal.hide().then(() => { + setTimeout(() => { + document.body.removeChild(modal); + }, 300); + }); + }) + .catch(error => alert(error)); + } + + private canChooseFolderProvider() { + return this.folderMappings && + this.folderMappings.find(f => f.FolderMappingID == state.currentItems.folder.folderMappingId).IsDefault; + } + + render() { + return ( + +

{state.localization.AddFolder}

+
+ {state.currentItems.folder.folderName.length > 0 &&[ + , + {state.currentItems.folder.folderName} + ]} + + this.nameField = el} + value={this.newFolderRequest.FolderName} + onInput={e => this.newFolderRequest = { + ...this.newFolderRequest, + FolderName: (e.target as HTMLInputElement).value, + }} + /> + {!this.newFolderRequest.FolderName && + {state.localization.FolderNameRequiredMessage} + } + {this.canChooseFolderProvider() && + [ + , + + ] + } + {this.canChooseFolderProvider() && this.folderMappings.find(m => m.FolderMappingID == this.newFolderRequest.FolderMappingId).IsDefault == false &&[ + , + this.newFolderRequest = { + ...this.newFolderRequest, + MappedName: (e.target as HTMLInputElement).value, + }} + /> + ]} +
+
+ this.handleCancel()} + > + {state.localization.Cancel} + + this.handleSave()} + > + {state.localization.Save} + +
+
+ ); + } +} diff --git a/DNN Platform/Modules/ResourceManager/ResourceManager.Web/src/components/dnn-rm-create-folder/readme.md b/DNN Platform/Modules/ResourceManager/ResourceManager.Web/src/components/dnn-rm-create-folder/readme.md new file mode 100644 index 00000000000..be5ce70478c --- /dev/null +++ b/DNN Platform/Modules/ResourceManager/ResourceManager.Web/src/components/dnn-rm-create-folder/readme.md @@ -0,0 +1,37 @@ +# dnn-rm-edit-folder + + + + + + +## Events + +| Event | Description | Type | +| --------------------- | ------------------------------------------------------------------------------------------------------------------ | ------------------- | +| `dnnRmFoldersChanged` | Fires when there is a possibility that some folders have changed. Can be used to force parts of the UI to refresh. | `CustomEvent` | + + +## Dependencies + +### Used by + + - [dnn-action-create-folder](../actions/dnn-action-create-folder) + +### Depends on + +- dnn-button + +### Graph +```mermaid +graph TD; + dnn-rm-create-folder --> dnn-button + dnn-button --> dnn-modal + dnn-button --> dnn-button + dnn-action-create-folder --> dnn-rm-create-folder + style dnn-rm-create-folder fill:#f9f,stroke:#333,stroke-width:4px +``` + +---------------------------------------------- + +*Built with [StencilJS](https://stenciljs.com/)* diff --git a/DNN Platform/Modules/ResourceManager/ResourceManager.Web/src/components/dnn-rm-edit-folder/dnn-rm-edit-folder.scss b/DNN Platform/Modules/ResourceManager/ResourceManager.Web/src/components/dnn-rm-edit-folder/dnn-rm-edit-folder.scss index 898f5863232..22d9a69b89e 100644 --- a/DNN Platform/Modules/ResourceManager/ResourceManager.Web/src/components/dnn-rm-edit-folder/dnn-rm-edit-folder.scss +++ b/DNN Platform/Modules/ResourceManager/ResourceManager.Web/src/components/dnn-rm-edit-folder/dnn-rm-edit-folder.scss @@ -1,14 +1,33 @@ :host { display: block; } +.general{ + display: flex; + .left{ + max-width: 256px; + border-right: 1px solid lightgray; + padding: 1em; + img{ + width: 100%; + } + } + .right{ + padding: 1em; + } +} .form{ + display: grid; + grid-template-columns: 1fr 2fr; + align-items: flex-end; label{ font-weight: bold; - margin-top: 0.5em; + text-align: right; + margin-right: 0.5em; + &::after{ + content: ':'; + } } - display: grid; - grid-template-columns: 1fr; } .controls{ @@ -16,4 +35,4 @@ display: flex; justify-content: flex-end; gap: 1em; -} \ No newline at end of file +} diff --git a/DNN Platform/Modules/ResourceManager/ResourceManager.Web/src/components/dnn-rm-edit-folder/dnn-rm-edit-folder.tsx b/DNN Platform/Modules/ResourceManager/ResourceManager.Web/src/components/dnn-rm-edit-folder/dnn-rm-edit-folder.tsx index 64f3b26c4a1..043187f1c7f 100644 --- a/DNN Platform/Modules/ResourceManager/ResourceManager.Web/src/components/dnn-rm-edit-folder/dnn-rm-edit-folder.tsx +++ b/DNN Platform/Modules/ResourceManager/ResourceManager.Web/src/components/dnn-rm-edit-folder/dnn-rm-edit-folder.tsx @@ -1,58 +1,112 @@ -import { Component, Host, h, Element, State, Event, EventEmitter } from '@stencil/core'; -import { CreateNewFolderRequest, FolderMappingInfo, ItemsClient } from '../../services/ItemsClient'; +import { IRoleGroup } from '@dnncommunity/dnn-elements/dist/types/components/dnn-permissions-grid/role-group-interface'; +import { IRole } from '@dnncommunity/dnn-elements/dist/types/components/dnn-permissions-grid/role-interface'; +import { Component, Element, Event, EventEmitter, Host, h, State, Prop } from '@stencil/core'; import state from '../../store/store'; - +import { FolderDetails, ItemsClient, SaveFolderDetailsRequest } from '../../services/ItemsClient'; +import { IPermissions, IRolePermission, IUserPermission } from '@dnncommunity/dnn-elements/dist/types/components/dnn-permissions-grid/permissions-interface'; +import { ISearchedUser } from '@dnncommunity/dnn-elements/dist/types/components/dnn-permissions-grid/searched-user-interface'; @Component({ tag: 'dnn-rm-edit-folder', styleUrl: 'dnn-rm-edit-folder.scss', shadow: true, }) export class DnnRmEditFolder { + + /** The ID of the folder to edit. */ + @Prop() folderId!: number; /** * Fires when there is a possibility that some folders have changed. * Can be used to force parts of the UI to refresh. */ - @Event() dnnRmFoldersChanged: EventEmitter; - - @Element() el : HTMLDnnRmEditFolderElement - - @State() folderMappings: FolderMappingInfo[]; - - @State() newFolderRequest: CreateNewFolderRequest = { - FolderMappingId: -1, - FolderName: "", - ParentFolderId: state.currentItems.folder.folderId, - } + @Event() dnnRmFoldersChanged: EventEmitter; + + @Element() el: HTMLDnnRmEditFolderElement; - private readonly itemsClient: ItemsClient; - private nameField: HTMLInputElement; + @State() roleGroups: IRoleGroup[] = []; + @State() roles: IRole[] = []; + @State() folderIconUrl: string; + @State() folderDetails: FolderDetails; + @State() foundUsers: ISearchedUser[]; - constructor(){ + private itemsClient: ItemsClient; + + constructor() { this.itemsClient = new ItemsClient(state.moduleId); } componentWillLoad() { - this.itemsClient.getFolderMappings() - .then(data => { - this.folderMappings = data.sort((a, b) => a.FolderMappingID - b.FolderMappingID); - this.newFolderRequest = { - ...this.newFolderRequest, - FolderMappingId: this.folderMappings[0].FolderMappingID, - ParentFolderId: state.currentItems.folder.folderId, - }; - }) - .catch(reason => console.error(reason)); - } + this.itemsClient.getFolderDetails(this.folderId) + .then(data => { + this.folderDetails = { + ...data, + permissions: { + ...data.permissions, + permissionDefinitions: data.permissions.permissionDefinitions.sort(a => { + switch (a.permissionName) { + case "View Folder": + return -1; + case "Browse Folder": + return 0; + case "Write to Folder": + return 1; + default: + break; + } + }), + rolePermissions: [ + ...data.permissions.rolePermissions.map(rp => { + return { + ...rp, + permissions: rp.permissions.sort(a => { + switch (a.permissionName) { + case "View Folder": + return -1; + case "Browse Folder": + return 0; + case "Write to Folder": + return 1; + } + }), + }; + }), + ], + userPermissions: [ + ...data.permissions.userPermissions.map(up => { + return { + ...up, + permissions: up.permissions.sort(a => { + switch (a.permissionName) { + case "View Folder": + return -1; + case "Browse Folder": + return 0; + case "Write to Folder": + return 1; + } + }), + }; + }), + ], + }, + }; + }) + .catch(error => alert(error)); + + this.itemsClient.getFolderIconUrl(this.folderId) + .then(data => this.folderIconUrl = data) + .catch(error => alert(error)); - componentDidLoad() { - setTimeout(() => { - this.nameField.focus(); - }, 350); - console.log({...state}); + this.itemsClient.getRoleGroups() + .then(data => this.roleGroups = data) + .catch(error => alert(error)); + + this.itemsClient.getRoles() + .then(data => this.roles = data) + .catch(error => alert(error)); } - private handleCancel(): void { + private closeModal(): void { const modal = this.el.parentElement as HTMLDnnModalElement; modal.hide().then(() => { setTimeout(() => { @@ -61,101 +115,218 @@ export class DnnRmEditFolder { }); } - private handleTypeChanged(e: Event): void { - const select = e.target as HTMLSelectElement; - const option = select.options[select.selectedIndex] as HTMLOptionElement; - const newValue = Number.parseInt(option.value); - this.newFolderRequest = { - ...this.newFolderRequest, - FolderMappingId: newValue, + private handleSave(): void { + const folderDetails: SaveFolderDetailsRequest = { + folderId: this.folderId, + folderName: this.folderDetails.folderName, + permissions: this.folderDetails.permissions, }; + this.itemsClient.saveFolderDetails(folderDetails) + .then(() => { + this.dnnRmFoldersChanged.emit(); + this.closeModal(); + }) + .catch(error => alert(error)); } - private handleSave(): void { - this.itemsClient.createNewFolder(this.newFolderRequest) - .then(() => { - this.dnnRmFoldersChanged.emit(); - state.currentItems = { - ...state.currentItems, - items: [], - }; - const modal = this.el.parentElement as HTMLDnnModalElement; - modal.hide().then(() => { - setTimeout(() => { - document.body.removeChild(modal); - }, 300); - }); - }) - .catch(error => alert(error)); + private handlePermissionsChanged(newPermissions: IPermissions): void { + newPermissions.rolePermissions.forEach(rolePermission => this.adjustRelatedPermissions(rolePermission)); + newPermissions.userPermissions.forEach(userPermission => this.adjustRelatedPermissions(userPermission)); + this.folderDetails = { + ...this.folderDetails, + permissions: newPermissions, + }; + } + + private adjustRelatedPermissions(permission: IRolePermission | IUserPermission): void { + const permissionId = + { + view: this.folderDetails.permissions.permissionDefinitions.find(p => p.permissionName === 'View Folder').permissionId, + browse: this.folderDetails.permissions.permissionDefinitions.find(p => p.permissionName === 'Browse Folder').permissionId, + write: this.folderDetails.permissions.permissionDefinitions.find(p => p.permissionName === 'Write to Folder').permissionId, + }; + + const viewPermission = permission.permissions.find(p => p.permissionId == permissionId.view); + // If view permission is denied, then deny all other permissions + if (viewPermission && viewPermission.allowAccess == false){ + // Deny all permissions + permission.permissions = [ + { + allowAccess: false, + fullControl: false, + permissionId: permissionId.view, + permissionCode: null, + permissionKey: null, + permissionName: "View Folder", + view: false, + }, + { + allowAccess: false, + fullControl: false, + permissionId: permissionId.browse, + permissionCode: null, + permissionKey: null, + permissionName: "Browse Folder", + view: false, + }, + { + allowAccess: false, + fullControl: false, + permissionId: permissionId.write, + permissionCode: null, + permissionKey: null, + permissionName: "Write to Folder", + view: false, + }, + ] + } + + // If browse was denied, then deny write + const browsePermission = permission.permissions.find(p => p.permissionId == permissionId.browse); + if (browsePermission && browsePermission.allowAccess == false){ + // Deny write + permission.permissions = [ + ...permission.permissions.filter(p => p.permissionId != permissionId.write), + { + allowAccess: false, + fullControl: false, + permissionId: permissionId.write, + permissionCode: null, + permissionKey: null, + permissionName: "Write to Folder", + view: false, + } + ] + } + + // If browse was allowed, then allow view + if (browsePermission && browsePermission.allowAccess == true){ + // Allow browse + permission.permissions = [ + { + allowAccess: true, + fullControl: false, + permissionId: permissionId.view, + permissionCode: null, + permissionKey: null, + permissionName: "Browse Folder", + view: false, + }, + ...permission.permissions.filter(p => p.permissionId != permissionId.view), + ]; + } + + // If write was allowed, then allow all other permissions + const writePermission = permission.permissions.find(p => p.permissionId == permissionId.write); + if (writePermission && writePermission.allowAccess == true){ + // Allow all permissions + permission.permissions = [ + { + allowAccess: true, + fullControl: false, + permissionId: permissionId.view, + permissionCode: null, + permissionKey: null, + permissionName: "View Folder", + view: false, + }, + { + allowAccess: true, + fullControl: false, + permissionId: permissionId.browse, + permissionCode: null, + permissionKey: null, + permissionName: "Browse Folder", + view: false, + }, + { + allowAccess: true, + fullControl: false, + permissionId: permissionId.write, + permissionCode: null, + permissionKey: null, + permissionName: "Write to Folder", + view: false, + }, + ] + } } - private canChooseFolderProvider() { - return this.folderMappings && - this.folderMappings.find(f => f.FolderMappingID == state.currentItems.folder.folderMappingId).IsDefault; + private handleUserSearchQueryChanged(detail: string): void { + this.itemsClient.searchUsers(detail) + .then(data => this.foundUsers = data) + .catch(error => alert(error)); } render() { return ( -

{state.localization.AddFolder}

-
- {state.currentItems.folder.folderName.length > 0 &&[ - , - {state.currentItems.folder.folderName} - ]} - - this.nameField = el} - value={this.newFolderRequest.FolderName} - onInput={e => this.newFolderRequest = { - ...this.newFolderRequest, - FolderName: (e.target as HTMLInputElement).value, - }} - /> - {!this.newFolderRequest.FolderName && - {state.localization.FolderNameRequiredMessage} - } - {this.canChooseFolderProvider() && - [ - , - - ] - } - {this.canChooseFolderProvider() && this.folderMappings.find(m => m.FolderMappingID == this.newFolderRequest.FolderMappingId).IsDefault == false &&[ - , - this.newFolderRequest = { - ...this.newFolderRequest, - MappedName: (e.target as HTMLInputElement).value, - }} - /> - ]} -
+

{state.localization?.Edit}

+ + +
+
+ {this.folderIconUrl && + + } + {this.folderDetails && +
+ + {this.folderDetails.folderId} + + + {this.folderDetails.createdBy} + + + {this.folderDetails.createdOnDate} + + + {this.folderDetails.lastModifiedBy} + + + {this.folderDetails.lastModifiedOnDate} +
+ } +
+
+
+ + + this.folderDetails = { + ...this.folderDetails, + folderName: (e.target as HTMLInputElement).value, + } + } + /> +
+
+
+
+ + {this.folderDetails && this.folderDetails.permissions && this.roleGroups && this.roles && + this.handlePermissionsChanged(e.detail)} + onUserSearchQueryChanged={e => this.handleUserSearchQueryChanged(e.detail)} + /> + } + +
this.handleCancel()} + onClick={() => this.closeModal()} > {state.localization.Cancel} this.handleSave()} > {state.localization.Save} diff --git a/DNN Platform/Modules/ResourceManager/ResourceManager.Web/src/components/dnn-rm-edit-folder/readme.md b/DNN Platform/Modules/ResourceManager/ResourceManager.Web/src/components/dnn-rm-edit-folder/readme.md index d34fa1b4186..53e91756e31 100644 --- a/DNN Platform/Modules/ResourceManager/ResourceManager.Web/src/components/dnn-rm-edit-folder/readme.md +++ b/DNN Platform/Modules/ResourceManager/ResourceManager.Web/src/components/dnn-rm-edit-folder/readme.md @@ -5,6 +5,13 @@ +## Properties + +| Property | Attribute | Description | Type | Default | +| ----------------------- | ----------- | ----------------------------- | -------- | ----------- | +| `folderId` _(required)_ | `folder-id` | The ID of the folder to edit. | `number` | `undefined` | + + ## Events | Event | Description | Type | @@ -16,19 +23,29 @@ ### Used by - - [dnn-action-create-folder](../actions/dnn-action-create-folder) + - [dnn-action-edit-item](../actions/dnn-action-edit-item) ### Depends on +- dnn-tabs +- dnn-tab +- dnn-permissions-grid - dnn-button ### Graph ```mermaid graph TD; + dnn-rm-edit-folder --> dnn-tabs + dnn-rm-edit-folder --> dnn-tab + dnn-rm-edit-folder --> dnn-permissions-grid dnn-rm-edit-folder --> dnn-button + dnn-permissions-grid --> dnn-checkbox + dnn-permissions-grid --> dnn-button + dnn-permissions-grid --> dnn-searchbox + dnn-permissions-grid --> dnn-collapsible dnn-button --> dnn-modal dnn-button --> dnn-button - dnn-action-create-folder --> dnn-rm-edit-folder + dnn-action-edit-item --> dnn-rm-edit-folder style dnn-rm-edit-folder fill:#f9f,stroke:#333,stroke-width:4px ``` diff --git a/DNN Platform/Modules/ResourceManager/ResourceManager.Web/src/components/dnn-rm-files-pane/dnn-rm-files-pane.tsx b/DNN Platform/Modules/ResourceManager/ResourceManager.Web/src/components/dnn-rm-files-pane/dnn-rm-files-pane.tsx index 148a9a8bd91..e7d671c89a7 100644 --- a/DNN Platform/Modules/ResourceManager/ResourceManager.Web/src/components/dnn-rm-files-pane/dnn-rm-files-pane.tsx +++ b/DNN Platform/Modules/ResourceManager/ResourceManager.Web/src/components/dnn-rm-files-pane/dnn-rm-files-pane.tsx @@ -27,6 +27,12 @@ export class DnnRmFilesPane { this.checkIfMoreItemsNeeded(); } + @Listen("dnnRmFoldersChanged", {target: "document"}) + handleFoldersChanged(){ + state.currentItems.items = []; + this.checkIfMoreItemsNeeded(); + } + componentDidUpdate() { const loadedFilesHeight = this.loadedFilesArea.getBoundingClientRect().height; const heightPerItem = loadedFilesHeight / state.currentItems.items.length; diff --git a/DNN Platform/Modules/ResourceManager/ResourceManager.Web/src/components/dnn-rm-files-pane/readme.md b/DNN Platform/Modules/ResourceManager/ResourceManager.Web/src/components/dnn-rm-files-pane/readme.md index 700f908cd1a..23130d24d9e 100644 --- a/DNN Platform/Modules/ResourceManager/ResourceManager.Web/src/components/dnn-rm-files-pane/readme.md +++ b/DNN Platform/Modules/ResourceManager/ResourceManager.Web/src/components/dnn-rm-files-pane/readme.md @@ -31,11 +31,22 @@ graph TD; dnn-rm-items-listview --> dnn-collapsible dnn-rm-items-listview --> dnn-rm-folder-context-menu dnn-rm-folder-context-menu --> dnn-action-create-folder + dnn-rm-folder-context-menu --> dnn-action-edit-item dnn-action-create-folder --> dnn-modal - dnn-action-create-folder --> dnn-rm-edit-folder - dnn-rm-edit-folder --> dnn-button + dnn-action-create-folder --> dnn-rm-create-folder + dnn-rm-create-folder --> dnn-button dnn-button --> dnn-modal dnn-button --> dnn-button + dnn-action-edit-item --> dnn-modal + dnn-action-edit-item --> dnn-rm-edit-folder + dnn-rm-edit-folder --> dnn-tabs + dnn-rm-edit-folder --> dnn-tab + dnn-rm-edit-folder --> dnn-permissions-grid + dnn-rm-edit-folder --> dnn-button + dnn-permissions-grid --> dnn-checkbox + dnn-permissions-grid --> dnn-button + dnn-permissions-grid --> dnn-searchbox + dnn-permissions-grid --> dnn-collapsible dnn-rm-items-cardview --> dnn-collapsible dnn-rm-items-cardview --> dnn-rm-folder-context-menu dnn-rm-right-pane --> dnn-rm-files-pane diff --git a/DNN Platform/Modules/ResourceManager/ResourceManager.Web/src/components/dnn-rm-folder-list-item/dnn-rm-folder-list-item.tsx b/DNN Platform/Modules/ResourceManager/ResourceManager.Web/src/components/dnn-rm-folder-list-item/dnn-rm-folder-list-item.tsx index 9d27ecc51ed..57f93e4c647 100644 --- a/DNN Platform/Modules/ResourceManager/ResourceManager.Web/src/components/dnn-rm-folder-list-item/dnn-rm-folder-list-item.tsx +++ b/DNN Platform/Modules/ResourceManager/ResourceManager.Web/src/components/dnn-rm-folder-list-item/dnn-rm-folder-list-item.tsx @@ -15,6 +15,9 @@ export class DnnRmFolderListItem { /** If true, this node will be expanded on load. */ @Prop({mutable: true}) expanded = false; + + /** The ID of the parent folder. */ + @Prop() parentFolderId!: number; /** Fires when a context menu is opened for this item. Emits the folder ID. */ @Event() dnnRmcontextMenuOpened: EventEmitter; @@ -26,22 +29,12 @@ export class DnnRmFolderListItem { } } - private dismissContextMenu() { - if (this.contextMenu && this.contextMenu.expanded){ - this.contextMenu.expanded = false; - requestAnimationFrame(() => { - this.contextMenu.style.display = "none"; - }); - } - } - @State() folderIconUrl: string; @Element() el!: HTMLDnnRmFolderListItemElement; private itemsClient: ItemsClient; private internalServicesClient: InternalServicesClient; - private contextMenu: HTMLDnnCollapsibleElement; constructor(){ this.itemsClient = new ItemsClient(state.moduleId); @@ -96,11 +89,27 @@ export class DnnRmFolderListItem { private handleContextMenu(e: MouseEvent): void { e.preventDefault(); - this.contextMenu.style.display = "block"; - this.contextMenu.style.left = `${e.pageX}px`; - this.contextMenu.style.top = `${e.pageY}px`; - this.contextMenu.expanded = true; - this.dnnRmcontextMenuOpened.emit(Number.parseInt(this.folder.data.key)); + this.itemsClient.getFolderItem(Number.parseInt(this.folder.data.key)) + .then(item => { + const collapsible = document.createElement("dnn-collapsible"); + const folderContextMenu = document.createElement("dnn-rm-folder-context-menu"); + collapsible.appendChild(folderContextMenu); + folderContextMenu.item = item; + collapsible.style.left = `${e.pageX}px`; + collapsible.style.top = `${e.pageY}px`; + collapsible.style.display = "block"; + this.el.shadowRoot.appendChild(collapsible); + setTimeout(() => { + collapsible.expanded = true; + }, 100); + this.dnnRmcontextMenuOpened.emit(Number.parseInt(this.folder.data.key)); + }) + .catch(reason => console.error(reason)); + } + + private dismissContextMenu() { + const existingMenus = this.el.shadowRoot.querySelectorAll(".contextMenu"); + existingMenus?.forEach(contextMenu => this.el.shadowRoot.removeChild(contextMenu)); } render() { @@ -131,13 +140,14 @@ export class DnnRmFolderListItem {
, this.folder.children && this.folder.children.length > 0 && this.folder.children.map(child => - + + ) ]} - this.contextMenu = el}> - -
); } diff --git a/DNN Platform/Modules/ResourceManager/ResourceManager.Web/src/components/dnn-rm-folder-list-item/readme.md b/DNN Platform/Modules/ResourceManager/ResourceManager.Web/src/components/dnn-rm-folder-list-item/readme.md index 15af50e763d..89ef76e4c8d 100644 --- a/DNN Platform/Modules/ResourceManager/ResourceManager.Web/src/components/dnn-rm-folder-list-item/readme.md +++ b/DNN Platform/Modules/ResourceManager/ResourceManager.Web/src/components/dnn-rm-folder-list-item/readme.md @@ -7,10 +7,11 @@ ## Properties -| Property | Attribute | Description | Type | Default | -| --------------------- | ---------- | -------------------------------------------- | ---------------- | ----------- | -| `expanded` | `expanded` | If true, this node will be expanded on load. | `boolean` | `false` | -| `folder` _(required)_ | -- | The basic information about the folder | `FolderTreeItem` | `undefined` | +| Property | Attribute | Description | Type | Default | +| ----------------------------- | ------------------ | -------------------------------------------- | ---------------- | ----------- | +| `expanded` | `expanded` | If true, this node will be expanded on load. | `boolean` | `false` | +| `folder` _(required)_ | -- | The basic information about the folder | `FolderTreeItem` | `undefined` | +| `parentFolderId` _(required)_ | `parent-folder-id` | The ID of the parent folder. | `number` | `undefined` | ## Events @@ -29,22 +30,33 @@ ### Depends on -- dnn-treeview-item -- [dnn-rm-folder-list-item](.) - dnn-collapsible - [dnn-rm-folder-context-menu](../context-menus/dnn-rm-folder-context-menu) +- dnn-treeview-item +- [dnn-rm-folder-list-item](.) ### Graph ```mermaid graph TD; dnn-rm-folder-list-item --> dnn-rm-folder-list-item - dnn-treeview-item --> dnn-collapsible dnn-rm-folder-context-menu --> dnn-action-create-folder + dnn-rm-folder-context-menu --> dnn-action-edit-item dnn-action-create-folder --> dnn-modal - dnn-action-create-folder --> dnn-rm-edit-folder - dnn-rm-edit-folder --> dnn-button + dnn-action-create-folder --> dnn-rm-create-folder + dnn-rm-create-folder --> dnn-button dnn-button --> dnn-modal dnn-button --> dnn-button + dnn-action-edit-item --> dnn-modal + dnn-action-edit-item --> dnn-rm-edit-folder + dnn-rm-edit-folder --> dnn-tabs + dnn-rm-edit-folder --> dnn-tab + dnn-rm-edit-folder --> dnn-permissions-grid + dnn-rm-edit-folder --> dnn-button + dnn-permissions-grid --> dnn-checkbox + dnn-permissions-grid --> dnn-button + dnn-permissions-grid --> dnn-searchbox + dnn-permissions-grid --> dnn-collapsible + dnn-treeview-item --> dnn-collapsible dnn-rm-folder-list --> dnn-rm-folder-list-item style dnn-rm-folder-list-item fill:#f9f,stroke:#333,stroke-width:4px ``` diff --git a/DNN Platform/Modules/ResourceManager/ResourceManager.Web/src/components/dnn-rm-folder-list/dnn-rm-folder-list.tsx b/DNN Platform/Modules/ResourceManager/ResourceManager.Web/src/components/dnn-rm-folder-list/dnn-rm-folder-list.tsx index fc6520ea678..f023bfd47f6 100644 --- a/DNN Platform/Modules/ResourceManager/ResourceManager.Web/src/components/dnn-rm-folder-list/dnn-rm-folder-list.tsx +++ b/DNN Platform/Modules/ResourceManager/ResourceManager.Web/src/components/dnn-rm-folder-list/dnn-rm-folder-list.tsx @@ -57,6 +57,7 @@ export class DnnRmFolderList { {state.rootFolders && state.rootFolders.Tree.children.map(item => diff --git a/DNN Platform/Modules/ResourceManager/ResourceManager.Web/src/components/dnn-rm-folder-list/readme.md b/DNN Platform/Modules/ResourceManager/ResourceManager.Web/src/components/dnn-rm-folder-list/readme.md index affba828b43..0679bdf88ea 100644 --- a/DNN Platform/Modules/ResourceManager/ResourceManager.Web/src/components/dnn-rm-folder-list/readme.md +++ b/DNN Platform/Modules/ResourceManager/ResourceManager.Web/src/components/dnn-rm-folder-list/readme.md @@ -19,17 +19,28 @@ ```mermaid graph TD; dnn-rm-folder-list --> dnn-rm-folder-list-item - dnn-rm-folder-list-item --> dnn-treeview-item - dnn-rm-folder-list-item --> dnn-rm-folder-list-item dnn-rm-folder-list-item --> dnn-collapsible dnn-rm-folder-list-item --> dnn-rm-folder-context-menu - dnn-treeview-item --> dnn-collapsible + dnn-rm-folder-list-item --> dnn-treeview-item + dnn-rm-folder-list-item --> dnn-rm-folder-list-item dnn-rm-folder-context-menu --> dnn-action-create-folder + dnn-rm-folder-context-menu --> dnn-action-edit-item dnn-action-create-folder --> dnn-modal - dnn-action-create-folder --> dnn-rm-edit-folder - dnn-rm-edit-folder --> dnn-button + dnn-action-create-folder --> dnn-rm-create-folder + dnn-rm-create-folder --> dnn-button dnn-button --> dnn-modal dnn-button --> dnn-button + dnn-action-edit-item --> dnn-modal + dnn-action-edit-item --> dnn-rm-edit-folder + dnn-rm-edit-folder --> dnn-tabs + dnn-rm-edit-folder --> dnn-tab + dnn-rm-edit-folder --> dnn-permissions-grid + dnn-rm-edit-folder --> dnn-button + dnn-permissions-grid --> dnn-checkbox + dnn-permissions-grid --> dnn-button + dnn-permissions-grid --> dnn-searchbox + dnn-permissions-grid --> dnn-collapsible + dnn-treeview-item --> dnn-collapsible dnn-rm-left-pane --> dnn-rm-folder-list style dnn-rm-folder-list fill:#f9f,stroke:#333,stroke-width:4px ``` diff --git a/DNN Platform/Modules/ResourceManager/ResourceManager.Web/src/components/dnn-rm-items-cardview/dnn-rm-items-cardview.tsx b/DNN Platform/Modules/ResourceManager/ResourceManager.Web/src/components/dnn-rm-items-cardview/dnn-rm-items-cardview.tsx index 1bed17459fd..a80e0153018 100644 --- a/DNN Platform/Modules/ResourceManager/ResourceManager.Web/src/components/dnn-rm-items-cardview/dnn-rm-items-cardview.tsx +++ b/DNN Platform/Modules/ResourceManager/ResourceManager.Web/src/components/dnn-rm-items-cardview/dnn-rm-items-cardview.tsx @@ -36,7 +36,7 @@ export class DnnRmItemsCardview { const collapsible = document.createElement("dnn-collapsible"); const folderContextMenu = document.createElement("dnn-rm-folder-context-menu"); collapsible.appendChild(folderContextMenu); - folderContextMenu.clickedFolderId = item.itemId; + folderContextMenu.item = item; collapsible.style.left = `${e.pageX}px`; collapsible.style.top = `${e.pageY}px`; collapsible.style.display = "block"; diff --git a/DNN Platform/Modules/ResourceManager/ResourceManager.Web/src/components/dnn-rm-items-cardview/readme.md b/DNN Platform/Modules/ResourceManager/ResourceManager.Web/src/components/dnn-rm-items-cardview/readme.md index b3085d8c942..6b0f2ccd9a5 100644 --- a/DNN Platform/Modules/ResourceManager/ResourceManager.Web/src/components/dnn-rm-items-cardview/readme.md +++ b/DNN Platform/Modules/ResourceManager/ResourceManager.Web/src/components/dnn-rm-items-cardview/readme.md @@ -29,11 +29,22 @@ graph TD; dnn-rm-items-cardview --> dnn-collapsible dnn-rm-items-cardview --> dnn-rm-folder-context-menu dnn-rm-folder-context-menu --> dnn-action-create-folder + dnn-rm-folder-context-menu --> dnn-action-edit-item dnn-action-create-folder --> dnn-modal - dnn-action-create-folder --> dnn-rm-edit-folder - dnn-rm-edit-folder --> dnn-button + dnn-action-create-folder --> dnn-rm-create-folder + dnn-rm-create-folder --> dnn-button dnn-button --> dnn-modal dnn-button --> dnn-button + dnn-action-edit-item --> dnn-modal + dnn-action-edit-item --> dnn-rm-edit-folder + dnn-rm-edit-folder --> dnn-tabs + dnn-rm-edit-folder --> dnn-tab + dnn-rm-edit-folder --> dnn-permissions-grid + dnn-rm-edit-folder --> dnn-button + dnn-permissions-grid --> dnn-checkbox + dnn-permissions-grid --> dnn-button + dnn-permissions-grid --> dnn-searchbox + dnn-permissions-grid --> dnn-collapsible dnn-rm-files-pane --> dnn-rm-items-cardview style dnn-rm-items-cardview fill:#f9f,stroke:#333,stroke-width:4px ``` diff --git a/DNN Platform/Modules/ResourceManager/ResourceManager.Web/src/components/dnn-rm-items-listview/dnn-rm-items-listview.tsx b/DNN Platform/Modules/ResourceManager/ResourceManager.Web/src/components/dnn-rm-items-listview/dnn-rm-items-listview.tsx index 99a5a805c59..301e7ccb026 100644 --- a/DNN Platform/Modules/ResourceManager/ResourceManager.Web/src/components/dnn-rm-items-listview/dnn-rm-items-listview.tsx +++ b/DNN Platform/Modules/ResourceManager/ResourceManager.Web/src/components/dnn-rm-items-listview/dnn-rm-items-listview.tsx @@ -80,7 +80,7 @@ export class DnnRmItemsListview { if (item.isFolder){ const collapsible = document.createElement("dnn-collapsible"); const folderContextMenu = document.createElement("dnn-rm-folder-context-menu"); - folderContextMenu.clickedFolderId = item.itemId; + folderContextMenu.item = item; collapsible.appendChild(folderContextMenu); collapsible.style.left = `${e.pageX}px`; collapsible.style.top = `${e.pageY}px`; diff --git a/DNN Platform/Modules/ResourceManager/ResourceManager.Web/src/components/dnn-rm-items-listview/readme.md b/DNN Platform/Modules/ResourceManager/ResourceManager.Web/src/components/dnn-rm-items-listview/readme.md index 54ca9a797f7..d3d18becb62 100644 --- a/DNN Platform/Modules/ResourceManager/ResourceManager.Web/src/components/dnn-rm-items-listview/readme.md +++ b/DNN Platform/Modules/ResourceManager/ResourceManager.Web/src/components/dnn-rm-items-listview/readme.md @@ -29,11 +29,22 @@ graph TD; dnn-rm-items-listview --> dnn-collapsible dnn-rm-items-listview --> dnn-rm-folder-context-menu dnn-rm-folder-context-menu --> dnn-action-create-folder + dnn-rm-folder-context-menu --> dnn-action-edit-item dnn-action-create-folder --> dnn-modal - dnn-action-create-folder --> dnn-rm-edit-folder - dnn-rm-edit-folder --> dnn-button + dnn-action-create-folder --> dnn-rm-create-folder + dnn-rm-create-folder --> dnn-button dnn-button --> dnn-modal dnn-button --> dnn-button + dnn-action-edit-item --> dnn-modal + dnn-action-edit-item --> dnn-rm-edit-folder + dnn-rm-edit-folder --> dnn-tabs + dnn-rm-edit-folder --> dnn-tab + dnn-rm-edit-folder --> dnn-permissions-grid + dnn-rm-edit-folder --> dnn-button + dnn-permissions-grid --> dnn-checkbox + dnn-permissions-grid --> dnn-button + dnn-permissions-grid --> dnn-searchbox + dnn-permissions-grid --> dnn-collapsible dnn-rm-files-pane --> dnn-rm-items-listview style dnn-rm-items-listview fill:#f9f,stroke:#333,stroke-width:4px ``` diff --git a/DNN Platform/Modules/ResourceManager/ResourceManager.Web/src/components/dnn-rm-left-pane/readme.md b/DNN Platform/Modules/ResourceManager/ResourceManager.Web/src/components/dnn-rm-left-pane/readme.md index 2ad5e6b62f5..a510e505c12 100644 --- a/DNN Platform/Modules/ResourceManager/ResourceManager.Web/src/components/dnn-rm-left-pane/readme.md +++ b/DNN Platform/Modules/ResourceManager/ResourceManager.Web/src/components/dnn-rm-left-pane/readme.md @@ -20,17 +20,28 @@ graph TD; dnn-rm-left-pane --> dnn-rm-folder-list dnn-rm-folder-list --> dnn-rm-folder-list-item - dnn-rm-folder-list-item --> dnn-treeview-item - dnn-rm-folder-list-item --> dnn-rm-folder-list-item dnn-rm-folder-list-item --> dnn-collapsible dnn-rm-folder-list-item --> dnn-rm-folder-context-menu - dnn-treeview-item --> dnn-collapsible + dnn-rm-folder-list-item --> dnn-treeview-item + dnn-rm-folder-list-item --> dnn-rm-folder-list-item dnn-rm-folder-context-menu --> dnn-action-create-folder + dnn-rm-folder-context-menu --> dnn-action-edit-item dnn-action-create-folder --> dnn-modal - dnn-action-create-folder --> dnn-rm-edit-folder - dnn-rm-edit-folder --> dnn-button + dnn-action-create-folder --> dnn-rm-create-folder + dnn-rm-create-folder --> dnn-button dnn-button --> dnn-modal dnn-button --> dnn-button + dnn-action-edit-item --> dnn-modal + dnn-action-edit-item --> dnn-rm-edit-folder + dnn-rm-edit-folder --> dnn-tabs + dnn-rm-edit-folder --> dnn-tab + dnn-rm-edit-folder --> dnn-permissions-grid + dnn-rm-edit-folder --> dnn-button + dnn-permissions-grid --> dnn-checkbox + dnn-permissions-grid --> dnn-button + dnn-permissions-grid --> dnn-searchbox + dnn-permissions-grid --> dnn-collapsible + dnn-treeview-item --> dnn-collapsible dnn-resource-manager --> dnn-rm-left-pane style dnn-rm-left-pane fill:#f9f,stroke:#333,stroke-width:4px ``` diff --git a/DNN Platform/Modules/ResourceManager/ResourceManager.Web/src/components/dnn-rm-right-pane/readme.md b/DNN Platform/Modules/ResourceManager/ResourceManager.Web/src/components/dnn-rm-right-pane/readme.md index fdfc430a43f..cc0ac3bc187 100644 --- a/DNN Platform/Modules/ResourceManager/ResourceManager.Web/src/components/dnn-rm-right-pane/readme.md +++ b/DNN Platform/Modules/ResourceManager/ResourceManager.Web/src/components/dnn-rm-right-pane/readme.md @@ -25,17 +25,29 @@ graph TD; dnn-rm-right-pane --> dnn-rm-status-bar dnn-rm-actions-bar --> dnn-vertical-overflow-menu dnn-rm-actions-bar --> dnn-action-create-folder + dnn-rm-actions-bar --> dnn-action-edit-item dnn-rm-actions-bar --> dnn-collapsible dnn-action-create-folder --> dnn-modal - dnn-action-create-folder --> dnn-rm-edit-folder - dnn-rm-edit-folder --> dnn-button + dnn-action-create-folder --> dnn-rm-create-folder + dnn-rm-create-folder --> dnn-button dnn-button --> dnn-modal dnn-button --> dnn-button + dnn-action-edit-item --> dnn-modal + dnn-action-edit-item --> dnn-rm-edit-folder + dnn-rm-edit-folder --> dnn-tabs + dnn-rm-edit-folder --> dnn-tab + dnn-rm-edit-folder --> dnn-permissions-grid + dnn-rm-edit-folder --> dnn-button + dnn-permissions-grid --> dnn-checkbox + dnn-permissions-grid --> dnn-button + dnn-permissions-grid --> dnn-searchbox + dnn-permissions-grid --> dnn-collapsible dnn-rm-files-pane --> dnn-rm-items-listview dnn-rm-files-pane --> dnn-rm-items-cardview dnn-rm-items-listview --> dnn-collapsible dnn-rm-items-listview --> dnn-rm-folder-context-menu dnn-rm-folder-context-menu --> dnn-action-create-folder + dnn-rm-folder-context-menu --> dnn-action-edit-item dnn-rm-items-cardview --> dnn-collapsible dnn-rm-items-cardview --> dnn-rm-folder-context-menu dnn-resource-manager --> dnn-rm-right-pane diff --git a/DNN Platform/Modules/ResourceManager/ResourceManager.Web/src/services/ItemsClient.ts b/DNN Platform/Modules/ResourceManager/ResourceManager.Web/src/services/ItemsClient.ts index 719127f837a..82c671f073b 100644 --- a/DNN Platform/Modules/ResourceManager/ResourceManager.Web/src/services/ItemsClient.ts +++ b/DNN Platform/Modules/ResourceManager/ResourceManager.Web/src/services/ItemsClient.ts @@ -1,4 +1,8 @@ import { DnnServicesFramework } from "@dnncommunity/dnn-elements"; +import { IPermissions } from "@dnncommunity/dnn-elements/dist/types/components/dnn-permissions-grid/permissions-interface"; +import { IRoleGroup } from "@dnncommunity/dnn-elements/dist/types/components/dnn-permissions-grid/role-group-interface"; +import { IRole } from "@dnncommunity/dnn-elements/dist/types/components/dnn-permissions-grid/role-interface"; +import { ISearchedUser } from "@dnncommunity/dnn-elements/dist/types/components/dnn-permissions-grid/searched-user-interface"; import { SortFieldInfo } from "../enums/SortField"; export class ItemsClient{ @@ -118,7 +122,7 @@ export class ItemsClient{ }); } - public createNewFolder(request: CreateNewFolderRequest, groupId = 1){ + public createNewFolder(request: CreateNewFolderRequest, groupId = 0){ return new Promise((resolve, reject) => { const url = `${this.requestUrl}CreateNewFolder`; const headers = this.sf.getModuleHeaders(); @@ -141,6 +145,120 @@ export class ItemsClient{ }); } + + public getFolderItem(folderId: number, groupId = 0){ + return new Promise((resolve, reject) => { + const url = `${this.requestUrl}GetFolderItem?folderId=${folderId}`; + const headers = this.sf.getModuleHeaders(); + headers.append("groupId", groupId.toString()); + fetch(url, { + headers, + }) + .then(response => { + if (response.status == 200){ + response.json().then(data => resolve(data)); + } + else{ + response.json().then(error => reject(error.ExceptionMessage || error.message)); + } + }) + .catch(reason => reject(reason)); + }); + } + + public getFolderDetails(folderId: number){ + return new Promise((resolve, reject) => { + const url = `${this.requestUrl}GetFolderDetails?folderId=${folderId}`; + fetch(url, { + headers: this.sf.getModuleHeaders(), + }) + .then(response => { + if (response.status == 200){ + response.json().then(data => resolve(data)); + } + else{ + response.json().then(error => reject(error.ExceptionMessage || error.message)); + } + }) + .catch(reason => reject(reason)); + }); + } + + public getRoleGroups(){ + return new Promise((resolve, reject) => { + const url = `${this.requestUrl}GetRoleGroups`; + fetch(url, { + headers: this.sf.getModuleHeaders(), + }) + .then(response => { + if (response.status == 200){ + response.json().then(data => resolve(data)); + } + else{ + response.json().then(error => reject(error.ExceptionMessage || error.message)); + } + }) + .catch(reason => reject(reason)); + }); + } + + public getRoles(){ + return new Promise((resolve, reject) => { + const url = `${this.requestUrl}GetRoles`; + fetch(url, { + headers: this.sf.getModuleHeaders(), + }) + .then(response => { + if (response.status == 200){ + response.json().then(data => resolve(data)); + } + else{ + response.json().then(error => reject(error.ExceptionMessage || error.message)); + } + }) + .catch(reason => reject(reason)); + }); + } + + public searchUsers(query: string) { + return new Promise((resolve, reject) => { + const url = `${this.requestUrl}GetSuggestionUsers?keyword=${query}&count=50`; + fetch(url, { + headers: this.sf.getModuleHeaders(), + }) + .then(response => { + if (response.status == 200){ + response.json().then(data => resolve(data)); + } + else{ + response.json().then(error => reject(error.ExceptionMessage || error.message)); + } + }) + .catch(reason => reject(reason)); + }); + } + + public saveFolderDetails(request: SaveFolderDetailsRequest){ + return new Promise((resolve, reject) => { + const url = `${this.requestUrl}SaveFolderDetails`; + const headers = this.sf.getModuleHeaders(); + headers.append("Content-Type", "application/json"); + fetch(url, { + method: "POST", + body: JSON.stringify(request), + headers, + }) + .then(response => { + if (response.status == 200){ + resolve(); + } + else{ + response.json().then(error => reject(error.ExceptionMessage || error.message)); + } + }) + .catch(reason => reject(reason)); + }); + } } export interface GetFolderContentResponse{ @@ -228,4 +346,22 @@ export interface CreateNewFolderResponse{ /** The ID of the folder mapping. */ FolderMappingID: number, +} + +export interface FolderDetails{ + folderId: number; + folderName: string; + createdOnDate: string; + createdBy: string; + lastModifiedOnDate: string; + lastModifiedBy: string; + type: string; + isVersioned: boolean; + permissions: IPermissions; +} + +export interface SaveFolderDetailsRequest{ + folderId: number; + folderName: string; + permissions: IPermissions; } \ No newline at end of file diff --git a/DNN Platform/Modules/ResourceManager/ResourceManager.Web/src/services/LocalizationClient.ts b/DNN Platform/Modules/ResourceManager/ResourceManager.Web/src/services/LocalizationClient.ts index e30b0fe894b..cdc013a57c2 100644 --- a/DNN Platform/Modules/ResourceManager/ResourceManager.Web/src/services/LocalizationClient.ts +++ b/DNN Platform/Modules/ResourceManager/ResourceManager.Web/src/services/LocalizationClient.ts @@ -43,80 +43,84 @@ export class LocalizationClient{ } } -export interface LocalizedStrings { - AddAsset: String; - AddFolder: String; - AssetsPanelEmpty_Subtitle: String; - AssetsPanelEmpty_Title: String; - Cancel: String; - Close: String; - Database: String; - DeleteFileDialogHeader: String; - DeleteFileDialogMessage: String; - DeleteFolderDialogHeader: String; - DeleteFolderDialogMessage: String; - FileAlreadyExistsMessage: String; - FileUploadedMessage: String; - FileUploadStoppedMessage: String; - FolderNamePlaceholder: String; - FolderNameRequiredMessage: String; - FolderParent: String; - FolderTypeRequiredMessage: String; - Name: String; - Save: String; - Secure: String; - Standard: String; - Type: String; - "UserHasNoPermissionToDeleteFolder.Error": String; - "UserHasNoPermissionToDownloadError": String; - FileUploadPanelMessage: String; - AssetsPanelNoSearchResults: String; - SearchInputPlaceholder: String; - Search: String; - UrlCopiedMessage: String; - Created: String; - Description: String; - LastModified: String; - Size: String; - Title: String; - URL: String; - ItemNameRequiredMessage: String; - "UserHasNoPermissionToReadFileProperties.Error": String; - GenericErrorMessage: String; - Items: String; - ItemSavedMessage: String; - FolderType: String; - CreatedOnDate: String; - ItemName: String; - LastModifiedOnDate: String; - FileSizeErrorMessage: String; - "UserHasNoPermissionToDeleteFile.Error": String; - "UserHasNoPermissionToManageFileProperties.Error": String; - "UserHasNoPermissionToManageFolder.Error": String; - NoFolderSelected: String; - SearchFolder: String; - DisabledForAnonymousUsersMessage: String; - "UserHasNoPermissionToAddFolders.Error": String; - "GroupIconCantBeDeleted.Error": String; - InvalidExtensionMessage: String; - Refresh: String; - SyncThisFolder: String; - SyncThisFolderAndSubfolders: String; - ManageFolderTypes: String; - AddFolderType: String; - FolderProvider: String; - FolderTypeDefinitions: String; - EditFolderType: String; - RemoveFolderType: String; - RemoveFolderTypeDialogBody: String; - RemoveFolderTypeDialogHeader: String; - MappedPath: String; - MoveItem: String; - NewLocation: String; - SortField_ItemName: String; - SortField_LastModifiedOnDate: String; - SortField_Size: String; - SortField_ParentFolder: String; - SortField_CreatedOnDate: String; - Sort: String; +export interface LocalizedStrings { + AddAsset: string; + AddFolder: string; + AssetsPanelEmpty_Subtitle: string; + AssetsPanelEmpty_Title: string; + Cancel: string; + Close: string; + Database: string; + DeleteFileDialogHeader: string; + DeleteFileDialogMessage: string; + DeleteFolderDialogHeader: string; + DeleteFolderDialogMessage: string; + Edit: string; + FileAlreadyExistsMessage: string; + FileUploadedMessage: string; + FileUploadStoppedMessage: string; + FolderNamePlaceholder: string; + FolderNameRequiredMessage: string; + FolderId: string; + FolderParent: string; + FolderTypeRequiredMessage: string; + General: string; + Name: string; + Permissions: string; + Save: string; + Secure: string; + Standard: string; + Type: string; + "UserHasNoPermissionToDeleteFolder.Error": string; + "UserHasNoPermissionToDownloadError": string; + FileUploadPanelMessage: string; + AssetsPanelNoSearchResults: string; + SearchInputPlaceholder: string; + Search: string; + UrlCopiedMessage: string; + Created: string; + Description: string; + LastModified: string; + Size: string; + Title: string; + URL: string; + ItemNameRequiredMessage: string; + "UserHasNoPermissionToReadFileProperties.Error": string; + GenericErrorMessage: string; + Items: string; + ItemSavedMessage: string; + FolderType: string; + CreatedOnDate: string; + ItemName: string; + LastModifiedOnDate: string; + FileSizeErrorMessage: string; + "UserHasNoPermissionToDeleteFile.Error": string; + "UserHasNoPermissionToManageFileProperties.Error": string; + "UserHasNoPermissionToManageFolder.Error": string; + NoFolderSelected: string; + SearchFolder: string; + DisabledForAnonymousUsersMessage: string; + "UserHasNoPermissionToAddFolders.Error": string; + "GroupIconCantBeDeleted.Error": string; + InvalidExtensionMessage: string; + Refresh: string; + SyncThisFolder: string; + SyncThisFolderAndSubfolders: string; + ManageFolderTypes: string; + AddFolderType: string; + FolderProvider: string; + FolderTypeDefinitions: string; + EditFolderType: string; + RemoveFolderType: string; + RemoveFolderTypeDialogBody: string; + RemoveFolderTypeDialogHeader: string; + MappedPath: string; + MoveItem: string; + NewLocation: string; + SortField_ItemName: string; + SortField_LastModifiedOnDate: string; + SortField_Size: string; + SortField_ParentFolder: string; + SortField_CreatedOnDate: string; + Sort: string; }; \ No newline at end of file diff --git a/DNN Platform/Modules/ResourceManager/Services/Dto/RoleGroupDto.cs b/DNN Platform/Modules/ResourceManager/Services/Dto/RoleGroupDto.cs new file mode 100644 index 00000000000..4dfbbeceff1 --- /dev/null +++ b/DNN Platform/Modules/ResourceManager/Services/Dto/RoleGroupDto.cs @@ -0,0 +1,83 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information + +namespace Dnn.Modules.ResourceManager.Services.Dto +{ + using System; + using System.Collections.Generic; + using System.Linq; + using System.Runtime.Serialization; + using System.Web; + + using DotNetNuke.Security.Roles; + + /// + /// A data-transfer-object for role groups. + /// + [DataContract] + public class RoleGroupDto + { + /// + /// Initializes a new instance of the class. + /// + public RoleGroupDto() + { + this.Id = -2; + } + + /// + /// Gets or sets the ID for this role group. + /// + [DataMember(Name = "id")] + public int Id { get; set; } + + /// + /// Gets or sets the name of the role group. + /// + [DataMember(Name = "name")] + public string Name { get; set; } + + /// + /// Gets or sets a value indicating how many roles are associated with this group. + /// + [DataMember(Name = "rolesCount")] + public int RolesCount { get; set; } + + /// + /// Gets or sets the description for this role group. + /// + [DataMember(Name = "description")] + public string Description { get; set; } + + /// + /// Converts a into a . + /// + /// The role group to convert from. + /// . + public static RoleGroupDto FromRoleGroupInfo(RoleGroupInfo roleGroup) + { + return new RoleGroupDto() + { + Id = roleGroup.RoleGroupID, + Name = roleGroup.RoleGroupName, + Description = roleGroup.Description, + RolesCount = roleGroup.Roles?.Count ?? 0, + }; + } + + /// + /// Converts this into a . + /// + /// . + public RoleGroupInfo ToRoleGroupInfo() + { + return new RoleGroupInfo() + { + RoleGroupID = this.Id, + RoleGroupName = this.Name, + Description = this.Description ?? string.Empty, + }; + } + } +} diff --git a/DNN Platform/Modules/ResourceManager/Services/ItemsController.cs b/DNN Platform/Modules/ResourceManager/Services/ItemsController.cs index 1247afc47d9..ae12fbd53e0 100644 --- a/DNN Platform/Modules/ResourceManager/Services/ItemsController.cs +++ b/DNN Platform/Modules/ResourceManager/Services/ItemsController.cs @@ -3,7 +3,8 @@ // See the LICENSE file in the project root for more information namespace Dnn.Modules.ResourceManager.Services { - using System; + using System; + using System.Collections.Generic; using System.IO; using System.Linq; using System.Net; @@ -15,13 +16,14 @@ namespace Dnn.Modules.ResourceManager.Services using Dnn.Modules.ResourceManager.Components; using Dnn.Modules.ResourceManager.Helpers; using Dnn.Modules.ResourceManager.Services.Attributes; - using Dnn.Modules.ResourceManager.Services.Dto; - using DotNetNuke.Abstractions; + using Dnn.Modules.ResourceManager.Services.Dto; using DotNetNuke.Common; using DotNetNuke.Common.Utilities; - using DotNetNuke.Entities.Icons; + using DotNetNuke.Entities.Icons; + using DotNetNuke.Entities.Users; using DotNetNuke.Security; - using DotNetNuke.Security.Permissions; + using DotNetNuke.Security.Permissions; + using DotNetNuke.Security.Roles; using DotNetNuke.Services.Assets; using DotNetNuke.Services.FileSystem; using DotNetNuke.UI.Modules; @@ -92,6 +94,19 @@ public HttpResponseMessage GetFolderContent(int folderId, int startIndex, int nu hasDeletePermission = permissionsManager.HasDeletePermission(moduleMode, folderId), hasManagePermission = permissionsManager.HasManagePermission(moduleMode, folderId), }); + } + + /// + /// Gets an item representation for a provided folder ID. + /// + /// The ID of the folder to get. + /// An Item viewmodel. + [HttpGet] + public IHttpActionResult GetFolderItem(int folderId) + { + var folder = FolderManager.Instance.GetFolder(folderId); + var item = this.GetItemViewModel(folder); + return this.Ok(item); } /// @@ -518,6 +533,103 @@ public IHttpActionResult GetFolderIconUrl(int folderId) var folderMappingId = FolderManager.Instance.GetFolder(folderId).FolderMappingID; var url = GetFolderIconUrl(this.PortalSettings.PortalId, folderMappingId); return this.Ok(new { url }); + } + + /// + /// Gets a list of role groups. + /// + /// A collection of role groups. + [HttpGet] + [ValidateAntiForgeryToken] + public IHttpActionResult GetRoleGroups() + { + if (!this.UserInfo.IsInRole(this.PortalSettings.AdministratorRoleName)) + { + return this.Unauthorized(); + } + + var groups = RoleController.GetRoleGroups(this.PortalSettings.PortalId) + .Cast() + .Select(RoleGroupDto.FromRoleGroupInfo); + + return this.Ok(groups); + } + + /// + /// Gets the roles for a rolegroup. + /// + /// A collection of roles. + [HttpGet] + [ValidateAntiForgeryToken] + public IHttpActionResult GetRoles() + { + var matchedRoles = RoleController.Instance.GetRoles(this.PortalSettings.PortalId) + .Where(r => r.Status == RoleStatus.Approved) + .OrderBy(r => r.RoleName) + .Select(r => new + { + IsSystemRole = r.IsSystemRole, + RoleGroupId = r.RoleGroupID, + RoleId = r.RoleID, + RoleName = r.RoleName, + }) + .ToList(); + + return this.Ok(matchedRoles); + } + + /// + /// Gets a list of users that match the search keyword. + /// + /// The keyword to search for. + /// The amount of results to return. + /// A collection of users. + [HttpGet] + [ValidateAntiForgeryToken] + public IHttpActionResult GetSuggestionUsers(string keyword, int count) + { + try + { + if (string.IsNullOrEmpty(keyword)) + { + return this.Ok(new List()); + } + + var displayMatch = keyword + "%"; + var totalRecords = 0; + var totalRecords2 = 0; + var matchedUsers = UserController.GetUsersByDisplayName( + this.PortalSettings.PortalId, + displayMatch, + 0, + count, + ref totalRecords, + false, + false); + matchedUsers.AddRange( + UserController.GetUsersByUserName( + this.PortalSettings.PortalId, + displayMatch, + 0, + count, + ref totalRecords2, + false, + false)); + var finalUsers = matchedUsers + .Cast() + .Where(x => x.Membership.Approved) + .Select(u => new + { + userId = u.UserID, + displayName = $"{u.DisplayName}", + }); + + return this.Ok(finalUsers.ToList().GroupBy(x => x.userId).Select(group => group.First())); + } + catch (Exception ex) + { + return this.InternalServerError(new Exception(ex.Message)); + } } private static string GetFileIconUrl(string extension)