Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implemented file/folder move in resource manager. #4149

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -312,4 +312,10 @@
<data name="RemoveFolderTypeDialogHeader.Text" xml:space="preserve">
<value>Remove Folder Type</value>
</data>
<data name="MoveItem.Text" xml:space="preserve">
<value>Move Item</value>
</data>
<data name="NewLocation.Text" xml:space="preserve">
<value>New Location</value>
</data>
</root>
Original file line number Diff line number Diff line change
Expand Up @@ -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))
Expand Down
20 changes: 19 additions & 1 deletion DNN Platform/Modules/ResourceManager/Components/IItemsManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ public interface IItemsManager
/// </summary>
/// <param name="fileId">id of the file to delete.</param>
/// <param name="moduleMode">Current mode of the module instance.</param>
/// <param name="groupId">Id of the group (For Group Mode).</param>
/// <param name="groupId">Id of the group (for group mode).</param>
void DeleteFile(int fileId, int moduleMode, int groupId);

/// <summary>
Expand All @@ -75,5 +75,23 @@ public interface IItemsManager
/// <param name="unlinkAllowedStatus">Unlink allowed status.</param>
/// <param name="moduleMode">Current mode of the module instance.</param>
void DeleteFolder(int folderId, bool unlinkAllowedStatus, int moduleMode);

/// <summary>
/// Moves a file into a folder.
/// </summary>
/// <param name="sourceFileId">The id of the file to move.</param>
/// <param name="destinationFolderId">The id of the folder to move the file into.</param>
/// <param name="moduleMode">Current mode of the module instance.</param>
/// <param name="groupId">Id of the group (gor group mode).</param>
void MoveFile(int sourceFileId, int destinationFolderId, int moduleMode, int groupId);

/// <summary>
/// Moves a folder into another folder.
/// </summary>
/// <param name="sourceFolderId">The id of the folder to move.</param>
/// <param name="destinationFolderId">The id of the folder into which to move the source folder.</param>
/// <param name="moduleMode">Current mode of the module instance.</param>
/// <param name="groupId">Id of the group (for group mode).</param>
void MoveFolder(int sourceFolderId, int destinationFolderId, int moduleMode, int groupId);
}
}
53 changes: 53 additions & 0 deletions DNN Platform/Modules/ResourceManager/Components/ItemsManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,59 @@ public void DeleteFolder(int folderId, bool unlinkAllowedStatus, int moduleMode)
AssetManager.Instance.DeleteFolder(folderId, unlinkAllowedStatus, nonDeletedSubfolders);
}

/// <inheritdoc/>
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);
}

/// <inheritdoc/>
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);
}

/// <inheritdoc />
protected override Func<IItemsManager> GetFactory()
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,8 @@
<Compile Include="Services\Dto\FileDetailsRequest.cs" />
<Compile Include="Services\Dto\FolderDetailsRequest.cs" />
<Compile Include="Services\Dto\FolderPermissions.cs" />
<Compile Include="Services\Dto\MoveFileRequest.cs" />
<Compile Include="Services\Dto\MoveFolderRequest.cs" />
<Compile Include="Services\Dto\Permission.cs" />
<Compile Include="Services\Dto\Permissions.cs" />
<Compile Include="Services\Dto\RolePermission.cs" />
Expand Down Expand Up @@ -284,4 +286,4 @@
</FlavorProperties>
</VisualStudio>
</ProjectExtensions>
</Project>
</Project>
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Original file line number Diff line number Diff line change
Expand Up @@ -10,23 +10,75 @@ 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() {
return {
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,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@ const FileDetails = ({file, handlers, validationErrors}) => (
<span className="details-label">{localizeService.getString("URL")}:</span>
<a target="_blank" rel="noopener noreferrer" href={itemService.getItemFullUrl(file.url)}>{itemService.getItemFullUrl(file.url)}</a>
</div>

</div>
<div className="separator"></div>
<div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ const Item = ({item, iconUrl, handlers, isHighlighted, isDetailed}) => (
{ handlers.onEdit ? <div className="rm-edit" onClick={handlers.onEdit}></div> : "" }
{ handlers.onCopyToClipboard ? <div className="rm-link" onClick={handlers.onCopyToClipboard}></div> : "" }
{ handlers.onDownload ? <div className="rm-download" onClick={handlers.onDownload}></div> : "" }
{ handlers.onMove ? <div className="rm-move" onClick={handlers.onMove}></div> : ""}
{ handlers.onDelete ? <div className="rm-delete" onClick={handlers.onDelete}></div> : "" }
</div>
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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";

Expand Down Expand Up @@ -46,6 +47,20 @@ class AssetsPanelContainer extends React.Component {
);
}

getMovePanel(showPanel, i) {
return (
<ReactCSSTransitionGroup
key={"item-move-" + i}
transitionName="dnn-slide-in-out"
transitionEnterTimeout={500}
transitionLeaveTimeout={300}
transitionLeave={!showPanel}
>
{showPanel && <ItemMoveContainer />}
</ReactCSSTransitionGroup>
);
}

handleScroll() {
const { folderPanelState, loadContent, searchFiles } = this.props;
const { totalCount, loadedItems, search, loading } = folderPanelState;
Expand Down Expand Up @@ -74,6 +89,7 @@ class AssetsPanelContainer extends React.Component {
const {
items,
itemEditing,
itemMoving,
search,
itemContainerDisabled,
loading,
Expand All @@ -86,18 +102,34 @@ class AssetsPanelContainer extends React.Component {
const { itemId, itemName, isFolder } = item;
result.push(<Item key={itemId + itemName} item={item} />);

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 (
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -180,6 +213,7 @@ function mapStateToProps(state) {
addFolderPanelState.expanded || addAssetPanelState.expanded,
loading: folderPanelState.loading,
itemEditing: itemDetailsState.itemEditing,
itemMoving: itemDetailsState.itemMoving,
itemWidth: folderPanelState.itemWidth,
};
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -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
};

Expand All @@ -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,
Expand Down Expand Up @@ -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,
Expand Down
Loading