Skip to content

Commit

Permalink
Use uuid for section id, allow for duplicate names (#139)
Browse files Browse the repository at this point in the history
  • Loading branch information
zachhannum authored Jul 4, 2022
1 parent 828ee1a commit 60f0318
Show file tree
Hide file tree
Showing 15 changed files with 290 additions and 231 deletions.
65 changes: 36 additions & 29 deletions .eslintrc.js
Original file line number Diff line number Diff line change
@@ -1,32 +1,39 @@
module.exports = {
extends: 'erb',
rules: {
// A temporary hack related to IDE not resolving correct package.json
'import/no-extraneous-dependencies': 'off',
'import/no-unresolved': 'error',
// Since React 17 and typescript 4.1 you can safely disable the rule
'react/react-in-jsx-scope': 'off',
'react/jsx-props-no-spreading': 'off',
"prettier/prettier": ["error", { endOfLine: "off" }],
extends: 'erb',
rules: {
// A temporary hack related to IDE not resolving correct package.json
'import/no-extraneous-dependencies': 'off',
'import/no-unresolved': 'error',
// Since React 17 and typescript 4.1 you can safely disable the rule
'react/react-in-jsx-scope': 'off',
'react/jsx-props-no-spreading': 'off',
'prettier/prettier': ['error', { endOfLine: 'auto' }],
'@typescript-eslint/no-shadow': 'off',
'no-restricted-syntax': 'off',
'react-hooks/exhaustive-deps': 'off',
'react/require-default-props': 'off',
'@typescript-eslint/no-use-before-define': 'off',
'no-param-reassign': 'off',
'import/prefer-default-export': 'off',
},
parserOptions: {
ecmaVersion: 2020,
sourceType: 'module',
project: './tsconfig.json',
tsconfigRootDir: __dirname,
createDefaultProgram: true,
},
settings: {
'import/resolver': {
// See https://github.com/benmosher/eslint-plugin-import/issues/1396#issuecomment-575727774 for line below
node: {},
webpack: {
config: require.resolve('./.erb/configs/webpack.config.eslint.ts'),
},
typescript: {},
},
parserOptions: {
ecmaVersion: 2020,
sourceType: 'module',
project: './tsconfig.json',
tsconfigRootDir: __dirname,
createDefaultProgram: true,
'import/parsers': {
'@typescript-eslint/parser': ['.ts', '.tsx'],
},
settings: {
'import/resolver': {
// See https://github.com/benmosher/eslint-plugin-import/issues/1396#issuecomment-575727774 for line below
node: {},
webpack: {
config: require.resolve('./.erb/configs/webpack.config.eslint.ts'),
},
typescript: {},
},
'import/parsers': {
'@typescript-eslint/parser': ['.ts', '.tsx'],
},
},
};
},
};
35 changes: 18 additions & 17 deletions app/renderer/components/SectionContextMenu.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,6 @@
import { useState, useEffect } from 'react';
import styled, { useTheme } from 'styled-components';
import Color from 'color';
import useStore from '../store/useStore';
import {
findItemDeep,
removeItem,
duplicateSection,
} from './TreeView/utilities';
import {
SectionDeleteIcon,
SectionDuplicateIcon,
Expand All @@ -19,8 +13,15 @@ import {
SectionContextMenuClosedEvent,
SectionContextMenuEventData,
SectionType,
SectionIdentifier,
} from 'types/types';
import { ContextMenu } from '../components';
import useStore from '../store/useStore';
import {
findItemDeep,
removeItem,
duplicateSection,
} from './TreeView/utilities';
import { ContextMenu } from '.';
import type { Position } from './ContextMenu';

const StyledContextMenuItem = styled.div`
Expand Down Expand Up @@ -55,18 +56,18 @@ const StyledContextMenuItem = styled.div`
`;

const SectionContextMenu = () => {
const [id, setId] = useState('');
const [id, setId] = useState<SectionIdentifier>({ id: '', name: '' });
const [isFolder, setIsFolder] = useState(false);
const [showMenu, setShowMenu] = useState(false);
const [renameSelected, setRenameSelected] = useState(false);
const [position, setPosition] = useState<Position>({ x: 0, y: 0 });
const theme = useTheme();
useEffect(() => {
const handleSectionContextMenu = (e: CustomEventInit) => {
const { id, x, y } = e.detail as SectionContextMenuEventData;
const { id, name, x, y } = e.detail as SectionContextMenuEventData;
setPosition({ x, y });
setShowMenu(true);
setId(id);
setId({ id, name });
const { content } = useStore.getState();
const item = findItemDeep(content, id) as Section;
setIsFolder(item.type === SectionType.folder);
Expand All @@ -86,17 +87,17 @@ const SectionContextMenu = () => {
}, [showMenu, setShowMenu]);

useEffect(() => {
if (!showMenu && id !== '') {
if (!showMenu && id.id !== '') {
const contextClosedEvent = new CustomEvent(
SectionContextMenuClosedEvent,
{
detail: { id: id, rename: renameSelected },
detail: { id: id.id, name: id.name, rename: renameSelected },
}
);
document.dispatchEvent(contextClosedEvent);
setRenameSelected(false);
}
}, [showMenu, id]);
}, [showMenu, id, renameSelected]);

/* Menu Item handlers */
const handleOpen = () => {
Expand All @@ -108,7 +109,7 @@ const SectionContextMenu = () => {
const handleDuplicate = () => {
const { content, setContentArray, setAddingSections } = useStore.getState();
setAddingSections(true);
setContentArray(duplicateSection(id, content));
setContentArray(duplicateSection(id.id, content));
setTimeout(() => {
setAddingSections(false);
}, 10);
Expand All @@ -123,9 +124,9 @@ const SectionContextMenu = () => {
const handleDelete = () => {
const { content, setContentArray, activeSectionId, setActiveSectionId } =
useStore.getState();
setContentArray(removeItem(content, id));
if (id === activeSectionId) {
setActiveSectionId('');
setContentArray(removeItem(content, id.id));
if (id.id === activeSectionId) {
setActiveSectionId({ id: '', name: '' });
}
setShowMenu(false);
};
Expand Down
25 changes: 17 additions & 8 deletions app/renderer/components/TreeView/SortableTree.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
/* eslint-disable no-useless-return */
/* eslint-disable consistent-return */
import { useEffect, useMemo, useRef, useState, useCallback } from 'react';
import { createPortal } from 'react-dom';
import {
Expand All @@ -22,6 +24,8 @@ import {
verticalListSortingStrategy,
} from '@dnd-kit/sortable';

import useStore from 'renderer/store/useStore';
import { Sections } from 'types/types';
import {
buildTree,
flattenTree,
Expand All @@ -31,9 +35,7 @@ import {
setProperty,
} from './utilities';
import type { FlattenedItem, SensorContext } from './types';
import { Sections } from 'types/types';
import { SortableTreeItem } from './components';
import useStore from 'renderer/store/useStore';

const measuring = {
droppable: {
Expand Down Expand Up @@ -174,15 +176,18 @@ export function SortableTree({
>
<SortableContext items={sortedIds} strategy={verticalListSortingStrategy}>
{flattenedItems.map(
({ id, canHaveChildren, collapsed, depth }, index) => (
({ id, name, canHaveChildren, collapsed, depth }, index) => (
<SortableTreeItem
key={id}
id={id}
animateIndex={
isIndexBetweenStartAndEndAnimationIdx(index) ? index - animateInFromCollapseStartIdx : 0
isIndexBetweenStartAndEndAnimationIdx(index)
? index - animateInFromCollapseStartIdx
: 0
}
animateIn={isIndexBetweenStartAndEndAnimationIdx(index)}
value={id}
uuid={id}
value={name}
depth={id === activeId && projected ? projected.depth : depth}
indentationWidth={indentationWidth}
indicator={indicator}
Expand All @@ -207,7 +212,8 @@ export function SortableTree({
animateIn={false}
depth={activeItem.depth}
clone
value={activeId}
uuid={activeId}
value={activeItem.name}
indentationWidth={indentationWidth}
canHaveChildren={activeItem.canHaveChildren}
/>
Expand Down Expand Up @@ -287,7 +293,7 @@ export function SortableTree({
setAnimateInFromCollapseStartIdx(startIdx);
setAnimateInFromCollapseEndIdx(endIdx);
} else {
//fallback in case item is collapsed before animation finishes
// fallback in case item is collapsed before animation finishes
setAnimateInFromCollapseStartIdx(-1);
setAnimateInFromCollapseEndIdx(-1);
useStore.getState().resetAnimatingCollapseRefCount();
Expand All @@ -303,7 +309,7 @@ export function SortableTree({
eventName: string,
activeId: string,
overId?: string
) {
): any {
if (overId && projected) {
if (eventName !== 'onDragEnd') {
if (
Expand All @@ -312,6 +318,7 @@ export function SortableTree({
overId === currentPosition.overId
) {
return;
// eslint-disable-next-line no-else-return
} else {
setCurrentPosition({
parentId: projected.parentId,
Expand All @@ -335,11 +342,13 @@ export function SortableTree({
const nextItem = sortedItems[overIndex + 1];
announcement = `${activeId} was ${movedVerb} before ${nextItem.id}.`;
} else {
// eslint-disable-next-line no-lonely-if
if (projected.depth > previousItem.depth) {
announcement = `${activeId} was ${nestedVerb} under ${previousItem.id}.`;
} else {
let previousSibling: FlattenedItem | undefined = previousItem;
while (previousSibling && projected.depth < previousSibling.depth) {
// eslint-disable-next-line prefer-destructuring
const parentId: string | null = previousSibling.parentId;
previousSibling = sortedItems.find(({ id }) => id === parentId);
}
Expand Down
Loading

0 comments on commit 60f0318

Please sign in to comment.