Skip to content

Commit

Permalink
add renaming for fs dashboard
Browse files Browse the repository at this point in the history
  • Loading branch information
chetbae committed Jul 7, 2023
1 parent 5eb2206 commit 918fdf3
Show file tree
Hide file tree
Showing 5 changed files with 128 additions and 55 deletions.
23 changes: 3 additions & 20 deletions deployment/server/css/dashboard.css
Original file line number Diff line number Diff line change
Expand Up @@ -65,23 +65,6 @@
}
}

/* Section: Action Bar */
.action-bar-section {
max-height: 0px;
overflow: hidden;
transition: 0.3s ease-in-out;
width: 100%;
display: flex;
flex-direction: row;
justify-content: space-around;
align-items: center;
}

.action-bar-section.visible {
max-height: 5vh;
min-height: 3vh;
}

/* Section: Main (Content) */
.main-section {
height: 92vh;
Expand Down Expand Up @@ -134,7 +117,7 @@
color: #589ed5;
}

#fs-back-btn {
/* #fs-back-btn {
font-size: 14px;
font-weight: 900;
letter-spacing: 3px;
Expand All @@ -150,7 +133,7 @@
#fs-back-btn.active {
cursor: pointer;
opacity: 100%;
}
} */

.fs-content-container {
display: flex;
Expand Down Expand Up @@ -229,6 +212,7 @@
align-items: center;
justify-content: center;
opacity: 0.4;
cursor: auto;
}

.action-bar-item-container.active {
Expand All @@ -242,7 +226,6 @@
flex-direction: row;
justify-content: center;
align-items: center;
cursor: pointer;
font-size: 30px;
width: 50%;
}
Expand Down
131 changes: 102 additions & 29 deletions src/Dashboard/DocumentSelector.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { IEntry, IFile, IFolder, fs_functions } from './FileSystem';
import { deleteEntry } from './Storage';
import { formatFilename } from './upload_functions';
import FileSystemManager from './FileSystem/FileSystemManager';
import { FileSystemManager } from './FileSystem';
import ShiftSelectionManager from './ShiftSelectionManager';
import { InitUploadArea } from './UploadArea';

Expand All @@ -13,8 +13,8 @@ const deleteButton: HTMLButtonElement = document.querySelector('#remove-doc');
// const navBackButton: HTMLButtonElement = document.querySelector('#fs-back-btn');
const navPathContainer: HTMLDivElement = document.querySelector('#nav-path-container');

const uploadDocumentsButton = document.querySelector('#upload-new-doc-button');
const newFolderButton = document.querySelector('#add-folder-button');
const uploadDocumentsButton: HTMLButtonElement = document.querySelector('#upload-new-doc-button');
const newFolderButton: HTMLButtonElement = document.querySelector('#add-folder-button');

const shiftSelection = new ShiftSelectionManager();
const fsm = FileSystemManager();
Expand All @@ -31,17 +31,28 @@ let shiftKeyIsPressed = false;
// navBackButton!.addEventListener('click', handleNavigateBack);
openButton!.addEventListener('click', handleOpenDocuments);
deleteButton!.addEventListener('click', handleDeleteDocuments);
uploadDocumentsButton!.addEventListener('click', () => InitUploadArea(currentPath.at(-1)));
uploadDocumentsButton!.addEventListener('click', handleUploadDocuments);
newFolderButton!.addEventListener('click', handleCreateFolder)

function handleUploadDocuments() {
const isImmutable = currentPath.at(-1).metadata['immutable'];
if (isImmutable) {
const stringPath = currentPath.map(folder => folder.name).join('/');
window.alert(`Cannot upload documents. ${stringPath} is immutable.`);
return false;
}
InitUploadArea(currentPath.at(-1));
}


window.addEventListener('keydown', (e) => {
if (e.metaKey) metaKeyIsPressed = true;
if (e.shiftKey) shiftKeyIsPressed = true;
// Lose focus on esc key
if (e.key === 'Escape') {
unselectAll();
shiftSelection.reset();
setSidebarActions();
updateActionBarButtons();
}
});

Expand All @@ -50,19 +61,29 @@ window.addEventListener('keyup', (e) => {
if (!e.shiftKey) shiftKeyIsPressed = false;
});

