mirror of
https://github.com/gitbutlerapp/gitbutler.git
synced 2024-11-23 03:26:36 +03:00
first stab at virtual branch UI
This commit is contained in:
parent
b52ad2d55f
commit
02e81b71dd
@ -61,6 +61,7 @@
|
||||
"inter-ui": "^3.19.3",
|
||||
"leven": "^4.0.0",
|
||||
"marked": "^5.0.2",
|
||||
"mm-jsr": "^3.0.2",
|
||||
"nanoevents": "^7.0.1",
|
||||
"nanoid": "^4.0.1",
|
||||
"postcss": "^8.4.14",
|
||||
@ -71,6 +72,7 @@
|
||||
"prettier-plugin-tailwindcss": "^0.3.0",
|
||||
"svelte": "~3.55.1",
|
||||
"svelte-check": "^3.0.1",
|
||||
"svelte-dnd-action": "^0.9.22",
|
||||
"svelte-floating-ui": "^1.5.2",
|
||||
"svelte-french-toast": "^1.0.3",
|
||||
"svelte-loadable-store": "^1.2.3",
|
||||
@ -88,7 +90,6 @@
|
||||
"xterm-addon-fit": "^0.7.0",
|
||||
"xterm-addon-ligatures": "^0.6.0",
|
||||
"xterm-addon-unicode11": "^0.5.0",
|
||||
"xterm-addon-webgl": "^0.14.0",
|
||||
"mm-jsr": "^3.0.2"
|
||||
"xterm-addon-webgl": "^0.14.0"
|
||||
}
|
||||
}
|
||||
|
@ -169,6 +169,9 @@ devDependencies:
|
||||
svelte-check:
|
||||
specifier: ^3.0.1
|
||||
version: 3.0.3(postcss-load-config@4.0.1)(postcss@8.4.21)(svelte@3.55.1)
|
||||
svelte-dnd-action:
|
||||
specifier: ^0.9.22
|
||||
version: 0.9.22(svelte@3.55.1)
|
||||
svelte-floating-ui:
|
||||
specifier: ^1.5.2
|
||||
version: 1.5.2
|
||||
@ -3683,6 +3686,14 @@ packages:
|
||||
- sugarss
|
||||
dev: true
|
||||
|
||||
/svelte-dnd-action@0.9.22(svelte@3.55.1):
|
||||
resolution: {integrity: sha512-lOQJsNLM1QWv5mdxIkCVtk6k4lHCtLgfE59y8rs7iOM6erchbLC9hMEFYSveZz7biJV0mpg7yDSs4bj/RT/YkA==}
|
||||
peerDependencies:
|
||||
svelte: '>=3.23.0'
|
||||
dependencies:
|
||||
svelte: 3.55.1
|
||||
dev: true
|
||||
|
||||
/svelte-eslint-parser@0.29.0(svelte@3.55.1):
|
||||
resolution: {integrity: sha512-2uzOw9vRpSO3fo6NkbH7UynfCopQbMz/7LO9KT05YPvkB0uuFvFHex8+Ccv3gSrxHRvKS7FwJmV4H8WNWIzgWQ==}
|
||||
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
|
||||
|
8
src/global.d.ts
vendored
Normal file
8
src/global.d.ts
vendored
Normal file
@ -0,0 +1,8 @@
|
||||
declare type Item = import('svelte-dnd-action').Item;
|
||||
declare type DndEvent<ItemType = Item> = import('svelte-dnd-action').DndEvent<ItemType>;
|
||||
declare namespace svelte.JSX {
|
||||
interface HTMLAttributes<T> {
|
||||
onconsider?: (event: CustomEvent<DndEvent<ItemType>> & { target: EventTarget & T }) => void;
|
||||
onfinalize?: (event: CustomEvent<DndEvent<ItemType>> & { target: EventTarget & T }) => void;
|
||||
}
|
||||
}
|
@ -36,7 +36,8 @@
|
||||
hotkeys.on('Meta+T', () => goto(`/projects/${$project.id}/terminal/`)),
|
||||
hotkeys.on('Meta+P', () => goto(`/projects/${$project.id}/`)),
|
||||
hotkeys.on('Meta+Shift+,', () => goto(`/projects/${$project.id}/settings/`)),
|
||||
hotkeys.on('Meta+R', () => goto(`/projects/${$project.id}/player/`))
|
||||
hotkeys.on('Meta+R', () => goto(`/projects/${$project.id}/player/`)),
|
||||
hotkeys.on('l f g', () => goto(`/projects_new/${$project.id}`))
|
||||
)
|
||||
);
|
||||
</script>
|
||||
|
48
src/routes/projects_new/[projectId]/+page.svelte
Normal file
48
src/routes/projects_new/[projectId]/+page.svelte
Normal file
@ -0,0 +1,48 @@
|
||||
<script lang="ts">
|
||||
import Board from './Board.svelte';
|
||||
import type { BranchLane } from './board';
|
||||
|
||||
let columnsData: BranchLane[] = [
|
||||
{
|
||||
id: 'c1',
|
||||
name: 'TODO',
|
||||
items: [
|
||||
{ id: 1, name: 'item41' },
|
||||
{ id: 2, name: 'item42' },
|
||||
{ id: 3, name: 'item43' },
|
||||
{ id: 4, name: 'item44' },
|
||||
{ id: 5, name: 'item45' },
|
||||
{ id: 6, name: 'item46' },
|
||||
{ id: 7, name: 'item47' },
|
||||
{ id: 8, name: 'item48' },
|
||||
{ id: 9, name: 'item49' }
|
||||
]
|
||||
},
|
||||
{
|
||||
id: 'c2',
|
||||
name: 'DOING',
|
||||
items: [
|
||||
{ id: 10, name: 'item50' },
|
||||
{ id: 11, name: 'item51' }
|
||||
]
|
||||
},
|
||||
{
|
||||
id: 'c3',
|
||||
name: 'DONE',
|
||||
items: [{ id: 13, name: 'item52' }]
|
||||
}
|
||||
];
|
||||
function handleBoardUpdated(newColumnsData: BranchLane[]) {
|
||||
// TODO: API calls
|
||||
columnsData = newColumnsData;
|
||||
}
|
||||
</script>
|
||||
|
||||
<Board columns={columnsData} onFinalUpdate={handleBoardUpdated} />
|
||||
|
||||
<style>
|
||||
:global(*) {
|
||||
box-sizing: border-box;
|
||||
margin: 0;
|
||||
}
|
||||
</style>
|
38
src/routes/projects_new/[projectId]/Board.svelte
Normal file
38
src/routes/projects_new/[projectId]/Board.svelte
Normal file
@ -0,0 +1,38 @@
|
||||
<script lang="ts">
|
||||
import { flip } from 'svelte/animate';
|
||||
import { dndzone } from 'svelte-dnd-action';
|
||||
import type { FileCard, BranchLane } from './board';
|
||||
import Lane from './Lane.svelte';
|
||||
const flipDurationMs = 300;
|
||||
|
||||
export let columns: BranchLane[];
|
||||
export let onFinalUpdate: (newColumns: BranchLane[]) => void;
|
||||
|
||||
function handleDndConsiderColumns(e: { detail: { items: BranchLane[] } }) {
|
||||
columns = e.detail.items;
|
||||
}
|
||||
function handleDndFinalizeColumns(e: { detail: { items: BranchLane[] } }) {
|
||||
onFinalUpdate(e.detail.items);
|
||||
}
|
||||
function handleItemFinalize(columnIdx: number, newItems: FileCard[]) {
|
||||
columns[columnIdx].items = newItems;
|
||||
onFinalUpdate([...columns]);
|
||||
}
|
||||
</script>
|
||||
|
||||
<section
|
||||
class="w-100"
|
||||
style="height: 90vh;"
|
||||
use:dndzone={{ items: columns, flipDurationMs, type: 'column' }}
|
||||
on:consider={handleDndConsiderColumns}
|
||||
on:finalize={handleDndFinalizeColumns}
|
||||
>
|
||||
{#each columns as { id, name, items }, idx (id)}
|
||||
<div
|
||||
class="float-left m-2 flex h-full w-64 border border-zinc-700 bg-zinc-900/50 p-2"
|
||||
animate:flip={{ duration: flipDurationMs }}
|
||||
>
|
||||
<Lane {name} {items} onDrop={(newItems) => handleItemFinalize(idx, newItems)} />
|
||||
</div>
|
||||
{/each}
|
||||
</section>
|
38
src/routes/projects_new/[projectId]/Lane.svelte
Normal file
38
src/routes/projects_new/[projectId]/Lane.svelte
Normal file
@ -0,0 +1,38 @@
|
||||
<script lang="ts">
|
||||
import { flip } from 'svelte/animate';
|
||||
import { dndzone } from 'svelte-dnd-action';
|
||||
import type { FileCard } from './board';
|
||||
const flipDurationMs = 150;
|
||||
export let name: string;
|
||||
export let items: FileCard[];
|
||||
export let onDrop: (items: FileCard[]) => void;
|
||||
|
||||
function handleDndConsiderCards(e: { detail: { items: FileCard[] } }) {
|
||||
console.warn('got consider', name);
|
||||
items = e.detail.items;
|
||||
}
|
||||
function handleDndFinalizeCards(e: { detail: { items: FileCard[] } }) {
|
||||
onDrop(e.detail.items);
|
||||
}
|
||||
</script>
|
||||
|
||||
<div class="h-full w-full overflow-y-hidden">
|
||||
<div class="flex h-12 items-center justify-center font-bold">
|
||||
{name}
|
||||
</div>
|
||||
<div
|
||||
class="overflow-y-scroll"
|
||||
style="height: calc(100% - 2.5em);"
|
||||
use:dndzone={{ items, flipDurationMs, zoneTabIndex: -1 }}
|
||||
on:consider={handleDndConsiderCards}
|
||||
on:finalize={handleDndFinalizeCards}
|
||||
>
|
||||
{#each items as item (item.id)}
|
||||
<div
|
||||
class="my-2 flex h-14 w-full items-center justify-center rounded border border-zinc-600 bg-zinc-700"
|
||||
>
|
||||
{item.name}
|
||||
</div>
|
||||
{/each}
|
||||
</div>
|
||||
</div>
|
10
src/routes/projects_new/[projectId]/board.ts
Normal file
10
src/routes/projects_new/[projectId]/board.ts
Normal file
@ -0,0 +1,10 @@
|
||||
export type FileCard = {
|
||||
id: number;
|
||||
name: string;
|
||||
};
|
||||
|
||||
export type BranchLane = {
|
||||
id: string;
|
||||
name: string;
|
||||
items: FileCard[];
|
||||
};
|
Loading…
Reference in New Issue
Block a user