Skip to content

Commit

Permalink
Merge pull request #131 from ujiro99/feature/collapse-group
Browse files Browse the repository at this point in the history
Feature/collapse group
  • Loading branch information
ujiro99 authored Aug 19, 2023
2 parents 355fc51 + 641d1e3 commit a13086d
Show file tree
Hide file tree
Showing 28 changed files with 792 additions and 221 deletions.
2 changes: 1 addition & 1 deletion jest.setup.js
Original file line number Diff line number Diff line change
@@ -1 +1 @@
Object.assign(global, require('jest-chrome'))
Object.assign(global, require('jest-chrome'))
2 changes: 1 addition & 1 deletion manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
"version": "0.7.8",
"default_locale": "en",
"action": {
"default_icon": "icon16.png",
"default_icon": "icon128.png",
"default_popup": "popup.html"
},
"background": {
Expand Down
672 changes: 573 additions & 99 deletions package-lock.json

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@
"@google-cloud/local-auth": "^2.1.0",
"@popperjs/core": "^2.11.6",
"apca-w3": "^0.1.9",
"caniuse-lite": "^1.0.30001519",
"chart.js": "^3.9.1",
"chartjs-plugin-datalabels": "^2.2.0",
"classnames": "^2.3.2",
Expand All @@ -32,7 +31,6 @@
"date-fns": "^2.29.3",
"date-fns-tz": "^2.0.0",
"googleapis": "^105.0.0",
"jest-chrome": "^0.8.0",
"mixpanel-browser": "^2.45.0",
"react": "^18.2.0",
"react-calendar": "^4.0.0",
Expand Down Expand Up @@ -70,6 +68,7 @@
"@typescript-eslint/eslint-plugin": "^5.49.0",
"@typescript-eslint/parser": "^5.49.0",
"autoprefixer": "^10.4.13",
"caniuse-lite": "^1.0.30001519",
"copy-webpack-plugin": "^11.0.0",
"cross-env": "^7.0.3",
"css-loader": "^6.7.3",
Expand All @@ -84,6 +83,7 @@
"eslint-plugin-react": "^7.32.1",
"jest": "^29.4.1",
"jest-environment-jsdom": "^29.4.1",
"jest-chrome": "^0.8.0",
"mini-css-extract-plugin": "^2.7.2",
"mversion": "^1.2.0",
"npm-build-zip": "^1.0.3",
Expand Down
Binary file modified public/icon128.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified public/icon16.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified public/icon48.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
6 changes: 5 additions & 1 deletion src/components/Heading.css
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,10 @@
}
}

& > * {
user-select: none;
}

h1 {
position: relative;
z-index: 0;
Expand All @@ -74,7 +78,7 @@
z-index: -1;
left: -6px;
bottom: 0;
width: calc(100% + 12px);
width: calc(100% + 10px);
height: 0.6rem;
border-radius: 2px;
}
Expand Down
2 changes: 1 addition & 1 deletion src/components/LineEditor.css
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,6 @@
}

&.mod-heading {
margin-left: -18px;
margin-left: -16px;
}
}
46 changes: 46 additions & 0 deletions src/components/MdWrapper.css
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
margin-right: 2px;
opacity: 0;
transition: opacity 0.2s ease-out;
cursor: grab;

@at-root {
.dragging $(this)__drag {
Expand Down Expand Up @@ -97,4 +98,49 @@
border-bottom-right-radius: var(--radius-md);
}
}

&__collapse {
width: 20px;
height: 20px;
padding: 0 6px 0 0;
border-radius: 5px;
display: flex;
align-items: center;
justify-content: center;
touch-action: none;
cursor: pointer;
border: none;
outline: none;
appearance: none;
background-color: transparent;
opacity: 0;
transition: opacity 0.2s ease-out;

svg {
@apply fill-gray-400;
transition: transform 250ms ease-out, fill 250ms ease-out;
}

&:hover {
svg {
@apply fill-gray-600;
}
}

@at-root {
.collapsed $(this)__collapse svg {
transform: rotate(-90deg);
}
}
}

&:hover &__collapse {
opacity: 1;
}

&:has(textarea) &__collapse,
&:hover:has(textarea) &__collapse {
transition: none;
opacity: 0;
}
}
12 changes: 12 additions & 0 deletions src/components/MdWrapper.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ const MENU_ID_PREFIX = 'md-wraper-menu-'
type Props = {
children: React.ReactNode
line: number
onCollapse?(): void
}

