Skip to content

Commit 6e979a7

Browse files
committed
enhance(rules): add the ability to duplicate rules
1 parent dab6332 commit 6e979a7

11 files changed

Lines changed: 110 additions & 61 deletions

File tree

File renamed without changes.
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
export const insertItemAtIndex = <T>(array: T[], item: T, index: number) => {
2+
const copy = [...array];
3+
copy.splice(index, 0, item);
4+
return copy;
5+
};
File renamed without changes.

src/helpers/remove-duplicates-from-array.spec.ts renamed to src/helpers/array-helpers/remove-duplicates-from-array.spec.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
import { describe, test, expect } from 'vitest';
2-
import { removeDuplicatesFromArray } from 'src/helpers/remove-duplicates-from-array';
1+
import { describe, expect, test } from 'vitest';
2+
import { removeDuplicatesFromArray } from 'src/helpers/array-helpers/remove-duplicates-from-array';
33

44
describe('remove duplicates from array', () => {
55
test('case 1', () => {
File renamed without changes.

src/stores/settings/derived/view-hotkeys-store.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ import {
1111
ConflictingHotkeys,
1212
HotkeysSearchTerm,
1313
} from 'src/stores/view/derived/hotkeys-store';
14-
import { groupArrayByProperty } from 'src/helpers/group-array-by-property';
14+
import { groupArrayByProperty } from 'src/helpers/array-helpers/group-array-by-property';
1515
import { lang } from 'src/lang/lang';
1616
import Lineage from 'src/main';
1717
import { OutlineModeStore } from 'src/stores/settings/derived/view-settings-store';

src/stores/settings/reducers/update-style-rules/handle-dnd.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { StyleRule } from 'src/stores/settings/types/style-rules-types';
22
import { MoveNodePayload } from 'src/stores/settings/reducers/update-style-rules/update-style-rules';
3-
import { moveArrayItem } from 'src/helpers/move-array-item';
3+
import { moveArrayItem } from 'src/helpers/array-helpers/move-array-item';
44

55
export const handleDND = (
66
rules: StyleRule[],

src/stores/settings/reducers/update-style-rules/update-style-rules.ts

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import { Settings } from 'src/stores/settings/settings-type';
88
import { fixConditionTypes } from 'src/stores/settings/reducers/update-style-rules/helpers/fix-condition-types';
99
import { handleDND } from 'src/stores/settings/reducers/update-style-rules/handle-dnd';
1010
import invariant from 'tiny-invariant';
11+
import { insertItemAtIndex } from 'src/helpers/array-helpers/insert-item-at-index';
1112

1213
export type MoveNodePayload = {
1314
documentPath: string;
@@ -64,6 +65,13 @@ export type StyleRulesAction =
6465
documentPath: string;
6566
id: string;
6667
};
68+
}
69+
| {
70+
type: 'settings/style-rules/duplicate-rule';
71+
payload: {
72+
documentPath: string;
73+
id: string;
74+
};
6775
};
6876

6977
export const updateStyleRules = (
@@ -193,5 +201,18 @@ export const updateStyleRules = (
193201
rule,
194202
];
195203
}
204+
} else if (action.type === 'settings/style-rules/duplicate-rule') {
205+
const index = rulesContainer.rules.findIndex(
206+
(r) => r.id === action.payload.id,
207+
);
208+
const rule = rulesContainer.rules[index];
209+
rulesContainer.rules = insertItemAtIndex(
210+
rulesContainer.rules,
211+
{
212+
...rule,
213+
id: id.styleRule(),
214+
},
215+
index + 1,
216+
);
196217
}
197218
};

src/view/components/container/left-sidebar/components/recent-cards/recent-cards.svelte

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
scrollCardIntoView
1111
} from 'src/view/components/container/left-sidebar/components/recent-cards/helpers/scroll-card-into-view';
1212
import NoItems from '../no-items/no-items.svelte';
13-
import { removeDuplicatesFromArray } from 'src/helpers/remove-duplicates-from-array';
13+
import { removeDuplicatesFromArray } from 'src/helpers/array-helpers/remove-duplicates-from-array';
1414
import { navigationHistoryStore } from 'src/stores/view/derived/navigation-history-store';
1515
import { PendingConfirmationStore } from 'src/stores/view/derived/pending-confirmation';
1616
import { NodeStylesStore } from 'src/stores/view/derived/style-rules';
Lines changed: 78 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,11 @@
11
<script lang="ts">
22
import { StyleRule } from '../../../../../../../../../stores/settings/types/style-rules-types';
33
import { getView } from '../../../../../../context';
4-
import { Trash } from 'lucide-svelte';
4+
import { MoreVertical } from 'lucide-svelte';
5+
import { Menu } from 'obsidian';
6+
import { get } from 'svelte/store';
7+
import { ActiveStyleRulesTab } from 'src/stores/settings/derived/style-rules';
8+
import { lang } from 'src/lang/lang';
59
610
export let rule: StyleRule;
711
@@ -23,28 +27,85 @@
2327
payload: { documentPath: view.file!.path, id: rule.id },
2428
});
2529
};
30+
31+
const moveRule = () => {
32+
const activeTab = get(ActiveStyleRulesTab(view));
33+
const activeTabIsGlobal = activeTab === 'global-rules';
34+
view.plugin.settings.dispatch({
35+
type: 'settings/style-rules/toggle-global',
36+
payload: {
37+
id: rule.id,
38+
documentPath: view.file!.path,
39+
},
40+
});
41+
view.plugin.settings.dispatch({
42+
type: 'settings/style-rules/set-active-tab',
43+
payload: {
44+
tab: activeTabIsGlobal ? 'document-rules' : 'global-rules',
45+
},
46+
});
47+
};
48+
49+
const duplicateRule = () => {
50+
view.plugin.settings.dispatch({
51+
type: 'settings/style-rules/duplicate-rule',
52+
payload: {
53+
id: rule.id,
54+
documentPath: view.file!.path,
55+
},
56+
});
57+
};
58+
59+
const showContextMenu = (e: MouseEvent) => {
60+
const target = e.target as HTMLElement;
61+
if (target.localName === 'input') return;
62+
const menu = new Menu();
63+
const activeTab = get(ActiveStyleRulesTab(view));
64+
const activeTabIsGlobal = activeTab === 'global-rules';
65+
menu.addItem((item) => {
66+
item.setTitle(
67+
activeTabIsGlobal
68+
? lang.modals_rules_rule_cm_move_to_document
69+
: lang.modals_rules_rule_cm_move_to_global,
70+
);
71+
item.setIcon(activeTabIsGlobal ? 'file-text' : 'globe');
72+
73+
item.onClick(moveRule);
74+
});
75+
menu.addItem((item) => {
76+
item.setTitle('Duplicate');
77+
item.setIcon('copy');
78+
item.onClick(duplicateRule);
79+
});
80+
menu.addItem((item) => {
81+
item.setTitle('Delete');
82+
item.setIcon('trash');
83+
item.onClick(deleteRule);
84+
if ('dom' in item) {
85+
// @ts-ignore
86+
item.dom.addClass('is-warning');
87+
}
88+
});
89+
menu.showAtMouseEvent(e);
90+
};
2691
</script>
92+
2793
<div class="rule-actions">
28-
<input
29-
type="checkbox"
30-
checked={rule.enabled}
31-
on:change={toggleRule}
32-
aria-label="Enable"
33-
/>
34-
<div
35-
class="clickable-icon delete-button"
36-
on:click={deleteRule}
37-
aria-label="Delete"
38-
>
39-
<Trash class="svg-icon" />
40-
</div>
94+
<input
95+
type="checkbox"
96+
checked={rule.enabled}
97+
on:change={toggleRule}
98+
aria-label="Enable"
99+
/>
100+
<div class="clickable-icon" on:click={showContextMenu} aria-label="Actions">
101+
<MoreVertical class="svg-icon" />
41102
</div>
103+
</div>
42104

43105
<style>
44-
.rule-actions{
106+
.rule-actions {
45107
display: flex;
46108
align-items: center;
47-
gap: 8px;
48109
padding-top: 4px;
49110
padding-bottom: 4px;
50111
padding-left: 8px;
@@ -53,7 +114,5 @@
53114
/*background-color: var(--color-base-30);*/
54115
justify-content: center;
55116
}
56-
.delete-button{
57-
color:var(--color-red)
58-
}
117+
59118
</style>

0 commit comments

Comments
 (0)