feat: add StackingBranchHeader contextMenu and handlers for contextMenuItems as well as their Modals

This commit is contained in:
ndom91 2024-10-02 18:14:58 +02:00 committed by Mattias Granlund
parent 9ba5ecbf65
commit b46c397c60
2 changed files with 175 additions and 5 deletions

View File

@ -5,6 +5,8 @@
import { Project } from '$lib/backend/projects';
import { BaseBranch } from '$lib/baseBranch/baseBranch';
import { BaseBranchService } from '$lib/baseBranch/baseBranchService';
import StackingBranchHeaderContextMenu from '$lib/branch/StackingBranchHeaderContextMenu.svelte';
import ContextMenu from '$lib/components/contextmenu/ContextMenu.svelte';
import { mapErrorToToast } from '$lib/gitHost/github/errorMap';
import { getGitHost } from '$lib/gitHost/interface/gitHost';
import { getGitHostListingService } from '$lib/gitHost/interface/gitHostListingService';
@ -24,6 +26,7 @@
import type { PullRequest } from '$lib/gitHost/interface/types';
let isLoading = $state(false);
let descriptionVisible = $state(false);
const branchStore = getContextStore(VirtualBranch);
const branch = $derived($branchStore);
@ -42,6 +45,9 @@
const baseBranchName = $derived($baseBranch.shortName);
const pr = $derived($prMonitor?.pr);
let contextMenu = $state<ReturnType<typeof ContextMenu>>();
let meatballButtonEl = $state<HTMLDivElement>();
// TODO: Get Branch Status
const branchType = $state<BranchColor>('integrated');
const lineColor = $derived(getColorFromBranchType(branchType));
@ -145,6 +151,14 @@
function editTitle(title: string) {
branchController.updateBranchName(branch.id, title);
}
function editDescription(_description: string) {
// branchController.updateBranchDescription(branch.id, description);
}
function addDescription() {
descriptionVisible = true;
}
</script>
<div class="branch-header">
@ -166,9 +180,31 @@
></Button>
</div>
<div class="branch-info__btns">
<Button size="tag" icon="kebab" style="ghost"></Button>
<Button
size="tag"
icon="kebab"
style="ghost"
bind:el={meatballButtonEl}
onclick={() => {
contextMenu?.toggle();
}}
></Button>
<StackingBranchHeaderContextMenu
bind:contextMenuEl={contextMenu}
target={meatballButtonEl}
{addDescription}
/>
</div>
</div>
{#if descriptionVisible}
<div class="branch-info__description">
<div class="branch-action__line" style:--bg-color={lineColor}></div>
<BranchLabel
name={branch.description}
onChange={(description) => editDescription(description)}
/>
</div>
{/if}
<div class="branch-action">
<div class="branch-action__line" style:--bg-color={lineColor}></div>
<div class="branch-action__body">
@ -209,6 +245,7 @@
padding: 8px 16px;
flex-grow: 1;
}
& .branch-info__btns {
display: flex;
gap: 0.25rem;
@ -220,19 +257,27 @@
}
}
.branch-info__description {
width: 100%;
display: flex;
justify-content: flex-start;
align-items: stretch;
}
.branch-action {
width: 100%;
display: flex;
justify-content: flex-start;
align-items: stretch;
.branch-action__line {
margin: 0 22px 0 22.5px;
border-left: 2px solid var(--bg-color, var(--clr-border-3));
}
.branch-action__body {
width: 100%;
padding: 4px 12px 12px 0px;
}
}
.branch-action__line {
margin: 0 22px 0 22.5px;
border-left: 2px solid var(--bg-color, var(--clr-border-3));
}
</style>

View File

@ -0,0 +1,125 @@
<script lang="ts">
import ContextMenu from '$lib/components/contextmenu/ContextMenu.svelte';
import ContextMenuItem from '$lib/components/contextmenu/ContextMenuItem.svelte';
import ContextMenuSection from '$lib/components/contextmenu/ContextMenuSection.svelte';
import TextBox from '$lib/shared/TextBox.svelte';
import { getContext, getContextStore } from '$lib/utils/context';
import { BranchController } from '$lib/vbranches/branchController';
import { VirtualBranch } from '$lib/vbranches/types';
import Button from '@gitbutler/ui/Button.svelte';
import Modal from '@gitbutler/ui/Modal.svelte';
interface Props {
contextMenuEl?: ReturnType<typeof ContextMenu>;
target?: HTMLElement;
addDescription: () => void;
}
let { contextMenuEl = $bindable(), target, addDescription }: Props = $props();
const branchStore = getContextStore(VirtualBranch);
const branchController = getContext(BranchController);
let deleteSeriesModal: Modal;
let deleteSeriesCommitsModal: Modal;
let renameSeriesModal: Modal;
let newSeriesName = $state('');
let isDeleting = $state(false);
const branch = $derived($branchStore);
</script>
<ContextMenu bind:this={contextMenuEl} {target}>
<ContextMenuSection>
<ContextMenuItem
label="Add a description"
on:click={() => {
addDescription();
contextMenuEl?.close();
}}
/>
<ContextMenuItem
label="Rename Series"
on:click={async () => {
renameSeriesModal.show(branch);
contextMenuEl?.close();
}}
/>
<ContextMenuItem
label="Delete Series & Commits"
on:click={() => {
deleteSeriesCommitsModal.show(branch);
contextMenuEl?.close();
}}
/>
<ContextMenuItem
label="Delete Series Only"
on:click={() => {
deleteSeriesModal.show(branch);
contextMenuEl?.close();
}}
/>
</ContextMenuSection>
</ContextMenu>
<Modal
width="small"
bind:this={renameSeriesModal}
onSubmit={(close) => {
branchController.updateBranchRemoteName(branch.id, newSeriesName);
close();
}}
>
<TextBox label="Series Name" id="newSeriesName" bind:value={newSeriesName} focus />
{#snippet controls(close)}
<Button style="ghost" outline type="reset" onclick={close}>Cancel</Button>
<Button style="pop" kind="solid" type="submit">Rename</Button>
{/snippet}
</Modal>
<Modal
width="small"
title="Delete Series"
bind:this={deleteSeriesModal}
onSubmit={async (close) => {
try {
isDeleting = true;
await branchController.saveAndUnapply(branch.id);
close();
} finally {
isDeleting = false;
}
}}
>
{#snippet children(branch)}
Are you sure you want to delete <code class="code-string">{branch.name}</code>?
{/snippet}
{#snippet controls(close)}
<Button style="ghost" outline onclick={close}>Cancel</Button>
<Button style="error" kind="solid" type="submit" loading={isDeleting}>Delete</Button>
{/snippet}
</Modal>
<Modal
width="small"
title="Delete Series & Commits"
bind:this={deleteSeriesCommitsModal}
onSubmit={async (close) => {
try {
isDeleting = true;
await branchController.unapplyWithoutSaving(branch.id);
close();
} finally {
isDeleting = false;
}
}}
>
{#snippet children(branch)}
Are you sure you want to delete <code class="code-string">{branch.name}</code>?
{/snippet}
{#snippet controls(close)}
<Button style="ghost" outline onclick={close}>Cancel</Button>
<Button style="error" kind="solid" type="submit" loading={isDeleting}>Delete</Button>
{/snippet}
</Modal>