export const MdWrapper: React.FC<Props> = (props: Props): JSX.Element => {
Expand Down Expand Up @@ -52,6 +53,11 @@ export const MdWrapper: React.FC<Props> = (props: Props): JSX.Element => {
onContextMenu={openContextMenu}
>
<Icon className="item-wrapper__drag" name="drag" />
{props.onCollapse && (
<button onClick={props.onCollapse} className="item-wrapper__collapse">
{collapseIcon}
</button>
)}
{props.children}
</div>

Expand All @@ -75,3 +81,9 @@ export const MdWrapper: React.FC<Props> = (props: Props): JSX.Element => {
</>
)
}

const collapseIcon = (
<svg width="10" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 70 41">
<path d="M30.76 39.2402C31.885 40.3638 33.41 40.995 35 40.995C36.59 40.995 38.115 40.3638 39.24 39.2402L68.24 10.2402C69.2998 9.10284 69.8768 7.59846 69.8494 6.04406C69.822 4.48965 69.1923 3.00657 68.093 1.90726C66.9937 0.807959 65.5106 0.178263 63.9562 0.150837C62.4018 0.123411 60.8974 0.700397 59.76 1.76024L35 26.5102L10.24 1.76024C9.10259 0.700397 7.59822 0.123411 6.04381 0.150837C4.4894 0.178263 3.00632 0.807959 1.90702 1.90726C0.807714 3.00657 0.178019 4.48965 0.150593 6.04406C0.123167 7.59846 0.700153 9.10284 1.75999 10.2402L30.76 39.2402Z" />
</svg>
)
2 changes: 2 additions & 0 deletions src/components/Menu/ReportSummary.css
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,8 @@
width: 18px;
height: 18px;
margin-right: 8px;
background: var(--bg-gray-100);
border-radius: 50%;
}

