mirror of
https://github.com/gitbutlerapp/gitbutler.git
synced 2024-12-25 10:33:21 +03:00
feat: add StackingBranchHeader contextMenu and handlers for contextMenuItems as well as their Modals
This commit is contained in:
parent
9ba5ecbf65
commit
b46c397c60
@ -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>
|
||||
|
@ -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>
|
Loading…
Reference in New Issue
Block a user