initial kanban reordering

Signed-off-by: Andrey Platov <andrey@hardcoreeng.com>
This commit is contained in:
Andrey Platov 2021-10-06 14:35:09 +02:00
parent 0d11546617
commit d2262bbb16
No known key found for this signature in database
GPG Key ID: C8787EFEB4B64AF0
6 changed files with 79 additions and 21 deletions

View File

@ -14,7 +14,7 @@
// //
import type { IntlString } from '@anticrm/platform' import type { IntlString } from '@anticrm/platform'
import type { Account, Arr, Ref, Space, Domain, State } from '@anticrm/core' import type { Account, Arr, Ref, Space, Domain, State, Doc } from '@anticrm/core'
import { DOMAIN_MODEL } from '@anticrm/core' import { DOMAIN_MODEL } from '@anticrm/core'
import { Model, Prop, TypeString } from '@anticrm/model' import { Model, Prop, TypeString } from '@anticrm/model'
import core from './component' import core from './component'
@ -48,4 +48,5 @@ export class TState extends TDoc implements State {
@Model(core.class.SpaceWithStates, core.class.Space) @Model(core.class.SpaceWithStates, core.class.Space)
export class TSpaceWithStates extends TSpace { export class TSpaceWithStates extends TSpace {
states!: Arr<Ref<State>> states!: Arr<Ref<State>>
order!: Arr<Ref<Doc>>
} }

View File

@ -209,4 +209,5 @@ export interface State extends Doc {
*/ */
export interface SpaceWithStates extends Space { export interface SpaceWithStates extends Space {
states: Arr<Ref<State>> states: Arr<Ref<State>>
order: Arr<Ref<Doc>>
} }

View File

@ -15,7 +15,7 @@
<script lang="ts"> <script lang="ts">
import { createEventDispatcher } from 'svelte' import { createEventDispatcher } from 'svelte'
import type { Ref, Space } from '@anticrm/core' import type { Ref, Space, SpaceWithStates } from '@anticrm/core'
import { Status, OK, Severity } from '@anticrm/platform' import { Status, OK, Severity } from '@anticrm/platform'
import { DatePicker, EditBox, Tabs, Section, Grid, Status as StatusControl } from '@anticrm/ui' import { DatePicker, EditBox, Tabs, Section, Grid, Status as StatusControl } from '@anticrm/ui'
import { UserBox, Card, UserInfo, Avatar } from '@anticrm/presentation' import { UserBox, Card, UserInfo, Avatar } from '@anticrm/presentation'
@ -30,7 +30,7 @@
import recruit from '../plugin' import recruit from '../plugin'
import contact from '@anticrm/contact' import contact from '@anticrm/contact'
export let space: Ref<Space> export let space: Ref<SpaceWithStates>
export let candidate: Ref<Candidate> // | null = null export let candidate: Ref<Candidate> // | null = null
export let employee: Ref<Employee> // | null = null export let employee: Ref<Employee> // | null = null
@ -47,10 +47,16 @@
if (state === undefined) { if (state === undefined) {
throw new Error('create application: state not found') throw new Error('create application: state not found')
} }
await client.createDoc(recruit.class.Applicant, _space, { const id = await client.createDoc(recruit.class.Applicant, _space, {
candidate, candidate,
state: state._id state: state._id
}) })
await client.updateDoc(core.class.SpaceWithStates, core.space.Model, space, {
$push: {
order: id
}
})
dispatch('close') dispatch('close')
} }

View File