&--fixed &__circle {
Expand Down
3 changes: 1 addition & 2 deletions src/components/Menu/ReportSummary.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ import { useTaskManager } from '@/hooks/useTaskManager'
import { useMode, MODE } from '@/hooks/useMode'
import { useAnalytics } from '@/hooks/useAnalytics'
import * as i18n from '@/services/i18n'
import { Icon } from '@/components/Icon'

import './ReportSummary.css'

Expand Down Expand Up @@ -107,7 +106,7 @@ export function ReportSummary(props: ReportSummaryProps): JSX.Element {
{ifNull(all.estimate.toHours().toFixed(1))}h
</span>
<span className="report-summary__label-symbol">:</span>
<span >{ifNull(all.percentage)}</span>
<span>{ifNull(all.percentage)}</span>
<span className="pl-2">%</span>
</div>
</div>
Expand Down
2 changes: 1 addition & 1 deletion src/components/Popup.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ function TaskList() {
function ToDo() {
return (
<div className="task-container">
<SortableTree indicator />
<SortableTree indicator collapsible />
<EmptyLine />
<SyncModal />
<AlarmModal />
Expand Down
2 changes: 1 addition & 1 deletion src/components/TrackingStatus/TrackingStatus.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,7 @@ export function TrackingStatus(): JSX.Element {
}

const task = node.data as Task
const hasEstimatedTime = !task.estimatedTimes.isEmpty()
const hasEstimatedTime = task.estimatedTimes && !task.estimatedTimes.isEmpty()
const estimatedTime = task.estimatedTimes
const elapsedTime = tracking.elapsedTime

Expand Down
10 changes: 8 additions & 2 deletions src/components/Tree/SortableTree.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -269,13 +269,18 @@ export function SortableTree({
const { depth, parentId } = projected

const clonedItems: FlattenedItem[] = flattenTree(items)
const overIndex = clonedItems.findIndex(({ id }) => id === over.id)
let overIndex = clonedItems.findIndex(({ id }) => id === over.id)
const activeIndex = clonedItems.findIndex(({ id }) => id === active.id)
const activeTreeItem = clonedItems[activeIndex]
const activeNode = root.find((n) => n.id === activeTreeItem.id)
const activeNode = root.find((n) => n.id === active.id)
const overNode = root.find((n) => n.id === over.id)

clonedItems[activeIndex] = { ...activeTreeItem, depth, parentId }

if (activeIndex < overIndex && overNode.collapsed) {
overIndex += overNode.size() - 1
}

let sortedItems = arrayMove(clonedItems, activeIndex, overIndex)
const newItems = buildTree(sortedItems)

Expand All @@ -291,6 +296,7 @@ export function SortableTree({
newRoot = updateLines(newRoot)
manager.setRoot(newRoot)
}

function handleDragCancel() {
resetState()
}
Expand Down
6 changes: 4 additions & 2 deletions src/components/Tree/components/TreeItem/SortableTreeItem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ export function SortableTreeItem({ id, depth, ...props }: Props) {
}

const [getItem] = useItemAdapter()
const item = getItem(id)
const { elm, isCollapsable } = getItem(id)

return (
<TreeItem
Expand All @@ -53,8 +53,10 @@ export function SortableTreeItem({ id, depth, ...props }: Props) {
...listeners,
}}
{...props}
// override onCollapse
onCollapse={isCollapsable ? props.onCollapse : undefined}
>
{item}
{elm}
</TreeItem>
)
}
12 changes: 1 addition & 11 deletions src/components/Tree/components/TreeItem/TreeItem.module.css
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
pointer-events: none;
width: 100%;
padding: 0;
margin-top: 20px;
margin-top: 20px;
opacity: 0.8;

.TreeItem {
Expand Down Expand Up @@ -111,13 +111,3 @@
-webkit-user-select: none;
}
}

.Collapse {
svg {
transition: transform 250ms ease;
}

&.collapsed svg {
transform: rotate(-90deg);
}
}
24 changes: 4 additions & 20 deletions src/components/Tree/components/TreeItem/TreeItem.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import React, { forwardRef, HTMLAttributes } from 'react'
import classNames from 'classnames'

import { Action, Handle, Remove } from '../'
import { Remove } from '../'
import styles from './TreeItem.module.css'

export interface Props extends Omit<HTMLAttributes<HTMLLIElement>, 'id'> {
Expand Down Expand Up @@ -58,11 +58,12 @@ export const TreeItem = forwardRef<HTMLDivElement, Props>(
indicator && styles.indicator,
disableSelection && styles.disableSelection,
disableInteraction && styles.disableInteraction,
collapsed && 'collapsed',
ghost && 'ghost',
clone && 'dragging',
dropTarget && 'drop-target',
dropTargetParent && 'drop-target-parent',
dropTargetBottom && 'drop-target-bottom'
dropTargetBottom && 'drop-target-bottom',
)}
ref={wrapperRef}
style={
Expand All @@ -74,18 +75,7 @@ export const TreeItem = forwardRef<HTMLDivElement, Props>(
{...handleProps}
>
<div className={styles.TreeItem} ref={ref} style={style}>
{onCollapse && (
<Action
onClick={onCollapse}
className={classNames(
styles.Collapse,
collapsed && styles.collapsed,
)}
>
{collapseIcon}
</Action>
)}
{props.children}
{React.cloneElement(props.children as any, { onCollapse })}
{!clone && onRemove && <Remove onClick={onRemove} />}
{clone && childCount && childCount > 1 ? (
<span className={styles.Count}>{childCount}</span>
Expand All @@ -95,9 +85,3 @@ export const TreeItem = forwardRef<HTMLDivElement, Props>(
)
},
)

const collapseIcon = (
<svg width="10" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 70 41">
<path d="M30.76 39.2402C31.885 40.3638 33.41 40.995 35 40.995C36.59 40.995 38.115 40.3638 39.24 39.2402L68.24 10.2402C69.2998 9.10284 69.8768 7.59846 69.8494 6.04406C69.822 4.48965 69.1923 3.00657 68.093 1.90726C66.9937 0.807959 65.5106 0.178263 63.9562 0.150837C62.4018 0.123411 60.8974 0.700397 59.76 1.76024L35 26.5102L10.24 1.76024C9.10259 0.700397 7.59822 0.123411 6.04381 0.150837C4.4894 0.178263 3.00632 0.807959 1.90702 1.90726C0.807714 3.00657 0.178019 4.48965 0.150593 6.04406C0.123167 7.59846 0.700153 9.10284 1.75999 10.2402L30.76 39.2402Z" />
</svg>
)
1 change: 1 addition & 0 deletions src/components/Tree/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ export interface TreeItem {
id: UniqueIdentifier
children: TreeItem[]
collapsed?: boolean
clone?: () => TreeItem
}

export type TreeItems = TreeItem[]
Expand Down
17 changes: 10 additions & 7 deletions src/components/Tree/utilities.ts
Original file line number Diff line number Diff line change
Expand Up @@ -162,18 +162,21 @@ export function setProperty<T extends keyof TreeItem>(
property: T,
setter: (value: TreeItem[T]) => TreeItem[T],
) {
for (const item of items) {
const newItems = items.map((item) => {
if (item.id === id) {
item[property] = setter(item[property])
continue
const newItem = item.clone()
newItem[property] = setter(newItem[property])
return newItem
}

if (item.children.length) {
item.children = setProperty(item.children, id, property, setter)
const newItem = item.clone()
newItem.children = setProperty(newItem.children, id, property, setter)
return newItem
}
}
return item
})

return [...items]
return [...newItems]
}

function countChildren(items: TreeItem[], count = 0): number {
Expand Down
Loading

0 comments on commit a13086d

Please sign in to comment.