window.addEventListener('keypress', (e) => {
if (e.key === 'Enter') {
const selections = getSelectionEntries();
if (selections.length === 1) {
const selected = selections[0];
handleRenaming(selected);
}
}
});

backgroundArea!.addEventListener('click', (e) => {
const target = e.target as Element;
// Lose focus if click event in main section is not a document tile
const isDocument = Boolean(target.closest('.document-entry'))
if (!isDocument) {
unselectAll();
shiftSelection.reset();
setSidebarActions();
updateActionBarButtons();
}
});

// gets user selected filenames
function getSelectionFilenames() {
function getSelectionEntries() {
return orderedEntries.filter((_, idx) => orderedSelection[idx]);
}

Expand Down Expand Up @@ -115,32 +136,44 @@ function select(idx: number, tile?: Element) {
orderedSelection[idx] = true;
}

// Determines whether to set delete doc or open doc to active
function setSidebarActions() {
// -1 if no selection, some value i if selected.
// if (idx=i) > orderedDocuments.length - samples.length, then no user uploads are selected.
const lastIdx = orderedSelection.lastIndexOf(true);
if (lastIdx === -1) {
// Determines whether to set action bar
function updateActionBarButtons() {
// set active if there is a selection
const nothingSelected = orderedSelection.every((selected) => !selected)
if (nothingSelected) {
openButton.classList.remove('active');
deleteButton.classList.remove('active');
}
else {
openButton.classList.add('active');
deleteButton.classList.add('active');
}

// update upload doc/add folder to active if parent folder isn't immutable
const isImmutable = currentPath.at(-1).metadata['immutable'];
if (isImmutable) {
uploadDocumentsButton.classList.remove('active');
newFolderButton.classList.remove('active');
deleteButton.classList.remove('active');
}
else {
uploadDocumentsButton.classList.add('active');
newFolderButton.classList.add('active');
}
}

// Creates a folder, folio, or manuscript tile element
function createTile(entry: IEntry) {
const doc = document.createElement('div');
doc.setAttribute('id', entry.name);
doc.classList.add('document-entry');
switch (entry.type) {
case 'folder':
doc.classList.add('folder-entry');
doc.setAttribute('id', entry.name);
break;
case 'file':
doc.classList.add('file-entry');
doc.setAttribute('id', (entry as IFile).content);
break;
}

Expand Down Expand Up @@ -200,28 +233,21 @@ function addShiftSelectionListener(tile: HTMLDivElement, index: number) {
select(idx);
});
}
setSidebarActions();
updateActionBarButtons();
}, false);
}