@ -44,7 +44,8 @@
description, description,
private: false, private: false,
members: [], members: [],
states: [] states: [],
order: []
}) })
const s1 = await client.createDoc(core.class.State, id, { const s1 = await client.createDoc(core.class.State, id, {
title: 'Initial', title: 'Initial',

View File

@ -53,11 +53,46 @@
return _space.states.map(id => map.get(id) as State ) return _space.states.map(id => map.get(id) as State )
} }
function sortObjects<T extends Doc> (objects: T[]): T[] {
if (_space === undefined) { return [] }
const map = objects.reduce((map, doc) => { map.set(doc._id, doc); return map }, new Map<Ref<Doc>, Doc>())
const x = _space.order.map(id => map.get(id) as T)
return x
}
const statesQuery = createQuery() const statesQuery = createQuery()
$: statesQuery.query(core.class.State, { _id: { $in: _space?.states ?? [] } }, result => { states = sort(result) }) $: statesQuery.query(core.class.State, { _id: { $in: _space?.states ?? [] } }, result => { states = sort(result) })
const query = createQuery() const query = createQuery()
$: query.query(_class, { space }, result => { objects = result }, options) $: query.query(_class, { space }, result => { objects = sortObjects(result) }, options)
function dragover(ev: MouseEvent, object: Doc) {
// if (dragswap(ev, i)) {
if (dragCard !== object) {
const dragover = objects.indexOf(object)
const dragging = objects.indexOf(dragCard)
console.log('dragover', dragover, dragging)
objects[dragover] = dragCard
objects[dragging] = object
}
}
async function move(to: number) {
client.updateDoc(core.class.SpaceWithStates, core.space.Model, space, {
$pull: {
order: dragCard._id
}
})
client.updateDoc(core.class.SpaceWithStates, core.space.Model, space, {
$push: {
order: {
$each: [dragCard._id],
$position: to < dragCardInitialPosition ? to : to
}
}
})
}
function getValue(doc: Doc, key: string): any { function getValue(doc: Doc, key: string): any {
if (key.length === 0) if (key.length === 0)
@ -77,7 +112,8 @@
showPopup(open, { object, space }, 'float') showPopup(open, { object, space }, 'float')
} }
let dragCard: (Doc & { state: Ref<State>}) | undefined let dragCard: Doc
let dragCardInitialPosition: number
async function cardPresenter(_class: Ref<Class<Doc>>): Promise<AnySvelteComponent> { async function cardPresenter(_class: Ref<Class<Doc>>): Promise<AnySvelteComponent> {
const clazz = client.getHierarchy().getClass(_class) const clazz = client.getHierarchy().getClass(_class)
@ -97,24 +133,39 @@
<KanbanPanel label={state.title} color={state.color} counter={4} <KanbanPanel label={state.title} color={state.color} counter={4}
on:dragover={(event) => { on:dragover={(event) => {
event.preventDefault() event.preventDefault()
if (dragCard.state !== state._id) {
client.updateDoc(_class, space, dragCard._id, { state: state._id })
}
}} }}
on:drop={(event) => { on:drop={(event) => {
event.preventDefault() event.preventDefault()
if (dragCard) { // if (selected !== -1) {
client.updateDoc(_class, space, dragCard._id, { state: state._id }) // client.updateDoc(_class, space, objects[selected]._id, { state: state._id })
dragCard = undefined // selected = -1
} // }
}} }}
> >
<KanbanCardEmpty label={'Create new application'} /> <KanbanCardEmpty label={'Create new application'} />
{#each objects.filter((c) => c.state === state._id) as object} {#each objects as object, j}
<svelte:component this={presenter} {object} draggable={true} {#if object.state === state._id}
on:dragstart={() => { <div
dragCard = object on:dragover|preventDefault={(ev) => {
}} dragover(ev, object)
on:dragend={() => { }}
dragCard = undefined on:drop|preventDefault={() => {
}}/> move(j)
}}
> {j}
<svelte:component this={presenter} {object} draggable={true}
on:dragstart={() => {
dragCardInitialPosition = j
dragCard = objects[j]
}}
on:dragend={() => {
dragCard = undefined
}}/>
</div>
{/if}
{/each} {/each}
</KanbanPanel> </KanbanPanel>
{/each} {/each}

View File

@ -129,7 +129,6 @@
dragover(ev, i) dragover(ev, i)
}} }}
on:drop|preventDefault={() => { on:drop|preventDefault={() => {
console.log('DROP')
move(i) move(i)
}} }}
on:dragstart={() => { on:dragstart={() => {
@ -137,7 +136,6 @@
dragState = states[i]._id dragState = states[i]._id
}} }}
on:dragend={() => { on:dragend={() => {
console.log('DRAGEND')
selected = undefined selected = undefined
}} }}
> >