From 707cae6ea98f87a999afdbe774078c3e685d72c3 Mon Sep 17 00:00:00 2001 From: Daniel Valadas Date: Mon, 5 Oct 2020 23:58:49 -0400 Subject: [PATCH] Implemented file/folder move in resource manager. --- .../App_LocalResources/ResourceManager.resx | 6 + .../Components/Common/Utils.cs | 2 +- .../Components/IItemsManager.cs | 20 +- .../Components/ItemsManager.cs | 53 ++++ .../Dnn.Modules.ResourceManager.csproj | 4 +- .../action types/itemDetailsActionsTypes.js | 6 +- .../app/actions/itemDetailsActions.js | 72 +++++- .../app/components/FileDetails.jsx | 1 - .../app/components/Item.jsx | 1 + .../app/containers/AssetsPanelContainer.jsx | 48 +++- .../app/containers/ItemContainer.jsx | 23 +- .../app/containers/ItemMoveContainer.jsx | 107 ++++++++ .../ManageFolderTypesPanelContainer.jsx | 4 +- .../app/containers/TopBarContainer.jsx | 12 +- .../ResourceManager.Web/app/less/Assets.less | 10 + .../app/reducers/itemDetails.js | 9 + .../app/services/itemsService.js | 14 ++ .../Services/Dto/MoveFileRequest.cs | 22 ++ .../Services/Dto/MoveFolderRequest.cs | 22 ++ .../Services/ItemsController.cs | 34 +++ yarn.lock | 231 +++++++++++++++++- 21 files changed, 659 insertions(+), 42 deletions(-) create mode 100644 DNN Platform/Modules/ResourceManager/ResourceManager.Web/app/containers/ItemMoveContainer.jsx create mode 100644 DNN Platform/Modules/ResourceManager/Services/Dto/MoveFileRequest.cs create mode 100644 DNN Platform/Modules/ResourceManager/Services/Dto/MoveFolderRequest.cs diff --git a/DNN Platform/Modules/ResourceManager/App_LocalResources/ResourceManager.resx b/DNN Platform/Modules/ResourceManager/App_LocalResources/ResourceManager.resx index 92a9e1330ba..1c35ffd4857 100644 --- a/DNN Platform/Modules/ResourceManager/App_LocalResources/ResourceManager.resx +++ b/DNN Platform/Modules/ResourceManager/App_LocalResources/ResourceManager.resx @@ -312,4 +312,10 @@ Remove Folder Type + + Move Item + + + New Location + \ No newline at end of file diff --git a/DNN Platform/Modules/ResourceManager/Components/Common/Utils.cs b/DNN Platform/Modules/ResourceManager/Components/Common/Utils.cs index 02858b13d8f..ecdac57e050 100644 --- a/DNN Platform/Modules/ResourceManager/Components/Common/Utils.cs +++ b/DNN Platform/Modules/ResourceManager/Components/Common/Utils.cs @@ -48,7 +48,7 @@ public static int GetFolderGroupId(int folderId) } var prefixLength = Constants.GroupFolderPathStart.Length; - var folderGroupIdString = folderPath.Substring(prefixLength); + var folderGroupIdString = folderPath.Substring(prefixLength - 1); folderGroupIdString = folderGroupIdString.Substring(0, folderGroupIdString.IndexOf("/")); if (!int.TryParse(folderGroupIdString, out var folderGroupId)) diff --git a/DNN Platform/Modules/ResourceManager/Components/IItemsManager.cs b/DNN Platform/Modules/ResourceManager/Components/IItemsManager.cs index 452cec51c56..02fa4716150 100644 --- a/DNN Platform/Modules/ResourceManager/Components/IItemsManager.cs +++ b/DNN Platform/Modules/ResourceManager/Components/IItemsManager.cs @@ -65,7 +65,7 @@ public interface IItemsManager /// /// id of the file to delete. /// Current mode of the module instance. - /// Id of the group (For Group Mode). + /// Id of the group (for group mode). void DeleteFile(int fileId, int moduleMode, int groupId); /// @@ -75,5 +75,23 @@ public interface IItemsManager /// Unlink allowed status. /// Current mode of the module instance. void DeleteFolder(int folderId, bool unlinkAllowedStatus, int moduleMode); + + /// + /// Moves a file into a folder. + /// + /// The id of the file to move. + /// The id of the folder to move the file into. + /// Current mode of the module instance. + /// Id of the group (gor group mode). + void MoveFile(int sourceFileId, int destinationFolderId, int moduleMode, int groupId); + + /// + /// Moves a folder into another folder. + /// + /// The id of the folder to move. + /// The id of the folder into which to move the source folder. + /// Current mode of the module instance. + /// Id of the group (for group mode). + void MoveFolder(int sourceFolderId, int destinationFolderId, int moduleMode, int groupId); } } diff --git a/DNN Platform/Modules/ResourceManager/Components/ItemsManager.cs b/DNN Platform/Modules/ResourceManager/Components/ItemsManager.cs index 79e9259575b..495703a4ef2 100644 --- a/DNN Platform/Modules/ResourceManager/Components/ItemsManager.cs +++ b/DNN Platform/Modules/ResourceManager/Components/ItemsManager.cs @@ -179,6 +179,59 @@ public void DeleteFolder(int folderId, bool unlinkAllowedStatus, int moduleMode) AssetManager.Instance.DeleteFolder(folderId, unlinkAllowedStatus, nonDeletedSubfolders); } + /// + public void MoveFile(int sourceFileId, int destinationFolderId, int moduleMode, int groupId) + { + var file = FileManager.Instance.GetFile(sourceFileId); + var destinationFolder = FolderManager.Instance.GetFolder(destinationFolderId); + + if (file == null || destinationFolder == null) + { + return; + } + + if (!this.permissionsManager.HasDeletePermission(moduleMode, file.FolderId)) + { + throw new FolderPermissionNotMetException(LocalizationHelper.GetString("UserHasNoPermissionToDeleteFolder.Error")); + } + + if (!this.permissionsManager.HasAddFilesPermission(moduleMode, destinationFolderId)) + { + throw new FolderPermissionNotMetException(LocalizationHelper.GetString("UserHasNoPermissionToManageFolder.Error")); + } + + FileManager.Instance.MoveFile(file, destinationFolder); + } + + /// + public void MoveFolder(int sourceFolderId, int destinationFolderId, int moduleMode, int groupId) + { + var sourceFolder = FolderManager.Instance.GetFolder(sourceFolderId); + var sourceFolderParent = FolderManager.Instance.GetFolder(sourceFolder.ParentID); + var destinationFolder = FolderManager.Instance.GetFolder(destinationFolderId); + + if (sourceFolder == null || destinationFolder == null || sourceFolderParent == null) + { + return; + } + + if ( + !this.permissionsManager.HasDeletePermission(moduleMode, sourceFolderId) || + !this.permissionsManager.HasDeletePermission(moduleMode, sourceFolderParent.FolderID)) + { + throw new FolderPermissionNotMetException(LocalizationHelper.GetString("UserHasNoPermissionToDeleteFolder.Error")); + } + + if ( + !this.permissionsManager.HasAddFilesPermission(moduleMode, destinationFolderId) || + !this.permissionsManager.HasAddFoldersPermission(moduleMode, destinationFolderId)) + { + throw new FolderPermissionNotMetException(LocalizationHelper.GetString("UserHasNoPermissionToManageFolder.Error")); + } + + FolderManager.Instance.MoveFolder(sourceFolder, destinationFolder); + } + /// protected override Func GetFactory() { diff --git a/DNN Platform/Modules/ResourceManager/Dnn.Modules.ResourceManager.csproj b/DNN Platform/Modules/ResourceManager/Dnn.Modules.ResourceManager.csproj index 7fd10f5cdc2..7c9154c86f2 100644 --- a/DNN Platform/Modules/ResourceManager/Dnn.Modules.ResourceManager.csproj +++ b/DNN Platform/Modules/ResourceManager/Dnn.Modules.ResourceManager.csproj @@ -129,6 +129,8 @@ + + @@ -284,4 +286,4 @@ - + \ No newline at end of file diff --git a/DNN Platform/Modules/ResourceManager/ResourceManager.Web/app/action types/itemDetailsActionsTypes.js b/DNN Platform/Modules/ResourceManager/ResourceManager.Web/app/action types/itemDetailsActionsTypes.js index b23614b3614..d1cd5d9e8f2 100644 --- a/DNN Platform/Modules/ResourceManager/ResourceManager.Web/app/action types/itemDetailsActionsTypes.js +++ b/DNN Platform/Modules/ResourceManager/ResourceManager.Web/app/action types/itemDetailsActionsTypes.js @@ -8,7 +8,11 @@ const itemDetailsActionsTypes = { CHANGE_PERMISSIONS: "CHANGE_PERMISSIONS", SET_VALIDATION_ERRORS: "SET_VALIDATION_ERRORS", ITEM_SAVED: "ITEM_SAVED", - SAVE_ITEM_ERROR: "SAVE_ITEM_ERROR" + SAVE_ITEM_ERROR: "SAVE_ITEM_ERROR", + MOVE_ITEM: "MOVE_ITEM", + MOVE_ITEM_ERROR: "MOVE_ITEM_ERROR", + CANCEL_MOVE_ITEM: "CANCEL_MOVE_ITEM", + ITEM_MOVED: "ITEM_MOVED", }; export default itemDetailsActionsTypes; \ No newline at end of file diff --git a/DNN Platform/Modules/ResourceManager/ResourceManager.Web/app/actions/itemDetailsActions.js b/DNN Platform/Modules/ResourceManager/ResourceManager.Web/app/actions/itemDetailsActions.js index 8c566a5f398..607d5976b1b 100644 --- a/DNN Platform/Modules/ResourceManager/ResourceManager.Web/app/actions/itemDetailsActions.js +++ b/DNN Platform/Modules/ResourceManager/ResourceManager.Web/app/actions/itemDetailsActions.js @@ -10,16 +10,16 @@ const itemDetailsActions = { : itemsService.getFileDetails(item.itemId); return dispatch => { getItemDetails() - .then( - response => dispatch({ - type: actionTypes.EDIT_ITEM, - data: {...response, ...itemData} - }), - reason => dispatch({ - type: actionTypes.EDIT_ITEM_ERROR, - data: reason.data && reason.data.message ? reason.data.message : localizeService.getString("GenericErrorMessage") - }) - ); + .then( + response => dispatch({ + type: actionTypes.EDIT_ITEM, + data: {...response, ...itemData} + }), + reason => dispatch({ + type: actionTypes.EDIT_ITEM_ERROR, + data: reason.data && reason.data.message ? reason.data.message : localizeService.getString("GenericErrorMessage") + }) + ); }; }, cancelEditItem() { @@ -27,6 +27,58 @@ const itemDetailsActions = { type: actionTypes.CANCEL_EDIT_ITEM }; }, + moveItem(item) { + const itemData = {isFolder: item.isFolder, iconUrl: item.iconUrl, thumbnailAvailable: item.thumbnailAvailable, thumbnailUrl: item.thumbnailUrl}; + let getItemDetails = () => item.isFolder + ? itemsService.getFolderDetails(item.itemId) + : itemsService.getFileDetails(item.itemId); + return dispatch => { + getItemDetails() + .then( + response => dispatch({ + type: actionTypes.MOVE_ITEM, + data: {...response, ...itemData} + }), + reason => dispatch({ + type: actionTypes.SAVE_ITEM_ERROR, + data: reason.data && reason.data.message ? reason.data.message : localizeService.getString("GenericErrorMessage") + }) + ); + }; + }, + moveFolder(sourceFolderId, destinationFolderId) { + return dispatch => { + itemsService.moveFolder(sourceFolderId, destinationFolderId) + .then( + () => { + dispatch({ + type: actionTypes.ITEM_MOVED, + }); + }, + reason => { + reason.data && reason.data.message ? reason.data.message : localizeService.getString("GenericErrorMessage") + } + ) + }; + }, + moveFile(sourceFileId, destinationFolderId) { + return dispatch => { + itemsService.moveFile(sourceFileId, destinationFolderId) + .then( + () => dispatch({ + type: actionTypes.ITEM_MOVED + }), + reason => { + reason.data && reason.data.message ? reason.data.message : localizeService.getString("GenericErrorMessage") + } + ) + } + }, + cancelMoveItem() { + return { + type: actionTypes.CANCEL_MOVE_ITEM + }; + }, changeName(event) { return { type: actionTypes.CHANGE_NAME, diff --git a/DNN Platform/Modules/ResourceManager/ResourceManager.Web/app/components/FileDetails.jsx b/DNN Platform/Modules/ResourceManager/ResourceManager.Web/app/components/FileDetails.jsx index 7170c02830e..70a4099f801 100644 --- a/DNN Platform/Modules/ResourceManager/ResourceManager.Web/app/components/FileDetails.jsx +++ b/DNN Platform/Modules/ResourceManager/ResourceManager.Web/app/components/FileDetails.jsx @@ -26,7 +26,6 @@ const FileDetails = ({file, handlers, validationErrors}) => ( {localizeService.getString("URL")}: {itemService.getItemFullUrl(file.url)} -
diff --git a/DNN Platform/Modules/ResourceManager/ResourceManager.Web/app/components/Item.jsx b/DNN Platform/Modules/ResourceManager/ResourceManager.Web/app/components/Item.jsx index 00ded13ccce..1bf4faab8b5 100644 --- a/DNN Platform/Modules/ResourceManager/ResourceManager.Web/app/components/Item.jsx +++ b/DNN Platform/Modules/ResourceManager/ResourceManager.Web/app/components/Item.jsx @@ -27,6 +27,7 @@ const Item = ({item, iconUrl, handlers, isHighlighted, isDetailed}) => ( { handlers.onEdit ?
: "" } { handlers.onCopyToClipboard ?
: "" } { handlers.onDownload ?
: "" } + { handlers.onMove ?
: ""} { handlers.onDelete ?
: "" }
diff --git a/DNN Platform/Modules/ResourceManager/ResourceManager.Web/app/containers/AssetsPanelContainer.jsx b/DNN Platform/Modules/ResourceManager/ResourceManager.Web/app/containers/AssetsPanelContainer.jsx index 0782563a4bc..ee1ea7707ed 100644 --- a/DNN Platform/Modules/ResourceManager/ResourceManager.Web/app/containers/AssetsPanelContainer.jsx +++ b/DNN Platform/Modules/ResourceManager/ResourceManager.Web/app/containers/AssetsPanelContainer.jsx @@ -10,6 +10,7 @@ import AddAssetPanelContainer from "../containers/AddAssetPanelContainer"; import TopBarContainer from "./TopBarContainer"; import Item from "../containers/ItemContainer"; import ItemDetailsContainer from "../containers/ItemDetailsContainer"; +import ItemMoveContainer from "../containers/ItemMoveContainer"; import localizeService from "../services/localizeService.js"; import ReactCSSTransitionGroup from "react-transition-group/CSSTransitionGroup"; @@ -46,6 +47,20 @@ class AssetsPanelContainer extends React.Component { ); } + getMovePanel(showPanel, i) { + return ( + + {showPanel && } + + ); + } + handleScroll() { const { folderPanelState, loadContent, searchFiles } = this.props; const { totalCount, loadedItems, search, loading } = folderPanelState; @@ -74,6 +89,7 @@ class AssetsPanelContainer extends React.Component { const { items, itemEditing, + itemMoving, search, itemContainerDisabled, loading, @@ -86,18 +102,34 @@ class AssetsPanelContainer extends React.Component { const { itemId, itemName, isFolder } = item; result.push(); - if ( - itemEditing && - ((isFolder && itemEditing.folderId === itemId) || - (!isFolder && itemEditing.fileId === itemId)) + if ( itemEditing && + ( + (isFolder && itemEditing.folderId === itemId) || + (!isFolder && itemEditing.fileId === itemId) + ) + ) { + propsPosition = this.getDetailsPosition(i); + } + + if ( itemMoving && + ( + (isFolder && itemMoving.folderId === itemId) || + (!isFolder && itemMoving.fileId === itemId) + ) ) { propsPosition = this.getDetailsPosition(i); } let showPanel = - i === propsPosition || - (propsPosition >= items.length && i === items.length - 1); - result.push(this.getDetailsPanel(showPanel, i)); + i === propsPosition || + (propsPosition >= items.length && i === items.length - 1); + if (itemEditing){ + result.push(this.getDetailsPanel(showPanel, i)); + } + + if (itemMoving) { + result.push(this.getMovePanel(showPanel, i)); + } } return ( @@ -149,6 +181,7 @@ AssetsPanelContainer.propTypes = { itemContainerDisabled: PropTypes.bool, loading: PropTypes.bool, itemEditing: PropTypes.object, + itemMoving: PropTypes.object, itemWidth: PropTypes.number, loadContent: PropTypes.func, searchFiles: PropTypes.func, @@ -180,6 +213,7 @@ function mapStateToProps(state) { addFolderPanelState.expanded || addAssetPanelState.expanded, loading: folderPanelState.loading, itemEditing: itemDetailsState.itemEditing, + itemMoving: itemDetailsState.itemMoving, itemWidth: folderPanelState.itemWidth, }; } diff --git a/DNN Platform/Modules/ResourceManager/ResourceManager.Web/app/containers/ItemContainer.jsx b/DNN Platform/Modules/ResourceManager/ResourceManager.Web/app/containers/ItemContainer.jsx index 78491a6ceb8..23b4c8a97de 100644 --- a/DNN Platform/Modules/ResourceManager/ResourceManager.Web/app/containers/ItemContainer.jsx +++ b/DNN Platform/Modules/ResourceManager/ResourceManager.Web/app/containers/ItemContainer.jsx @@ -11,7 +11,7 @@ import localizeService from "../services/localizeService"; class ItemContainer extends React.Component { render() { - const { item, itemEditing, loadContent, editItem, downloadFile, deleteFolder, + const { item, itemEditing, loadContent, editItem, moveItem, downloadFile, deleteFolder, deleteFile, copyFileUrlToClipboard, openDialog, closeDialog, folderPanelState, uploadedFiles, newFolderId } = this.props; const isFolder = item.isFolder; @@ -64,6 +64,24 @@ class ItemContainer extends React.Component { openDialog(dialogHeader, dialogMessage, yesFunction, noFunction); } + function onMoveFolder(item, event) { + event.stopPropagation(); + if (!isFolder) { + return; + } + + moveItem(item); + } + + function onMoveFile(item, event) { + event.stopPropagation(); + if(isFolder) { + return; + } + + moveItem(item); + } + function onDeleteFile(event) { event.stopPropagation(); if (isFolder) { @@ -98,6 +116,7 @@ class ItemContainer extends React.Component { onEdit: hasManagePermission ? onEditItem.bind(this, item) : null, onCopyToClipboard: isFolder ? null : copyFileUrlToClipboard.bind(this, item), onDownload: isFolder ? null : downloadFile.bind(this, item.itemId), + onMove: (hasManagePermission && hasDeletePermission) ? isFolder ? onMoveFolder.bind(this, item) : onMoveFile.bind(this, item) : null, onDelete: hasDeletePermission ? isFolder ? onDeleteFolder : onDeleteFile : null }; @@ -111,6 +130,7 @@ ItemContainer.propTypes = { item: PropTypes.object, loadContent: PropTypes.func, editItem: PropTypes.func, + moveItem: PropTypes.func, downloadFile: PropTypes.func, deleteFolder: PropTypes.func, deleteFile: PropTypes.func, @@ -142,6 +162,7 @@ function mapDispatchToProps(dispatch) { ...bindActionCreators({ loadContent: folderPanelActions.loadContent, editItem: itemDetailsActions.editItem, + moveItem: itemDetailsActions.moveItem, downloadFile: folderPanelActions.downloadFile, deleteFolder: folderPanelActions.deleteFolder, deleteFile: folderPanelActions.deleteFile, diff --git a/DNN Platform/Modules/ResourceManager/ResourceManager.Web/app/containers/ItemMoveContainer.jsx b/DNN Platform/Modules/ResourceManager/ResourceManager.Web/app/containers/ItemMoveContainer.jsx new file mode 100644 index 00000000000..fd452473a01 --- /dev/null +++ b/DNN Platform/Modules/ResourceManager/ResourceManager.Web/app/containers/ItemMoveContainer.jsx @@ -0,0 +1,107 @@ +import React from "react"; +import PropTypes from "prop-types"; +import { bindActionCreators } from "redux"; +import { connect } from "react-redux"; +import itemDetailsActions from "../actions/itemDetailsActions"; +import localizeService from "../services/localizeService"; +import FolderPicker from "../components/FolderSelector/FolderPicker" +import folderPanelActions from "../actions/folderPanelActions"; + +class ItemMoveContainer extends React.Component { + constructor(props) { + super(props); + this.state = { + selectedFolderId: this.props.folderPanelState.currentFolderId, + selectedFolderName: this.props.folderPanelState.currentFolderName, + }; + } + + handleFolderChange(e){ + this.setState({ + ...this.state, + selectedFolderId: e.key, + selectedFolderName: e.value, + }); + } + + handleItemMove(){ + if (this.state.selectedFolderId === this.props.folderPanelState.currentFolderId){ + this.props.cancelMoveItem(); + return; + } + + if (this.props.itemMoving.isFolder){ + this.props.moveFolder(this.props.itemMoving.folderId, this.state.selectedFolderId); + } + else { + this.props.moveFile(this.props.itemMoving.fileId, this.state.selectedFolderId); + } + } + + componentWillUnmount(){ + this.props.loadContent(this.props.folderPanelState, this.state.selectedFolderId); + } + + render() { + const { cancelMoveItem, homeFolderId } = this.props; + return ( +
+

{localizeService.getString("MoveItem")}

+ +
+ + this.handleFolderChange(e)} + homeFolderId={homeFolderId} + noFolderSelectedValue={localizeService.getString("NoFolderSelected")} + searchFolderPlaceHolder={localizeService.getString("SearchFolder")} + /> +
+ +
+ + +
+
+ ); + } +} + +ItemMoveContainer.propTypes = { + itemMoving: PropTypes.object, + cancelMoveItem: PropTypes.func, + moveItem: PropTypes.func, + moveFolder: PropTypes.func, + moveFile: PropTypes.func, + loadContent: PropTypes.func, + folderPanelState: PropTypes.object, + homeFolderId: PropTypes.number, +}; + +function mapStateToProps(state) { + const itemDetailsState = state.itemDetails; + return { + folderPanelState: state.folderPanel, + itemMoving: itemDetailsState.itemMoving, + homeFolderId: state.module.homeFolderId, + }; +} + +function mapDispatchToProps(dispatch) { + return { + ...bindActionCreators({ + cancelMoveItem: itemDetailsActions.cancelMoveItem, + moveItem: itemDetailsActions.moveItem, + moveFolder: itemDetailsActions.moveFolder, + moveFile: itemDetailsActions.moveFile, + loadContent: folderPanelActions.loadContent, + }, dispatch) + }; +} + +export default connect(mapStateToProps, mapDispatchToProps)(ItemMoveContainer); diff --git a/DNN Platform/Modules/ResourceManager/ResourceManager.Web/app/containers/ManageFolderTypesPanelContainer.jsx b/DNN Platform/Modules/ResourceManager/ResourceManager.Web/app/containers/ManageFolderTypesPanelContainer.jsx index f34cbb41f93..4c69a4f981a 100644 --- a/DNN Platform/Modules/ResourceManager/ResourceManager.Web/app/containers/ManageFolderTypesPanelContainer.jsx +++ b/DNN Platform/Modules/ResourceManager/ResourceManager.Web/app/containers/ManageFolderTypesPanelContainer.jsx @@ -12,7 +12,9 @@ class ManageFolderTypesPanelContainer extends React.Component { constructor(props) { super(props); this.props.loadFolderMappings(); - this.props.getAddFolderTypeUrl(); + if (props.isAdmin){ + this.props.getAddFolderTypeUrl(); + } } handleConfirmRemoveFolderType(e, folderTypeMappingId) { diff --git a/DNN Platform/Modules/ResourceManager/ResourceManager.Web/app/containers/TopBarContainer.jsx b/DNN Platform/Modules/ResourceManager/ResourceManager.Web/app/containers/TopBarContainer.jsx index 39576d0b55c..5dd5dce8d68 100644 --- a/DNN Platform/Modules/ResourceManager/ResourceManager.Web/app/containers/TopBarContainer.jsx +++ b/DNN Platform/Modules/ResourceManager/ResourceManager.Web/app/containers/TopBarContainer.jsx @@ -98,11 +98,13 @@ class TopBarContainer extends React.Component { label="" prependWith={} withIcon={false} /> - + : {localizeService.getString("DisabledForAnonymousUsersMessage")} } diff --git a/DNN Platform/Modules/ResourceManager/ResourceManager.Web/app/less/Assets.less b/DNN Platform/Modules/ResourceManager/ResourceManager.Web/app/less/Assets.less index a97d952103c..25d1e9df41a 100644 --- a/DNN Platform/Modules/ResourceManager/ResourceManager.Web/app/less/Assets.less +++ b/DNN Platform/Modules/ResourceManager/ResourceManager.Web/app/less/Assets.less @@ -845,6 +845,10 @@ top: 96px; background-image: url(/DesktopModules/ResourceManager/Images/download.svg); } + &.rm-move { + top: 64px; + background-image: url(/DesktopModules/ResourceManager/Images/move.svg); + } &.rm-delete { background-image: url(/DesktopModules/ResourceManager/Images/delete.svg); background-color: #195774; @@ -919,6 +923,12 @@ padding: 25px 10px; box-sizing: border-box; overflow: hidden; + &.item-move{ + overflow: visible; + .dnn-folder-selector{ + border: 1px solid gray; + } + } } ul.tabControl { background-color: #FFF; diff --git a/DNN Platform/Modules/ResourceManager/ResourceManager.Web/app/reducers/itemDetails.js b/DNN Platform/Modules/ResourceManager/ResourceManager.Web/app/reducers/itemDetails.js index dfd6234b6ab..f9be76284df 100644 --- a/DNN Platform/Modules/ResourceManager/ResourceManager.Web/app/reducers/itemDetails.js +++ b/DNN Platform/Modules/ResourceManager/ResourceManager.Web/app/reducers/itemDetails.js @@ -11,6 +11,9 @@ export default function itemDetailsReducer(state = initialState, action) { case itemDetailsActionsTypes.EDIT_ITEM: { return { ...state, itemEditing: data }; } + case itemDetailsActionsTypes.MOVE_ITEM: { + return { ...state, itemMoving: data }; + } case itemDetailsActionsTypes.CHANGE_NAME: { let itemEditing = { ...state.itemEditing, fileName: data, folderName: data}; return { ...state, itemEditing }; @@ -36,6 +39,12 @@ export default function itemDetailsReducer(state = initialState, action) { delete res.itemEditing; return res; } + case itemDetailsActionsTypes.ITEM_MOVED : + case itemDetailsActionsTypes.CANCEL_MOVE_ITEM : { + let res = { ...state }; + delete res.itemMoving; + return res; + } } return state; diff --git a/DNN Platform/Modules/ResourceManager/ResourceManager.Web/app/services/itemsService.js b/DNN Platform/Modules/ResourceManager/ResourceManager.Web/app/services/itemsService.js index 57a1d11cd1d..97389ae4268 100644 --- a/DNN Platform/Modules/ResourceManager/ResourceManager.Web/app/services/itemsService.js +++ b/DNN Platform/Modules/ResourceManager/ResourceManager.Web/app/services/itemsService.js @@ -16,6 +16,8 @@ const SAVE_FILE_DETAILS_ENDPOINT = "Items/SaveFileDetails"; const SAVE_FOLDER_DETAILS_ENDPOINT = "Items/SaveFolderDetails"; const REMOVE_FOLDER_TYPE_ENDPOINT = "Items/RemoveFolderType"; const ADD_FOLDER_TYPE_URL_ENDPOINT = "Items/GetAddFolderTypeUrl"; +const MOVE_FOLDER_URL_ENDPOINT = "Items/MoveFolder"; +const MOVE_FILE_URL_ENDPOINT = "Items/MoveFile"; function getUrl(endpoint, ignoreCurrentModuleAPI=false) { return api.getServiceRoot(ignoreCurrentModuleAPI) + endpoint; @@ -59,6 +61,16 @@ function deleteFile(fileId) { return api.post(getUrl(DELETE_FILE_ENDPOINT), {fileId}, { "Content-Type":"application/json" }); } +function moveFolder(sourceFolderId, destinationFolderId) { + const data = { sourceFolderId, destinationFolderId } + return api.post(getUrl(MOVE_FOLDER_URL_ENDPOINT), data, { "Content-Type": "application/json" }); +} + +function moveFile(sourceFileId, destinationFolderId) { + const data = {sourceFileId, destinationFolderId}; + return api.post(getUrl(MOVE_FILE_URL_ENDPOINT), data, {"Content-Type": "application/json"}); +} + function getFileDetails(fileId) { return api.get(getUrl(FILE_DETAILS_ENDPOINT), {fileId}); } @@ -142,4 +154,6 @@ export default { saveFolderDetails, removeFolderType, getAddFolderTypeUrl, + moveFolder, + moveFile, }; \ No newline at end of file diff --git a/DNN Platform/Modules/ResourceManager/Services/Dto/MoveFileRequest.cs b/DNN Platform/Modules/ResourceManager/Services/Dto/MoveFileRequest.cs new file mode 100644 index 00000000000..5dbc8188617 --- /dev/null +++ b/DNN Platform/Modules/ResourceManager/Services/Dto/MoveFileRequest.cs @@ -0,0 +1,22 @@ +// 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 +{ + /// + /// Represents a request to move a file into a folder. + /// + public class MoveFileRequest + { + /// + /// Gets or sets the id of the file to move. + /// + public int SourceFileId { get; set; } + + /// + /// Gets or sets the id of the folder to move the file into. + /// + public int DestinationFolderId { get; set; } + } +} diff --git a/DNN Platform/Modules/ResourceManager/Services/Dto/MoveFolderRequest.cs b/DNN Platform/Modules/ResourceManager/Services/Dto/MoveFolderRequest.cs new file mode 100644 index 00000000000..1f45a1c1a96 --- /dev/null +++ b/DNN Platform/Modules/ResourceManager/Services/Dto/MoveFolderRequest.cs @@ -0,0 +1,22 @@ +// 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 +{ + /// + /// Represents a request to move a folder to another folder. + /// + public class MoveFolderRequest + { + /// + /// Gets or sets the id of the folder to move. + /// + public int SourceFolderId { get; set; } + + /// + /// Gets or sets the id of the folder into which to move the source folder. + /// + public int DestinationFolderId { get; set; } + } +} diff --git a/DNN Platform/Modules/ResourceManager/Services/ItemsController.cs b/DNN Platform/Modules/ResourceManager/Services/ItemsController.cs index 79491e4ebd0..24696025b4c 100644 --- a/DNN Platform/Modules/ResourceManager/Services/ItemsController.cs +++ b/DNN Platform/Modules/ResourceManager/Services/ItemsController.cs @@ -471,6 +471,40 @@ public HttpResponseMessage GetSortOptions() return this.Request.CreateResponse(HttpStatusCode.OK, sortOptions); } + /// + /// Attempts to move a file into a folder. + /// + /// The file move request, . + /// A 0 status code if succeeded. + [HttpPost] + [ValidateAntiForgeryToken] + public HttpResponseMessage MoveFile(MoveFileRequest moveFileRequest) + { + var groupId = this.FindGroupId(this.Request); + var moduleId = this.Request.FindModuleId(); + var moduleMode = new SettingsManager(moduleId, groupId).Mode; + + ItemsManager.Instance.MoveFile(moveFileRequest.SourceFileId, moveFileRequest.DestinationFolderId, moduleMode, groupId); + return this.Request.CreateResponse(HttpStatusCode.OK, new { Status = 0 }); + } + + /// + /// Attempts to move a folder into another folder. + /// + /// The folder move request, . + /// A 0 status code if succeeded. + [HttpPost] + [ValidateAntiForgeryToken] + public HttpResponseMessage MoveFolder(MoveFolderRequest moveFolderRequest) + { + var groupId = this.FindGroupId(this.Request); + var moduleId = this.Request.FindModuleId(); + var moduleMode = new SettingsManager(moduleId, groupId).Mode; + + ItemsManager.Instance.MoveFolder(moveFolderRequest.SourceFolderId, moveFolderRequest.DestinationFolderId, moduleMode, groupId); + return this.Request.CreateResponse(HttpStatusCode.OK, new { Status = 0 }); + } + private static string GetFileIconUrl(string extension) { if (!string.IsNullOrEmpty(extension) && File.Exists(HttpContext.Current.Server.MapPath(IconController.IconURL("Ext" + extension, "32x32", "Standard")))) diff --git a/yarn.lock b/yarn.lock index 27295b2b649..ad1bf9d5a26 100644 --- a/yarn.lock +++ b/yarn.lock @@ -16,6 +16,13 @@ dependencies: "@babel/highlight" "^7.10.3" +"@babel/code-frame@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.10.4.tgz#168da1a36e90da68ae8d49c0f1b48c7c6249213a" + integrity sha512-vG6SvB6oYEhvgisZNFRmRCUkLz11c7rp+tbNTynGqc6mS1d5ATd/sGyV6W0KZZnXRKMTzZDRgQT3Ou9jhpAfUg== + dependencies: + "@babel/highlight" "^7.10.4" + "@babel/core@7.1.6": version "7.1.6" resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.1.6.tgz#3733cbee4317429bc87c62b29cf8587dba7baeb3" @@ -97,6 +104,15 @@ lodash "^4.17.13" source-map "^0.5.0" +"@babel/generator@^7.11.5": + version "7.11.6" + resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.11.6.tgz#b868900f81b163b4d464ea24545c61cbac4dc620" + integrity sha512-DWtQ1PV3r+cLbySoHrwn9RWEgKMBLLma4OBQloPRyDYvc5msJM9kvTLo1YnlJd1P/ZuKbdli3ijr5q3FvAF3uA== + dependencies: + "@babel/types" "^7.11.5" + jsesc "^2.5.1" + source-map "^0.5.0" + "@babel/helper-annotate-as-pure@^7.0.0": version "7.0.0" resolved "https://registry.yarnpkg.com/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.0.0.tgz#323d39dd0b50e10c7c06ca7d7638e6864d8c5c32" @@ -129,6 +145,18 @@ "@babel/traverse" "^7.4.4" "@babel/types" "^7.4.4" +"@babel/helper-create-class-features-plugin@^7.10.4": + version "7.10.5" + resolved "https://registry.yarnpkg.com/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.10.5.tgz#9f61446ba80e8240b0a5c85c6fdac8459d6f259d" + integrity sha512-0nkdeijB7VlZoLT3r/mY3bUkw3T8WG/hNw+FATs/6+pG2039IJWjTYL0VTISqsNHMUTEnwbVnc89WIJX9Qed0A== + dependencies: + "@babel/helper-function-name" "^7.10.4" + "@babel/helper-member-expression-to-functions" "^7.10.5" + "@babel/helper-optimise-call-expression" "^7.10.4" + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/helper-replace-supers" "^7.10.4" + "@babel/helper-split-export-declaration" "^7.10.4" + "@babel/helper-create-class-features-plugin@^7.3.0", "@babel/helper-create-class-features-plugin@^7.4.4": version "7.4.4" resolved "https://registry.yarnpkg.com/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.4.4.tgz#fc3d690af6554cc9efc607364a82d48f58736dba" @@ -176,6 +204,15 @@ "@babel/template" "^7.10.3" "@babel/types" "^7.10.3" +"@babel/helper-function-name@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.10.4.tgz#d2d3b20c59ad8c47112fa7d2a94bc09d5ef82f1a" + integrity sha512-YdaSyz1n8gY44EmN7x44zBn9zQ1Ry2Y+3GTA+3vH6Mizke1Vw0aWDM66FOYEPw8//qKkmqOckrGgTYa+6sceqQ== + dependencies: + "@babel/helper-get-function-arity" "^7.10.4" + "@babel/template" "^7.10.4" + "@babel/types" "^7.10.4" + "@babel/helper-get-function-arity@^7.0.0": version "7.0.0" resolved "https://registry.yarnpkg.com/@babel/helper-get-function-arity/-/helper-get-function-arity-7.0.0.tgz#83572d4320e2a4657263734113c42868b64e49c3" @@ -190,6 +227,13 @@ dependencies: "@babel/types" "^7.10.3" +"@babel/helper-get-function-arity@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/helper-get-function-arity/-/helper-get-function-arity-7.10.4.tgz#98c1cbea0e2332f33f9a4661b8ce1505b2c19ba2" + integrity sha512-EkN3YDB+SRDgiIUnNgcmiD361ti+AVbL3f3Henf6dqqUyr5dMsorno0lJWJuLhDhkI5sYEpgj6y9kB8AOU1I2A== + dependencies: + "@babel/types" "^7.10.4" + "@babel/helper-hoist-variables@^7.4.4": version "7.4.4" resolved "https://registry.yarnpkg.com/@babel/helper-hoist-variables/-/helper-hoist-variables-7.4.4.tgz#0298b5f25c8c09c53102d52ac4a98f773eb2850a" @@ -204,6 +248,13 @@ dependencies: "@babel/types" "^7.0.0" +"@babel/helper-member-expression-to-functions@^7.10.4", "@babel/helper-member-expression-to-functions@^7.10.5": + version "7.11.0" + resolved "https://registry.yarnpkg.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.11.0.tgz#ae69c83d84ee82f4b42f96e2a09410935a8f26df" + integrity sha512-JbFlKHFntRV5qKw3YC0CvQnDZ4XMwgzzBbld7Ly4Mj4cbFy3KywcR8NtNctRToMWJOVvLINJv525Gd6wwVEx/Q== + dependencies: + "@babel/types" "^7.11.0" + "@babel/helper-module-imports@^7.0.0": version "7.0.0" resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.0.0.tgz#96081b7111e486da4d2cd971ad1a4fe216cc2e3d" @@ -230,11 +281,23 @@ dependencies: "@babel/types" "^7.0.0" +"@babel/helper-optimise-call-expression@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.10.4.tgz#50dc96413d594f995a77905905b05893cd779673" + integrity sha512-n3UGKY4VXwXThEiKrgRAoVPBMqeoPgHVqiHZOanAJCG9nQUL2pLRQirUzl0ioKclHGpGqRgIOkgcIJaIWLpygg== + dependencies: + "@babel/types" "^7.10.4" + "@babel/helper-plugin-utils@^7.0.0": version "7.0.0" resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.0.0.tgz#bbb3fbee98661c569034237cc03967ba99b4f250" integrity sha512-CYAOUCARwExnEixLdB6sDm2dIJ/YgEAKDM1MOeMeZu9Ld/bDgVo8aiWrXwcY7OBh+1Ea2uUcVRcxKk0GJvW7QA== +"@babel/helper-plugin-utils@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.10.4.tgz#2f75a831269d4f677de49986dff59927533cf375" + integrity sha512-O4KCvQA6lLiMU9l2eawBPMf1xPP8xPfB3iEQw150hOVTqj/rfXz0ThTb4HEzqQfs2Bmo5Ay8BzxfzVtBrr9dVg== + "@babel/helper-regex@^7.0.0", "@babel/helper-regex@^7.4.4": version "7.4.4" resolved "https://registry.yarnpkg.com/@babel/helper-regex/-/helper-regex-7.4.4.tgz#a47e02bc91fb259d2e6727c2a30013e3ac13c4a2" @@ -263,6 +326,16 @@ "@babel/traverse" "^7.4.4" "@babel/types" "^7.4.4" +"@babel/helper-replace-supers@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/helper-replace-supers/-/helper-replace-supers-7.10.4.tgz#d585cd9388ea06e6031e4cd44b6713cbead9e6cf" + integrity sha512-sPxZfFXocEymYTdVK1UNmFPBN+Hv5mJkLPsYWwGBxZAxaWfFu+xqp7b6qWD0yjNuNL2VKc6L5M18tOXUP7NU0A== + dependencies: + "@babel/helper-member-expression-to-functions" "^7.10.4" + "@babel/helper-optimise-call-expression" "^7.10.4" + "@babel/traverse" "^7.10.4" + "@babel/types" "^7.10.4" + "@babel/helper-simple-access@^7.1.0": version "7.1.0" resolved "https://registry.yarnpkg.com/@babel/helper-simple-access/-/helper-simple-access-7.1.0.tgz#65eeb954c8c245beaa4e859da6188f39d71e585c" @@ -285,11 +358,23 @@ dependencies: "@babel/types" "^7.10.1" +"@babel/helper-split-export-declaration@^7.10.4", "@babel/helper-split-export-declaration@^7.11.0": + version "7.11.0" + resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.11.0.tgz#f8a491244acf6a676158ac42072911ba83ad099f" + integrity sha512-74Vejvp6mHkGE+m+k5vHY93FX2cAtrw1zXrZXRlG4l410Nm9PxfEiVTn1PjDPV5SnmieiueY4AFg2xqhNFuuZg== + dependencies: + "@babel/types" "^7.11.0" + "@babel/helper-validator-identifier@^7.10.3": version "7.10.3" resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.10.3.tgz#60d9847f98c4cea1b279e005fdb7c28be5412d15" integrity sha512-bU8JvtlYpJSBPuj1VUmKpFGaDZuLxASky3LhaKj3bmpSTY6VWooSM8msk+Z0CZoErFye2tlABF6yDkT3FOPAXw== +"@babel/helper-validator-identifier@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.10.4.tgz#a78c7a7251e01f616512d31b10adcf52ada5e0d2" + integrity sha512-3U9y+43hz7ZM+rzG24Qe2mufW5KhvFg/NhnNph+i9mgCtdTCtMJuI1TMkrIUiK7Ix4PYlRF9I5dhqaLYA/ADXw== + "@babel/helper-wrap-function@^7.1.0": version "7.2.0" resolved "https://registry.yarnpkg.com/@babel/helper-wrap-function/-/helper-wrap-function-7.2.0.tgz#c4e0012445769e2815b55296ead43a958549f6fa" @@ -327,6 +412,15 @@ chalk "^2.0.0" js-tokens "^4.0.0" +"@babel/highlight@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.10.4.tgz#7d1bdfd65753538fabe6c38596cdb76d9ac60143" + integrity sha512-i6rgnR/YgPEQzZZnbTHHuZdlE8qyoBNalD6F+q4vAFlcMEcqmkoG+mPqJYJCo63qPf74+Y1UZsl3l6f7/RIkmA== + dependencies: + "@babel/helper-validator-identifier" "^7.10.4" + chalk "^2.0.0" + js-tokens "^4.0.0" + "@babel/parser@^7.0.0", "@babel/parser@^7.1.0", "@babel/parser@^7.1.3", "@babel/parser@^7.1.6", "@babel/parser@^7.2.2", "@babel/parser@^7.4.3", "@babel/parser@^7.4.4": version "7.4.4" resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.4.4.tgz#5977129431b8fe33471730d255ce8654ae1250b6" @@ -337,6 +431,11 @@ resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.10.3.tgz#7e71d892b0d6e7d04a1af4c3c79d72c1f10f5315" integrity sha512-oJtNJCMFdIMwXGmx+KxuaD7i3b8uS7TTFYW/FNG2BT8m+fmGHoiPYoH0Pe3gya07WuFmM5FCDIr1x0irkD/hyA== +"@babel/parser@^7.10.4", "@babel/parser@^7.11.5": + version "7.11.5" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.11.5.tgz#c7ff6303df71080ec7a4f5b8c003c58f1cf51037" + integrity sha512-X9rD8qqm695vgmeaQ4fvz/o3+Wk4ZzQvSHkDBgpYKxpD4qTAUm88ZKtHkVqIOsYFFbIQ6wQYhC6q7pjqVK0E0Q== + "@babel/plugin-proposal-async-generator-functions@^7.1.0", "@babel/plugin-proposal-async-generator-functions@^7.2.0": version "7.2.0" resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.2.0.tgz#b289b306669dce4ad20b0252889a15768c9d417e" @@ -354,6 +453,14 @@ "@babel/helper-create-class-features-plugin" "^7.3.0" "@babel/helper-plugin-utils" "^7.0.0" +"@babel/plugin-proposal-class-properties@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.10.4.tgz#a33bf632da390a59c7a8c570045d1115cd778807" + integrity sha512-vhwkEROxzcHGNu2mzUC0OFFNXdZ4M23ib8aRRcJSsW8BZK9pQMD7QB7csl97NBbgGZO7ZyHUyKDnxzOaP4IrCg== + dependencies: + "@babel/helper-create-class-features-plugin" "^7.10.4" + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/plugin-proposal-class-properties@^7.3.0": version "7.4.4" resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.4.4.tgz#93a6486eed86d53452ab9bab35e368e9461198ce" @@ -490,6 +597,13 @@ dependencies: "@babel/helper-plugin-utils" "^7.0.0" +"@babel/plugin-transform-arrow-functions@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.10.4.tgz#e22960d77e697c74f41c501d44d73dbf8a6a64cd" + integrity sha512-9J/oD1jV0ZCBcgnoFWFq1vJd4msoKb/TCpGNFyyLt0zABdcvgK3aYikZ8HjzB14c26bc7E3Q1yugpwGy2aTPNA== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/plugin-transform-async-to-generator@^7.1.0", "@babel/plugin-transform-async-to-generator@^7.2.0", "@babel/plugin-transform-async-to-generator@^7.4.4": version "7.4.4" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.4.4.tgz#a3f1d01f2f21cadab20b33a82133116f14fb5894" @@ -1044,6 +1158,15 @@ "@babel/parser" "^7.10.3" "@babel/types" "^7.10.3" +"@babel/template@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.10.4.tgz#3251996c4200ebc71d1a8fc405fba940f36ba278" + integrity sha512-ZCjD27cGJFUB6nmCB1Enki3r+L5kJveX9pq1SvAUKoICy6CZ9yD8xO086YXdYhvNjBdnekm4ZnaP5yC8Cs/1tA== + dependencies: + "@babel/code-frame" "^7.10.4" + "@babel/parser" "^7.10.4" + "@babel/types" "^7.10.4" + "@babel/traverse@^7.0.0", "@babel/traverse@^7.1.0", "@babel/traverse@^7.1.6", "@babel/traverse@^7.2.2", "@babel/traverse@^7.4.3", "@babel/traverse@^7.4.4": version "7.4.4" resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.4.4.tgz#0776f038f6d78361860b6823887d4f3937133fe8" @@ -1059,6 +1182,21 @@ globals "^11.1.0" lodash "^4.17.11" +"@babel/traverse@^7.10.4": + version "7.11.5" + resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.11.5.tgz#be777b93b518eb6d76ee2e1ea1d143daa11e61c3" + integrity sha512-EjiPXt+r7LiCZXEfRpSJd+jUMnBd4/9OUv7Nx3+0u9+eimMwJmG0Q98lw4/289JCoxSE8OolDMNZaaF/JZ69WQ== + dependencies: + "@babel/code-frame" "^7.10.4" + "@babel/generator" "^7.11.5" + "@babel/helper-function-name" "^7.10.4" + "@babel/helper-split-export-declaration" "^7.11.0" + "@babel/parser" "^7.11.5" + "@babel/types" "^7.11.5" + debug "^4.1.0" + globals "^11.1.0" + lodash "^4.17.19" + "@babel/traverse@^7.7.0": version "7.10.3" resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.10.3.tgz#0b01731794aa7b77b214bcd96661f18281155d7e" @@ -1092,6 +1230,15 @@ lodash "^4.17.13" to-fast-properties "^2.0.0" +"@babel/types@^7.10.4", "@babel/types@^7.11.0", "@babel/types@^7.11.5": + version "7.11.5" + resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.11.5.tgz#d9de577d01252d77c6800cee039ee64faf75662d" + integrity sha512-bvM7Qz6eKnJVFIn+1LPtjlBFPVN5jNDc1XmN15vWe7Q3DPBufWWsLiIvUu7xW87uTG6QoggpIDnUgLQvPheU+Q== + dependencies: + "@babel/helper-validator-identifier" "^7.10.4" + lodash "^4.17.19" + to-fast-properties "^2.0.0" + "@cnakazawa/watch@^1.0.3": version "1.0.3" resolved "https://registry.yarnpkg.com/@cnakazawa/watch/-/watch-1.0.3.tgz#099139eaec7ebf07a27c1786a3ff64f39464d2ef" @@ -1100,6 +1247,32 @@ exec-sh "^0.3.2" minimist "^1.2.0" +"@dnnsoftware/dnn-react-common@9.7.0": + version "2.1.2" + resolved "https://registry.yarnpkg.com/@dnnsoftware/dnn-react-common/-/dnn-react-common-2.1.2.tgz#8af42e5f4fe8075fb80b7f62d2b1f0893fe397d3" + integrity sha512-OvPmcaMGZbSnlxweT0jmhDe9lSiJYxNtHHht+mj8XHKts9g6/41RIP9EnCCbdaOt+bieuu15yG9EHI5aWHS++g== + dependencies: + interact.js "^1.2.8" + moment "^2.22.2" + raw-loader "0.5.1" + react-accessible-tooltip "^2.0.3" + react-collapse "^4.0.3" + react-custom-scrollbars "^4.2.1" + react-day-picker "^7.1.10" + react-height "^3.0.0" + react-modal "^3.5.1" + react-motion "^0.5.2" + react-scrollbar "^0.5.4" + react-slider "0.11.2" + react-tabs "2.3.0" + react-test-utils "0.0.1" + react-tooltip "^3.8.4" + react-widgets "^4.4.4" + redux-undo "^1.0.0-beta9" + scroll "^2.0.3" + shortid "^2.2.13" + throttle-debounce "^2.0.1" + "@emotion/cache@^10.0.9": version "10.0.9" resolved "https://registry.yarnpkg.com/@emotion/cache/-/cache-10.0.9.tgz#e0c7b7a289f7530edcfad4dcf3858bd2e5700a6f" @@ -3645,18 +3818,6 @@ babel-code-frame@^6.26.0: esutils "^2.0.2" js-tokens "^3.0.2" -babel-eslint@10.1.0: - version "10.1.0" - resolved "https://registry.yarnpkg.com/babel-eslint/-/babel-eslint-10.1.0.tgz#6968e568a910b78fb3779cdd8b6ac2f479943232" - integrity sha512-ifWaTHQ0ce+448CYop8AdrQiBsGrnC+bMgfyKFdi6EsPLTAWG+QfyDeM6OH+FmWnKvEq5NnBMLvlBUPKQZoDSg== - dependencies: - "@babel/code-frame" "^7.0.0" - "@babel/parser" "^7.7.0" - "@babel/traverse" "^7.7.0" - "@babel/types" "^7.7.0" - eslint-visitor-keys "^1.0.0" - resolve "^1.12.0" - babel-eslint@^10.0.1: version "10.0.1" resolved "https://registry.yarnpkg.com/babel-eslint/-/babel-eslint-10.0.1.tgz#919681dc099614cd7d31d45c8908695092a1faed" @@ -3669,6 +3830,18 @@ babel-eslint@^10.0.1: eslint-scope "3.7.1" eslint-visitor-keys "^1.0.0" +babel-eslint@^10.1.0: + version "10.1.0" + resolved "https://registry.yarnpkg.com/babel-eslint/-/babel-eslint-10.1.0.tgz#6968e568a910b78fb3779cdd8b6ac2f479943232" + integrity sha512-ifWaTHQ0ce+448CYop8AdrQiBsGrnC+bMgfyKFdi6EsPLTAWG+QfyDeM6OH+FmWnKvEq5NnBMLvlBUPKQZoDSg== + dependencies: + "@babel/code-frame" "^7.0.0" + "@babel/parser" "^7.7.0" + "@babel/traverse" "^7.7.0" + "@babel/types" "^7.7.0" + eslint-visitor-keys "^1.0.0" + resolve "^1.12.0" + babel-helper-builder-react-jsx@^6.24.1: version "6.26.0" resolved "https://registry.yarnpkg.com/babel-helper-builder-react-jsx/-/babel-helper-builder-react-jsx-6.26.0.tgz#39ff8313b75c8b65dceff1f31d383e0ff2a408a0" @@ -8353,7 +8526,7 @@ global-prefix@^3.0.0: kind-of "^6.0.2" which "^1.3.1" -global@^4.3.0, global@^4.3.2: +global@^4.3.0, global@^4.3.2, global@~4.3.0: version "4.3.2" resolved "https://registry.yarnpkg.com/global/-/global-4.3.2.tgz#e76989268a6c74c38908b1305b10fc0e394e9d0f" integrity sha1-52mJJopsdMOJCLEwWxD8DjlOnQ8= @@ -10673,6 +10846,11 @@ lodash@^4.17.13, lodash@^4.17.14, lodash@^4.2.1: resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.15.tgz#b447f6670a0455bbfeedd11392eff330ea097548" integrity sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A== +lodash@^4.17.19: + version "4.17.20" + resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.20.tgz#b44a9b6297bcb698f1c51a3545a2b3b368d59c52" + integrity sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA== + loglevel@^1.4.1, loglevel@^1.6.1: version "1.6.1" resolved "https://registry.yarnpkg.com/loglevel/-/loglevel-1.6.1.tgz#e0fc95133b6ef276cdc8887cdaf24aa6f156f8fa" @@ -13125,6 +13303,13 @@ raf@^3.1.0, raf@^3.4.0: dependencies: performance-now "^2.1.0" +rafl@~1.2.1: + version "1.2.2" + resolved "https://registry.yarnpkg.com/rafl/-/rafl-1.2.2.tgz#fe930f758211020d47e38815f5196a8be4150740" + integrity sha1-/pMPdYIRAg1H44gV9Rlqi+QVB0A= + dependencies: + global "~4.3.0" + railroad-diagrams@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/railroad-diagrams/-/railroad-diagrams-1.0.0.tgz#eb7e6267548ddedfb899c1b90e57374559cddb7e" @@ -13188,6 +13373,11 @@ raw-body@2.4.0: iconv-lite "0.4.24" unpipe "1.0.0" +raw-loader@0.5.1: + version "0.5.1" + resolved "https://registry.yarnpkg.com/raw-loader/-/raw-loader-0.5.1.tgz#0c3d0beaed8a01c966d9787bf778281252a979aa" + integrity sha1-DD0L6u2KAclm2Xh793goElKpeao= + raw-loader@2.0.0, raw-loader@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/raw-loader/-/raw-loader-2.0.0.tgz#e2813d9e1e3f80d1bbade5ad082e809679e20c26" @@ -13615,6 +13805,14 @@ react-syntax-highlighter@^8.0.1: prismjs "^1.8.4" refractor "^2.4.1" +react-tabs@2.3.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/react-tabs/-/react-tabs-2.3.0.tgz#0c37e786f288d369824acd06a96bd1818ab8b0dc" + integrity sha512-pYaefgVy76/36AMEP+B8YuVVzDHa3C5UFZ3REU78zolk0qMxEhKvUFofvDCXyLZwf0RZjxIfiwok1BEb18nHyA== + dependencies: + classnames "^2.2.0" + prop-types "^15.5.0" + react-tabs@3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/react-tabs/-/react-tabs-3.0.0.tgz#60311a17c755eb6aa9b3310123e67db421605127" @@ -14624,6 +14822,13 @@ schema-utils@^1.0.0: ajv-errors "^1.0.0" ajv-keywords "^3.1.0" +scroll@^2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/scroll/-/scroll-2.0.3.tgz#0951b785544205fd17753bc3d294738ba16fc2ab" + integrity sha512-3ncZzf8gUW739h3LeS68nSssO60O+GGjT3SxzgofQmT8PIoyHzebql9HHPJopZX8iT6TKOdwaWFMqL6LzUN3DQ== + dependencies: + rafl "~1.2.1" + scroll@^3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/scroll/-/scroll-3.0.1.tgz#d5afb59fb3592ee3df31c89743e78b39e4cd8a26"