function handleOpenDocuments() {
getSelectionFilenames().forEach((entry: IEntry) => {
getSelectionEntries().forEach((entry: IEntry) => {
// Open document if it is a file and not a folder
if (entry.type === 'file') openFile(entry as IFile);
});
shiftSelection.reset();
unselectAll();
setSidebarActions();
updateActionBarButtons();
}

function handleDeleteDocuments() {
// abort if parent folder is immutable
const isImmutable = currentPath.at(-1).metadata['immutable'];
if (isImmutable) {
window.alert(`Cannot delete documents. ${currentPath.join('/')} is immutable.`);
return;
}

function deleteFileEntry(file: IFile): Promise<boolean> {
return new Promise((resolve, reject) => {
deleteEntry(file.content)
Expand Down Expand Up @@ -249,7 +275,7 @@ function handleDeleteDocuments() {
});
}

const allEntries = getSelectionFilenames();
const allEntries = getSelectionEntries();
const deletableEntries = allEntries.filter(entry => entry.metadata['immutable'] !== true);
const immutableEntries = allEntries.filter(entry => entry.metadata['immutable'] === true);

Expand Down Expand Up @@ -323,19 +349,63 @@ function updateNavPath(currentPath: IFolder[]): void {
}

function handleCreateFolder() {
// abort if parent folder is immutable
// abort if parent folder
const isImmutable = currentPath.at(-1).metadata['immutable'];
if (isImmutable) {
const stringPath = currentPath.map(folder => folder.name).join('>');
window.alert(`Cannot add folder. ${stringPath} is immutable.`);
return;
const stringPath = currentPath.map(folder => folder.name).join('/');
window.alert(`Cannot add Folder. ${stringPath} is immutable.`);
return false;
}

const folder = fs_functions.createFolder('new file');
fs_functions.addEntry(folder, currentPath.at(-1));
updateDocumentSelector();
}

// opens prompt to rename entry in file system, persist in local storage, and updates tile name
function handleRenaming(entry: IEntry): boolean {
// abort if parent folder
const isImmutable = currentPath.at(-1).metadata['immutable'];
if (isImmutable) {
const stringPath = currentPath.map(folder => folder.name).join('/');
window.alert(`Cannot rename ${entry.name}. ${stringPath} is immutable.`);
return false;
}
// or entry is immutable
const immutable = entry.metadata['immutable'];
if (immutable) {
window.alert(`Cannot rename ${entry.name}. Entry is immutable.`);
return false;
}

const oldName = entry.name;
const newName = promptNewName();
if (newName) {
const succeeded = fs_functions.renameEntry(entry, currentPath.at(-1), newName);
if (succeeded) {
fsm.setFileSystem(currentPath.at(0));
updateTileName(entry, oldName, newName);
return true;
}
}
return false;
}

function promptNewName() {
const newName = window.prompt('Enter new name:');
return newName;
}

// updates text and if applicable, id of tile element
function updateTileName(entry: IEntry, oldName: string, newName: string) {
const isFolder = (entry.type === 'folder');
// get tile element
const id: string = isFolder ? oldName : (entry as IFile).content;
const tile = document.getElementById(id);
if (isFolder) tile.setAttribute('id', newName);
tile.querySelector('.filename-text').innerHTML = formatFilename(newName, 25);
}

export async function updateDocumentSelector(newPath?: IFolder[]): Promise<void> {
if (!newPath) newPath = currentPath;
currentPath = newPath;
Expand All @@ -360,6 +430,9 @@ export async function updateDocumentSelector(newPath?: IFolder[]): Promise<void>
// update path display
updateNavPath(currentPath);

// update action bar
updateActionBarButtons();

// // update back button if at root
// if (newPath.length === 1) {
// navBackButton.classList.remove('active');
Expand Down
6 changes: 2 additions & 4 deletions src/Dashboard/FileSystem/FileSystemManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { fetchUploadedDocuments } from '../Storage';
import { samples_names } from '../samples';

// Manager is used for accessing local storage and tracking the position of current folder
const FileSystemManager = () => {
export const FileSystemManager = () => {

async function getRoot(): Promise<IFolder> {
return await getFileSystem()
Expand Down Expand Up @@ -96,6 +96,4 @@ const FileSystemManager = () => {
}

return FileSystemProps;
}

export default FileSystemManager;
}
20 changes: 19 additions & 1 deletion src/Dashboard/FileSystem/fs_functions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,23 @@ const removeEntry = (entry: IEntry, parent: IFolder): boolean => {
return true;
}

const renameEntry = (entry: IEntry, parent: IFolder, newName: string): boolean => {
try {
// Check if newName already exists in parent
const names = getAllNames(parent);
if (names.includes(newName)) {
window.alert(`Duplicate name: ${newName} already exists in ${parent.name}.`);
return false;
}
entry.name = newName;
} catch (e) {
console.error(e);
window.alert(`Error renaming ${entry.name} to ${newName}`);
return false;
}
return true;
}

const getAllNames = (folder: IFolder) => {
const names = folder.content.map(entry => entry.name);
return names;
Expand All @@ -107,5 +124,6 @@ export const fs_functions = {
removeEntry: removeEntry,
addMetadata: addMetadata,
removeMetadata: removeMetadata,
getAllNames: getAllNames
getAllNames: getAllNames,
renameEntry: renameEntry,
}
3 changes: 2 additions & 1 deletion src/Dashboard/FileSystem/index.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
export { IEntry, IFile, IFolder, EntryType } from './fs_interface';
export { fs_functions } from './fs_functions';
export { fs_functions } from './fs_functions';
export { FileSystemManager } from './FileSystemManager';

0 comments on commit 918fdf3

Please sign in to comment.