Signed-off-by: Alexander Platov <sas_lord@mail.ru>
This commit is contained in:
Alexander Platov
2022-04-02 11:06:48 +07:00
committed by GitHub
parent e2ae4b157e
commit b6de3da74a
75 changed files with 1007 additions and 379 deletions
@@ -15,14 +15,15 @@
-->
<script lang="ts">
import type { IntlString } from '@anticrm/platform'
import type { Asset, IntlString } from '@anticrm/platform'
import { createEventDispatcher } from 'svelte'
import type { Ref, Class, Space, DocumentQuery } from '@anticrm/core'
import { Button, Label } from '@anticrm/ui'
import { Button, Label, IconAttachment, IconExpand, IconClose, MiniToggle } from '@anticrm/ui'
import SpaceSelect from './SpaceSelect.svelte'
import presentation from '@anticrm/presentation'
import tracker from '../plugin'
export let spaceClass: Ref<Class<Space>> | undefined = undefined
export let space: Ref<Space> | undefined = undefined
@@ -31,8 +32,10 @@
export let spacePlaceholder: IntlString | undefined = undefined
export let label: IntlString
export let labelProps: any | undefined = undefined
export let icon: Asset | undefined = undefined
export let okAction: () => void
export let canSave: boolean = false
export let createMore: boolean | undefined = undefined
export let okLabel: IntlString = presentation.string.Create
export let cancelLabel: IntlString = presentation.string.Cancel
@@ -40,24 +43,31 @@
const dispatch = createEventDispatcher()
</script>
<form class="antiCard w-165" on:submit|preventDefault={ () => {} }>
<form class="antiCard dialog" on:submit|preventDefault={ () => {} }>
<div class="antiCard-header">
<div class="antiCard-header__title"><Label {label} params={labelProps ?? {}} /></div>
{#if $$slots.error}
<div class="antiCard-header__error">
<slot name="error" />
</div>
{/if}
<div class="antiCard-header__title-wrap">
<Button icon={icon} label={presentation.string.Save} size={'small'} kind={'no-border'} disabled on:click={() => { }} />
<span class="antiCard-header__divider"></span>
<span class="antiCard-header__title"><Label {label} params={labelProps ?? {}} /></span>
</div>
<div class="buttons-group small-gap">
<Button icon={IconExpand} kind={'transparent'} on:click={() => { }} />
<Button icon={IconClose} kind={'transparent'} on:click={() => { dispatch('close') }} />
</div>
</div>
<div class="antiCard-content"><slot /></div>
{#if spaceClass && spaceLabel && spacePlaceholder}
<div class="antiCard-pool">
<div class="antiCard-pool__separator" />
<SpaceSelect _class={spaceClass} spaceQuery={spaceQuery} label={spaceLabel} placeholder={spacePlaceholder} bind:value={space} />
<slot name="pool" />
</div>
{/if}
<div class="antiCard-footer">
<Button disabled={!canSave} label={okLabel} size={'small'} transparent primary on:click={() => { okAction(); dispatch('close') }} />
<Button label={cancelLabel} size={'small'} transparent on:click={() => { dispatch('close') }} />
<div class="antiCard-footer reverse">
<div class="buttons-group text-sm">
{#if createMore !== undefined}
<MiniToggle label={tracker.string.CreateMore} bind:on={createMore} />
{/if}
<Button disabled={!canSave} label={okLabel} kind={'primary'} on:click={() => { okAction(); dispatch('close') }} />
</div>
<Button icon={IconAttachment} kind={'transparent'} on:click={() => { }} />
</div>
</form>
@@ -13,17 +13,19 @@
// limitations under the License.
-->
<script lang="ts">
import { Asset, IntlString } from '@anticrm/platform'
import contact, { Employee } from '@anticrm/contact'
import core, { Data, generateId, Ref, SortingOrder } from '@anticrm/core'
import { OK, Status } from '@anticrm/platform'
import { getClient, UserBox } from '@anticrm/presentation'
import { Issue, IssuePriority, IssueStatus, Team } from '@anticrm/tracker'
import { StyledTextBox } from '@anticrm/text-editor'
import { EditBox, Grid, Status as StatusControl } from '@anticrm/ui'
import { EditBox, Grid, Status as StatusControl, Button, showPopup } from '@anticrm/ui'
import { createEventDispatcher } from 'svelte'
import tracker from '../plugin'
import { calcRank } from '../utils'
import Card from './Card.svelte';
import Card from './Card.svelte'
import SelectPopup from './SelectPopup.svelte'
export let space: Ref<Team>
export let parent: Ref<Issue> | undefined
@@ -85,37 +87,84 @@ import Card from './Card.svelte';
await client.createDoc(tracker.class.Issue, _space, value, taskId)
}
interface IPair {
icon: Asset
label: IntlString
}
const statuses: Array<IPair> =
[{ icon: tracker.icon.StatusBacklog, label: tracker.string.Backlog },
{ icon: tracker.icon.StatusTodo, label: tracker.string.Todo },
{ icon: tracker.icon.StatusInProgress, label: tracker.string.InProgress },
{ icon: tracker.icon.StatusDone, label: tracker.string.Done },
{ icon: tracker.icon.StatusCanceled, label: tracker.string.Canceled }]
let selectStatus: IPair = statuses[0]
const priorities: Array<IPair> =
[{ icon: tracker.icon.PriorityNoPriority, label: tracker.string.NoPriority },
{ icon: tracker.icon.PriorityUrgent, label: tracker.string.Urgent },
{ icon: tracker.icon.PriorityHigh, label: tracker.string.High },
{ icon: tracker.icon.PriorityMedium, label: tracker.string.Medium },
{ icon: tracker.icon.PriorityLow, label: tracker.string.Low }]
let selectPriority: IPair = priorities[0]
</script>
<!-- canSave: object.title.length > 0 && _space != null -->
<Card
label={tracker.string.NewIssue}
okAction={createIssue}
canSave={object.title.length > 0 && _space != null}
icon={tracker.icon.Home}
canSave={true}
okLabel={tracker.string.SaveIssue}
spaceClass={tracker.class.Team}
spaceLabel={tracker.string.Team}
spacePlaceholder={tracker.string.SelectTeam}
createMore={false}
bind:space={_space}
on:close={() => {
dispatch('close')
}}
>
<StatusControl slot="error" {status} />
<Grid column={1} rowGap={1.5}>
<EditBox
label={tracker.string.Title}
bind:value={object.title}
placeholder={tracker.string.IssueTitlePlaceholder}
maxWidth={'16rem'}
focus
<EditBox
bind:value={object.title}
placeholder={tracker.string.IssueTitlePlaceholder}
maxWidth={'37.5rem'}
kind={'large-style'}
focus
/>
<!-- <StyledTextBox alwaysEdit bind:content={object.description} placeholder={tracker.string.IssueDescriptionPlaceholder}/> -->
<!-- <UserBox
_class={contact.class.Employee}
title={tracker.string.Assignee}
caption={tracker.string.Assignee}
bind:value={assignee}
allowDeselect
titleDeselect={tracker.string.TaskUnAssign}
/> -->
<div style="height: 30px"></div>
<div slot="pool" class="flex-row-center text-sm gap-1-5">
<Button
label={selectStatus.label}
icon={selectStatus.icon}
width={'min-content'}
size={'small'}
kind={'no-border'}
on:click={(ev) => {
showPopup(SelectPopup, { value: statuses, placeholder: tracker.string.SetStatus, searchable: true }, ev.currentTarget, (result) => {
if (result !== undefined) { selectStatus = result }
})
}}
/>
<StyledTextBox alwaysEdit bind:content={object.description} placeholder={tracker.string.IssueDescriptionPlaceholder}/>
<UserBox
_class={contact.class.Employee}
title={tracker.string.Assignee}
caption={tracker.string.Assignee}
bind:value={assignee}
allowDeselect
titleDeselect={tracker.string.TaskUnAssign}
<Button
label={selectPriority.label}
icon={selectPriority.icon}
width={'min-content'}
size={'small'}
kind={'no-border'}
on:click={(ev) => {
showPopup(SelectPopup, { value: priorities, placeholder: tracker.string.SetStatus }, ev.currentTarget, (result) => {
if (result !== undefined) { selectPriority = result }
})
}}
/>
</Grid>
</div>
</Card>
@@ -1,6 +1,6 @@
<script lang="ts">
import { Ref, Space } from '@anticrm/core'
import ui, { ActionIcon, Button, IconEdit, IconSearch, showPopup } from '@anticrm/ui'
import { Button, IconSearch, showPopup } from '@anticrm/ui'
import tracker from '../plugin'
import CreateIssue from './CreateIssue.svelte'
export let currentSpace: Ref<Space>
@@ -10,17 +10,15 @@
}
</script>
<div class="flex-between mt-4 mb-4">
<div class="flex-grow">
<div class="antiNav-subheader gap-2">
<div class="flex-grow text-md">
<Button
icon={IconEdit}
icon={tracker.icon.NewIssue}
label={tracker.string.NewIssue}
justify={'left'}
width={'100%'}
size={'small'}
on:click={(evt) => newIssue(evt.currentTarget)}
on:click={() => newIssue(null)}
/>
</div>
<div class="ml-2">
<ActionIcon icon={IconSearch} label={ui.string.Search} action={async () => {}} size={'large'} />
</div>
<Button icon={tracker.icon.Magnifier} on:click={async () => {}} />
</div>
@@ -0,0 +1,64 @@
<!--
// 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 { Asset, IntlString } from '@anticrm/platform'
import { translate } from '@anticrm/platform'
import { afterUpdate, createEventDispatcher } from 'svelte'
import type { Ref, Class, Space, DocumentQuery } from '@anticrm/core'
import { createQuery } from '@anticrm/presentation'
import { Icon, Label } from '@anticrm/ui'
import tracker from '../plugin'
export let _class: Ref<Class<Space>>
export let spaceQuery: DocumentQuery<Space> | undefined
export let placeholder: IntlString | undefined = undefined
export let placeholderParam: any | undefined = undefined
export let searchable: boolean = false
export let value: Array<{
icon: Asset
label: IntlString
}>
let search: string = ''
let input: HTMLInputElement
let objects: Space[] = []
let phTraslate: string = ''
$: if (placeholder) translate(placeholder, placeholderParam ?? {}).then(res => { phTraslate = res })
const dispatch = createEventDispatcher()
// const query = createQuery()
// $: query.query(_class, { ...(spaceQuery ?? {}), name: { $like: '%' + search + '%' } }, result => { objects = result })
// afterUpdate(() => { dispatch('update', Date.now()) })
</script>
<div class="selectPopup">
{#if searchable}
<div class="header">
<input bind:this={input} type='text' bind:value={search} placeholder={phTraslate} on:input={(ev) => { }} on:change/>
</div>
{/if}
<div class="scroll">
<div class="box">
{#each value.filter(el => el.label.toLowerCase().includes(search.toLowerCase())) as space}
<button class="menu-item" on:click={() => { dispatch('close', space) }}>
<div class="icon"><Icon icon={space.icon} size={'small'} /></div>
<span class="label"><Label label={space.label} /></span>
</button>
{/each}
</div>
</div>
</div>