Skip to content

Commit

Permalink
Merge pull request #7594 from weseek/feat/115447-119724-limit-directo…
Browse files Browse the repository at this point in the history
…ry-maximum-deps

feat: Maximum folder hierarchy of two levels
  • Loading branch information
Ryoji Shimizu authored Apr 27, 2023
2 parents 08a338f + e4ccc3c commit ab0088b
Show file tree
Hide file tree
Showing 4 changed files with 60 additions and 35 deletions.
30 changes: 21 additions & 9 deletions apps/app/src/components/Bookmarks/BookmarkFolderItem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -152,11 +152,19 @@ export const BookmarkFolderItem: FC<BookmarkFolderItemProps> = (props: BookmarkF
}
};

const isDroppable = (item: DragItemDataType, type: string | null| symbol): boolean => {
const isDropable = (item: DragItemDataType, type: string | null| symbol): boolean => {
if (type === DRAG_ITEM_TYPE.FOLDER) {
if (item.bookmarkFolder.parent === bookmarkFolder._id || item.bookmarkFolder._id === bookmarkFolder._id) {
return false;
}

// Maximum folder hierarchy of 2 levels
// If the drop source folder has child folders, the drop source folder cannot be moved because the drop source folder hierarchy is already 2.
// If the destination folder has a parent, the source folder cannot be moved because the destination folder hierarchy is already 2.
if (item.bookmarkFolder.children.length !== 0 || bookmarkFolder.parent != null) {
return false;
}

return item.root !== root || item.level >= level;
}

Expand Down Expand Up @@ -228,7 +236,7 @@ export const BookmarkFolderItem: FC<BookmarkFolderItemProps> = (props: BookmarkF
useDragMode={true}
useDropMode={true}
onDropItem={itemDropHandler}
isDropable={isDroppable}
isDropable={isDropable}
>
<li
className={'list-group-item list-group-item-action border-0 py-0 pr-3 d-flex align-items-center'}
Expand Down Expand Up @@ -277,13 +285,17 @@ export const BookmarkFolderItem: FC<BookmarkFolderItemProps> = (props: BookmarkF
</DropdownToggle>
</div>
</BookmarkFolderItemControl>
<button
type="button"
className="border-0 rounded btn btn-page-item-control p-0 grw-visible-on-hover"
onClick={onClickPlusButton}
>
<i className="icon-plus d-block p-0" />
</button>
{/* Maximum folder hierarchy of 2 levels */}
{!(bookmarkFolder.parent != null) && (
<button
id='create-bookmark-folder-button'
type="button"
className="border-0 rounded btn btn-page-item-control p-0 grw-visible-on-hover"
onClick={onClickPlusButton}
>
<i className="icon-plus d-block p-0" />
</button>
)}
</div>
</li>
</DragAndDropWrapper>
Expand Down
35 changes: 14 additions & 21 deletions apps/app/src/components/Bookmarks/BookmarkFolderMenuItem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import React, {
import { useTranslation } from 'next-i18next';
import {
DropdownItem,
DropdownMenu, DropdownToggle, UncontrolledDropdown, UncontrolledTooltip,
DropdownMenu, DropdownToggle, UncontrolledDropdown,
} from 'reactstrap';

import {
Expand Down Expand Up @@ -201,29 +201,22 @@ export const BookmarkFolderMenuItem = (props: Props): JSX.Element => {
>
<i className="icon-fw icon-trash grw-page-control-dropdown-icon"></i>
</DropdownToggle>
<DropdownToggle
color="transparent"
onClick={e => e.stopPropagation()}
onMouseEnter={onMouseEnterHandler}
>
{childrenExists
? <TriangleIcon />
: (
<i className="icon-plus d-block pl-0" />
)}
</DropdownToggle>
{/* Maximum folder hierarchy of 2 levels */}
{item.parent == null && (
<DropdownToggle
color="transparent"
onClick={e => e.stopPropagation()}
onMouseEnter={onMouseEnterHandler}
>
{childrenExists
? <TriangleIcon />
: <i className="icon-plus d-block pl-0" />
}
</DropdownToggle>
)}
{renderBookmarkSubMenuItem()}

</UncontrolledDropdown >
<UncontrolledTooltip
modifiers={{ preventOverflow: { boundariesElement: 'window' } }}
autohide={false}
placement="top"
target={`bookmark-delete-button-${item._id}`}
fade={false}
>
{t('bookmark_folder.delete')}
</UncontrolledTooltip>
</>
);
};
21 changes: 18 additions & 3 deletions apps/app/src/server/models/bookmark-folder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ import monggoose, {
Types, Document, Model, Schema,
} from 'mongoose';


import { IBookmarkFolder, BookmarkFolderItems, MyBookmarkList } from '~/interfaces/bookmark-info';
import { IPageHasId } from '~/interfaces/page';

Expand All @@ -16,7 +15,6 @@ import { InvalidParentBookmarkFolderError } from './errors';
const logger = loggerFactory('growi:models:bookmark-folder');
const Bookmark = monggoose.model('Bookmark');


export interface BookmarkFolderDocument extends Document {
_id: Types.ObjectId
name: string
Expand All @@ -39,7 +37,11 @@ export interface BookmarkFolderModel extends Model<BookmarkFolderDocument>{
const bookmarkFolderSchema = new Schema<BookmarkFolderDocument, BookmarkFolderModel>({
name: { type: String },
owner: { type: Schema.Types.ObjectId, ref: 'User', index: true },
parent: { type: Schema.Types.ObjectId, ref: 'BookmarkFolder', required: false },
parent: {
type: Schema.Types.ObjectId,
ref: 'BookmarkFolder',
required: false,
},
bookmarks: {
type: [{
type: Schema.Types.ObjectId, ref: 'Bookmark', required: false,
Expand Down Expand Up @@ -154,6 +156,19 @@ bookmarkFolderSchema.statics.updateBookmarkFolder = async function(bookmarkFolde
const parentFolder = parentId ? await this.findById(parentId) : null;
updateFields.parent = parentFolder?._id ?? null;

// Maximum folder hierarchy of 2 levels
// If the destination folder (parentFolder) has a parent, the source folder cannot be moved because the destination folder hierarchy is already 2.
// If the drop source folder has child folders, the drop source folder cannot be moved because the drop source folder hierarchy is already 2.
if (parentId != null) {
if (parentFolder?.parent != null) {
throw new Error('Update bookmark folder failed');
}
const bookmarkFolder = await this.findById(bookmarkFolderId).populate('children');
if (bookmarkFolder?.children?.length !== 0) {
throw new Error('Update bookmark folder failed');
}
}

const bookmarkFolder = await this.findByIdAndUpdate(bookmarkFolderId, { $set: updateFields }, { new: true });
if (bookmarkFolder == null) {
throw new Error('Update bookmark folder failed');
Expand Down
9 changes: 7 additions & 2 deletions apps/app/src/server/routes/apiv3/bookmark-folder.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import { ErrorV3 } from '@growi/core';
import { body } from 'express-validator';

import { BookmarkFolderItems } from '~/interfaces/bookmark-info';
import { apiV3FormValidator } from '~/server/middlewares/apiv3-form-validator';
import { InvalidParentBookmarkFolderError } from '~/server/models/errors';
import loggerFactory from '~/utils/logger';
Expand All @@ -17,7 +16,13 @@ const router = express.Router();
const validator = {
bookmarkFolder: [
body('name').isString().withMessage('name must be a string'),
body('parent').isMongoId().optional({ nullable: true }),
body('parent').isMongoId().optional({ nullable: true })
.custom(async(parent: string) => {
const parentFolder = await BookmarkFolder.findById(parent);
if (parentFolder == null || parentFolder.parent != null) {
throw new Error('Maximum folder hierarchy of 2 levels');
}
}),
],
bookmarkPage: [
body('pageId').isMongoId().withMessage('Page ID must be a valid mongo ID'),
Expand Down

0 comments on commit ab0088b

Please sign in to comment.