mirror of
https://github.com/gitbutlerapp/gitbutler.git
synced 2024-12-29 20:43:37 +03:00
tag component update, collapsable branches frontend added
This commit is contained in:
parent
c6bc57cb90
commit
e107f6b00c
93
gitbutler-ui/src/lib/components/ActiveBranchStatus.svelte
Normal file
93
gitbutler-ui/src/lib/components/ActiveBranchStatus.svelte
Normal file
@ -0,0 +1,93 @@
|
||||
<script lang="ts">
|
||||
import Tag from '$lib/components/Tag.svelte';
|
||||
import { normalizeBranchName } from '$lib/utils/branch';
|
||||
import { open } from '@tauri-apps/api/shell';
|
||||
import type { BaseBranch, Branch } from '$lib/vbranches/types';
|
||||
|
||||
export let base: BaseBranch | undefined | null;
|
||||
export let branch: Branch;
|
||||
export let prUrl: string | undefined;
|
||||
export let isUnapplied = false;
|
||||
export let hasIntegratedCommits = false;
|
||||
export let isLaneCollapsed = false;
|
||||
</script>
|
||||
|
||||
{#if !branch.upstream}
|
||||
{#if !branch.active}
|
||||
<Tag
|
||||
icon="virtual-branch-small"
|
||||
color="light"
|
||||
help="These changes are stashed away from your working directory."
|
||||
reversedDirection
|
||||
verticalOrientation={isLaneCollapsed}>unapplied</Tag
|
||||
>
|
||||
{:else if hasIntegratedCommits}
|
||||
<Tag
|
||||
icon="removed-branch-small"
|
||||
color="success"
|
||||
help="These changes have been integrated upstream, update your workspace to make this lane disappear."
|
||||
reversedDirection
|
||||
verticalOrientation={isLaneCollapsed}>integrated</Tag
|
||||
>
|
||||
{:else}
|
||||
<Tag
|
||||
icon="virtual-branch-small"
|
||||
color="light"
|
||||
help="These changes are in your working directory."
|
||||
reversedDirection
|
||||
verticalOrientation={isLaneCollapsed}>virtual</Tag
|
||||
>
|
||||
{/if}
|
||||
{#if !isUnapplied}
|
||||
<Tag
|
||||
disabled
|
||||
help="Branch name that will be used when pushing. You can change it from the lane menu."
|
||||
verticalOrientation={isLaneCollapsed}
|
||||
>
|
||||
origin/{branch.upstreamName
|
||||
? branch.upstreamName
|
||||
: normalizeBranchName(branch.name)}</Tag
|
||||
>
|
||||
{/if}
|
||||
{:else}
|
||||
<Tag
|
||||
color="dark"
|
||||
icon="remote-branch-small"
|
||||
help="At least some of your changes have been pushed"
|
||||
verticalOrientation={isLaneCollapsed}
|
||||
reversedDirection>remote</Tag
|
||||
>
|
||||
<Tag
|
||||
icon="open-link"
|
||||
color="ghost"
|
||||
border
|
||||
clickable
|
||||
shrinkable
|
||||
verticalOrientation={isLaneCollapsed}
|
||||
on:click={(e) => {
|
||||
const url = base?.branchUrl(branch.upstream?.name);
|
||||
if (url) open(url);
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
}}
|
||||
>
|
||||
{isLaneCollapsed ? 'View branch' : `origin/${branch.upstream?.name}`}
|
||||
</Tag>
|
||||
{#if prUrl}
|
||||
<Tag
|
||||
icon="pr-small"
|
||||
color="ghost"
|
||||
border
|
||||
clickable
|
||||
verticalOrientation={isLaneCollapsed}
|
||||
on:click={(e) => {
|
||||
const url = prUrl;
|
||||
if (url) open(url);
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
}}
|
||||
>
|
||||
View PR
|
||||
</Tag>
|
||||
{/if}
|
||||
{/if}
|
@ -121,6 +121,7 @@
|
||||
{projectPath}
|
||||
{user}
|
||||
{githubService}
|
||||
hasNextSibling={branches.find((b) => b.order === branch.order + 1)}
|
||||
></BranchLane>
|
||||
</div>
|
||||
{/each}
|
||||
|
@ -131,8 +131,6 @@
|
||||
}
|
||||
|
||||
let isLaneCollapsed: boolean;
|
||||
|
||||
$: console.log('collapsed', isLaneCollapsed);
|
||||
</script>
|
||||
|
||||
{#if isLaneCollapsed}
|
||||
@ -154,7 +152,6 @@
|
||||
/>
|
||||
</div>
|
||||
{:else}
|
||||
<div class="branch-card-wrapper">
|
||||
<div
|
||||
class="branch-card"
|
||||
data-tauri-drag-region
|
||||
@ -295,15 +292,14 @@
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
<style lang="postcss">
|
||||
.branch-card-wrapper {
|
||||
/* .branch-card-wrapper {
|
||||
position: relative;
|
||||
display: flex;
|
||||
height: 100%;
|
||||
}
|
||||
} */
|
||||
.branch-card {
|
||||
height: 100%;
|
||||
position: relative;
|
||||
@ -432,5 +428,10 @@
|
||||
flex-direction: column;
|
||||
padding: var(--space-12);
|
||||
height: 100%;
|
||||
border-right: 1px solid var(--clr-theme-container-outline-light);
|
||||
}
|
||||
|
||||
/* .brach-collapsed {
|
||||
display: none;
|
||||
} */
|
||||
</style>
|
||||
|
@ -1,16 +1,18 @@
|
||||
<script lang="ts">
|
||||
import BranchHeaderSecondaryActions from './BranchHeaderSecondaryActions.svelte';
|
||||
import ActiveBranchStatus from './ActiveBranchStatus.svelte';
|
||||
import BranchLabel from './BranchLabel.svelte';
|
||||
import BranchLanePopupMenu from './BranchLanePopupMenu.svelte';
|
||||
// import BranchLanePopupMenu from './BranchLanePopupMenu.svelte';
|
||||
import MergeButton from './MergeButton.svelte';
|
||||
import Tag from './Tag.svelte';
|
||||
import { clickOutside } from '$lib/clickOutside';
|
||||
// import { clickOutside } from '$lib/clickOutside';
|
||||
import Button from '$lib/components/Button.svelte';
|
||||
import Icon, { type IconColor } from '$lib/components/Icon.svelte';
|
||||
import { normalizeBranchName } from '$lib/utils/branch';
|
||||
// import { normalizeBranchName } from '$lib/utils/branch';
|
||||
import * as toasts from '$lib/utils/toasts';
|
||||
import { tooltip } from '$lib/utils/tooltip';
|
||||
import { open } from '@tauri-apps/api/shell';
|
||||
// import { open } from '@tauri-apps/api/shell';
|
||||
import toast from 'svelte-french-toast';
|
||||
import type { BranchService } from '$lib/branches/service';
|
||||
import type { GitHubService } from '$lib/github/service';
|
||||
@ -121,18 +123,40 @@
|
||||
</script>
|
||||
|
||||
{#if isLaneCollapsed}
|
||||
<div class="collapsed-lane" data-remove-from-draggable data-tauri-drag-region>
|
||||
<div class="card collapsed-lane" data-tauri-drag-region>
|
||||
<div class="collapsed-lane__actions">
|
||||
<BranchHeaderSecondaryActions
|
||||
{visible}
|
||||
{isUnapplied}
|
||||
{branch}
|
||||
{branchController}
|
||||
{projectId}
|
||||
bind:isLaneCollapsed
|
||||
bind:meatballButton
|
||||
<div class="collapsed-lane__draggable" data-drag-handle>
|
||||
<Icon name="draggable-narrow" />
|
||||
</div>
|
||||
<Button
|
||||
icon="unfold-lane"
|
||||
kind="outlined"
|
||||
color="neutral"
|
||||
help="Collapse lane"
|
||||
on:click={() => {
|
||||
isLaneCollapsed = false;
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
<div class="collapsed-lane__info">
|
||||
<h3 class="collapsed-lane__label text-base-13 text-bold">
|
||||
{branch.name}
|
||||
</h3>
|
||||
|
||||
<div class="collapsed-lane__info__details">
|
||||
<ActiveBranchStatus
|
||||
{base}
|
||||
{branch}
|
||||
{isUnapplied}
|
||||
{hasIntegratedCommits}
|
||||
{isLaneCollapsed}
|
||||
prUrl={$pr$?.htmlUrl}
|
||||
/>
|
||||
{#if branch.selectedForChanges}
|
||||
<Tag color="pop" filled icon="target" verticalOrientation>Default branch</Tag>
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{:else}
|
||||
<div class="header__wrapper">
|
||||
@ -146,7 +170,14 @@
|
||||
/>
|
||||
</div>
|
||||
<div class="header__remote-branch">
|
||||
{#if !branch.upstream}
|
||||
<ActiveBranchStatus
|
||||
{base}
|
||||
{branch}
|
||||
{isUnapplied}
|
||||
{hasIntegratedCommits}
|
||||
prUrl={$pr$?.htmlUrl}
|
||||
/>
|
||||
<!-- {#if !branch.upstream}
|
||||
{#if !branch.active}
|
||||
<Tag
|
||||
icon="virtual-branch-small"
|
||||
@ -179,14 +210,9 @@
|
||||
: normalizeBranchName(branch.name)}</Tag
|
||||
>
|
||||
{/if}
|
||||
{:else}
|
||||
<Tag
|
||||
color="dark"
|
||||
icon="remote-branch-small"
|
||||
help="At least some of your changes have been pushed"
|
||||
reversedDirection>remote</Tag
|
||||
>
|
||||
<Tag
|
||||
{:else} -->
|
||||
{#if branch.upstream}
|
||||
<!-- <Tag
|
||||
icon="open-link"
|
||||
color="ghost"
|
||||
border
|
||||
@ -216,7 +242,7 @@
|
||||
>
|
||||
View PR
|
||||
</Tag>
|
||||
{/if}
|
||||
{/if} -->
|
||||
{#if prIcon}
|
||||
<div
|
||||
class="pr-status"
|
||||
@ -355,15 +381,40 @@
|
||||
</Button>
|
||||
{:else}
|
||||
<div class="header__buttons">
|
||||
<BranchHeaderSecondaryActions
|
||||
{visible}
|
||||
{isUnapplied}
|
||||
{branch}
|
||||
{branchController}
|
||||
{projectId}
|
||||
bind:isLaneCollapsed
|
||||
bind:meatballButton
|
||||
<Button
|
||||
icon="fold-lane"
|
||||
kind="outlined"
|
||||
color="neutral"
|
||||
help="Collapse lane"
|
||||
on:click={() => {
|
||||
isLaneCollapsed = true;
|
||||
}}
|
||||
/>
|
||||
<Button
|
||||
icon="kebab"
|
||||
kind="outlined"
|
||||
color="neutral"
|
||||
on:click={() => {
|
||||
console.log('meatballButton', meatballButton);
|
||||
visible = !visible;
|
||||
}}
|
||||
/>
|
||||
<div
|
||||
class="branch-popup-menu"
|
||||
use:clickOutside={{
|
||||
trigger: meatballButton,
|
||||
handler: () => (visible = false)
|
||||
}}
|
||||
>
|
||||
<BranchLanePopupMenu
|
||||
{branchController}
|
||||
{branch}
|
||||
{projectId}
|
||||
{isUnapplied}
|
||||
bind:visible
|
||||
on:action
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
@ -435,12 +486,12 @@
|
||||
gap: var(--space-4);
|
||||
}
|
||||
.draggable {
|
||||
display: flex;
|
||||
cursor: grab;
|
||||
position: absolute;
|
||||
right: var(--space-4);
|
||||
top: var(--space-6);
|
||||
opacity: 0;
|
||||
display: flex;
|
||||
cursor: grab;
|
||||
color: var(--clr-theme-scale-ntrl-50);
|
||||
transition:
|
||||
opacity var(--transition-slow),
|
||||
@ -450,13 +501,13 @@
|
||||
color: var(--clr-theme-scale-ntrl-40);
|
||||
}
|
||||
}
|
||||
/*
|
||||
|
||||
.branch-popup-menu {
|
||||
position: absolute;
|
||||
top: calc(100% + var(--space-4));
|
||||
right: 0;
|
||||
z-index: 10;
|
||||
} */
|
||||
}
|
||||
|
||||
.header__remote-branch {
|
||||
color: var(--clr-theme-scale-ntrl-50);
|
||||
@ -472,4 +523,53 @@
|
||||
.pr-status {
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
/* COLLAPSABLE LANE */
|
||||
|
||||
.collapsed-lane {
|
||||
user-select: none;
|
||||
align-items: center;
|
||||
height: 100%;
|
||||
gap: var(--space-16);
|
||||
padding: var(--space-8) var(--space-8) var(--space-16);
|
||||
}
|
||||
|
||||
.collapsed-lane__actions {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
gap: var(--space-4);
|
||||
}
|
||||
.collapsed-lane__draggable {
|
||||
cursor: grab;
|
||||
transform: rotate(90deg);
|
||||
margin-bottom: var(--space-4);
|
||||
}
|
||||
|
||||
.collapsed-lane__info {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: row-reverse;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
|
||||
writing-mode: vertical-rl;
|
||||
gap: var(--space-8);
|
||||
/* flex-direction: column-reverse; */
|
||||
/* writing-mode: vertical-rl;
|
||||
background-color: aquamarine; */
|
||||
}
|
||||
|
||||
.collapsed-lane__info__details {
|
||||
display: flex;
|
||||
flex-direction: row-reverse;
|
||||
align-items: center;
|
||||
gap: var(--space-4);
|
||||
}
|
||||
|
||||
.collapsed-lane__label {
|
||||
color: var(--clr-theme-scale-ntrl-0);
|
||||
transform: rotate(180deg);
|
||||
padding: var(--space-8) 0;
|
||||
}
|
||||
</style>
|
||||
|
@ -18,10 +18,10 @@
|
||||
|
||||
<div style="display: contents;">
|
||||
<Button
|
||||
icon="fold-lane"
|
||||
icon={isLaneCollapsed ? 'unfold-lane' : 'fold-lane'}
|
||||
kind="outlined"
|
||||
color="neutral"
|
||||
help="Fold this lane"
|
||||
help={isLaneCollapsed ? 'Expand lane' : 'Collapse lane'}
|
||||
on:click={() => {
|
||||
isLaneCollapsed = !isLaneCollapsed;
|
||||
}}
|
||||
|
@ -34,6 +34,7 @@
|
||||
export let user: User | undefined;
|
||||
export let projectPath: string;
|
||||
export let githubService: GitHubService;
|
||||
export let hasNextSibling: Branch | undefined;
|
||||
|
||||
$: selectedOwnership = writable(Ownership.fromBranch(branch));
|
||||
$: selected = setSelected($selectedFiles, branch);
|
||||
@ -60,6 +61,8 @@
|
||||
if (!match) $selectedFiles = [];
|
||||
return match;
|
||||
}
|
||||
|
||||
$: console.log('hasNextSibling', hasNextSibling?.name);
|
||||
</script>
|
||||
|
||||
<div
|
||||
@ -103,7 +106,9 @@
|
||||
selectable={$commitBoxOpen && !isUnapplied}
|
||||
on:close={() => {
|
||||
const selectedId = selected?.id;
|
||||
selectedFiles.update((fileIds) => fileIds.filter((file) => file.id != selectedId));
|
||||
selectedFiles.update((fileIds) =>
|
||||
fileIds.filter((file) => file.id != selectedId)
|
||||
);
|
||||
}}
|
||||
/>
|
||||
<Resizer
|
||||
|
@ -24,6 +24,7 @@
|
||||
export let disabled = false;
|
||||
export let clickable = false;
|
||||
export let shrinkable = false;
|
||||
export let verticalOrientation = false;
|
||||
</script>
|
||||
|
||||
<div
|
||||
@ -41,17 +42,18 @@
|
||||
class:disabled
|
||||
class:shrinkable
|
||||
class:iconLeft={reversedDirection}
|
||||
class:verticalOrientation
|
||||
class:not-button={!clickable}
|
||||
on:click
|
||||
role={clickable ? 'button' : undefined}
|
||||
class:clickable
|
||||
use:tooltip={help}
|
||||
>
|
||||
<span class="label">
|
||||
<span class="label" class:verticalLabel={verticalOrientation}>
|
||||
<slot />
|
||||
</span>
|
||||
{#if icon}
|
||||
<div class="icon">
|
||||
<div class="icon" class:verticalIcon={verticalOrientation}>
|
||||
<Icon name={icon} />
|
||||
</div>
|
||||
{/if}
|
||||
@ -226,4 +228,20 @@
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
}
|
||||
|
||||
.verticalOrientation {
|
||||
writing-mode: vertical-rl;
|
||||
height: max-content;
|
||||
width: var(--size-btn-s);
|
||||
padding: var(--space-4) var(--space-2);
|
||||
transform: rotate(180deg);
|
||||
}
|
||||
|
||||
.verticalIcon {
|
||||
transform: rotate(90deg);
|
||||
}
|
||||
|
||||
.verticalLabel {
|
||||
padding: var(--space-2) 0;
|
||||
}
|
||||
</style>
|
||||
|
Loading…
Reference in New Issue
Block a user