Fixes for Todo's (#1208)

Signed-off-by: Andrey Sobolev <haiodo@gmail.com>
This commit is contained in:
Andrey Sobolev 2022-03-28 15:04:41 +07:00 committed by GitHub
parent 78b1d38340
commit 1ee8f0f0fe
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
15 changed files with 140 additions and 36 deletions

View File

@ -14,6 +14,7 @@
"docker:staging": "../../common/scripts/docker_tag.sh hardcoreeng/tool staging",
"docker:push": "../../common/scripts/docker_tag.sh hardcoreeng/tool",
"run-local": "cross-env MINIO_ACCESS_KEY=minioadmin MINIO_SECRET_KEY=minioadmin MINIO_ENDPOINT=localhost MONGO_URL=mongodb://localhost:27017 TRANSACTOR_URL=ws:/localhost:3333 TELEGRAM_DATABASE=telegram-service ELASTIC_URL=http://localhost:9200 REKONI_URL=http://localhost:4004 ts-node ./src/index.ts",
"upgrade": "rushx run-local upgrade",
"lint": "eslint src",
"format": "prettier --write src && eslint --fix src"
},

View File

@ -288,7 +288,10 @@ export function createModel (builder: Builder): void {
const applicantKanbanLookup: Lookup<Applicant> = {
attachedTo: recruit.mixin.Candidate,
assignee: contact.class.Employee
assignee: contact.class.Employee,
_id: {
todoItems: task.class.TodoItem
}
}
builder.createDoc(view.class.Viewlet, core.space.Model, {

View File

@ -334,9 +334,12 @@ export function createModel (builder: Builder): void {
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
options: {
lookup: {
assignee: contact.class.Employee
assignee: contact.class.Employee,
_id: {
todoItems: task.class.TodoItem
}
}
} as FindOptions<Doc>, // TODO: fix
} as FindOptions<Doc>,
config: []
})

View File

@ -69,10 +69,9 @@
{#if show}<Close size={'small'} />{:else}<Calendar size={'medium'} />{/if}
</div>
</button>
<div class="group">
<span class="label"><Label label={title} /></span>
{#if value !== undefined}
{#if value != null}
<DatePresenter {value} withTime={withTime} {bigDay} wraped={opened} />
{:else}
<span class="result not-selected"><Label label={ui.string.NotSelected} /></span>

View File

@ -14,7 +14,7 @@
-->
<script lang="ts">
import { afterUpdate, onDestroy } from 'svelte'
import { tooltipstore as tooltip, closeTooltip } from '..'
import { tooltipstore as tooltip, closeTooltip, Component } from '..'
import type { TooltipAligment } from '..'
import Label from './Label.svelte'
@ -163,7 +163,11 @@
{#if $tooltip.label}<div class="fs-title mb-4">
<Label label={$tooltip.label} params={$tooltip.props ?? {}} />
</div>{/if}
<svelte:component this={$tooltip.component} {...$tooltip.props} />
{#if typeof $tooltip.component === 'string'}
<Component is={$tooltip.component} props={$tooltip.props}/>
{:else}
<svelte:component this={$tooltip.component} {...$tooltip.props} />
{/if}
</div>
<div bind:this={nubHTML} class="nub {nubDirection ?? ''}" />
{:else if $tooltip.label}

View File

@ -17,12 +17,13 @@
import { CommentsPresenter } from '@anticrm/chunter-resources'
import { formatName } from '@anticrm/contact'
import type { WithLookup } from '@anticrm/core'
import notification from '@anticrm/notification'
import { Avatar } from '@anticrm/presentation'
import type { Applicant } from '@anticrm/recruit'
import { ActionIcon, Component, IconMoreH, showPanel } from '@anticrm/ui'
import task, { TodoItem } from '@anticrm/task'
import { ActionIcon, Component, IconMoreH, showPanel, Tooltip } from '@anticrm/ui'
import view from '@anticrm/view'
import ApplicationPresenter from './ApplicationPresenter.svelte'
import notification from '@anticrm/notification'
export let object: WithLookup<Applicant>
export let draggable: boolean
@ -30,6 +31,9 @@
function showCandidate () {
showPanel(view.component.EditDoc, object.attachedTo, object.attachedToClass, 'full')
}
$: todoItems = (object.$lookup?.todoItems as TodoItem[]) ?? []
$: doneTasks = todoItems.filter((it) => it.done)
</script>
<div class="card-container" {draggable} class:draggable on:dragstart on:dragend>
@ -38,7 +42,7 @@
<Avatar avatar={object.$lookup?.attachedTo?.avatar} size={'medium'} />
<div class="flex-grow flex-col min-w-0 ml-2">
<div class="fs-title over-underline lines-limit-2" on:click={showCandidate}>
{formatName(object.$lookup?.attachedTo?.name)}
{formatName(object.$lookup?.attachedTo?.name ?? '')}
</div>
<div class="text-sm lines-limit-2">{object.$lookup?.attachedTo?.title ?? ''}</div>
</div>
@ -54,6 +58,13 @@
<div class="flex-row-center">
<div class="sm-tool-icon step-lr75">
<ApplicationPresenter value={object} />
{#if todoItems.length > 0}
<Tooltip label={task.string.TodoItems} component={task.component.TodoItemsPopup} props={{ value: object }}>
<div class="ml-2">
( {doneTasks?.length}/ {todoItems.length} )
</div>
</Tooltip>
{/if}
</div>
{#if (object.attachments ?? 0) > 0}
<div class="step-lr75"><AttachmentsPresenter value={object} /></div>

View File

@ -74,6 +74,7 @@
"CantStatusDelete": "Can't delete status",
"CantStatusDeleteError": "There are objects in the given state. Move or delete them first.",
"Tasks": "Tasks",
"Assigned": "Assigned to me"
"Assigned": "Assigned to me",
"TodoItems": "Todos"
}
}

View File

@ -74,6 +74,7 @@
"CantStatusDelete": "Невозможно удалить статус",
"CantStatusDeleteError": "Есть объекты с данным статусом. Сначала переместите или удалите их. ",
"Tasks": "Задачи",
"Assigned": "Назначения"
"Assigned": "Назначения",
"TodoItems": "Todos"
}
}

View File

@ -13,33 +13,52 @@
// limitations under the License.
-->
<script lang="ts">
import { CommentsPresenter } from '@anticrm/chunter-resources'
import { AttachmentsPresenter } from '@anticrm/attachment-resources'
import { CommentsPresenter } from '@anticrm/chunter-resources'
import type { WithLookup } from '@anticrm/core'
import notification from '@anticrm/notification'
import { Avatar } from '@anticrm/presentation'
import type { Issue } from '@anticrm/task'
import { ActionIcon, Component, IconMoreH, showPopup } from '@anticrm/ui'
import type { Issue, TodoItem } from '@anticrm/task'
import { ActionIcon, Component, IconMoreH, showPopup, Tooltip } from '@anticrm/ui'
import { ContextMenu } from '@anticrm/view-resources'
import task from '../plugin'
import TaskPresenter from './TaskPresenter.svelte'
import notification from '@anticrm/notification'
export let object: WithLookup<Issue>
export let draggable: boolean
const showMenu = (ev?: Event): void => {
showPopup(ContextMenu, { object }, ev ? ev.target as HTMLElement : null)
showPopup(ContextMenu, { object }, ev ? (ev.target as HTMLElement) : null)
}
$: todoItems = (object.$lookup?.todoItems as TodoItem[]) ?? []
$: doneTasks = todoItems.filter((it) => it.done)
</script>
<div class="card-container" {draggable} class:draggable on:dragstart on:dragend>
<div class="flex-between mb-2">
<TaskPresenter value={object} />
<div class="flex">
<TaskPresenter value={object} />
{#if todoItems.length > 0}
<Tooltip label={task.string.TodoItems} component={task.component.TodoItemsPopup} props={{ value: object }}>
<div class="ml-2">
( {doneTasks?.length}/ {todoItems.length} )
</div>
</Tooltip>
{/if}
</div>
<div class="flex-row-center">
<div class="mr-2">
<Component is={notification.component.NotificationPresenter} props={{ value: object }} />
</div>
<ActionIcon label={task.string.More} action={(evt) => { showMenu(evt) }} icon={IconMoreH} size={'small'} />
<ActionIcon
label={task.string.More}
action={(evt) => {
showMenu(evt)
}}
icon={IconMoreH}
size={'small'}
/>
</div>
</div>
<div class="caption-color mb-3 lines-limit-4">{object.name}</div>
@ -54,7 +73,7 @@
{/if}
</div>
<Avatar avatar={object.$lookup?.assignee?.avatar} size={'x-small'} />
</div>
</div>
</div>
<style lang="scss">
@ -62,10 +81,12 @@
display: flex;
flex-direction: column;
padding: 1rem 1.25rem;
background-color: rgba(222, 222, 240, .06);
border-radius: .75rem;
background-color: rgba(222, 222, 240, 0.06);
border-radius: 0.75rem;
user-select: none;
&.draggable { cursor: grab; }
&.draggable {
cursor: grab;
}
}
</style>

View File

@ -19,7 +19,6 @@
export let value: State
</script>
{#if value}
<div class="overflow-label state-container" style="background-color: {getPlatformColor(value.color)}">
{value.title}

View File

@ -24,15 +24,18 @@
export let item: TodoItem
let name: string = ''
let dueTo: Date | undefined
let dueTo: Date | undefined | null = null
let _itemId: Ref<TodoItem>
$: if (_itemId !== item._id) {
_itemId = item._id
name = item.name
dueTo = new Date(item.dueTo ?? 0)
console.log('AHTUNG', item, dueTo)
if (item.dueTo != null) {
dueTo = new Date(item.dueTo)
} else {
dueTo = null
}
}
const dispatch = createEventDispatcher()

View File

@ -0,0 +1,54 @@
<!--
// 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 type { WithLookup } from '@anticrm/core'
import type { Task, TodoItem } from '@anticrm/task'
import task from '@anticrm/task'
import { Table } from '@anticrm/view-resources'
import plugin from '../../plugin'
export let value: WithLookup<Task>
$: todos = (value.$lookup?.todoItems as TodoItem[]) ?? []
</script>
<div class="applications-container">
{#if todos.length > 0}
<Table
_class={task.class.TodoItem}
config={[
{ key: 'name', label: plugin.string.TodoName },
'dueTo',
{ key: 'done', presenter: plugin.component.TodoStatePresenter, label: plugin.string.TodoState }
]}
options={{}}
query={{ attachedTo: value._id }}
/>
{/if}
</div>
<style lang="scss">
.applications-container {
display: flex;
flex-direction: column;
.title {
margin-right: 0.75rem;
font-weight: 500;
font-size: 1.25rem;
color: var(--theme-caption-color);
}
}
</style>

View File

@ -15,17 +15,15 @@
-->
<script lang="ts">
import type { TodoItem } from '@anticrm/task'
import { Label } from '@anticrm/ui'
import { getPlatformColor, Label } from '@anticrm/ui'
import task from '../../plugin'
export let value: TodoItem
export let value: boolean
$: color = value.done ? '#60B96E' : '#6F7BC5'
$: text = value.done ? task.string.DoneState : task.string.UndoneState
$: color = value ? getPlatformColor(2) : getPlatformColor(10)
$: text = value ? task.string.DoneState : task.string.UndoneState
</script>
{#if value }
{#if value !== undefined }
<div class="overflow-label state-container" style="background-color: {color};">
<Label label={text}/>
</div>

View File

@ -37,6 +37,7 @@ import TaskItem from './components/TaskItem.svelte'
import TaskPresenter from './components/TaskPresenter.svelte'
import TemplatesIcon from './components/TemplatesIcon.svelte'
import TodoItemPresenter from './components/todos/TodoItemPresenter.svelte'
import TodoItemsPopup from './components/todos/TodoItemsPopup.svelte'
import Todos from './components/todos/Todos.svelte'
import TodoStatePresenter from './components/todos/TodoStatePresenter.svelte'
import AssignedTasks from './components/AssignedTasks.svelte'
@ -147,7 +148,8 @@ export default async (): Promise<Resources> => ({
DoneStateEditor,
KanbanTemplateEditor,
KanbanTemplateSelector,
AssignedTasks
AssignedTasks,
TodoItemsPopup
},
actionImpl: {
CreateTask: createTask,

View File

@ -227,7 +227,11 @@ const task = plugin(taskId, {
},
component: {
KanbanTemplateEditor: '' as AnyComponent,
KanbanTemplateSelector: '' as AnyComponent
KanbanTemplateSelector: '' as AnyComponent,
TodoItemsPopup: '' as AnyComponent
},
string: {
TodoItems: '' as IntlString
}
})