mirror of
https://github.com/gitbutlerapp/gitbutler.git
synced 2025-01-04 15:53:30 +03:00
Put stashed branches in the sidenav again
This commit is contained in:
parent
a561a004f7
commit
d9102716d8
@ -2,7 +2,7 @@ import type { PullRequest } from '$lib/github/types';
|
||||
import type { Branch, RemoteBranch } from '$lib/vbranches/types';
|
||||
import { CombinedBranch } from '$lib/branches/types';
|
||||
import { Observable, combineLatest } from 'rxjs';
|
||||
import { map, startWith, switchMap } from 'rxjs/operators';
|
||||
import { startWith, switchMap } from 'rxjs/operators';
|
||||
import type { RemoteBranchService } from '$lib/stores/remoteBranches';
|
||||
import type { GitHubService } from '$lib/github/service';
|
||||
import type { VirtualBranchService } from '$lib/vbranches/branchStoresCache';
|
||||
@ -17,7 +17,7 @@ export class BranchService {
|
||||
remoteBranchService: RemoteBranchService,
|
||||
private githubService: GitHubService
|
||||
) {
|
||||
const vbranchesWithEmpty$ = vbranchService.activeBranches$.pipe(startWith([]));
|
||||
const vbranchesWithEmpty$ = vbranchService.branches$.pipe(startWith([]));
|
||||
const branchesWithEmpty$ = remoteBranchService.branches$.pipe(startWith([]));
|
||||
const prWithEmpty$ = githubService.prs$.pipe(startWith([]));
|
||||
|
||||
@ -32,8 +32,7 @@ export class BranchService {
|
||||
);
|
||||
observer.next(contributions);
|
||||
})
|
||||
),
|
||||
map((branches) => branches.filter((b) => !b.vbranch || b.vbranch.active))
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -18,7 +18,7 @@
|
||||
$: branchService = data.branchService;
|
||||
|
||||
$: project$ = data.project$;
|
||||
$: branches = vbranchService.branches$;
|
||||
$: activeBranches$ = vbranchService.activeBranches$;
|
||||
$: error$ = vbranchService.branchesError$;
|
||||
$: githubEnabled$ = githubService.isEnabled$;
|
||||
|
||||
@ -63,7 +63,7 @@
|
||||
project={$project$}
|
||||
{cloud}
|
||||
base={$base$}
|
||||
branches={$branches}
|
||||
branches={$activeBranches$}
|
||||
projectPath={$project$?.path}
|
||||
branchesError={$error$}
|
||||
user={$user$}
|
||||
|
@ -120,7 +120,6 @@
|
||||
{projectPath}
|
||||
{user}
|
||||
{githubService}
|
||||
readonly={!branch.active}
|
||||
></BranchLane>
|
||||
</div>
|
||||
{/each}
|
||||
|
@ -12,7 +12,7 @@
|
||||
import Button from '$lib/components/Button.svelte';
|
||||
import toast from 'svelte-french-toast';
|
||||
import { tooltip } from '$lib/utils/tooltip';
|
||||
import Toggle from '$lib/components/Toggle.svelte';
|
||||
import { goto } from '$app/navigation';
|
||||
|
||||
export let readonly = false;
|
||||
export let branch: Branch;
|
||||
@ -27,6 +27,7 @@
|
||||
let meatballButton: HTMLDivElement;
|
||||
let visible = false;
|
||||
let container: HTMLDivElement;
|
||||
let isApplying = false;
|
||||
|
||||
function handleBranchNameChange() {
|
||||
branchController.updateBranchName(branch.id, branch.name);
|
||||
@ -160,44 +161,55 @@
|
||||
Set as default
|
||||
</Button>
|
||||
{/if}
|
||||
<Toggle
|
||||
checked={!readonly}
|
||||
help="Toggle to stash branch"
|
||||
on:change={async () => {
|
||||
try {
|
||||
if (readonly) await branchController.applyBranch(branch.id);
|
||||
else await branchController.unapplyBranch(branch.id);
|
||||
} catch (e) {
|
||||
const err = 'Failed to apply/unapply branch';
|
||||
toast.error(err);
|
||||
console.error(err, e);
|
||||
}
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
<div class="relative" bind:this={meatballButton}>
|
||||
<Button
|
||||
icon="kebab"
|
||||
kind="outlined"
|
||||
color="neutral"
|
||||
on:click={() => (visible = !visible)}
|
||||
/>
|
||||
<div
|
||||
class="branch-popup-menu"
|
||||
use:clickOutside={{
|
||||
trigger: meatballButton,
|
||||
handler: () => (visible = false)
|
||||
}}
|
||||
>
|
||||
<BranchLanePopupMenu
|
||||
{branchController}
|
||||
{branch}
|
||||
{projectId}
|
||||
{readonly}
|
||||
bind:visible
|
||||
on:action
|
||||
{#if readonly}
|
||||
<Button
|
||||
help="Restores these changes into your working directory"
|
||||
icon="plus-small"
|
||||
color="primary"
|
||||
kind="outlined"
|
||||
loading={isApplying}
|
||||
on:click={async () => {
|
||||
isApplying = true;
|
||||
try {
|
||||
await branchController.applyBranch(branch.id);
|
||||
goto(`/${projectId}/board`);
|
||||
} catch (e) {
|
||||
const err = 'Failed to apply branch';
|
||||
toast.error(err);
|
||||
console.error(err, e);
|
||||
} finally {
|
||||
isApplying = false;
|
||||
}
|
||||
}}
|
||||
>
|
||||
Apply
|
||||
</Button>
|
||||
{:else}
|
||||
<Button
|
||||
icon="kebab"
|
||||
kind="outlined"
|
||||
color="neutral"
|
||||
on:click={() => (visible = !visible)}
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
class="branch-popup-menu"
|
||||
use:clickOutside={{
|
||||
trigger: meatballButton,
|
||||
handler: () => (visible = false)
|
||||
}}
|
||||
>
|
||||
<BranchLanePopupMenu
|
||||
{branchController}
|
||||
{branch}
|
||||
{projectId}
|
||||
{readonly}
|
||||
bind:visible
|
||||
on:action
|
||||
/>
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -257,8 +269,7 @@
|
||||
.header__buttons {
|
||||
display: flex;
|
||||
position: relative;
|
||||
align-items: center;
|
||||
gap: var(--space-10);
|
||||
gap: var(--space-4);
|
||||
}
|
||||
.header__label {
|
||||
display: flex;
|
||||
|
@ -11,6 +11,7 @@
|
||||
|
||||
export let includePrs: Writable<boolean | undefined>;
|
||||
export let includeRemote: Writable<boolean | undefined>;
|
||||
export let includeStashed: Writable<boolean | undefined>;
|
||||
export let hideBots: Writable<boolean | undefined>;
|
||||
export let hideInactive: Writable<boolean | undefined>;
|
||||
</script>
|
||||
@ -26,6 +27,10 @@
|
||||
<ContextMenuItem label="Remote" on:click={() => ($includeRemote = !$includeRemote)}>
|
||||
<Checkbox small bind:checked={$includeRemote} slot="control" />
|
||||
</ContextMenuItem>
|
||||
|
||||
<ContextMenuItem label="Stashed" on:click={() => ($includeStashed = !$includeStashed)}>
|
||||
<Checkbox small bind:checked={$includeStashed} slot="control" />
|
||||
</ContextMenuItem>
|
||||
</ContextMenuSection>
|
||||
|
||||
<ContextMenuSection>
|
||||
|
@ -31,13 +31,14 @@
|
||||
|
||||
let includePrs = persisted(true, 'includePrs_' + projectId);
|
||||
let includeRemote = persisted(true, 'includeRemote_' + projectId);
|
||||
let includeStashed = persisted(true, 'includeStashed_' + projectId);
|
||||
let hideBots = persisted(false, 'hideBots_' + projectId);
|
||||
let hideInactive = persisted(false, 'hideInactive_' + projectId);
|
||||
|
||||
let filtersActive = derived(
|
||||
[includePrs, includeRemote, hideBots, hideInactive],
|
||||
([prs, remote, bots, inactive]) => {
|
||||
return !prs || !remote || bots || inactive;
|
||||
[includePrs, includeRemote, includeStashed, hideBots, hideInactive],
|
||||
([prs, remote, stashed, bots, inactive]) => {
|
||||
return !prs || !remote || !stashed || bots || inactive;
|
||||
}
|
||||
);
|
||||
|
||||
@ -48,16 +49,19 @@
|
||||
textFilter$,
|
||||
storeToObservable(includePrs),
|
||||
storeToObservable(includeRemote),
|
||||
storeToObservable(includeStashed),
|
||||
storeToObservable(hideBots),
|
||||
storeToObservable(hideInactive)
|
||||
],
|
||||
(branches, search, includePrs, includeRemote, hideBots, hideInactive) => {
|
||||
(branches, search, includePrs, includeRemote, includeStashed, hideBots, hideInactive) => {
|
||||
const filteredByType = filterByType(branches, {
|
||||
includePrs,
|
||||
includeRemote,
|
||||
includeStashed,
|
||||
hideBots
|
||||
});
|
||||
const filteredBySearch = filterByText(filteredByType, search);
|
||||
console.log(branches);
|
||||
return hideInactive ? filterInactive(filteredBySearch) : filteredBySearch;
|
||||
}
|
||||
);
|
||||
@ -75,6 +79,7 @@
|
||||
params: {
|
||||
includePrs: boolean;
|
||||
includeRemote: boolean;
|
||||
includeStashed: boolean;
|
||||
hideBots: boolean;
|
||||
}
|
||||
): CombinedBranch[] {
|
||||
@ -83,6 +88,7 @@
|
||||
return !params.hideBots || !b.pr.author?.isBot;
|
||||
}
|
||||
if (params.includeRemote && b.remoteBranch) return true;
|
||||
if (params.includeStashed && b.vbranch) return true;
|
||||
return false;
|
||||
});
|
||||
}
|
||||
@ -149,6 +155,7 @@
|
||||
{visible}
|
||||
{includePrs}
|
||||
{includeRemote}
|
||||
{includeStashed}
|
||||
{hideBots}
|
||||
{hideInactive}
|
||||
showPrCheckbox={$githubEnabled$}
|
||||
|
@ -0,0 +1,37 @@
|
||||
<script lang="ts">
|
||||
import { page } from '$app/stores';
|
||||
import Icon from '$lib/icons/Icon.svelte';
|
||||
import type { Branch } from '$lib/vbranches/types';
|
||||
import { slide } from 'svelte/transition';
|
||||
|
||||
export let branch: Branch;
|
||||
export let projectId: string;
|
||||
|
||||
$: href = `/${projectId}/stashed/${branch.id}`;
|
||||
$: selected = $page.url.href.includes(href);
|
||||
</script>
|
||||
|
||||
<a class="item" {href} class:selected transition:slide={{ duration: 250 }}>
|
||||
<Icon name="branch" />
|
||||
<div class="text-color-2 flex-grow truncate">
|
||||
{branch.name}
|
||||
{branch.files[0]?.modifiedAt}
|
||||
</div>
|
||||
</a>
|
||||
|
||||
<style lang="postcss">
|
||||
.item {
|
||||
display: flex;
|
||||
gap: var(--space-10);
|
||||
padding-top: var(--space-10);
|
||||
padding-bottom: var(--space-10);
|
||||
padding-left: var(--space-8);
|
||||
padding-right: var(--space-8);
|
||||
border-radius: var(--radius-m);
|
||||
}
|
||||
.item:hover,
|
||||
.item:focus,
|
||||
.selected {
|
||||
background-color: var(--clr-theme-container-pale);
|
||||
}
|
||||
</style>
|
@ -0,0 +1,86 @@
|
||||
<script lang="ts">
|
||||
import type { PageData } from './$types';
|
||||
import { page } from '$app/stores';
|
||||
import BranchLane from '../../components/BranchLane.svelte';
|
||||
import Button from '$lib/components/Button.svelte';
|
||||
import Modal from '$lib/components/Modal.svelte';
|
||||
import { goto } from '$app/navigation';
|
||||
|
||||
export let data: PageData;
|
||||
|
||||
let applyConflictedModal: Modal;
|
||||
let deleteBranchModal: Modal;
|
||||
|
||||
$: projectId = data.projectId;
|
||||
$: user$ = data.user$;
|
||||
$: cloud = data.cloud;
|
||||
$: project$ = data.project$;
|
||||
|
||||
$: branchController = data.branchController;
|
||||
$: vbranchService = data.vbranchService;
|
||||
$: baseBranchService = data.baseBranchService;
|
||||
$: baseBranch$ = baseBranchService.base$;
|
||||
$: branchService = data.branchService;
|
||||
|
||||
$: branches$ = vbranchService.branches$;
|
||||
$: error$ = vbranchService.branchesError$;
|
||||
$: branch = $branches$?.find((b) => b.id == $page.params.branchId);
|
||||
$: githubService = data.githubService;
|
||||
</script>
|
||||
|
||||
{#if $error$}
|
||||
<p>Error...</p>
|
||||
{:else if !$branches$}
|
||||
<p>Loading...</p>
|
||||
{:else if branch}
|
||||
<BranchLane
|
||||
{branch}
|
||||
{branchController}
|
||||
{branchService}
|
||||
base={$baseBranch$}
|
||||
{cloud}
|
||||
project={$project$}
|
||||
readonly={!branch.active}
|
||||
user={$user$}
|
||||
projectPath={$project$.path}
|
||||
{githubService}
|
||||
/>
|
||||
{:else}
|
||||
<p>Branch no longer exists</p>
|
||||
{/if}
|
||||
|
||||
<Modal width="small" title="Merge conflicts" bind:this={applyConflictedModal}>
|
||||
<p>Applying this branch will introduce merge conflicts.</p>
|
||||
<svelte:fragment slot="controls" let:item let:close>
|
||||
<Button kind="outlined" color="neutral" on:click={close}>Cancel</Button>
|
||||
<Button
|
||||
color="primary"
|
||||
on:click={() => {
|
||||
branchController.applyBranch(item.id);
|
||||
close();
|
||||
goto(`/${projectId}/board`);
|
||||
}}
|
||||
>
|
||||
Update
|
||||
</Button>
|
||||
</svelte:fragment>
|
||||
</Modal>
|
||||
|
||||
<Modal width="small" title="Delete branch" bind:this={deleteBranchModal} let:item>
|
||||
<div>
|
||||
Deleting <code>{item.name}</code> cannot be undone.
|
||||
</div>
|
||||
<svelte:fragment slot="controls" let:close let:item>
|
||||
<Button kind="outlined" color="neutral" on:click={close}>Cancel</Button>
|
||||
<Button
|
||||
color="error"
|
||||
on:click={() => {
|
||||
branchController.deleteBranch(item.id);
|
||||
close();
|
||||
goto(`/${projectId}/board`);
|
||||
}}
|
||||
>
|
||||
Delete
|
||||
</Button>
|
||||
</svelte:fragment>
|
||||
</Modal>
|
Loading…
Reference in New Issue
Block a user