Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Tracker: Updating cards in Kanban #2032

Merged
merged 4 commits into from
Jun 8, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
126 changes: 60 additions & 66 deletions packages/kanban/src/components/Kanban.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -281,73 +281,71 @@
}
</script>

<div class="flex-col kanban-container top-divider">
<div class="scrollable">
<ScrollBox>
<div class="kanban-content">
{#each states as state, si}
{@const stateObjects = getStateObjects(objects, state, dragCard)}

<div
class="panel-container step-lr75"
bind:this={stateRefs[si]}
on:dragover={(event) => panelDragOver(event, state)}
on:drop={() => {
move(state._id)
isDragging = false
}}
>
{#if $$slots.header !== undefined}
<slot name="header" state={toAny(state)} count={stateObjects.length} />
{:else}
<div class="header">
<div class="bar" style="background-color: {getPlatformColor(state.color)}" />
<div class="flex-between label">
<div>
<span class="lines-limit-2">{state.title}</span>
</div>
<div class="kanban-container top-divider">
<ScrollBox>
<div class="kanban-content">
{#each states as state, si}
{@const stateObjects = getStateObjects(objects, state, dragCard)}

<div
class="panel-container step-lr75"
bind:this={stateRefs[si]}
on:dragover={(event) => panelDragOver(event, state)}
on:drop={() => {
move(state._id)
isDragging = false
}}
>
{#if $$slots.header !== undefined}
<slot name="header" state={toAny(state)} count={stateObjects.length} />
{:else}
<div class="header">
<div class="bar" style="background-color: {getPlatformColor(state.color)}" />
<div class="flex-between label">
<div>
<span class="lines-limit-2">{state.title}</span>
</div>
</div>
{/if}
<Scroller padding={'.5rem 0'} on:dragover on:drop>
<slot name="beforeCard" {state} />
{#each stateObjects as object}
{@const dragged = isDragging && object.it._id === dragCard?._id}
</div>
{/if}
<Scroller padding={'.5rem 0'} on:dragover on:drop>
<slot name="beforeCard" {state} />
{#each stateObjects as object}
{@const dragged = isDragging && object.it._id === dragCard?._id}
<div
transition:slideD|local={{ isDragging }}
class="step-tb75"
on:dragover|preventDefault={(evt) => cardDragOver(evt, object)}
on:drop|preventDefault={(evt) => cardDrop(evt, object)}
>
<div
transition:slideD|local={{ isDragging }}
class="step-tb75"
on:dragover|preventDefault={(evt) => cardDragOver(evt, object)}
on:drop|preventDefault={(evt) => cardDrop(evt, object)}
class="card-container"
class:selection={selection !== undefined ? objects[selection]?._id === object.it._id : false}
class:checked={checkedSet.has(object.it._id)}
on:mouseover={() => dispatch('obj-focus', object.it)}
on:focus={() => {}}
on:contextmenu={(evt) => showMenu(evt, object)}
draggable={true}
class:draggable={true}
on:dragstart
on:dragend
class:dragged
on:dragstart={() => onDragStart(object, state)}
on:dragend={() => {
isDragging = false
}}
>
<div
class="card-container"
class:selection={selection !== undefined ? objects[selection]?._id === object.it._id : false}
class:checked={checkedSet.has(object.it._id)}
on:mouseover={() => dispatch('obj-focus', object.it)}
on:focus={() => {}}
on:contextmenu={(evt) => showMenu(evt, object)}
draggable={true}
class:draggable={true}
on:dragstart
on:dragend
class:dragged
on:dragstart={() => onDragStart(object, state)}
on:dragend={() => {
isDragging = false
}}
>
<slot name="card" object={toAny(object.it)} {dragged} />
</div>
<slot name="card" object={toAny(object.it)} {dragged} />
</div>
{/each}
<slot name="afterCard" {space} {state} />
</Scroller>
</div>
{/each}
<slot name="afterPanel" />
</div>
</ScrollBox>
</div>
</div>
{/each}
<slot name="afterCard" {space} {state} />
</Scroller>
</div>
{/each}
<slot name="afterPanel" />
</div>
</ScrollBox>
{#if isDragging}
<slot name="doneBar" onDone={updateDone} />
{/if}
Expand All @@ -362,7 +360,6 @@
.kanban-content {
display: flex;
padding: 1.5rem 2rem 0;
height: 100%;
}

.scrollable {
Expand Down Expand Up @@ -416,9 +413,7 @@
.panel-container {
display: flex;
flex-direction: column;
align-items: stretch;
width: 20rem;
height: 100%;
background-color: transparent;
border: 1px solid transparent;
border-radius: 0.25rem;
Expand All @@ -428,7 +423,6 @@
flex-direction: column;
height: 4rem;
min-height: 4rem;
user-select: none;

.bar {
height: 0.375rem;
Expand Down
12 changes: 11 additions & 1 deletion packages/theme/styles/_layouts.scss
Original file line number Diff line number Diff line change
Expand Up @@ -221,7 +221,7 @@ input.search {
min-width: 0;
font-weight: 500;
text-align: left;
color: var(--theme-content-accent-color);
color: var(--accent-color);

overflow: hidden;
visibility: visible;
Expand Down Expand Up @@ -259,6 +259,16 @@ input.search {
align-items: baseline;
.icon { transform: translateY(.2rem); }
}
// Presenters on the card
.card-container .flex-presenter,
.card-container .inline-presenter {
.icon { display: none; }
.label {
font-size: .75rem;
color: var(--dark-color);
}
&:hover .label { color: var(--content-color); }
}

.buttons-group {
display: grid;
Expand Down
2 changes: 1 addition & 1 deletion packages/ui/src/components/Button.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -298,7 +298,7 @@
&.link-bordered {
padding: 0 0.375rem;
color: var(--accent-color);
border-color: var(--button-border-color);
border-color: var(--divider-color);
&:hover {
color: var(--accent-color);
background-color: var(--button-bg-hover);
Expand Down
67 changes: 67 additions & 0 deletions packages/ui/src/components/ProgressCircle.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
<!--
// Copyright © 2020 Anticrm Platform Contributors.
//
// Licensed under the Eclipse Public License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License. You may
// obtain a copy of the License at https://www.eclipse.org/legal/epl-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//
// See the License for the specific language governing permissions and
// limitations under the License.
-->
<script lang="ts">
import { getPlatformColor } from '../colors'
import { IconSize } from '../types'

export let value: number
export let min: number = 0
export let max: number = 100
export let color: number = 5
export let size: IconSize = 'small'
export let primary: boolean = false

if (value > max) value = max
if (value < min) value = min

const lenghtC: number = Math.PI * 14 - 1
const procC: number = lenghtC / (max - min)
$: dashOffset = (value - min) * procC
</script>

<svg class="svg-{size}" fill="none" viewBox="0 0 16 16">
<circle
cx={8}
cy={8}
r={7}
class="progress-circle"
style:stroke={'var(--divider-color)'}
style:opacity={'.5'}
style:transform={`rotate(${-78 + ((dashOffset + 1) * 360) / (lenghtC + 1)}deg)`}
style:stroke-dasharray={lenghtC}
style:stroke-dashoffset={dashOffset === 0 ? 0 : dashOffset + 3}
/>
<circle
cx={8}
cy={8}
r={7}
class="progress-circle"
style:stroke={primary ? 'var(--primary-bg-color)' : getPlatformColor(color)}
style:opacity={dashOffset === 0 ? 0 : 1}
style:transform={'rotate(-82deg)'}
style:stroke-dasharray={lenghtC}
style:stroke-dashoffset={dashOffset === 0 ? lenghtC : lenghtC - dashOffset + 1}
/>
</svg>

<style lang="scss">
.progress-circle {
stroke-width: 2px;
stroke-linecap: round;
transform-origin: center;
transition: transform 0.6s ease 0s, stroke-dashoffset 0.6s ease 0s, stroke-dasharray 0.6s ease 0s,
opacity 0.6s ease 0s;
}
</style>
1 change: 1 addition & 0 deletions packages/ui/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ export { default as Tooltip } from './components/Tooltip.svelte'
export { default as TooltipInstance } from './components/TooltipInstance.svelte'
export { default as CheckBox } from './components/CheckBox.svelte'
export { default as Progress } from './components/Progress.svelte'
export { default as ProgressCircle } from './components/ProgressCircle.svelte'
export { default as Tabs } from './components/Tabs.svelte'
export { default as ScrollBox } from './components/ScrollBox.svelte'
export { default as PopupMenu } from './components/PopupMenu.svelte'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
const prioritiesInfo = defaultPriorities.map((p) => ({ id: p, ...issuePriorities[p] }))

const handlePriorityEditorOpened = (event: MouseEvent) => {
event.stopPropagation()
if (!isEditable) {
return
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@
}

const handleProjectEditorOpened = (event: MouseEvent) => {
event.stopPropagation()
if (!isEditable) {
return
}
Expand Down
23 changes: 17 additions & 6 deletions plugins/tracker-resources/src/components/issues/Board.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@
import { Class, Doc, FindOptions, Ref, SortingOrder, WithLookup } from '@anticrm/core'
import { Kanban, TypeState } from '@anticrm/kanban'
import { createQuery } from '@anticrm/presentation'
import { Issue, Team } from '@anticrm/tracker'
import { Button, Icon, IconAdd, showPopup, Tooltip } from '@anticrm/ui'
import type { Issue, IssueStatus, Team } from '@anticrm/tracker'
import { Button, Icon, IconAdd, showPopup, Tooltip, showPanel } from '@anticrm/ui'
import { focusStore, ListSelectionProvider, SelectDirection, selectionStore } from '@anticrm/view-resources'
import ActionContext from '@anticrm/view-resources/src/components/ActionContext.svelte'
import Menu from '@anticrm/view-resources/src/components/Menu.svelte'
Expand All @@ -29,6 +29,7 @@
import IssuePresenter from './IssuePresenter.svelte'
import PriorityEditor from './PriorityEditor.svelte'
import ProjectEditor from '../projects/ProjectEditor.svelte'
import SubIssuesSelector from './edit/SubIssuesSelector.svelte'

export let currentSpace: Ref<Team>
export let baseMenuClass: Ref<Class<Doc>> | undefined = undefined
Expand All @@ -43,17 +44,19 @@
currentTeam = res.shift()
})

let issueStatuses: WithLookup<IssueStatus>[] | undefined
let states: TypeState[] | undefined
$: statusesQuery.query(
tracker.class.IssueStatus,
{ attachedTo: currentSpace },
(issueStatuses) => {
states = issueStatuses.map((status) => ({
(is) => {
states = is.map((status) => ({
_id: status._id,
title: status.name,
color: status.color ?? status.$lookup?.category?.color ?? 0,
icon: status.$lookup?.category?.icon ?? undefined
}))
issueStatuses = is
},
{
lookup: { category: tracker.class.IssueStatusCategory },
Expand Down Expand Up @@ -152,7 +155,12 @@
</svelte:fragment>
<svelte:fragment slot="card" let:object>
{@const issue = toIssue(object)}
<div class="tracker-card">
<div
class="tracker-card"
on:click={() => {
showPanel(tracker.component.EditIssue, object._id, object._class, 'content')
}}
>
<div class="flex-col mr-6">
<IssuePresenter value={object} {currentTeam} />
<span class="fs-bold caption-color mt-1 lines-limit-2">
Expand All @@ -168,7 +176,10 @@
isEditable={true}
/>
</div>
<div class="buttons-group xsmall-gap mt-10px">
<div class="buttons-group xxsmall-gap mt-10px">
{#if issue && issueStatuses && issue.subIssues > 0}
<SubIssuesSelector {issue} {currentTeam} {issueStatuses} />
{/if}
<PriorityEditor
value={issue}
isEditable={true}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
<script lang="ts">
import { Issue, IssuePriority } from '@anticrm/tracker'
import { getClient } from '@anticrm/presentation'
import { Tooltip } from '@anticrm/ui'
import { tooltip } from '@anticrm/ui'
import type { ButtonKind, ButtonSize } from '@anticrm/ui'
import tracker from '../../plugin'
import PrioritySelector from '../PrioritySelector.svelte'
Expand Down Expand Up @@ -50,7 +50,7 @@

{#if value}
{#if isEditable}
<Tooltip label={tracker.string.SetPriority} fill>
<div class="clear-mins" use:tooltip={{ label: tracker.string.SetPriority }}>
<PrioritySelector
{kind}
{size}
Expand All @@ -61,7 +61,7 @@
priority={value.priority}
onPriorityChange={handlePriorityChanged}
/>
</Tooltip>
</div>
{:else}
<PrioritySelector {kind} {size} {width} {justify} {isEditable} {shouldShowLabel} priority={value.priority} />
{/if}
Expand Down
Loading