Update popups (#2421)

Signed-off-by: Alexander Platov <sas_lord@mail.ru>
This commit is contained in:
Alexander Platov 2022-12-07 08:02:03 +03:00 committed by GitHub
parent d9fac2dddb
commit 6b46af0384
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
36 changed files with 465 additions and 500 deletions

View File

@ -71,12 +71,12 @@
/>
</div>
</div>
<Scroller autoscroll>
<Scroller>
<div class="antiCard-content">
<slot />
</div>
</Scroller>
{#if $$slots.header || $$slots.pool}
{#if $$slots.pool}
<div class="antiCard-pool">
<slot name="pool" />
</div>

View File

@ -6,19 +6,20 @@
import StyledTextEditor from './StyledTextEditor.svelte'
export let label: IntlString | undefined = undefined
export let content: string
export let content: string | undefined
export let placeholder: IntlString = textEditorPlugin.string.EditorPlaceholder
export let showButtons = true
export let buttonSize: IconSize = 'small'
export let focus = false
export let emphasized: boolean = false
export let isScrollable: boolean = false
export let maxHeight: 'max' | 'card' | 'limited' | string | undefined = undefined
let rawValue: string
let oldContent = ''
$: if (oldContent !== content) {
$: if (content && oldContent !== content) {
oldContent = content
rawValue = content
}
@ -42,10 +43,9 @@
<!-- svelte-ignore a11y-click-events-have-key-events -->
<div
class="antiComponent styled-box clear-mins"
class:antiEmphasized={emphasized}
on:click={() => {
if (focused) {
textEditor?.focus()
}
textEditor?.focus()
}}
>
{#if label}
@ -71,7 +71,12 @@
rawValue = evt.detail
dispatch('changeContent')
}}
/>
>
<slot />
<svelte:fragment slot="right">
<slot name="right" />
</svelte:fragment>
</StyledTextEditor>
</div>
<style lang="scss">
@ -81,7 +86,7 @@
.label {
padding-bottom: 0.25rem;
font-size: 0.75rem;
color: var(--theme-caption-color);
color: var(--caption-color);
opacity: 0.3;
transition: top 200ms;
pointer-events: none;

View File

@ -83,8 +83,8 @@
<!-- svelte-ignore a11y-click-events-have-key-events -->
<div
class="antiComponent styled-box clear-mins"
class:emphasized
class:emphasized-focus={(mode === Mode.Edit || alwaysEdit) && focused}
class:antiEmphasized={emphasized}
class:antiEmphasized-focus={(mode === Mode.Edit || alwaysEdit) && focused}
on:click={() => {
if (alwaysEdit && focused) {
textEditor?.focus()
@ -182,14 +182,4 @@
user-select: none;
}
}
.emphasized {
padding: 1rem;
background-color: var(--theme-bg-accent-color);
border: 1px solid var(--theme-bg-accent-hover);
border-radius: 0.5rem;
&.emphasized-focus {
background-color: var(--theme-bg-focused-color);
border-color: var(--theme-bg-focused-border);
}
}
</style>

View File

@ -480,14 +480,26 @@
</div>
</div>
{#if showButtons}
<div class="buttons-group xsmall-gap my-4">
{#each defActions.filter((it) => it.hidden === undefined || it.hidden === true) as a}
<StyleButton icon={a.icon} size={buttonSize} on:click={(evt) => handleAction(a, evt)} />
{/each}
<div class="flex-grow">
{#if $$slots.right}
<div class="flex-between">
<div class="buttons-group xsmall-gap mt-4">
{#each defActions.filter((it) => it.hidden === undefined || it.hidden === true) as a}
<StyleButton icon={a.icon} size={buttonSize} on:click={(evt) => handleAction(a, evt)} />
{/each}
<slot />
</div>
<div class="buttons-group xsmall-gap mt-4">
<slot name="right" />
</div>
</div>
{:else}
<div class="buttons-group xsmall-gap mt-4">
{#each defActions.filter((it) => it.hidden === undefined || it.hidden === true) as a}
<StyleButton icon={a.icon} size={buttonSize} on:click={(evt) => handleAction(a, evt)} />
{/each}
<slot />
</div>
</div>
{/if}
{/if}
</div>
@ -536,5 +548,15 @@
}
}
}
.formatPanel {
position: sticky;
top: 1.25rem;
margin: -0.5rem -0.5rem 0.25rem;
padding: 0.5rem;
background-color: var(--body-accent);
border-radius: 0.5rem;
box-shadow: var(--button-shadow);
z-index: 1;
}
}
</style>

View File

@ -238,7 +238,7 @@
--menu-bg-select: #f0f3f9;
--menu-icon-hover: #282a30;
--header-bg-color: linear-gradient(0deg, #eee, #f6f6f6);
--popup-bg-color: linear-gradient(136.61deg, #fff 13.72%, #fefefe 74.3%);
--popup-bg-color: linear-gradient(136.61deg, #fff 13.72%, #f8f8f8 74.3%);
--popup-bg-hover: #f0f3f9;
--popup-divider: #eff1f4;
--popup-shadow: rgb(0 0 0 / 20%) 0px 4px 24px; // Dark

View File

@ -419,6 +419,7 @@ input.search {
.my-4 { margin: 1rem 0; }
.m-0-5 { margin: .125rem; }
.m-1 { margin: .25rem; }
.pl-1 { padding-left: .25rem; }
.pl-2 { padding-left: .5rem; }

View File

@ -342,3 +342,21 @@
// Replacing the background of a text editor in Activity
.activity-content .ref-container .textInput { background-color: var(--body-color) !important; }
// Emphasized
.antiEmphasized {
padding: .75rem;
background-color: var(--body-accent);
border: 1px solid var(--button-border-color);
border-radius: .5rem;
transition-property: border, background-color;
transition-duration: .15s;
transition-timing-function: var(--timing-main);
&:hover,
&:focus-within {
background-color: var(--body-color);
border-color: var(--button-border-hover);
}
}

View File

@ -65,6 +65,7 @@
touch-action: manipulation;
scrollbar-color: var(--theme-menu-color) var(--theme-bg-color);
scrollbar-width: none;
--body-font-size: .875rem;
--font-family: 'IBM Plex Sans', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto;
--timing-shadow: cubic-bezier(0,.65,.35,1);
--timing-main: cubic-bezier(0.25, 0.46, 0.45, 0.94);
@ -110,7 +111,7 @@ body {
font-family: var(--font-family);
font-weight: 400;
font-size: .875rem;
font-size: var(--body-font-size);
color: var(--content-color);
background-color: var(--body-color);
user-select: none;

View File

@ -143,6 +143,7 @@
color: var(--accent-color);
background-color: transparent;
border: 1px solid transparent;
border-radius: 0.125rem;
transition-property: border, background-color, color, box-shadow;
transition-duration: 0.15s;

View File

@ -31,6 +31,7 @@
export let placeholder: IntlString | undefined = undefined
export let alwaysEdit = false
export let showButtons = false
export let emphasized: boolean = false
export let buttonSize: IconSize = 'small'
export let maxHeight: 'max' | 'card' | 'limited' | string = 'max'
export let focusable: boolean = false
@ -204,6 +205,7 @@
{buttonSize}
{maxHeight}
{focusable}
{emphasized}
on:changeSize
on:attach={() => attach()}
/>

View File

@ -117,38 +117,32 @@
/>
</div>
<svelte:fragment slot="pool">
<div class="flex flex-wrap" style:gap={'0.2vw'}>
<UserBoxList
items={object.authors}
size="small"
label={document.string.Authors}
emptyLabel={document.string.Authors}
kind="no-border"
width={'min-content'}
on:update={({ detail }) => (object.authors = detail)}
/>
</div>
<div class="flex flex-wrap" style:gap={'0.2vw'}>
<UserBoxList
items={object.approvers}
size="small"
label={document.string.Approvers}
emptyLabel={document.string.Approvers}
kind="no-border"
width={'min-content'}
on:update={({ detail }) => (object.approvers = detail)}
/>
</div>
<div class="flex flex-wrap" style:gap={'0.2vw'}>
<UserBoxList
items={object.reviewers}
size="small"
label={document.string.Reviewers}
emptyLabel={document.string.Reviewers}
kind="no-border"
width={'min-content'}
on:update={({ detail }) => (object.reviewers = detail)}
/>
</div>
<UserBoxList
items={object.authors}
size="small"
label={document.string.Authors}
emptyLabel={document.string.Authors}
kind="no-border"
width={'min-content'}
on:update={({ detail }) => (object.authors = detail)}
/>
<UserBoxList
items={object.approvers}
size="small"
label={document.string.Approvers}
emptyLabel={document.string.Approvers}
kind="no-border"
width={'min-content'}
on:update={({ detail }) => (object.approvers = detail)}
/>
<UserBoxList
items={object.reviewers}
size="small"
label={document.string.Reviewers}
emptyLabel={document.string.Reviewers}
kind="no-border"
width={'min-content'}
on:update={({ detail }) => (object.reviewers = detail)}
/>
</svelte:fragment>
</Card>

View File

@ -27,6 +27,7 @@
deviceOptionsStore as deviceInfo,
TabList
} from '@hcengineering/ui'
import type { TabItem } from '@hcengineering/ui'
import view from '@hcengineering/view'
import hr from '../plugin'
import ScheduleMonthView from './ScheduleView.svelte'
@ -83,6 +84,11 @@
else if (res.id === 'ModeYear') mode = CalendarMode.Year
}
}
const viewslist: TabItem[] = [
{ id: 'chart', icon: view.icon.Views },
{ id: 'stats', icon: view.icon.Table }
]
</script>
<div class="ac-header divide {twoRows ? 'flex-col-reverse' : 'full'} withSettings">
@ -151,20 +157,14 @@
{/if}
<div class="flex-row-center gap-2">
{#if mode === CalendarMode.Month}
<Button
icon={view.icon.Views}
selected={display === 'chart'}
<TabList
items={viewslist}
multiselect={false}
selected={display}
kind={'secondary'}
size={'small'}
on:click={() => {
display = 'chart'
}}
/>
<Button
size={'small'}
icon={view.icon.Table}
selected={display === 'stats'}
on:click={() => {
display = 'stats'
on:select={(result) => {
if (result.detail !== undefined) display = result.detail.id
}}
/>
{/if}

View File

@ -15,7 +15,7 @@
-->
<script lang="ts">
import { DocumentQuery } from '@hcengineering/core'
import { Button, Icon, Label, Scroller, SearchEdit, showPopup, IconAdd, eventToHTMLElement } from '@hcengineering/ui'
import { Button, Icon, Label, Scroller, SearchEdit, showPopup, IconAdd } from '@hcengineering/ui'
import type { Category } from '@hcengineering/inventory'
import inventory from '../plugin'
import CreateCategory from './CreateCategory.svelte'
@ -29,8 +29,8 @@
resultQuery = search === '' ? {} : { $search: search }
}
function showCreateDialog (ev: MouseEvent) {
showPopup(CreateCategory, { space: inventory.space.Category }, eventToHTMLElement(ev))
function showCreateDialog () {
showPopup(CreateCategory, { space: inventory.space.Category }, 'top')
}
$: twoRows = $deviceInfo.twoRows

View File

@ -19,7 +19,7 @@
import { OK, Status } from '@hcengineering/platform'
import { Card, getClient } from '@hcengineering/presentation'
import type { Category } from '@hcengineering/inventory'
import { EditBox, Grid, Status as StatusControl } from '@hcengineering/ui'
import { EditBox, Button, Status as StatusControl } from '@hcengineering/ui'
import { createEventDispatcher } from 'svelte'
import inventory from '../plugin'
@ -64,13 +64,10 @@
}}
>
<StatusControl slot="error" {status} />
<Grid column={1} rowGap={1.5}>
<EditBox
label={inventory.string.Category}
icon={inventory.icon.Categories}
bind:value={name}
placeholder={inventory.string.Category}
focus
/>
</Grid>
<div class="flex-row-center clear-mins">
<div class="mr-3">
<Button focusIndex={1} icon={inventory.icon.Categories} size={'medium'} kind={'link-bordered'} disabled />
</div>
<EditBox bind:value={name} placeholder={inventory.string.Category} kind={'large-style'} focus />
</div>
</Card>

View File

@ -16,7 +16,7 @@
<script lang="ts">
import { Account, generateId, Ref, Doc } from '@hcengineering/core'
import { Card, createQuery, getClient } from '@hcengineering/presentation'
import { DropdownLabels, EditBox, Grid } from '@hcengineering/ui'
import { DropdownLabels, EditBox, Button } from '@hcengineering/ui'
import { createEventDispatcher } from 'svelte'
import inventory from '../plugin'
import { Category, Product } from '@hcengineering/inventory'
@ -76,19 +76,18 @@
dispatch('close')
}}
>
<Grid column={1} rowGap={1.75}>
<EditBox
label={inventory.string.Product}
icon={inventory.icon.Products}
bind:value={doc.name}
placeholder={inventory.string.Product}
focus
/>
<div class="flex-row-center clear-mins">
<div class="mr-3">
<Button focusIndex={1} icon={inventory.icon.Products} size={'medium'} kind={'link-bordered'} disabled />
</div>
<EditBox bind:value={doc.name} placeholder={inventory.string.Product} kind={'large-style'} focus />
</div>
<svelte:fragment slot="pool">
<DropdownLabels
items={categories}
bind:selected={doc.attachedTo}
placeholder={inventory.string.Categories}
label={inventory.string.Category}
/>
</Grid>
</svelte:fragment>
</Card>

View File

@ -180,7 +180,7 @@
/>
</svelte:fragment>
{#if targetClass._id === contact.class.Person}
<div class="flex-between flex-row-top mt-2 mb-2">
<div class="flex-between flex-row-top">
<div class="flex-col flex-grow">
<EditBox
placeholder={contact.string.PersonFirstNamePlaceholder}
@ -221,7 +221,7 @@
</div>
</div>
{:else}
<div class="flex-row-center clear-mins mt-2 mb-2">
<div class="flex-row-center clear-mins">
<div class="mr-3">
<Button icon={contact.icon.Company} size={'medium'} kind={'link-bordered'} disabled />
</div>

View File

@ -20,7 +20,7 @@
import { OK, Status } from '@hcengineering/platform'
import { Card, getClient, SpaceSelector, UserBox } from '@hcengineering/presentation'
import task, { calcRank } from '@hcengineering/task'
import { createFocusManager, EditBox, FocusHandler, Label, Status as StatusControl } from '@hcengineering/ui'
import { createFocusManager, EditBox, FocusHandler, Label, Status as StatusControl, Button } from '@hcengineering/ui'
import { createEventDispatcher } from 'svelte'
import lead from '../plugin'
@ -135,15 +135,15 @@
<Label label={lead.string.CreateLead} />
</div>
</svelte:fragment>
<StatusControl slot="error" {status} />
<EditBox
focusIndex={1}
label={lead.string.LeadName}
bind:value={title}
icon={lead.icon.Lead}
placeholder={lead.string.LeadPlaceholder}
focus
/>
<div class="flex-row-center clear-mins">
<div class="mr-3">
<Button focusIndex={1} icon={lead.icon.Lead} size={'medium'} kind={'link-bordered'} disabled />
</div>
<EditBox focusIndex={1} bind:value={title} placeholder={lead.string.LeadPlaceholder} kind={'large-style'} focus />
</div>
<svelte:fragment slot="pool">
{#if !preserveCustomer}
<UserBox

View File

@ -471,78 +471,72 @@
</div>
</div>
<svelte:fragment slot="pool">
<div class="flex-col flex-grow">
<div class="flex flex-wrap">
<ChannelsDropdown
editable={!loading}
focusIndex={10}
bind:value={channels}
highlighted={matchedChannels.map((it) => it.provider)}
/>
<YesNo
disabled={loading}
focusIndex={100}
label={recruit.string.Onsite}
tooltip={recruit.string.WorkLocationPreferences}
bind:value={object.onsite}
/>
<YesNo
disabled={loading}
focusIndex={101}
label={recruit.string.Remote}
tooltip={recruit.string.WorkLocationPreferences}
bind:value={object.remote}
/>
<Component
is={tags.component.TagsDropdownEditor}
props={{
disabled: loading,
focusIndex: 102,
items: skills,
key,
targetClass: recruit.mixin.Candidate,
showTitle: false,
elements,
newElements,
countLabel: recruit.string.NumberSkills
}}
on:open={(evt) => {
addTagRef(evt.detail)
}}
on:delete={(evt) => {
skills = skills.filter((it) => it._id !== evt.detail)
}}
/>
</div>
{#if skills.length > 0}
<div class="skills-box p-1 mt-2">
<Component
is={tags.component.TagsEditor}
props={{
disabled: loading,
focusIndex: 102,
items: skills,
key,
targetClass: recruit.mixin.Candidate,
showTitle: false,
elements,
newElements,
countLabel: recruit.string.NumberSkills
}}
on:open={(evt) => {
addTagRef(evt.detail)
}}
on:delete={(evt) => {
skills = skills.filter((it) => it._id !== evt.detail)
}}
on:change={(evt) => {
evt.detail.tag.weight = evt.detail.weight
skills = skills
}}
/>
</div>
{/if}
</div>
<ChannelsDropdown
editable={!loading}
focusIndex={10}
bind:value={channels}
highlighted={matchedChannels.map((it) => it.provider)}
/>
<YesNo
disabled={loading}
focusIndex={100}
label={recruit.string.Onsite}
tooltip={recruit.string.WorkLocationPreferences}
bind:value={object.onsite}
/>
<YesNo
disabled={loading}
focusIndex={101}
label={recruit.string.Remote}
tooltip={recruit.string.WorkLocationPreferences}
bind:value={object.remote}
/>
<Component
is={tags.component.TagsDropdownEditor}
props={{
disabled: loading,
focusIndex: 102,
items: skills,
key,
targetClass: recruit.mixin.Candidate,
showTitle: false,
elements,
newElements,
countLabel: recruit.string.NumberSkills
}}
on:open={(evt) => {
addTagRef(evt.detail)
}}
on:delete={(evt) => {
skills = skills.filter((it) => it._id !== evt.detail)
}}
/>
{#if skills.length > 0}
<Component
is={tags.component.TagsEditor}
props={{
disabled: loading,
focusIndex: 102,
items: skills,
key,
targetClass: recruit.mixin.Candidate,
showTitle: false,
elements,
newElements,
countLabel: recruit.string.NumberSkills
}}
on:open={(evt) => {
addTagRef(evt.detail)
}}
on:delete={(evt) => {
skills = skills.filter((it) => it._id !== evt.detail)
}}
on:change={(evt) => {
evt.detail.tag.weight = evt.detail.weight
skills = skills
}}
/>
{/if}
</svelte:fragment>
<svelte:fragment slot="footer">
@ -606,7 +600,8 @@
<style lang="scss">
.resume {
padding: 0.5rem 0.75rem;
margin: -0.375rem 0rem -0.375rem -0.375rem;
padding: 0.375rem;
background: var(--accent-bg-color);
border: 1px dashed var(--divider-color);
border-radius: 0.5rem;

View File

@ -150,6 +150,21 @@
/>
</div>
</div>
{#key template?.description}
<AttachmentStyledBox
bind:this={descriptionBox}
{objectId}
_class={recruit.class.Vacancy}
space={objectId}
alwaysEdit
showButtons={false}
maxHeight={'card'}
content={template?.description ?? ''}
placeholder={recruit.string.FullDescription}
emphasized
/>
{/key}
<svelte:fragment slot="header">
<UserBox
focusIndex={3}
@ -179,19 +194,6 @@
}}
/>
</svelte:fragment>
{#key template?.description}
<AttachmentStyledBox
bind:this={descriptionBox}
{objectId}
_class={recruit.class.Vacancy}
space={objectId}
alwaysEdit
showButtons={false}
maxHeight={'card'}
content={template?.description ?? ''}
placeholder={recruit.string.FullDescription}
/>
{/key}
<svelte:fragment slot="footer">
<Button
icon={IconAttachment}

View File

@ -19,8 +19,8 @@
import { Card, getClient } from '@hcengineering/presentation'
import type { Opinion, Review } from '@hcengineering/recruit'
import task, { SpaceWithStates } from '@hcengineering/task'
import { StyledTextEditor } from '@hcengineering/text-editor'
import { EditBox, Grid, Label, Status as StatusControl } from '@hcengineering/ui'
import { StyledTextArea } from '@hcengineering/text-editor'
import { EditBox, Status as StatusControl } from '@hcengineering/ui'
import { createEventDispatcher } from 'svelte'
import recruit from '../../plugin'
@ -88,27 +88,11 @@
}}
>
<StatusControl slot="error" {status} />
<Grid column={1} rowGap={1.75}>
<EditBox
bind:value={doc.value}
label={recruit.string.OpinionValue}
placeholder={recruit.string.OpinionValuePlaceholder}
focus
/>
<div class="mt-1 mb-1">
<Label label={recruit.string.Description} />:
</div>
<div class="description flex">
<StyledTextEditor bind:content={doc.description} />
</div>
</Grid>
<EditBox
bind:value={doc.value}
label={recruit.string.OpinionValue}
placeholder={recruit.string.OpinionValuePlaceholder}
focus
/>
<StyledTextArea placeholder={recruit.string.Description} bind:content={doc.description} emphasized />
</Card>
<style lang="scss">
.description {
height: 10rem;
padding: 0.5rem;
border: 1px solid var(--theme-menu-divider);
border-radius: 8px;
}
</style>

View File

@ -21,7 +21,7 @@
import { Card, getClient, UserBox, UserBoxList } from '@hcengineering/presentation'
import type { Candidate, Review } from '@hcengineering/recruit'
import task from '@hcengineering/task'
import { StyledTextBox } from '@hcengineering/text-editor'
import { StyledTextArea } from '@hcengineering/text-editor'
import { DateRangePresenter, EditBox, Status as StatusControl } from '@hcengineering/ui'
import view from '@hcengineering/view'
import { createEventDispatcher } from 'svelte'
@ -150,14 +150,7 @@
<StatusControl slot="error" {status} />
<EditBox placeholder={recruit.string.Title} bind:value={title} kind={'large-style'} focus />
<EditBox placeholder={recruit.string.Location} bind:value={location} kind={'small-style'} />
<StyledTextBox
emphasized
showButtons={false}
bind:content={description}
label={recruit.string.Description}
alwaysEdit
placeholder={recruit.string.AddDescription}
/>
<StyledTextArea bind:content={description} placeholder={recruit.string.AddDescription} emphasized />
<svelte:fragment slot="pool">
{#if !preserveCandidate}
<UserBox

View File

@ -24,8 +24,8 @@
export let opinions: number
const createApp = (ev: MouseEvent): void => {
showPopup(CreateOpinion, { review: objectId }, ev.target as HTMLElement)
const createApp = (): void => {
showPopup(CreateOpinion, { review: objectId }, 'top')
}
</script>

View File

@ -27,8 +27,8 @@
export let reviews: number
export let label: IntlString = recruit.string.Reviews
const createApp = (ev: MouseEvent): void => {
showPopup(CreateReview, { candidate: objectId, preserveCandidate: true }, ev.target as HTMLElement)
const createApp = (): void => {
showPopup(CreateReview, { candidate: objectId, preserveCandidate: true }, 'top')
}
let wSection: number
</script>

View File

@ -103,7 +103,9 @@
"DocumentColor": "",
"Rank": "",
"IssueTitlePlaceholder": "Issue title",
"SubIssueTitlePlaceholder": "Sub-issue title",
"IssueDescriptionPlaceholder": "Add description",
"SubIssueDescriptionPlaceholder": "Add sub-issue description",
"AddIssueTooltip": "Add issue...",
"NewIssueDialogClose": "Do you want to close this dialog?",
"NewIssueDialogCloseNote": "All changes will be lost",

View File

@ -103,7 +103,9 @@
"DocumentColor": "",
"Rank": "",
"IssueTitlePlaceholder": "Имя задачи",
"SubIssueTitlePlaceholder": "Имя подзадачи",
"IssueDescriptionPlaceholder": "Описание задачи",
"SubIssueDescriptionPlaceholder": "Описание подзадачи",
"AddIssueTooltip": "Добавить задачу\u2026",
"NewIssueDialogClose": "Вы действительно хотите закрыть окно?",
"NewIssueDialogCloseNote": "Все внесенные изменения будут потеряны",

View File

@ -699,69 +699,68 @@
space={_space}
alwaysEdit
showButtons={false}
emphasized
bind:content={object.description}
placeholder={tracker.string.IssueDescriptionPlaceholder}
on:changeSize={() => dispatch('changeContent')}
/>
<IssueTemplateChilds bind:children={subIssues} sprint={object.sprint} project={object.project} isScrollable />
<svelte:fragment slot="pool">
<div class="flex flex-wrap" style:gap={'0.2vw'}>
{#if issueStatuses}
<div id="status-editor">
<StatusEditor
value={object}
statuses={issueStatuses}
kind="no-border"
size="small"
shouldShowLabel={true}
on:change={({ detail }) => (object.status = detail)}
/>
</div>
<PriorityEditor
{#if issueStatuses}
<div id="status-editor">
<StatusEditor
value={object}
shouldShowLabel
isEditable
statuses={issueStatuses}
kind="no-border"
size="small"
justify="center"
on:change={({ detail }) => (object.priority = detail)}
shouldShowLabel={true}
on:change={({ detail }) => (object.status = detail)}
/>
<AssigneeEditor
value={object}
size="small"
kind="no-border"
width={'min-content'}
on:change={({ detail }) => (object.assignee = detail)}
/>
<Component
is={tags.component.TagsDropdownEditor}
props={{
items: labels,
key,
targetClass: tracker.class.Issue,
countLabel: tracker.string.NumberLabels
}}
on:open={(evt) => {
addTagRef(evt.detail)
}}
on:delete={(evt) => {
labels = labels.filter((it) => it._id !== evt.detail)
}}
/>
<EstimationEditor kind={'no-border'} size={'small'} value={object} />
<ProjectSelector value={object.project} onChange={handleProjectIdChanged} />
<SprintSelector
value={object.sprint}
onChange={handleSprintIdChanged}
useProject={(!originalIssue && object.project) || undefined}
/>
{#if object.dueDate !== null}
<DatePresenter bind:value={object.dueDate} editable />
{/if}
{:else}
<Spinner size="small" />
</div>
<PriorityEditor
value={object}
shouldShowLabel
isEditable
kind="no-border"
size="small"
justify="center"
on:change={({ detail }) => (object.priority = detail)}
/>
<AssigneeEditor
value={object}
size="small"
kind="no-border"
width={'min-content'}
on:change={({ detail }) => (object.assignee = detail)}
/>
<Component
is={tags.component.TagsDropdownEditor}
props={{
items: labels,
key,
targetClass: tracker.class.Issue,
countLabel: tracker.string.NumberLabels
}}
on:open={(evt) => {
addTagRef(evt.detail)
}}
on:delete={(evt) => {
labels = labels.filter((it) => it._id !== evt.detail)
}}
/>
<EstimationEditor kind={'no-border'} size={'small'} value={object} />
<ProjectSelector value={object.project} onChange={handleProjectIdChanged} />
<SprintSelector
value={object.sprint}
onChange={handleSprintIdChanged}
useProject={(!originalIssue && object.project) || undefined}
/>
{#if object.dueDate !== null}
<DatePresenter bind:value={object.dueDate} editable />
{/if}
</div>
{:else}
<Spinner size="small" />
{/if}
<ActionIcon icon={IconMoreH} size={'medium'} action={showMoreActions} />
</svelte:fragment>
<svelte:fragment slot="footer">

View File

@ -21,6 +21,7 @@
import { createEventDispatcher } from 'svelte'
import tracker from '../../plugin'
import ProjectStatusSelector from './ProjectStatusSelector.svelte'
import { StyledTextArea } from '@hcengineering/text-editor'
export let space: Ref<Team>
const dispatch = createEventDispatcher()
@ -63,17 +64,13 @@
<svelte:fragment slot="header">
<SpaceSelector _class={tracker.class.Team} label={tracker.string.Team} bind:space />
</svelte:fragment>
<div class="label">
<EditBox bind:value={object.label} placeholder={tracker.string.ProjectNamePlaceholder} kind="large-style" focus />
</div>
<div class="description">
<EditBox
bind:value={object.description}
placeholder={tracker.string.ProjectDescriptionPlaceholder}
kind="editbox"
/>
</div>
<div slot="pool" class="flex-row-center text-sm gap-1-5">
<EditBox bind:value={object.label} placeholder={tracker.string.ProjectNamePlaceholder} kind={'large-style'} focus />
<StyledTextArea
bind:content={object.description}
placeholder={tracker.string.ProjectDescriptionPlaceholder}
emphasized
/>
<svelte:fragment slot="pool">
<ProjectStatusSelector selectedProjectStatus={object.status} onProjectStatusChange={handleProjectStatusChanged} />
<EmployeeBox
label={tracker.string.ProjectLead}
@ -87,7 +84,7 @@
<!-- TODO: add labels after customize IssueNeedsToBeCompletedByThisDate -->
<DatePresenter bind:value={object.startDate} labelNull={tracker.string.StartDate} editable />
<DatePresenter bind:value={object.targetDate} labelNull={tracker.string.TargetDate} editable />
</div>
</svelte:fragment>
</Card>
<style>

View File

@ -74,105 +74,100 @@
}
</script>
<div>
<div class="fs-title flex-between header">
<div class="flex-center">
<Label {label} />
<div class="projectTitle">
<Label label={title} />
</div>
<div class="fs-title flex-between header">
<div class="flex-center">
<Label {label} />
<div class="projectTitle">
<Label label={title} />
</div>
<Button size="small" icon={IconAdd} label={tracker.string.Project} kind="secondary" on:click={showCreateDialog} />
</div>
<div class="itemsContainer">
<Button size="small" icon={IconAdd} label={tracker.string.Project} kind={'primary'} on:click={showCreateDialog} />
</div>
<div class="itemsContainer">
<div class="flex-center">
<div class="flex-center">
<div class="flex-center">
<div class="buttonWrapper">
<Button
size="small"
shape="rectangle-right"
selected={mode === 'all'}
label={tracker.string.AllProjects}
on:click={() => handleViewModeChanged('all')}
/>
</div>
<div class="buttonWrapper">
<Button
size="small"
shape="rectangle"
selected={mode === 'backlog'}
label={tracker.string.BacklogProjects}
on:click={() => handleViewModeChanged('backlog')}
/>
</div>
<div class="buttonWrapper">
<Button
size="small"
shape="rectangle"
selected={mode === 'active'}
label={tracker.string.ActiveProjects}
on:click={() => handleViewModeChanged('active')}
/>
</div>
<div class="buttonWrapper">
<Button
size="small"
shape="rectangle-left"
selected={mode === 'closed'}
label={tracker.string.ClosedProjects}
on:click={() => handleViewModeChanged('closed')}
/>
</div>
</div>
<!-- <div class="ml-3 filterButton">
<div class="buttonWrapper">
<Button
size="small"
icon={IconAdd}
kind={'link-bordered'}
borderStyle={'dashed'}
label={tracker.string.Filter}
on:click={() => {}}
shape="rectangle-right"
selected={mode === 'all'}
label={tracker.string.AllProjects}
on:click={() => handleViewModeChanged('all')}
/>
</div> -->
</div>
<div class="buttonWrapper">
<Button
size="small"
shape="rectangle"
selected={mode === 'backlog'}
label={tracker.string.BacklogProjects}
on:click={() => handleViewModeChanged('backlog')}
/>
</div>
<div class="buttonWrapper">
<Button
size="small"
shape="rectangle"
selected={mode === 'active'}
label={tracker.string.ActiveProjects}
on:click={() => handleViewModeChanged('active')}
/>
</div>
<div class="buttonWrapper">
<Button
size="small"
shape="rectangle-left"
selected={mode === 'closed'}
label={tracker.string.ClosedProjects}
on:click={() => handleViewModeChanged('closed')}
/>
</div>
</div>
<!-- <div class="flex-center">
<div class="flex-center">
<div class="buttonWrapper">
<Button selected size="small" shape="rectangle-right" icon={tracker.icon.ProjectsList} />
</div>
<div class="buttonWrapper">
<Button size="small" shape="rectangle-left" icon={tracker.icon.ProjectsTimeline} />
</div>
</div>
<div class="ml-3">
<Button size="small" icon={IconOptions} />
</div>
<!-- <div class="ml-3 filterButton">
<Button
size="small"
icon={IconAdd}
kind={'link-bordered'}
borderStyle={'dashed'}
label={tracker.string.Filter}
on:click={() => {}}
/>
</div> -->
</div>
<ProjectsListBrowser
_class={tracker.class.Project}
itemsConfig={[
{ key: '', presenter: tracker.component.IconPresenter },
{ key: '', presenter: tracker.component.ProjectPresenter, props: { kind: 'list' } },
{
key: '$lookup.lead',
presenter: tracker.component.LeadPresenter,
props: { _class: tracker.class.Project, defaultClass: contact.class.Employee, shouldShowLabel: false }
},
{ key: '', presenter: tracker.component.ProjectMembersPresenter, props: { kind: 'link' } },
{ key: '', presenter: tracker.component.TargetDatePresenter },
{ key: '', presenter: tracker.component.ProjectStatusPresenter }
]}
projects={resultProjects}
/>
<!-- <div class="flex-center">
<div class="flex-center">
<div class="buttonWrapper">
<Button selected size="small" shape="rectangle-right" icon={tracker.icon.ProjectsList} />
</div>
<div class="buttonWrapper">
<Button size="small" shape="rectangle-left" icon={tracker.icon.ProjectsTimeline} />
</div>
</div>
<div class="ml-3">
<Button size="small" icon={IconOptions} />
</div>
</div> -->
</div>
<ProjectsListBrowser
_class={tracker.class.Project}
itemsConfig={[
{ key: '', presenter: tracker.component.IconPresenter },
{ key: '', presenter: tracker.component.ProjectPresenter, props: { kind: 'list' } },
{
key: '$lookup.lead',
presenter: tracker.component.LeadPresenter,
props: { _class: tracker.class.Project, defaultClass: contact.class.Employee, shouldShowLabel: false }
},
{ key: '', presenter: tracker.component.ProjectMembersPresenter, props: { kind: 'link' } },
{ key: '', presenter: tracker.component.TargetDatePresenter },
{ key: '', presenter: tracker.component.ProjectStatusPresenter }
]}
projects={resultProjects}
/>
<style lang="scss">
.header {
min-height: 3.5rem;
padding-left: 2.25rem;
padding-right: 1.35rem;
border-bottom: 1px solid var(--theme-button-border-hovered);
padding: 0.5rem 0.75rem 0.5rem 2.25rem;
}
.projectTitle {

View File

@ -22,6 +22,7 @@
import tracker from '../../plugin'
import ProjectSelector from '../ProjectSelector.svelte'
import SprintStatusSelector from './SprintStatusSelector.svelte'
import { StyledTextArea } from '@hcengineering/text-editor'
export let space: Ref<Team>
const dispatch = createEventDispatcher()
@ -71,17 +72,13 @@
<svelte:fragment slot="header">
<SpaceSelector _class={tracker.class.Team} label={tracker.string.Team} bind:space />
</svelte:fragment>
<div class="label">
<EditBox bind:value={object.label} placeholder={tracker.string.SprintNamePlaceholder} kind="large-style" focus />
</div>
<div class="description">
<EditBox
bind:value={object.description}
placeholder={tracker.string.ProjectDescriptionPlaceholder}
kind="editbox"
/>
</div>
<div slot="pool" class="flex-row-center text-sm gap-1-5">
<EditBox bind:value={object.label} placeholder={tracker.string.SprintNamePlaceholder} kind={'large-style'} focus />
<StyledTextArea
bind:content={object.description}
placeholder={tracker.string.ProjectDescriptionPlaceholder}
emphasized
/>
<svelte:fragment slot="pool">
<SprintStatusSelector selectedSprintStatus={object.status} onSprintStatusChange={handleProjectStatusChanged} />
<ProjectSelector value={object.project} onChange={handleProjectIdChanged} />
<EmployeeBox
@ -105,7 +102,7 @@
label={tracker.string.TargetDate}
detail={ui.string.SelectDate}
/>
</div>
</svelte:fragment>
</Card>
<style>

View File

@ -86,7 +86,7 @@
<Label label={title} />
</div>
</div>
<Button size="small" icon={IconAdd} label={tracker.string.Sprint} kind="secondary" on:click={showCreateDialog} />
<Button size="small" icon={IconAdd} label={tracker.string.Sprint} kind={'primary'} on:click={showCreateDialog} />
</div>
<div class="itemsContainer">
<div class="flex-center">
@ -183,10 +183,7 @@
<style lang="scss">
.header {
min-height: 3.5rem;
padding-left: 2.25rem;
padding-right: 1.35rem;
border-bottom: 1px solid var(--theme-button-border-hovered);
padding: 0.5rem 0.75rem 0.5rem 2.25rem;
}
.projectTitle {

View File

@ -136,32 +136,20 @@
createMore={false}
>
<svelte:fragment slot="header">
<div class="flex-row-center">
<SpaceSelector
_class={tracker.class.Team}
label={tracker.string.Team}
bind:space={_space}
on:space={(evt) => {
spaceRef = evt.detail
}}
/>
</div>
<SpaceSelector
_class={tracker.class.Team}
label={tracker.string.Team}
bind:space={_space}
on:space={(evt) => {
spaceRef = evt.detail
}}
/>
</svelte:fragment>
<svelte:fragment slot="title" let:label>
<div class="flex-row-center gap-1">
<div class="mr-2">
<Label {label} />
</div>
</div>
<Label {label} />
</svelte:fragment>
<EditBox
bind:value={object.title}
placeholder={tracker.string.IssueTitlePlaceholder}
maxWidth={'37.5rem'}
kind={'large-style'}
focus
/>
<EditBox bind:value={object.title} placeholder={tracker.string.IssueTitlePlaceholder} kind={'large-style'} focus />
<AttachmentStyledBox
bind:this={descriptionBox}
{objectId}
@ -169,7 +157,7 @@
space={_space}
alwaysEdit
showButtons={false}
maxHeight={'card'}
emphasized
bind:content={object.description}
placeholder={tracker.string.IssueDescriptionPlaceholder}
/>
@ -180,42 +168,40 @@
teamId={spaceRef?.identifier ?? 'TSK'}
/>
<svelte:fragment slot="pool">
<div class="flex flex-wrap" style:gap={'0.2vw'}>
<PriorityEditor
value={object}
shouldShowLabel
isEditable
kind="no-border"
size="small"
justify="center"
on:change={({ detail }) => (object.priority = detail)}
/>
<AssigneeEditor
value={object}
size="small"
kind="no-border"
width={'min-content'}
on:change={({ detail }) => (object.assignee = detail)}
/>
<Component
is={tags.component.TagsDropdownEditor}
props={{
items: labels,
key,
targetClass: tracker.class.Issue,
countLabel: tracker.string.NumberLabels
}}
on:open={(evt) => {
addTagRef(evt.detail)
}}
on:delete={(evt) => {
labels = labels.filter((it) => it._id !== evt.detail)
}}
/>
<EstimationEditor kind={'no-border'} size={'small'} value={object} />
<ProjectSelector value={object.project} onChange={handleProjectIdChanged} />
<SprintSelector value={object.sprint} onChange={handleSprintIdChanged} useProject={object.project ?? undefined} />
</div>
<PriorityEditor
value={object}
shouldShowLabel
isEditable
kind="no-border"
size="small"
justify="center"
on:change={({ detail }) => (object.priority = detail)}
/>
<AssigneeEditor
value={object}
size="small"
kind="no-border"
width={'min-content'}
on:change={({ detail }) => (object.assignee = detail)}
/>
<Component
is={tags.component.TagsDropdownEditor}
props={{
items: labels,
key,
targetClass: tracker.class.Issue,
countLabel: tracker.string.NumberLabels
}}
on:open={(evt) => {
addTagRef(evt.detail)
}}
on:delete={(evt) => {
labels = labels.filter((it) => it._id !== evt.detail)
}}
/>
<EstimationEditor kind={'no-border'} size={'small'} value={object} />
<ProjectSelector value={object.project} onChange={handleProjectIdChanged} />
<SprintSelector value={object.sprint} onChange={handleSprintIdChanged} useProject={object.project ?? undefined} />
</svelte:fragment>
<svelte:fragment slot="footer">
<Button

View File

@ -107,28 +107,26 @@
$: labelRefs = labels.map((it) => ({ ...(it as unknown as TagReference), _id: generateId(), tag: it._id }))
</script>
<div bind:this={thisRef} class="flex-col root clear-mins" class:antiPopup={showBorder}>
<div class="flex-row-top clear-mins">
<div class="w-full flex-col content">
<EditBox
bind:value={newIssue.title}
bind:focusInput={focusIssueTitle}
maxWidth="33rem"
placeholder={tracker.string.IssueTitlePlaceholder}
focus
/>
<div class="mt-4 clear-mins">
{#key newIssue.description}
<StyledTextArea
bind:content={newIssue.description}
placeholder={tracker.string.IssueDescriptionPlaceholder}
showButtons={false}
{isScrollable}
{maxHeight}
on:changeContent
/>
{/key}
</div>
<div bind:this={thisRef} class="flex-col antiEmphasized clear-mins" class:antiPopup={showBorder}>
<div class="flex-col w-full clear-mins">
<EditBox
bind:value={newIssue.title}
bind:focusInput={focusIssueTitle}
kind={'large-style'}
placeholder={tracker.string.SubIssueTitlePlaceholder}
focus
/>
<div class="mt-4 clear-mins">
{#key newIssue.description}
<StyledTextArea
bind:content={newIssue.description}
placeholder={tracker.string.SubIssueDescriptionPlaceholder}
showButtons={false}
{isScrollable}
{maxHeight}
on:changeContent
/>
{/key}
</div>
</div>
<div class="mt-4 flex-between">
@ -186,17 +184,3 @@
</div>
</div>
</div>
<style lang="scss">
.root {
padding: 0.5rem 1.5rem;
background-color: var(--theme-bg-accent-color);
border: 1px solid var(--theme-button-border-enabled);
border-radius: 0.5rem;
overflow: hidden;
.content {
padding-top: 0.3rem;
}
}
</style>

View File

@ -76,7 +76,7 @@
labelParams={{ subIssues: 0 }}
kind={'transparent'}
size={'small'}
showTooltip={{ label: tracker.string.AddSubIssues, props: { subIssues: 1 }, direction: 'bottom' }}
showTooltip={{ label: tracker.string.AddSubIssues, props: { subIssues: 1 } }}
on:click={() => {
closeTooltip()
isCreating = true

View File

@ -77,10 +77,10 @@
</svelte:fragment>
<svelte:fragment slot="extra">
<Button
size="small"
size={'small'}
icon={IconAdd}
label={tracker.string.IssueTemplate}
kind="secondary"
kind={'primary'}
on:click={showCreateDialog}
/>

View File

@ -165,7 +165,9 @@ export default mergeIds(trackerId, tracker, {
Duplicate: '' as IntlString,
IssueTitlePlaceholder: '' as IntlString,
SubIssueTitlePlaceholder: '' as IntlString,
IssueDescriptionPlaceholder: '' as IntlString,
SubIssueDescriptionPlaceholder: '' as IntlString,
Unassigned: '' as IntlString,
AddIssueTooltip: '' as IntlString,
NewIssueDialogClose: '' as IntlString,

View File

@ -258,10 +258,10 @@
dispatch('close')
}}
>
<div class="flex flex-wrap flex-row">
<div class="flex-row-stretch flex-wrap">
{#each attributes as attribute, i}
<div
class="mr-2 mb-2"
class="m-0-5 border-radius-1 overflow-label"
style={getStyle(attribute)}
bind:this={elements[i]}
draggable={true}