Add KanbanView. Move icons. (#143)

Signed-off-by: Alexander Platov <sas_lord@mail.ru>
This commit is contained in:
Alexander Platov
2021-09-06 18:00:43 +02:00
committed by GitHub
parent e9f12766c1
commit bb08165fef
26 changed files with 417 additions and 184 deletions
@@ -0,0 +1,114 @@
<!--
// Copyright © 2020, 2021 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 { UserInfo } from '@anticrm/presentation'
import { ActionIcon, Label, IconMoreH, IconFile } from '@anticrm/ui'
interface ICard {
_id: number
firstName: string
lastName: string
description: string
state: number
}
export let card: ICard
export let draggable: boolean
</script>
<div class="card-container" {draggable} class:draggable on:dragstart on:dragend>
<div class="header">
<UserInfo value={{firstName: card.firstName, lastName: card.lastName }} subtitle={'Candidate'} size={'small'} />
<ActionIcon icon={IconMoreH} label={'More..'} direction={'left'} />
</div>
<div class="content">
<div class="flex-row-center item">
<IconFile size={'large'} />
<span>Team Interview</span>
</div>
<div class="description">{card.description}</div>
<div class="tags">
<div class="tag">
<IconFile size={'small'} />
<span><Label label={'Application'} /></span>
</div>
</div>
</div>
</div>
<style lang="scss">
.card-container {
display: flex;
flex-direction: column;
align-items: stretch;
background-color: var(--theme-button-bg-hovered);
border: 1px solid var(--theme-bg-accent-color);
border-radius: .75rem;
user-select: none;
.header {
display: flex;
justify-content: space-between;
align-items: center;
padding: .75rem 1rem;
width: 100%;
min-height: 3.75rem;
background-color: var(--theme-button-bg-focused);
border-radius: .75rem .75rem 0 0;
}
.content {
display: flex;
flex-direction: column;
align-items: stretch;
padding: 1rem;
.item {
font-weight: 500;
font-size: 1rem;
color: var(--theme-caption-color);
span { margin-left: .5em; }
}
.description {
margin-top: .5rem;
}
.tags {
display: flex;
margin-top: 1rem;
.tag {
display: flex;
align-items: center;
padding: .5rem .75rem;
font-size: .75rem;
text-align: center;
background-color: var(--theme-bg-accent-color);
color: var(--theme-caption-color);
border-radius: .5rem;
span { margin-left: .3em; }
}
.tag + .tag { margin-left: .75rem; }
}
}
&.draggable {
cursor: grab;
}
}
:global(.card-container + .card-container) { margin-top: .75rem; }
</style>
@@ -0,0 +1,54 @@
<!--
// Copyright © 2020, 2021 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 type { IntlString } from '@anticrm/platform'
import { Label } from '@anticrm/ui'
import { IconAdd } from '@anticrm/ui'
export let label: IntlString
</script>
<div class="card-container">
<div class="icon">
<IconAdd size={'small'} />
</div>
<Label {label} />
</div>
<style lang="scss">
.card-container {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
padding: .75rem 1.5rem;
color: var(--theme-content-dark-color);
background-color: var(--theme-button-bg-hovered);
border: 1px dotted var(--theme-bg-accent-color);
border-radius: .75rem;
cursor: pointer;
.icon {
margin-bottom: .25rem;
opacity: .4;
}
&:hover {
color: var(--theme-caption-color);
.icon { opacity: 1; }
}
}
</style>
@@ -0,0 +1,82 @@
<!--
// Copyright © 2020, 2021 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 type { IntlString } from '@anticrm/platform'
import { Label, ScrollBox } from '@anticrm/ui'
export let label: IntlString
export let color: string
export let counter: number
</script>
<div class="panel-container" on:dragover on:drop>
<div class="header" style="background-color: {color}">
<div class="title"><Label {label} /></div>
<div class="counter">{counter}</div>
</div>
<div class="scroll">
<ScrollBox vertical>
<slot />
</ScrollBox>
</div>
</div>
<style lang="scss">
.panel-container {
display: flex;
flex-direction: column;
align-items: stretch;
width: 20rem;
height: 100%;
background-color: var(--theme-button-bg-enabled);
border: 1px solid var(--theme-bg-accent-color);
border-radius: .75rem;
.header {
display: flex;
justify-content: space-between;
align-items: center;
margin: .75rem;
padding: .5rem;
min-height: 2.75rem;
font-weight: 500;
border: 1px solid rgba(0, 0, 0, .1);
border-radius: .5rem;
.title {
padding-left: .5rem;
color: var(--theme-caption-color);
}
.counter {
display: flex;
justify-content: center;
align-items: center;
width: 1.75rem;
height: 1.75rem;
color: var(--theme-contnet-accent-color);
background-color: rgba(0, 0, 0, .08);
border-radius: 50%;
}
}
.scroll {
margin: .5rem .75rem .75rem;
height: 100%;
}
}
:global(.panel-container + .panel-container) { margin-left: .75rem; }
</style>
@@ -0,0 +1,68 @@
<!--
// Copyright © 2020, 2021 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 type { IntlString } from '@anticrm/platform'
import { Label } from '@anticrm/ui'
import { IconAdd } from '@anticrm/ui'
export let label: IntlString
</script>
<div class="panel-container">
<div class="circle">
<div class="icon">
<IconAdd size={'large'} />
</div>
</div>
<Label {label} />
</div>
<style lang="scss">
.panel-container {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
width: 20rem;
height: 100%;
padding: .75rem;
color: var(--theme-caption-color);
background-color: var(--theme-button-bg-enabled);
border: 1px dotted var(--theme-bg-accent-color);
border-radius: .75rem;
cursor: pointer;
.circle {
display: flex;
justify-content: center;
align-items: center;
margin-bottom: 1.25rem;
width: 5rem;
height: 5rem;
background-color: var(--theme-bg-accent-color);
border-radius: 50%;
.icon { opacity: .6; }
}
&:hover {
background-color: var(--theme-bg-accent-hover);
box-shadow: 0 .75rem 2.5rem rgba(0, 0, 0, .15);
.circle .icon { opacity: 1; }
}
}
</style>
@@ -24,6 +24,11 @@
import { createQuery } from '@anticrm/presentation'
import KanbanPanel from './KanbanPanel.svelte'
import KanbanPanelEmpty from './KanbanPanelEmpty.svelte'
import KanbanCard from './KanbanCard.svelte'
import KanbanCardEmpty from './KanbanCardEmpty.svelte'
export let _class: Ref<Class<Doc>>
export let space: Ref<Space>
export let open: AnyComponent
@@ -52,78 +57,79 @@
function onClick(object: Doc) {
showPopup(open, { object, space }, 'float')
}
interface ICard {
_id: number
firstName: string
lastName: string
description: string
state: number
}
let dragCard: ICard
let states: Array<Object> = [
{ _id: 0, label: 'In progress', color: '#7C6FCD' },
{ _id: 1, label: 'Under review', color: '#6F7BC5' },
{ _id: 2, label: 'Interview', color: '#A5D179' },
{ _id: 3, label: 'Offer', color: '#77C07B' },
{ _id: 4, label: 'Assigned', color: '#F28469' }
]
const cards: Array<ICard> = [
{ _id: 0, firstName: 'Chen', lastName: 'Rosamund', description: '8:30AM, July 12 Voltron, San Francisco', state: 0 },
{ _id: 1, firstName: 'Chen', lastName: 'Rosamund', description: '8:30AM, July 12 Voltron, San Francisco', state: 0 },
{ _id: 2, firstName: 'Chen', lastName: 'Rosamund', description: '8:30AM, July 12 Voltron, San Francisco', state: 0 },
{ _id: 3, firstName: 'Chen', lastName: 'Rosamund', description: '8:30AM, July 12 Voltron, San Francisco', state: 1 },
{ _id: 4, firstName: 'Chen', lastName: 'Rosamund', description: '8:30AM, July 12 Voltron, San Francisco', state: 1 },
{ _id: 5, firstName: 'Chen', lastName: 'Rosamund', description: '8:30AM, July 12 Voltron, San Francisco', state: 2 },
{ _id: 6, firstName: 'Chen', lastName: 'Rosamund', description: '8:30AM, July 12 Voltron, San Francisco', state: 3 },
]
</script>
{#await buildModel(client, _class, config, options)}
<Loading/>
{:then model}
KANBAN
<div class="container">
<ScrollBox vertical stretch noShift>
<table class="table-body">
<thead>
<tr class="tr-head">
{#each model as attribute}
<th><Label label = {attribute.label}/></th>
<div class="kanban-container">
<ScrollBox>
<div class="kanban-content">
{#each states as state}
<KanbanPanel label={state.label} color={state.color} counter={4}
on:dragover={(event) => {
event.preventDefault()
}}
on:drop={(event) => {
event.preventDefault()
if (dragCard) {
dragCard.state = state._id
dragCard = undefined
}
}}
>
<KanbanCardEmpty label={'Create new application'} />
{#each cards.filter((c) => c.state === state._id) as card}
<KanbanCard {card} draggable={true}
on:dragstart={() => {
dragCard = card
}}
on:dragend={() => {
dragCard = undefined
}}
/>
{/each}
</tr>
</thead>
{#if objects}
<tbody>
{#each objects as object (object._id)}
<tr class="tr-body" on:click={() => onClick(object)}>
{#each model as attribute}
<td><svelte:component this={attribute.presenter} value={getValue(object, attribute.key)}/></td>
{/each}
</tr>
{/each}
</tbody>
{/if}
</table>
</KanbanPanel>
{/each}
<KanbanPanelEmpty label={'Add new column'} />
</div>
</ScrollBox>
</div>
{/await}
<style lang="scss">
.container {
flex-grow: 1;
position: relative;
padding-bottom: 2.5rem;
.kanban-container {
margin-bottom: 1.25rem;
height: 100%;
&::before {
position: absolute;
content: '';
top: 2.5rem;
bottom: 0;
width: 100%;
background-color: var(--theme-table-bg-color);
border-radius: 0 0 1.25rem 1.25rem;
}
}
th, td {
padding: .5rem 1.5rem;
text-align: left;
&:first-child { padding-left: 2.5rem; }
}
th {
position: sticky;
top: 0;
height: 2.5rem;
font-weight: 500;
font-size: .75rem;
color: var(--theme-content-dark-color);
background-color: var(--theme-bg-color);
box-shadow: inset 0 -1px 0 0 var(--theme-bg-focused-color);
}
.tr-body {
height: 3.75rem;
color: var(--theme-caption-color);
border-bottom: 1px solid var(--theme-button-border-hovered);
&:last-child { border-bottom: none; }
&:hover { background-color: var(--theme-table-bg-hover); }
.kanban-content {
display: flex;
margin: 0 2.5rem;
height: 100%;
}
</style>