Skip to content

Commit 4e4e202

Browse files
committed
Experimental: Display workspace rules in unassigned panel
- Add new RulesList.svelte component to display workspace rules in the unassigned panel. - Integrate RulesList in UnassignedView.svelte gated by new workspaceRulesEnabled feature flag. - Enhance ExperimentalSettings.svelte to allow toggling the workspace rules experimental feature. - Update uiFeatureFlags to include workspaceRulesEnabled persisted flag. - Update rulesService for correct Svelte query mutation usage and new listWorkspaceRules method for selector transformation. - Adds an experimental feature for listing rules; does not include full backend implementation yet. - Adds stub for backendService as placeholder for future backend integration.
1 parent f6b4627 commit 4e4e202

File tree

6 files changed

+92
-8
lines changed

6 files changed

+92
-8
lines changed
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
<script lang="ts">
2+
import ReduxResult from '$components/ReduxResult.svelte';
3+
import RulesService from '$lib/rules/rulesService.svelte';
4+
import { getContext } from '@gitbutler/shared/context';
5+
import Button from '@gitbutler/ui/Button.svelte';
6+
7+
type Props = {
8+
projectId: string;
9+
};
10+
11+
const { projectId }: Props = $props();
12+
13+
const rulesService = getContext(RulesService);
14+
const [_, creatingRule] = rulesService.createWorkspaceRule;
15+
16+
const rules = $derived(rulesService.listWorkspaceRules(projectId));
17+
</script>
18+
19+
<div class="rules-list">
20+
<ReduxResult {projectId} result={rules.current}>
21+
{#snippet children(rules)}
22+
<div>
23+
{#each rules as rule (rule.id)}
24+
<pre class="text-12">
25+
{JSON.stringify(rules, null, 2)}
26+
</pre>
27+
{:else}
28+
<p class="text-12 text-grey">No rules found.</p>
29+
{/each}
30+
</div>
31+
{/snippet}
32+
</ReduxResult>
33+
<Button
34+
wide
35+
icon="plus-small"
36+
kind="outline"
37+
disabled
38+
tooltip="Not implemented yet"
39+
loading={creatingRule.current.isLoading}>Add new rule</Button
40+
>
41+
</div>
42+
43+
<style lang="postcss">
44+
.rules-list {
45+
display: flex;
46+
flex-direction: column;
47+
padding: 12px;
48+
gap: 8px;
49+
}
50+
51+
.text-grey {
52+
color: var(--clr-text-2);
53+
}
54+
</style>

apps/desktop/src/components/UnassignedView.svelte

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
<script lang="ts">
2+
import RulesList from '$components/RulesList.svelte';
23
import UnassignedFoldButton from '$components/UnassignedFoldButton.svelte';
34
import WorktreeChanges from '$components/WorktreeChanges.svelte';
45
import WorktreeTipsFooter from '$components/WorktreeTipsFooter.svelte';
56
import noChanges from '$lib/assets/illustrations/no-changes.svg?raw';
7+
import { workspaceRulesEnabled } from '$lib/config/uiFeatureFlags';
68
import { DefinedFocusable } from '$lib/focus/focusManager.svelte';
79
import { IntelligentScrollingService } from '$lib/intelligentScrolling/service';
810
import { UncommittedService } from '$lib/selection/uncommittedService.svelte';
@@ -103,6 +105,10 @@
103105
</Button>
104106
</div>
105107
{/if}
108+
109+
{#if $workspaceRulesEnabled}
110+
<RulesList {projectId} />
111+
{/if}
106112
</div>
107113
{:else}
108114
<div

apps/desktop/src/components/profileSettings/ExperimentalSettings.svelte

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
<script lang="ts">
22
import { SettingsService } from '$lib/config/appSettingsV2';
3-
import { ircEnabled, ircServer } from '$lib/config/uiFeatureFlags';
3+
import { ircEnabled, ircServer, workspaceRulesEnabled } from '$lib/config/uiFeatureFlags';
44
import { User } from '$lib/user/user';
55
import { getContext, getContextStore } from '@gitbutler/shared/context';
66
import SectionCard from '@gitbutler/ui/SectionCard.svelte';
@@ -79,11 +79,28 @@
7979
{/if}
8080

8181
<SectionCard
82-
labelFor="irc"
82+
labelFor="rules"
8383
roundedTop={!$settingsStore?.featureFlags.actions}
84-
roundedBottom={!$ircEnabled}
84+
roundedBottom={false}
8585
orientation="row"
8686
>
87+
{#snippet title()}
88+
Workspace Rules
89+
{/snippet}
90+
{#snippet caption()}
91+
Go full dominatrix on your workspace and add a bunch rules that can automatically trigger
92+
actions.
93+
{/snippet}
94+
{#snippet actions()}
95+
<Toggle
96+
id="rules"
97+
checked={$workspaceRulesEnabled}
98+
onclick={() => workspaceRulesEnabled.set(!$workspaceRulesEnabled)}
99+
/>
100+
{/snippet}
101+
</SectionCard>
102+
103+
<SectionCard labelFor="irc" roundedTop={false} roundedBottom={!$ircEnabled} orientation="row">
87104
{#snippet title()}
88105
IRC
89106
{/snippet}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export default class BackendService {}

apps/desktop/src/lib/config/uiFeatureFlags.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,3 +10,4 @@ export const autoSelectBranchNameFeature = persisted(false, 'autoSelectBranchLan
1010
export const ircEnabled = persistWithExpiration(false, 'feature-irc', 1440 * 30);
1111
export const ircServer = persistWithExpiration('', 'feature-irc-server', 1440 * 30);
1212
export const rewrapCommitMessage = persistWithExpiration(true, 'rewrap-commit-msg', 1440 * 30);
13+
export const workspaceRulesEnabled = persisted(false, 'workspace-rules-enabled');

apps/desktop/src/lib/rules/rulesService.svelte.ts

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,19 +16,22 @@ export default class RulesService {
1616
}
1717

1818
get createWorkspaceRule() {
19-
return this.api.endpoints.createWorkspaceRule.useMutation;
19+
return this.api.endpoints.createWorkspaceRule.useMutation();
2020
}
2121

2222
get deleteWorkspaceRule() {
23-
return this.api.endpoints.deleteWorkspaceRule.useMutation;
23+
return this.api.endpoints.deleteWorkspaceRule.useMutation();
2424
}
2525

2626
get updateWorkspaceRule() {
27-
return this.api.endpoints.updateWorkspaceRule.useMutation;
27+
return this.api.endpoints.updateWorkspaceRule.useMutation();
2828
}
2929

30-
get listWorkspaceRules() {
31-
return this.api.endpoints.listWorkspaceRules.useQuery;
30+
listWorkspaceRules(projectId: string) {
31+
return this.api.endpoints.listWorkspaceRules.useQuery(
32+
{ projectId },
33+
{ transform: (result) => workspaceRulesSelectors.selectAll(result) }
34+
);
3235
}
3336
}
3437

@@ -80,3 +83,5 @@ function injectEndpoints(api: BackendApi) {
8083
const workspaceRulesAdapter = createEntityAdapter<WorkspaceRule, WorkspaceRuleId>({
8184
selectId: (rule) => rule.id
8285
});
86+
87+
const workspaceRulesSelectors = workspaceRulesAdapter.getSelectors();

0 commit comments

Comments
 (0)