Skip to content

Commit 2b8d543

Browse files
committed
Make id optional in type Stack
1 parent 9b7d544 commit 2b8d543

15 files changed

+94
-54
lines changed

apps/desktop/cypress/e2e/review.cy.ts

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -183,13 +183,13 @@ describe('Review', () => {
183183
cy.getByTestId('create-review-box-title-input')
184184
.should('be.visible')
185185
.should('be.enabled')
186-
.should('have.value', mockBackend.getCommitTitle(stack.id))
186+
.should('have.value', mockBackend.getCommitTitle(stack.id!))
187187
.clear()
188188
.type(prTitle);
189189

190190
cy.getByTestId('create-review-box-description-input')
191191
.should('be.visible')
192-
.should('contain', mockBackend.getCommitMessage(stack.id))
192+
.should('contain', mockBackend.getCommitMessage(stack.id!))
193193
.click()
194194
.clear()
195195
.type(prDescription);
@@ -251,13 +251,13 @@ describe('Review', () => {
251251
cy.getByTestId('create-review-box-title-input')
252252
.should('be.visible')
253253
.should('be.enabled')
254-
.should('have.value', mockBackend.getCommitTitle(stack.id))
254+
.should('have.value', mockBackend.getCommitTitle(stack.id!))
255255
.clear()
256256
.type(prTitle);
257257

258258
cy.getByTestId('create-review-box-description-input')
259259
.should('be.visible')
260-
.should('contain', mockBackend.getCommitMessage(stack.id))
260+
.should('contain', mockBackend.getCommitMessage(stack.id!))
261261
.click()
262262
.clear()
263263
.type(prDescription);
@@ -333,7 +333,7 @@ describe('Review', () => {
333333
cy.getByTestId('create-review-box-title-input')
334334
.should('be.visible')
335335
.should('be.enabled')
336-
.should('have.value', mockBackend.getCommitTitle(stack.id));
336+
.should('have.value', mockBackend.getCommitTitle(stack.id!));
337337

338338
cy.getByTestId('create-review-box-template-toggle').click();
339339
enabledTemplates = true;
@@ -343,7 +343,7 @@ describe('Review', () => {
343343
cy.getByTestId('create-review-box-title-input')
344344
.should('be.visible')
345345
.should('be.enabled')
346-
.should('have.value', mockBackend.getCommitTitle(stack.id))
346+
.should('have.value', mockBackend.getCommitTitle(stack.id!))
347347
.clear()
348348
.type(prTitle);
349349

apps/desktop/cypress/e2e/selection.cy.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ describe('Selection', () => {
3737

3838
for (const stack of stacks) {
3939
const stackName = stack.heads[0]?.name;
40-
const stackId = stack.id;
40+
const stackId = stack.id!;
4141
if (!stackName) continue;
4242

4343
cy.getByTestIdByValue('branch-header', stackName)
@@ -51,7 +51,7 @@ describe('Selection', () => {
5151
.scrollIntoView()
5252
.should('be.visible')
5353
.within(() => {
54-
const changedFileNames = mockBackend.getBranchChangesFileNames(stack.id, stackName);
54+
const changedFileNames = mockBackend.getBranchChangesFileNames(stackId, stackName);
5555
for (const fileName of changedFileNames) {
5656
cy.getByTestId('file-list-item', fileName).should('be.visible');
5757
}
@@ -71,7 +71,7 @@ describe('Selection', () => {
7171
// Select the initial commit which should be local only
7272
cy.getByTestId('commit-row', 'Initial commit').first().click();
7373

74-
cy.getByTestIdByValue('stack', stack.id)
74+
cy.getByTestIdByValue('stack', stack.id!)
7575
.should('be.visible')
7676
.within(() => {
7777
cy.getByTestId('commit-drawer-title').should('contain', 'Initial commit');

apps/desktop/cypress/e2e/unifiedDiffView.cy.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -54,11 +54,11 @@ describe('Unified Diff View', () => {
5454
.should('contain', stackName)
5555
.click()
5656
.then(() => {
57-
cy.getByTestIdByValue('stack', stack.id)
57+
cy.getByTestIdByValue('stack', stack.id!)
5858
.should('be.visible')
5959
.within(() => {
6060
// Check if the file list is updated
61-
const changedFileNames = mockBackend.getBranchChangesFileNames(stack.id, stackName);
61+
const changedFileNames = mockBackend.getBranchChangesFileNames(stack.id!, stackName);
6262
for (const fileName of changedFileNames) {
6363
cy.getByTestId('file-list-item', fileName).should('be.visible').click();
6464
}

apps/desktop/src/components/IntegrateUpstreamModal.svelte

Lines changed: 18 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22
import { writeClipboard } from '$lib/backend/clipboard';
33
import { BASE_BRANCH_SERVICE } from '$lib/baseBranch/baseBranchService.svelte';
44
import { DEFAULT_FORGE_FACTORY } from '$lib/forge/forgeFactory.svelte';
5-
import { type Stack } from '$lib/stacks/stack';
65
import {
76
getBaseBranchResolution,
87
type BaseBranchResolutionApproach,
@@ -86,12 +85,14 @@
8685
);
8786
const forceIntegratedBranches = mergedAssociatedReviews.map((r) => r.sourceBranch);
8887
89-
results.set(status.stack.id, {
90-
branchId: status.stack.id,
91-
approach: getResolutionApproachV3(status),
92-
deleteIntegratedBranches: true,
93-
forceIntegratedBranches
94-
});
88+
if (status.stack.id) {
89+
results.set(status.stack.id, {
90+
branchId: status.stack.id,
91+
approach: getResolutionApproachV3(status),
92+
deleteIntegratedBranches: true,
93+
forceIntegratedBranches
94+
});
95+
}
9596
}
9697
9798
statuses = statusesTmp;
@@ -266,22 +267,22 @@
266267
}
267268
</script>
268269

269-
{#snippet stackStatus(stack: Stack, stackStatus: StackStatus)}
270-
{@const branchShouldBeDeletedMap = getBranchShouldBeDeletedMap(stack.id, stackStatus)}
270+
{#snippet stackStatus(stackId: string, stackStatus: StackStatus)}
271+
{@const branchShouldBeDeletedMap = getBranchShouldBeDeletedMap(stackId, stackStatus)}
271272
<IntegrationSeriesRow
272273
testId={TestId.IntegrateUpstreamSeriesRow}
273274
series={integrationRowSeries(stackStatus)}
274275
{branchShouldBeDeletedMap}
275276
updateBranchShouldBeDeletedMap={(_, shouldBeDeleted) =>
276-
updateBranchShouldBeDeletedMap(stack.id, shouldBeDeleted)}
277+
updateBranchShouldBeDeletedMap(stackId, shouldBeDeleted)}
277278
>
278-
{#if !stackFullyIntegrated(stackStatus) && results.get(stack.id)}
279+
{#if !stackFullyIntegrated(stackStatus) && results.get(stackId)}
279280
<Select
280-
value={results.get(stack.id)!.approach.type}
281+
value={results.get(stackId)!.approach.type}
281282
maxWidth={130}
282283
onselect={(value) => {
283-
const result = results.get(stack.id)!;
284-
results.set(stack.id, { ...result, approach: { type: value as OperationType } });
284+
const result = results.get(stackId)!;
285+
results.set(stackId, { ...result, approach: { type: value as OperationType } });
285286
}}
286287
options={integrationOptions(stackStatus)}
287288
>
@@ -397,7 +398,9 @@
397398
<div class="scroll-wrap">
398399
<ScrollableContainer maxHeight="15rem">
399400
{#each statuses as { stack, status }}
400-
{@render stackStatus(stack, status)}
401+
{#if stack.id}
402+
{@render stackStatus(stack.id, status)}
403+
{/if}
401404
{/each}
402405
</ScrollableContainer>
403406
</div>

apps/desktop/src/components/LineLocksWarning.svelte

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,9 @@
2121

2222
<ReduxResult result={stacksResult.current} {projectId}>
2323
{#snippet children(stacks)}
24-
{@const lockedToStacks = stacks.filter((stack) => lockedToStackIds.includes(stack.id))}
24+
{@const lockedToStacks = stacks.filter(
25+
(stack) => stack.id && lockedToStackIds.includes(stack.id)
26+
)}
2527
{@const stackNames = lockedToStacks.map(getStackName)}
2628
<div data-testid={TestId.UnifiedDiffViewLockWarning}>
2729
{#if stackNames.length > 1}

apps/desktop/src/components/MultiStackCreateNew.svelte

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
Textbox
2020
} from '@gitbutler/ui';
2121
import { slugify } from '@gitbutler/ui/utils/string';
22+
import { isDefined } from '@gitbutler/ui/utils/typeguards';
2223
2324
type Props = {
2425
el?: HTMLButtonElement;
@@ -46,13 +47,16 @@
4647
4748
// Create options for the selector (stack represented by first branch name)
4849
const stackOptions = $derived(
49-
allStacks.map((stack) => {
50-
const firstBranchName = stack.heads[0]?.name ?? `Stack ${stack.id.slice(0, 8)}`;
51-
return {
52-
label: firstBranchName,
53-
value: stack.id
54-
};
55-
})
50+
allStacks
51+
.map((stack) => {
52+
if (!stack.id) return;
53+
const firstBranchName = stack.heads[0]?.name ?? `Stack ${stack?.id.slice(0, 8)}`;
54+
return {
55+
label: firstBranchName,
56+
value: stack.id
57+
};
58+
})
59+
.filter(isDefined)
5660
);
5761
5862
// Set default selected stack and handle if current selected stack is no longer available

apps/desktop/src/components/MultiStackView.svelte

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
import { UI_STATE } from '$lib/state/uiState.svelte';
2121
import { throttle } from '$lib/utils/misc';
2222
import { inject } from '@gitbutler/shared/context';
23+
import { isDefined } from '@gitbutler/ui/utils/typeguards';
2324
import { flip } from 'svelte/animate';
2425
import type { Stack } from '$lib/stacks/stack';
2526
@@ -128,7 +129,9 @@
128129
ondrop={() => {
129130
stackService.updateStackOrder({
130131
projectId,
131-
stacks: mutableStacks.map((b, i) => ({ id: b.id, order: i }))
132+
stacks: mutableStacks
133+
.map((b, i) => (b.id ? { id: b.id, order: i } : undefined))
134+
.filter(isDefined)
132135
});
133136
}}
134137
>
@@ -143,21 +146,25 @@
143146
`StackView` instead of being set imperatively in the dragstart handler.
144147
-->
145148
{#each mutableStacks as stack, i (stack.id)}
146-
{@const laneState = uiState.lane(stack.id)}
149+
<!-- TODO: What fallback id should we use? -->
150+
{@const laneId = stack.id || 'fallback-id'}
151+
{@const laneState = uiState.lane(laneId)}
147152
{@const selection = laneState.selection}
148153
<div
149154
class="reorderable-stack"
150155
role="presentation"
151156
animate:flip={{ duration: 150 }}
152157
onmousedown={onReorderMouseDown}
153158
ondragstart={(e) => {
159+
if (!stack.id) return;
154160
onReorderStart(e, stack.id, () => {
155161
draggingStack = true;
156162
selection.set(undefined);
157-
intelligentScrollingService.show(projectId, stack.id, 'stack');
163+
intelligentScrollingService.show(projectId, laneId, 'stack');
158164
});
159165
}}
160166
ondragover={(e) => {
167+
if (!stack.id) return;
161168
throttledDragOver(e, mutableStacks, stack.id);
162169
}}
163170
ondragend={() => {

apps/desktop/src/components/RulesList.svelte

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
import { typedKeys } from '$lib/utils/object';
2121
import { inject } from '@gitbutler/shared/context';
2222
import { Button, chipToasts, Select, SelectItem, Icon } from '@gitbutler/ui';
23+
import { isDefined } from '@gitbutler/ui/utils/typeguards';
2324
import type { Snippet } from 'svelte';
2425
2526
type Props = {
@@ -271,10 +272,16 @@
271272
<ReduxResult {projectId} result={stackEntries.current}>
272273
{#snippet children(stacks)}
273274
{@const stackOptions = [
274-
...stacks.map((stack) => ({
275-
label: getStackName(stack),
276-
value: encodeStackTarget({ type: 'stackId', subject: stack.id })
277-
})),
275+
...stacks
276+
.map((stack) =>
277+
stack.id
278+
? {
279+
label: getStackName(stack),
280+
value: encodeStackTarget({ type: 'stackId', subject: stack.id })
281+
}
282+
: undefined
283+
)
284+
.filter(isDefined),
278285
{ separator: true } as const,
279286
{
280287
label: 'Leftmost stack',

apps/desktop/src/components/WorkspaceView.svelte

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
import { STACK_SERVICE } from '$lib/stacks/stackService.svelte';
2121
import { UI_STATE, type ExclusiveAction } from '$lib/state/uiState.svelte';
2222
import { inject } from '@gitbutler/shared/context';
23+
import { isDefined } from '@gitbutler/ui/utils/typeguards';
2324
import { setContext } from 'svelte';
2425
import { writable } from 'svelte/store';
2526
@@ -52,13 +53,17 @@
5253
5354
const stackFocusables = $derived(
5455
stacksResult.current?.data
55-
? stacksResult.current.data.map((stack) => stackFocusableId(stack.id))
56+
? stacksResult.current.data
57+
.map((stack) => (stack.id ? stackFocusableId(stack.id) : undefined))
58+
.filter(isDefined)
5659
: []
5760
);
5861
5962
const uncommittedFocusables = $derived(
6063
stacksResult.current?.data
61-
? stacksResult.current.data.map((stack) => uncommittedFocusableId(stack.id))
64+
? stacksResult.current.data
65+
.map((stack) => (stack.id ? uncommittedFocusableId(stack.id) : undefined))
66+
.filter(isDefined)
6267
: []
6368
);
6469

apps/desktop/src/components/codegen/CodegenPage.svelte

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@
4949
5050
const firstStack = stacks.current.data[0];
5151
const firstHead = firstStack?.heads[0];
52-
if (firstHead) {
52+
if (firstHead && firstStack.id) {
5353
selectedBranch = {
5454
stackId: firstStack.id,
5555
head: firstHead.name
@@ -122,9 +122,11 @@
122122
<ReduxResult result={stacks.current} {projectId}>
123123
{#snippet children(stacks, { projectId })}
124124
{#each stacks as stack}
125-
{#each stack.heads as head}
126-
{@render sidebarContentEntry(projectId, stack.id, head.name)}
127-
{/each}
125+
{#if stack.id}
126+
{#each stack.heads as head}
127+
{@render sidebarContentEntry(projectId, stack.id, head.name)}
128+
{/each}
129+
{/if}
128130
{/each}
129131
{/snippet}
130132
</ReduxResult>

0 commit comments

Comments
 (0)