mirror of
https://github.com/hcengineering/platform.git
synced 2026-09-23 18:15:03 +02:00
@@ -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>
|
||||
Reference in New Issue
Block a user