Skip to content

Commit

Permalink
Use submenus for move and sort menu options
Browse files Browse the repository at this point in the history
  • Loading branch information
mgmeyers committed Apr 28, 2024
1 parent 0f46f4c commit b234b34
Show file tree
Hide file tree
Showing 3 changed files with 159 additions and 125 deletions.
44 changes: 30 additions & 14 deletions src/components/Item/ItemMenu.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Menu, TFile, TFolder } from 'obsidian';
import { Menu, Platform, TFile, TFolder } from 'obsidian';
import { Dispatch, StateUpdater, useCallback } from 'preact/hooks';
import { StateManager } from 'src/StateManager';
import { Path } from 'src/dnd/types';
Expand Down Expand Up @@ -257,20 +257,36 @@ export function useItemMenu({

menu.addSeparator();

const lanes = stateManager.state.children;
for (let i = 0, len = lanes.length; i < len; i++) {
menu.addItem((item) =>
item
const addMoveToOptions = (menu: Menu) => {
const lanes = stateManager.state.children;
if (lanes.length <= 1) return;
for (let i = 0, len = lanes.length; i < len; i++) {
menu.addItem((item) =>
item
.setIcon('lucide-square-kanban')
.setChecked(path[0] === i)
.setTitle(lanes[i].data.title)
.onClick(() => {
if (path[0] === i) return;
stateManager.setState((boardData) => {
return moveEntity(boardData, path, [i, 0]);
});
})
);
}
};

if (Platform.isPhone) {
addMoveToOptions(menu);
} else {
menu.addItem((item) => {
const submenu = (item as any)
.setTitle(t('Move to list'))
.setIcon('lucide-square-kanban')
.setChecked(path[0] === i)
.setTitle(lanes[i].data.title)
.onClick(() => {
if (path[0] === i) return;
stateManager.setState((boardData) => {
return moveEntity(boardData, path, [i, 0]);
});
})
);
.setSubmenu();

addMoveToOptions(submenu);
});
}

menu.showAtPosition(coordinates);
Expand Down
239 changes: 128 additions & 111 deletions src/components/Lane/LaneMenu.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import update from 'immutability-helper';
import { Menu } from 'obsidian';
import { Menu, Platform } from 'obsidian';
import { Dispatch, StateUpdater, useContext, useEffect, useMemo, useState } from 'preact/hooks';
import { Path } from 'src/dnd/types';
import { defaultSort } from 'src/helpers/util';
Expand Down Expand Up @@ -71,7 +71,7 @@ export function useSettingsMenu({ setEditState, path, lane }: UseSettingsMenuPar
const [confirmAction, setConfirmAction] = useState<LaneAction>(null);

const settingsMenu = useMemo(() => {
const taskSortOptions = new Set<string>();
const metadataSortOptions = new Set<string>();
let canSortDate = false;
let canSortTags = false;

Expand All @@ -80,7 +80,7 @@ export function useSettingsMenu({ setEditState, path, lane }: UseSettingsMenuPar
if (taskData) {
taskData.forEach((m) => {
if (m.key === 'repeat') return;
if (!taskSortOptions.has(m.key)) taskSortOptions.add(m.key);
if (!metadataSortOptions.has(m.key)) metadataSortOptions.add(m.key);
});
}

Expand All @@ -103,7 +103,7 @@ export function useSettingsMenu({ setEditState, path, lane }: UseSettingsMenuPar
})
.addSeparator()
.addItem((i) => {
i.setIcon('corner-left-down')
i.setIcon('arrow-left-to-line')
.setTitle(t('Insert list before'))
.onClick(() =>
boardModifiers.insertLane(path, {
Expand All @@ -119,7 +119,7 @@ export function useSettingsMenu({ setEditState, path, lane }: UseSettingsMenuPar
);
})
.addItem((i) => {
i.setIcon('lucide-corner-right-down')
i.setIcon('arrow-right-to-line')
.setTitle(t('Insert list after'))
.onClick(() => {
const newPath = [...path];
Expand Down Expand Up @@ -151,10 +151,12 @@ export function useSettingsMenu({ setEditState, path, lane }: UseSettingsMenuPar
.setTitle(t('Delete list'))
.onClick(() => setConfirmAction('delete'));
})
.addSeparator()
.addItem((item) => {
.addSeparator();

const addSortOptions = (menu: Menu) => {
menu.addItem((item) => {
item
.setIcon('lucide-move-vertical')
.setIcon('arrow-down-up')
.setTitle(t('Sort by card text'))
.onClick(() => {
const children = lane.children.slice();
Expand Down Expand Up @@ -187,120 +189,77 @@ export function useSettingsMenu({ setEditState, path, lane }: UseSettingsMenuPar
});
});

if (canSortDate) {
menu.addItem((item) => {
item
.setIcon('lucide-move-vertical')
.setTitle(t('Sort by date'))
.onClick(() => {
const children = lane.children.slice();
const mod = lane.data.sorted === LaneSort.DateAsc ? -1 : 1;
if (canSortDate) {
menu.addItem((item) => {
item
.setIcon('arrow-down-up')
.setTitle(t('Sort by date'))
.onClick(() => {
const children = lane.children.slice();
const mod = lane.data.sorted === LaneSort.DateAsc ? -1 : 1;

children.sort((a, b) => {
const aDate: moment.Moment | undefined = a.data.metadata.time || a.data.metadata.date;
const bDate: moment.Moment | undefined = b.data.metadata.time || b.data.metadata.date;
children.sort((a, b) => {
const aDate: moment.Moment | undefined =
a.data.metadata.time || a.data.metadata.date;
const bDate: moment.Moment | undefined =
b.data.metadata.time || b.data.metadata.date;

if (aDate && !bDate) return -1 * mod;
if (bDate && !aDate) return 1 * mod;
if (!aDate && !bDate) return 0;
if (aDate && !bDate) return -1 * mod;
if (bDate && !aDate) return 1 * mod;
if (!aDate && !bDate) return 0;

return (aDate.isBefore(bDate) ? -1 : 1) * mod;
});
return (aDate.isBefore(bDate) ? -1 : 1) * mod;
});

boardModifiers.updateLane(
path,
update(lane, {
children: {
$set: children,
},
data: {
sorted: {
$set:
lane.data.sorted === LaneSort.DateAsc ? LaneSort.DateDsc : LaneSort.DateAsc,
boardModifiers.updateLane(
path,
update(lane, {
children: {
$set: children,
},
},
})
);
});
});
}

if (canSortTags) {
menu.addItem((item) => {
item
.setIcon('lucide-move-vertical')
.setTitle(t('Sort by tags'))
.onClick(() => {
const tagSortOrder = stateManager.getSetting('tag-sort');
const children = lane.children.slice();
const desc = lane.data.sorted === LaneSort.TagsAsc ? true : false;

children.sort((a, b) => {
const tagsA = a.data.metadata.tags;
const tagsB = b.data.metadata.tags;

if (!tagsA?.length && !tagsB?.length) return 0;
if (!tagsA?.length) return 1;
if (!tagsB?.length) return -1;

const aSortOrder = tagSortOrder?.findIndex((sort) => tagsA.includes(sort.tag)) ?? -1;
const bSortOrder = tagSortOrder?.findIndex((sort) => tagsB.includes(sort.tag)) ?? -1;

if (aSortOrder > -1 && bSortOrder < 0) return desc ? 1 : -1;
if (bSortOrder > -1 && aSortOrder < 0) return desc ? -1 : 1;
if (aSortOrder > -1 && bSortOrder > -1) {
return desc ? bSortOrder - aSortOrder : aSortOrder - bSortOrder;
}

if (desc) return defaultSort(tagsB.join(''), tagsA.join(''));
return defaultSort(tagsA.join(''), tagsB.join(''));
});

boardModifiers.updateLane(
path,
update(lane, {
children: {
$set: children,
},
data: {
sorted: {
$set:
lane.data.sorted === LaneSort.TagsAsc ? LaneSort.TagsDsc : LaneSort.TagsAsc,
data: {
sorted: {
$set:
lane.data.sorted === LaneSort.DateAsc ? LaneSort.DateDsc : LaneSort.DateAsc,
},
},
},
})
);
});
});
}
})
);
});
});
}

if (taskSortOptions.size) {
taskSortOptions.forEach((k) => {
menu.addItem((i) => {
i.setIcon('lucide-move-vertical')
.setTitle(t('Sort by') + ' ' + lableToName(k).toLocaleLowerCase())
if (canSortTags) {
menu.addItem((item) => {
item
.setIcon('arrow-down-up')
.setTitle(t('Sort by tags'))
.onClick(() => {
const tagSortOrder = stateManager.getSetting('tag-sort');
const children = lane.children.slice();
const desc = lane.data.sorted === k + '-asc' ? true : false;
const desc = lane.data.sorted === LaneSort.TagsAsc ? true : false;

children.sort((a, b) => {
const valA = a.data.metadata.inlineMetadata?.find((m) => m.key === k);
const valB = b.data.metadata.inlineMetadata?.find((m) => m.key === k);

if (valA === undefined && valB === undefined) return 0;
if (valA === undefined) return 1;
if (valB === undefined) return -1;

if (desc) {
return defaultSort(
anyToString(valB.value, stateManager),
anyToString(valA.value, stateManager)
);
const tagsA = a.data.metadata.tags;
const tagsB = b.data.metadata.tags;

if (!tagsA?.length && !tagsB?.length) return 0;
if (!tagsA?.length) return 1;
if (!tagsB?.length) return -1;

const aSortOrder =
tagSortOrder?.findIndex((sort) => tagsA.includes(sort.tag)) ?? -1;
const bSortOrder =
tagSortOrder?.findIndex((sort) => tagsB.includes(sort.tag)) ?? -1;

if (aSortOrder > -1 && bSortOrder < 0) return desc ? 1 : -1;
if (bSortOrder > -1 && aSortOrder < 0) return desc ? -1 : 1;
if (aSortOrder > -1 && bSortOrder > -1) {
return desc ? bSortOrder - aSortOrder : aSortOrder - bSortOrder;
}
return defaultSort(
anyToString(valA.value, stateManager),
anyToString(valB.value, stateManager)
);

if (desc) return defaultSort(tagsB.join(''), tagsA.join(''));
return defaultSort(tagsA.join(''), tagsB.join(''));
});

boardModifiers.updateLane(
Expand All @@ -311,13 +270,71 @@ export function useSettingsMenu({ setEditState, path, lane }: UseSettingsMenuPar
},
data: {
sorted: {
$set: lane.data.sorted === k + '-asc' ? k + '-desc' : k + '-asc',
$set:
lane.data.sorted === LaneSort.TagsAsc ? LaneSort.TagsDsc : LaneSort.TagsAsc,
},
},
})
);
});
});
}

if (metadataSortOptions.size) {
metadataSortOptions.forEach((k) => {
menu.addItem((i) => {
i.setIcon('arrow-down-up')
.setTitle(t('Sort by') + ' ' + lableToName(k).toLocaleLowerCase())
.onClick(() => {
const children = lane.children.slice();
const desc = lane.data.sorted === k + '-asc' ? true : false;

children.sort((a, b) => {
const valA = a.data.metadata.inlineMetadata?.find((m) => m.key === k);
const valB = b.data.metadata.inlineMetadata?.find((m) => m.key === k);

if (valA === undefined && valB === undefined) return 0;
if (valA === undefined) return 1;
if (valB === undefined) return -1;

if (desc) {
return defaultSort(
anyToString(valB.value, stateManager),
anyToString(valA.value, stateManager)
);
}
return defaultSort(
anyToString(valA.value, stateManager),
anyToString(valB.value, stateManager)
);
});

boardModifiers.updateLane(
path,
update(lane, {
children: {
$set: children,
},
data: {
sorted: {
$set: lane.data.sorted === k + '-asc' ? k + '-desc' : k + '-asc',
},
},
})
);
});
});
});
}
};

if (Platform.isPhone) {
addSortOptions(menu);
} else {
menu.addItem((item) => {
const submenu = (item as any).setTitle(t('Sort by')).setIcon('arrow-down-up').setSubmenu();

addSortOptions(submenu);
});
}

Expand Down
1 change: 1 addition & 0 deletions src/lang/locale/en.ts
Original file line number Diff line number Diff line change
Expand Up @@ -232,6 +232,7 @@ const en = {
'Add label': 'Add label',
'Move to top': 'Move to top',
'Move to bottom': 'Move to bottom',
'Move to list': 'Move to list',

// components/Lane/LaneForm.tsx
'Enter list title...': 'Enter list title...',
Expand Down

0 comments on commit b234b34

Please sign in to comment.