From ecca46c73ebcd99e7243319ac8420204e16bf396 Mon Sep 17 00:00:00 2001 From: subnub Date: Fri, 21 Jun 2024 03:38:53 -0400 Subject: [PATCH] fixed and improved context menu, removed more SCSS, added expand and improved quick access items --- backend/controllers/file.ts | 3 +- backend/db/utils/fileUtils/index.ts | 8 +- backend/services/FileService/index.ts | 11 +- src/api/filesAPI.ts | 6 +- src/components/Dataform/DataForm.jsx | 22 +- src/components/FolderItem/index.jsx | 455 +++++++++--------- .../NewContextMenu/NewContextMenu.jsx | 104 +++- src/components/QuickAccess/index.jsx | 28 +- .../QuickAccessItem/QuickAccessItem.jsx | 25 +- src/components/QuickAccessItem/index.jsx | 5 +- src/styles/components/file_panel.scss | 5 - src/styles/styles.scss | 12 + 12 files changed, 392 insertions(+), 292 deletions(-) diff --git a/backend/controllers/file.ts b/backend/controllers/file.ts index f13c45e..d880942 100644 --- a/backend/controllers/file.ts +++ b/backend/controllers/file.ts @@ -219,8 +219,9 @@ class FileController { try { const user = req.user; + const limit = req.query.limit?.toString(); - const quickList = await fileService.getQuickList(user); + const quickList = await fileService.getQuickList(user, limit); res.send(quickList); } catch (e: unknown) { diff --git a/backend/db/utils/fileUtils/index.ts b/backend/db/utils/fileUtils/index.ts index f4508b7..bee31cf 100644 --- a/backend/db/utils/fileUtils/index.ts +++ b/backend/db/utils/fileUtils/index.ts @@ -82,18 +82,14 @@ class DbUtil { return file; }; - getQuickList = async (userID: string, s3Enabled: boolean) => { + getQuickList = async (userID: string, limit: number) => { let query: any = { "metadata.owner": userID }; - if (!s3Enabled) { - query = { ...query, "metadata.personalFile": null }; - } - const fileList = (await conn.db .collection("fs.files") .find(query) .sort({ uploadDate: -1 }) - .limit(10) + .limit(limit) .toArray()) as FileInterface[]; return fileList; diff --git a/backend/services/FileService/index.ts b/backend/services/FileService/index.ts index 450ee75..0ac11b9 100644 --- a/backend/services/FileService/index.ts +++ b/backend/services/FileService/index.ts @@ -102,14 +102,13 @@ class MongoFileService { return { ...currentFile, parentName }; }; - getQuickList = async (user: userAccessType | UserInterface) => { + getQuickList = async ( + user: userAccessType | UserInterface, + limit: number | string = 12 + ) => { const userID = user._id; - const s3Enabled = user.s3Enabled ? true : false; - const quickList = await dbUtilsFile.getQuickList( - userID.toString(), - s3Enabled - ); + const quickList = await dbUtilsFile.getQuickList(userID.toString(), +limit); if (!quickList) throw new NotFoundError("Quick List Not Found Error"); diff --git a/src/api/filesAPI.ts b/src/api/filesAPI.ts index a665568..e753cce 100644 --- a/src/api/filesAPI.ts +++ b/src/api/filesAPI.ts @@ -40,6 +40,10 @@ export const getFilesList = async ({ }; export const getQuickFilesList = async () => { - const response = await axios.get(`/file-service/quick-list`); + const response = await axios.get(`/file-service/quick-list`, { + params: { + limit: 12, + }, + }); return response.data; }; diff --git a/src/components/Dataform/DataForm.jsx b/src/components/Dataform/DataForm.jsx index e8a7dce..18e23f4 100644 --- a/src/components/Dataform/DataForm.jsx +++ b/src/components/Dataform/DataForm.jsx @@ -142,15 +142,19 @@ const DataForm = (props) => { {!props.listView ? (
- {files?.pages.map((file) => ( - + {files?.pages.map((filePage, index) => ( + + {filePage.map((file) => ( + + ))} + ))}
) : ( diff --git a/src/components/FolderItem/index.jsx b/src/components/FolderItem/index.jsx index 6a963d3..c55a68a 100644 --- a/src/components/FolderItem/index.jsx +++ b/src/components/FolderItem/index.jsx @@ -1,7 +1,11 @@ -import FolderItem from "./FolderItem" -import {startSetSelectedItem, setRightSelected, setLastSelected} from "../../actions/selectedItem" -import mobileCheck from "../../utils/mobileCheck" -import {connect} from "react-redux"; +import FolderItem from "./FolderItem"; +import { + startSetSelectedItem, + setRightSelected, + setLastSelected, +} from "../../actions/selectedItem"; +import mobileCheck from "../../utils/mobileCheck"; +import { connect } from "react-redux"; import React from "react"; import { startRenameFolder, startRemoveFolder } from "../../actions/folders"; import Swal from "sweetalert2"; @@ -10,240 +14,239 @@ import mobilecheck from "../../utils/mobileCheck"; import { setMobileContextMenu } from "../../actions/mobileContextMenu"; class FolderItemContainer extends React.Component { + constructor(props) { + super(props); - constructor(props) { - super(props) + this.lastTouch = 0; - this.lastTouch = 0; + this.state = { + contextSelected: false, + }; + } - this.state = { - contextSelected: false + shouldComponentUpdate = (nextProp, nextState) => { + return ( + nextProp.itemSelected !== this.props.itemSelected || + nextProp.listView !== this.props.listView || + nextProp.rightSelected !== this.props.rightSelected || + nextProp.name !== this.props.name || + nextProp.quickFilesLength !== this.props.quickFilesLength || + nextState.contextSelected !== this.state.contextSelected + ); + }; + + onTouchStart = () => { + const date = new Date(); + this.lastTouch = date.getTime(); + }; + + onTouchMove = () => { + this.lastTouch = 0; + }; + + onTouchEnd = () => { + if (this.lastTouch === 0) { + return; + } + + const date = new Date(); + const difference = date - this.lastTouch; + + this.lastTouch = 0; + + if (difference > 500) { + this.selectContext(); + } + }; + + getContextMenu = (e) => { + if (e) e.preventDefault(); + + const isMobile = mobileCheck(); + + const windowX = window.innerWidth; + const windowY = window.innerHeight; + + let styleObj = { right: 0, left: 0, top: "-14px", bottom: 0 }; + + if (isMobile) { + styleObj = { bottom: 0, left: "2px", top: "unset" }; + } else { + const clientY = e.nativeEvent.clientY; + const clientX = e.nativeEvent.clientX; + + if (clientY < windowY / 3) { + const bottomSize = + this.props.quickFilesLength === 0 ? "-126px" : "-190px"; + + styleObj = { bottom: bottomSize, top: "unset" }; + } + + if (clientY > (windowY / 4) * 3.5) { + styleObj = { bottom: "unset", top: "-190px" }; + } + + if (clientX > windowX / 2) { + styleObj = { ...styleObj, left: "unset", right: 0 }; + } else { + styleObj = { ...styleObj, left: 0, right: "unset" }; + } + } + + this.setState(() => styleObj); + + this.props.dispatch(startSetSelectedItem(this.props._id, false)); + this.props.dispatch(setLastSelected(0)); + this.props.dispatch(setRightSelected(this.props._id)); + }; + + getClassName = () => { + let classname = ""; + + if (this.props.listView) { + classname += "file__item__listview"; + } else { + classname += "folder__item__wrapper"; + } + + if (this.props._id === this.props.selected) { + classname += " file__item--selected"; + } + + return classname; + }; + + changeEditNameMode = async () => { + let inputValue = this.props.name; + + const { value: folderName } = await Swal.fire({ + title: "Enter A File Name", + input: "text", + inputValue: inputValue, + showCancelButton: true, + inputValidator: (value) => { + if (!value) { + return "Please Enter a Name"; } + }, + }); + + if (folderName === undefined || folderName === null) { + return; } - shouldComponentUpdate = (nextProp, nextState) => { + this.props.dispatch( + startRenameFolder( + this.props._id, + folderName, + this.props.drive, + this.props.parent + ) + ); + }; - return (nextProp.itemSelected !== this.props.itemSelected - || nextProp.listView !== this.props.listView - || nextProp.rightSelected !== this.props.rightSelected - || nextProp.name !== this.props.name - || nextProp.quickFilesLength !== this.props.quickFilesLength - || nextState.contextSelected !== this.state.contextSelected) + closeEditNameMode = () => { + this.setState(() => { + return { + ...this.state, + editNameMode: false, + }; + }); + }; + + changeDeleteMode = async () => { + Swal.fire({ + title: "Confirm Deletion", + text: "You cannot undo this action", + icon: "warning", + showCancelButton: true, + confirmButtonColor: "#3085d6", + cancelButtonColor: "#d33", + confirmButtonText: "Yes, delete", + }).then((result) => { + if (result.value) { + this.props.dispatch( + startRemoveFolder( + this.props._id, + [...this.props.parentList, this.props._id], + this.props.drive, + this.props.parent, + this.props.personalFolder + ) + ); + } + }); + }; + + closeContext = () => { + this.setState(() => { + return { + ...this.state, + contextSelected: false, + }; + }); + }; + + selectContext = (e) => { + if (e) e.stopPropagation(); + if (e) e.preventDefault(); + + if (mobilecheck()) { + this.props.dispatch(setMobileContextMenu(false, this.props)); + + return; } - onTouchStart = () => { - const date = new Date(); - this.lastTouch = date.getTime(); - } + this.setState(() => { + return { + ...this.state, + contextSelected: { + width: e.clientX, + height: e.clientY, + }, + }; + }); + }; - onTouchMove = () => { - - this.lastTouch = 0; - } - - onTouchEnd = () => { - - if (this.lastTouch === 0) { - return; - } - - const date = new Date(); - const difference = date - this.lastTouch; - - this.lastTouch = 0; - - if (difference > 500) { - this.selectContext() - } - - } - - getContextMenu = (e) => { - - if (e) e.preventDefault(); - - const isMobile = mobileCheck(); - - const windowX = window.innerWidth; - const windowY = window.innerHeight; - - let styleObj = {right:0, left:0, top: "-14px", bottom: 0} - - if (isMobile) { - - styleObj = {bottom: 0, left: "2px", top:"unset"} - - } else { - - const clientY = e.nativeEvent.clientY; - const clientX = e.nativeEvent.clientX; - - - if (clientY < (windowY / 3)) { - - const bottomSize = this.props.quickFilesLength === 0 ? "-126px" : "-190px" - - styleObj = {bottom: bottomSize, top:"unset"} - } - - if (clientY > ((windowY / 4) * 3.5)) { - - styleObj = {bottom:"unset", top: "-190px"} - } - - if (clientX > windowX / 2) { - - styleObj = {...styleObj, left:"unset", right:0} - - } else { - - styleObj = {...styleObj, left:0, right:"unset"} - } - } - - this.setState(() => styleObj) - - this.props.dispatch(startSetSelectedItem(this.props._id, false)) - this.props.dispatch(setLastSelected(0)); - this.props.dispatch(setRightSelected(this.props._id)) - - } - - getClassName = () => { - - let classname = ""; - - if (this.props.listView) { - - classname += "file__item__listview" - - } else { - - classname += "folder__item__wrapper" - } - - if (this.props._id === this.props.selected) { - - classname += " file__item--selected" - } - - return classname; - } - - changeEditNameMode = async() => { - - let inputValue = this.props.name; - - const { value: folderName} = await Swal.fire({ - title: 'Enter A File Name', - input: 'text', - inputValue: inputValue, - showCancelButton: true, - inputValidator: (value) => { - if (!value) { - return 'Please Enter a Name' - } - } - }) - - if (folderName === undefined || folderName === null) { - - return; - } - - this.props.dispatch(startRenameFolder(this.props._id, folderName, this.props.drive, this.props.parent)); - } - - closeEditNameMode = () => { - - this.setState(() => { - - return { - ...this.state, - editNameMode: false - } - }) - } - - changeDeleteMode = async() => { - - Swal.fire({ - title: 'Confirm Deletion', - text: "You cannot undo this action", - icon: 'warning', - showCancelButton: true, - confirmButtonColor: '#3085d6', - cancelButtonColor: '#d33', - confirmButtonText: 'Yes, delete' - }).then((result) => { - if (result.value) { - this.props.dispatch(startRemoveFolder(this.props._id, [...this.props.parentList, this.props._id], this.props.drive, this.props.parent, this.props.personalFolder)) - } - }) - } - - - closeContext = () => { - - this.setState(() => { - return { - ...this.state, - contextSelected: false - } - }) - } - - selectContext = (e) => { - - if (e) e.stopPropagation() - if (e) e.preventDefault(); - - if (mobilecheck()) { - - this.props.dispatch(setMobileContextMenu(false, this.props)) - - return; - } - - this.setState(() => { - return { - ...this.state, - contextSelected: !this.state.contextSelected - } - }) - } - - startMoveFolder = async() => { - - this.props.dispatch(setMoverID(this.props._id, this.props.parent, false, this.props.drive, this.props.personalFolder)); - } - - render() { - - return - } + startMoveFolder = async () => { + this.props.dispatch( + setMoverID( + this.props._id, + this.props.parent, + false, + this.props.drive, + this.props.personalFolder + ) + ); + }; + render() { + return ( + + ); + } } const connectPropToState = (state) => ({ - listView: state.filter.listView, - rightSelected: state.selectedItem.rightSelected, - resetSelected: state.selectedItem.resetSelected, - selected: state.selectedItem.selected, - quickFilesLength: state.quickFiles.length -}) + listView: state.filter.listView, + rightSelected: state.selectedItem.rightSelected, + resetSelected: state.selectedItem.resetSelected, + selected: state.selectedItem.selected, + quickFilesLength: state.quickFiles.length, +}); -export default connect(connectPropToState)(FolderItemContainer); \ No newline at end of file +export default connect(connectPropToState)(FolderItemContainer); diff --git a/src/components/NewContextMenu/NewContextMenu.jsx b/src/components/NewContextMenu/NewContextMenu.jsx index 79f1d98..c79f610 100644 --- a/src/components/NewContextMenu/NewContextMenu.jsx +++ b/src/components/NewContextMenu/NewContextMenu.jsx @@ -1,25 +1,91 @@ +import classNames from "classnames"; import React from "react"; class NewContextMenu extends React.Component { - - constructor(props) { - super(props); - } + constructor(props) { + super(props); + } - render() { - return ( - // settings__folder__margin -
- -
- ) - } + render() { + return ( + // settings__folder__margin +
+ +
+ ); + } } -export default NewContextMenu; \ No newline at end of file +export default NewContextMenu; diff --git a/src/components/QuickAccess/index.jsx b/src/components/QuickAccess/index.jsx index 7d9d053..51bf350 100644 --- a/src/components/QuickAccess/index.jsx +++ b/src/components/QuickAccess/index.jsx @@ -1,11 +1,13 @@ import { useSelector } from "react-redux"; import QuickAccessItem from "../QuickAccessItem"; -import React from "react"; +import React, { useState } from "react"; import { useQuickFiles } from "../../hooks/files"; +import classNames from "classnames"; const QuickAccess = (props) => { const { data: quickfilesList } = useQuickFiles(); const currentRouteType = useSelector((state) => state.main.currentRouteType); + const [quickAccessExpanded, setQuickAccessExpanded] = useState(false); return (
{ currentRouteType === "home" ? { display: "block" } : { display: "none" } } > -
-

+
+

Quick Access

+ setQuickAccessExpanded(!quickAccessExpanded)} + className={classNames("cursor-pointer animate", { + "rotate-180": quickAccessExpanded, + })} + > + +
{ return (
{ props.fileClick(props._id, props, true); @@ -134,28 +137,22 @@ const QuickAccessItem = (props) => {

{capitalize(props.filename)}

Created {moment(props.uploadDate).calendar()} diff --git a/src/components/QuickAccessItem/index.jsx b/src/components/QuickAccessItem/index.jsx index 6b98ed9..54b4360 100644 --- a/src/components/QuickAccessItem/index.jsx +++ b/src/components/QuickAccessItem/index.jsx @@ -63,7 +63,10 @@ class QuickAccessItemContainer extends React.Component { this.setState(() => { return { ...this.state, - contextSelected: !this.state.contextSelected, + contextSelected: { + width: e.clientX, + height: e.clientY, + }, }; }); }; diff --git a/src/styles/components/file_panel.scss b/src/styles/components/file_panel.scss index 55d9791..cf437ad 100644 --- a/src/styles/components/file_panel.scss +++ b/src/styles/components/file_panel.scss @@ -802,16 +802,11 @@ & .settings__drop { display: none; position: absolute; - // left:-60%; - // right:50%; - //bottom:auto; min-width: 215px; background: #ffffff; box-shadow: 0px 2px 4px rgba(0, 0, 0, 0.15), inset 0px 1px 0px #f5f7fa; border-radius: 4px; - //top: -100%; margin-top: -5px; - transform: translate(0%, -80%); z-index: 2; // @media (max-width: $desktop-breakpoint) { // transform: translate(-6%,-80%) !important; diff --git a/src/styles/styles.scss b/src/styles/styles.scss index 2cc0af4..5c0963d 100644 --- a/src/styles/styles.scss +++ b/src/styles/styles.scss @@ -40,3 +40,15 @@ @import "./components/main.scss"; @import "./components/settings.scss"; @import "./components/MobileContextMenu"; + +.animate { + transition: 0.3s ease all; +} + +.animate-medium { + transition: 0.6s ease all; +} + +.animate-very-long { + transition: 6s ease all; +}