New themes (#3049)

Signed-off-by: Alexander Platov <sas_lord@mail.ru>
Signed-off-by: Denis Bykhov <bykhov.denis@gmail.com>
Co-authored-by: Denis Bykhov <bykhov.denis@gmail.com>
This commit is contained in:
Alexander Platov 2023-04-23 20:37:24 +03:00 committed by GitHub
parent 84f1c91233
commit 67b7c9df24
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
138 changed files with 2263 additions and 1599 deletions

View File

@ -529,7 +529,7 @@ export function createModel (builder: Builder): void {
{
key: '',
presenter: tracker.component.IssuePresenter,
props: { type: 'issue', listProps: { fixed: 'left' } }
props: { type: 'issue', listProps: { key: 'issue', fixed: 'left' } }
},
{
key: '',
@ -544,7 +544,11 @@ export function createModel (builder: Builder): void {
presenter: tags.component.LabelsPresenter,
props: { kind: 'list', full: false, lookupField: 'labels', listProps: { optional: true, compression: true } }
},
{ key: '', presenter: tracker.component.DueDatePresenter, props: { kind: 'list' } },
{
key: '',
presenter: tracker.component.DueDatePresenter,
props: { kind: 'list', listProps: { optional: true, compression: true } }
},
{
key: '',
presenter: tracker.component.ComponentEditor,
@ -575,15 +579,17 @@ export function createModel (builder: Builder): void {
}
}
},
{ key: '', presenter: view.component.DividerPresenter, props: { type: 'divider' } },
{
key: '',
presenter: tracker.component.EstimationEditor,
props: { kind: 'list', size: 'small', listProps: { optional: true } }
props: { kind: 'list', size: 'small', listProps: { key: 'estimation', fixed: 'left' } }
},
{ key: '', presenter: view.component.DividerPresenter, props: { type: 'divider' } },
{
key: 'modifiedOn',
presenter: tracker.component.ModificationDatePresenter,
props: { listProps: { fixed: 'right', optional: true } }
props: { listProps: { key: 'modified', fixed: 'left' } }
},
{
key: '$lookup.assignee',

View File

@ -302,7 +302,7 @@
}
</script>
<div class="kanban-container top-divider">
<div class="kanban-container">
<ScrollBox>
<div class="kanban-content">
{#each categories as state, si (typeof state === 'object' ? state.name : state)}
@ -360,7 +360,6 @@
position: relative;
width: 100%;
height: 100%;
background: var(--board-bg-color);
}
.kanban-content {
display: flex;

View File

@ -25,13 +25,13 @@
align-items: center;
padding: 0.75rem 1.5rem;
color: var(--dark-color);
background-color: var(--board-card-bg-color);
border: 1px dotted var(--divider-color);
background-color: var(--theme-kanban-card-bg-color);
border: 1px dotted var(--theme-kanban-card-border);
border-radius: 0.75rem;
cursor: pointer;
&:hover {
color: var(--caption-color);
color: var(--theme-caption-color);
}
}
</style>

View File

@ -106,13 +106,14 @@
<style lang="scss">
.card-container {
background-color: var(--board-card-bg-color);
background-color: var(--theme-kanban-card-bg-color);
border: 1px solid var(--theme-kanban-card-border);
border-radius: 0.25rem;
// transition: box-shadow .15s ease-in-out;
&:hover {
background-color: var(--board-card-bg-hover);
}
// &:hover {
// background-color: var(--board-card-bg-hover);
// }
&.checked {
background-color: var(--highlight-select);
box-shadow: inset 0 0 1px 1px var(--highlight-select-border);
@ -123,7 +124,7 @@
}
&.selection,
&.checked.selection {
box-shadow: inset 0 0 1px 1px var(--primary-bg-color);
box-shadow: inset 0 0 1px 1px var(--primary-button-enabled);
animation: anim-border 1s ease-in-out;
&:hover {

View File

@ -36,7 +36,7 @@
<Button
focus
label={presentation.string.Ok}
size={'small'}
size={'large'}
kind={'primary'}
loading={processing}
on:click={() => {
@ -55,7 +55,7 @@
{#if canSubmit}
<Button
label={presentation.string.Cancel}
size={'small'}
size={'large'}
on:click={() => {
dispatch('close', false)
}}
@ -71,14 +71,14 @@
padding: 2rem 1.75rem 1.75rem;
width: 30rem;
max-width: 40rem;
background: var(--popup-bg-color);
background: var(--theme-bg-color);
border-radius: 1.25rem;
user-select: none;
box-shadow: var(--popup-shadow);
.message {
margin-bottom: 1.75rem;
color: var(--accent-color);
color: var(--theme-content-color);
}
.footer {
flex-shrink: 0;

View File

@ -20,6 +20,7 @@
export let onClick: ((event: MouseEvent) => void) | undefined = undefined
export let noUnderline = false
export let inline = false
export let colorInherit: boolean = false
export let shrink: number = 0
function clickHandler (e: MouseEvent) {
@ -53,13 +54,14 @@
class:cursor-pointer={!disableClick}
class:noUnderline
class:inline
class:colorInherit
style:flex-shrink={shrink}
on:click={clickHandler}
>
<slot />
</span>
{:else}
<a {href} class:noUnderline class:inline style:flex-shrink={shrink} on:click={clickHandler}>
<a {href} class:noUnderline class:inline class:colorInherit style:flex-shrink={shrink} on:click={clickHandler}>
<slot />
</a>
{/if}
@ -70,32 +72,41 @@
display: flex;
align-items: center;
min-width: 0;
color: var(--accent-color);
// overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
cursor: pointer;
font-weight: inherit;
&:not(.colorInherit) {
color: var(--theme-content-color);
}
&.colorInherit {
color: inherit;
}
&.inline {
display: inline-flex;
align-items: center;
}
&.noUnderline {
color: var(--caption-color);
font-weight: 500;
&:not(.colorInherit) {
color: var(--theme-caption-color);
}
}
&:not(.noUnderline) {
&:hover {
color: var(--caption-color);
text-decoration: underline;
&:not(.colorInherit) {
color: var(--theme-caption-color);
}
}
}
&:active {
color: var(--accent-color);
color: var(--theme-content-color);
}
}
</style>

View File

@ -361,7 +361,7 @@
align-items: center;
width: 1rem;
height: 1rem;
color: var(--caption-color);
color: var(--theme-caption-color);
opacity: 0.6;
cursor: pointer;
@ -383,8 +383,8 @@
.formatPanelRef {
padding: 0.5rem;
background-color: var(--body-color);
border: 1px solid var(--divider-color);
background-color: var(--theme-comp-header-color);
border: 1px solid var(--theme-divider-color);
border-radius: 0.5rem 0.5rem 0 0;
border-bottom: 0;
@ -402,8 +402,8 @@
align-items: flex-end;
min-height: 2.75rem;
padding: 0.75rem 1rem;
background-color: var(--body-accent);
border: 1px solid var(--divider-color);
background-color: var(--theme-refinput-color);
border: 1px solid var(--theme-divider-color);
border-radius: 0.5rem;
&.withoutTopBorder {
@ -417,7 +417,7 @@
align-items: center;
width: calc(100% - 1.75rem);
height: 100%;
color: var(--content-color);
color: var(--theme-content-color);
background-color: transparent;
border: none;
outline: none;
@ -468,19 +468,18 @@
.icon {
width: 1.25rem;
height: 1.25rem;
color: var(--dark-color);
color: var(--theme-dark-color);
cursor: pointer;
&:hover {
color: var(--caption-color);
color: var(--theme-caption-color);
}
}
&:focus {
border: 1px solid var(--primary-button-focused-border);
box-shadow: 0 0 0 3px var(--primary-button-outline);
box-shadow: 0 0 0 2px var(--primary-button-focused-border);
& > .icon {
color: var(--caption-color);
color: var(--theme-caption-color);
}
}

View File

@ -15,16 +15,17 @@
/* Common Colors */
* {
--primary-button-color: #fff;
--primary-button-enabled: #4474F6;
--primary-button-hovered: #2A5FF6;
--primary-button-pressed: #194CD7;
--primary-button-focused: #194CD7;
--primary-button-disabled: #5771B9;
--primary-button-focused-border: #7393EB;
--primary-button-outline: rgba(87, 132, 255, .3);
--primary-button-border: rgba(255, 255, 255, .09);
// --primary-button-color: #fff;
// --primary-button-enabled: #4474F6;
// --primary-button-hovered: #2A5FF6;
// --primary-button-pressed: #194CD7;
// --primary-button-focused: #194CD7;
// --primary-button-disabled: #5771B9;
// --primary-button-focused-border: #7393EB;
// --primary-button-outline: rgba(87, 132, 255, .3);
// --primary-button-border: rgba(255, 255, 255, .09);
--white-color: #fff;
--duotone-color: rgba(126, 134, 158, .25);
--system-error-color: #EE7A7A;
@ -52,6 +53,67 @@
/* Dark Theme */
.theme-dark {
--primary-button-color: #fff;
--primary-button-enabled: #205DC2;
--primary-button-hovered: #1A53AF;
--primary-button-pressed: #144CA8;
--primary-button-focused: #144CA8;
--primary-button-disabled: #6E9FED;
--primary-button-focused-border: #6E9FED;
--primary-button-border: rgba(255, 255, 255, .09);
--primary-button-outline: rgba(87, 132, 255, .3); // OLD
--theme-button-enabled: rgba(255, 255, 255, .02);
--theme-button-hovered: rgba(255, 255, 255, .04);
--theme-button-pressed: rgba(255, 255, 255, .08);
--theme-button-focused: rgba(255, 255, 255, .04);
--theme-button-disabled: rgba(255, 255, 255, .02);
--theme-button-border: rgba(255, 255, 255, .06);
--theme-refinput-color: rgba(255, 255, 255, .03);
--theme-bg-color: #1A1A28;
--theme-back-color: #0f0f18;
--theme-statusbar-color: #2C2C35;
--theme-navpanel-color: #14141F;
--theme-navpanel-hovered: rgba(255, 255, 255, .04);
--theme-navpanel-selected: rgba(255, 255, 255, .07);
--theme-navpanel-divider: rgba(255, 255, 255, .1);
--theme-navpanel-border: transparent;
--theme-navpanel-icons-color: #7F7F7F;
--theme-comp-header-color: #1F1F2C;
--theme-divider-color: rgba(255, 255, 255, .06);
--theme-trans-color: rgba(255, 255, 255, .3);
--theme-darker-color: rgba(255, 255, 255, .4);
--theme-halfcontent-color: rgba(255, 255, 255, .5);
--theme-dark-color: rgba(255, 255, 255, .6);
--theme-content-color: rgba(255, 255, 255, .8);
--theme-caption-color: #FFF;
--theme-list-border-color: rgba(255, 255, 255, .05);
--theme-list-header-color: #C88C65;
--theme-list-subheader-color: #262634;
--theme-list-row-color: #21212F;
--theme-list-button-color: #262633;
--theme-list-divider-color: rgba(255, 255, 255, .09);
--theme-list-subheader-divider: transparent;
--theme-table-border-color: rgba(255, 255, 255, .1);
--theme-table-header-color: #1C1C29;
--theme-table-row-color: #21212F;
--theme-kanban-card-bg-color: rgba(222, 222, 240, .04);
--theme-kanban-card-border: transparent;
--theme-kanban-card-footer: #D9D9D9;
--theme-tablist-color: rgba(0, 0, 0, .02);
--theme-checkbox-color: #000;
--theme-checkbox-bg-color: #FFF;
--theme-checkbox-border: rgba(0, 0, 0, .12);
--theme-checkbox-disabled: #999;
--theme-progress-color: #FFFFFF;
--body-color: #1f2023;
--body-accent: #222326;
--board-bg-color: #1c1d1f;
@ -61,7 +123,7 @@
--accent-bg-color: #27282b;
--accent-shadow: rgb(0 0 0 / 10%) 0px 2px 4px;
--highlight-hover: #28292b;
--highlight-hover: #282834;
--highlight-select: #252b3a;
--highlight-select-border: #44506b;
--highlight-select-hover: #2c3346;
@ -106,7 +168,7 @@
--button-bg-hover: #37383b;
--button-border-color: #3c3f44;
--button-border-hover: #45484e;
--button-shadow: rgb(0 0 0 / 25%) 0px 1px 1px;
--button-shadow: rgb(0 0 0 / 15%) 0px 1px 1px 1px;
--button-disabled-color: #313236;
--noborder-bg-color: #313236;
--noborder-bg-hover: #37383b;
@ -135,6 +197,67 @@
/* Light Theme */
.theme-light {
--primary-button-color: #fff;
--primary-button-enabled: #2B5190;
--primary-button-hovered: #1A53AF; // DARK
--primary-button-pressed: #144CA8; // DARK
--primary-button-focused: #144CA8; // DARK
--primary-button-disabled: #6E9FED; // DARK
--primary-button-focused-border: #6E9FED; // DARK
--primary-button-border: rgba(255, 255, 255, .09);
--primary-button-outline: rgba(87, 132, 255, .3); // OLD
--theme-button-enabled: rgba(0, 0, 0, .02);
--theme-button-hovered: rgba(0, 0, 0, .04);
--theme-button-pressed: rgba(0, 0, 0, .08);
--theme-button-focused: rgba(0, 0, 0, .04);
--theme-button-disabled: rgba(0, 0, 0, .02);
--theme-button-border: rgba(0, 0, 0, .06);
--theme-refinput-color: rgba(0, 0, 0, .03);
--theme-bg-color: #F1F1F4;
--theme-back-color: #D9D9DD;
--theme-statusbar-color: #bfbfc6;
--theme-navpanel-color: #E8E8ED;
--theme-navpanel-hovered: rgba(218, 218, 231, .5);
--theme-navpanel-selected: #DADAE7;
--theme-navpanel-divider: rgba(0, 0, 0, .06);
--theme-navpanel-border: rgba(0, 0, 0, .06);
--theme-navpanel-icons-color: #7F7F7F;
--theme-comp-header-color: #FBFBFC;
--theme-divider-color: rgba(0, 0, 0, .06);
--theme-trans-color: rgba(0, 0, 0, .3);
--theme-darker-color: rgba(0, 0, 0, .4);
--theme-halfcontent-color: rgba(0, 0, 0, .5);
--theme-dark-color: rgba(0, 0, 0, .6);
--theme-content-color: rgba(0, 0, 0, .8);
--theme-caption-color: #000;
--theme-list-border-color: rgba(0, 0, 0, .09);
--theme-list-header-color: #ECD4CA;
--theme-list-subheader-color: #EEEEF0;
--theme-list-row-color: #F7F7F8;
--theme-list-button-color: #F2F2F4;
--theme-list-divider-color: rgba(0, 0, 0, .07);
--theme-list-subheader-divider: rgba(0, 0, 0, .06);
--theme-table-border-color: rgba(0, 0, 0, .1);
--theme-table-header-color: #EFEFF2;
--theme-table-row-color: #F4F4F6;
--theme-kanban-card-bg-color: rgba(0, 0, 0, .03);
--theme-kanban-card-border: rgba(0, 0, 0, .04);
--theme-kanban-card-footer: rgba(0, 0, 0, .04);
--theme-tablist-color: rgba(0, 0, 0, .02);
--theme-checkbox-color: #000;
--theme-checkbox-bg-color: #FFF;
--theme-checkbox-border: rgba(0, 0, 0, .12);
--theme-checkbox-disabled: #999;
--theme-progress-color: rgba(0, 0, 0, .5);
--body-color: #fff;
--body-accent: #fafafa; // HZ
--board-bg-color: #f4f5f8;
@ -144,7 +267,7 @@
--accent-bg-color: #eff0f2; // HZ
--accent-shadow: rgb(0 0 0 / 10%) 0px 2px 4px; // Dark
--highlight-hover: #f9f9f9;
--highlight-hover: #F0F0F1;
--highlight-select: #f0f4ff;
--highlight-select-border: #e6eaff;
--highlight-select-hover: #e4ebff;
@ -189,7 +312,7 @@
--button-bg-hover: #f4f5f8;
--button-border-color: #dfe1e4;
--button-border-hover: #c9cbcd;
--button-shadow: rgb(0 0 0 / 7%) 0px 1px 1px;
--button-shadow: rgb(0 0 0 / 20%) 0px 1px 2px 1px;
--button-disabled-color: #eff1f4;
--noborder-bg-color: #eff1f4;
--noborder-bg-hover: #f4f5f8;

View File

@ -363,10 +363,11 @@ input.search {
}
}
.buttons-divider {
min-width: 1px;
flex-shrink: 0;
width: 1px;
height: 1.5rem;
background-color: var(--divider-color);
max-height: 1.5rem;
background-color: var(--theme-list-divider-color);
}
.labels-row {
@ -467,6 +468,7 @@ input.search {
.mb-8 { margin-bottom: 2rem; }
.mb-9 { margin-bottom: 2.25rem; }
.mb-10 { margin-bottom: 2.5rem; }
.mx-0-5 { margin: 0 .125rem; }
.mx-1 { margin: 0 .25rem; }
.mx-2 { margin: 0 .5rem; }
.mx-3 { margin: 0 .75rem; }
@ -475,6 +477,7 @@ input.search {
.mx-auto { margin: 0 auto; }
.my-2 { margin: .5rem 0; }
.my-4 { margin: 1rem 0; }
.my-5 { margin: 1.25rem 0; }
.m-0-5 { margin: .125rem; }
.m-1 { margin: .25rem; }
@ -484,6 +487,7 @@ input.search {
.pl-3 { padding-left: .75rem; }
.pl-4 { padding-left: 1rem; }
.pl-8 { padding-left: 2rem; }
.pl-10 { padding-left: 2.5rem; }
.pr-1 { padding-right: .25rem; }
.pr-2 { padding-right: .5rem; }
.pr-3 { padding-right: .75rem; }
@ -504,6 +508,7 @@ input.search {
.px-2 { padding: 0 .5rem; }
.px-3 { padding: 0 .75rem; }
.px-4 { padding: 0 1rem; }
.px-10 { padding: 0 2.5rem; }
.py-1 { padding: 0.25rem 0; }
.py-4 { padding: 1rem 0; }
.py-8 { padding: 2rem 0; }
@ -612,6 +617,7 @@ input.search {
.min-w-min { min-width: min-content; }
.min-h-0 { min-height: 0; }
.min-h-2 { min-height: .5rem; }
.min-h-4 { min-height: 1rem; }
.min-h-7 { min-height: 1.75rem; }
.min-h-30 { min-height: 7.5rem; }
.min-h-60 { min-height: 15rem; }
@ -623,7 +629,9 @@ input.search {
.max-w-60 { max-width: 15rem; }
.max-w-80 { max-width: 20rem; }
.max-w-240 { max-width: 60rem; }
.max-h-0 { max-height: 0; }
.max-h-2 { max-height: .5rem; }
.max-h-4 { max-height: 1rem; }
.max-h-30 { max-height: 7.5rem; }
.max-h-50 { max-height: 12.5rem; }
.max-h-60 { max-height: 15rem; }
@ -642,20 +650,20 @@ input.search {
height: 1em;
}
.svg-x-small {
width: .857em;
height: .857em;
width: .75rem;
height: .75rem;
}
.svg-small {
width: 1.143em;
height: 1.143em;
width: 1rem;
height: 1rem;
}
.svg-medium {
width: 1.429em;
height: 1.429em;
width: 1.25rem;
height: 1.25rem;
}
.svg-large {
width: 1.715em;
height: 1.715em;
width: 1.5rem;
height: 1.5rem;
}
.svg-full {
width: inherit;
@ -767,26 +775,26 @@ a.no-line {
}
.focused-button {
background-color: var(--button-bg-color);
background-color: var(--theme-button-enabled);
border: 1px solid transparent;
& > .icon { color: var(--accent-color); }
& > .icon { color: var(--theme-content-color); }
&.selected {
background-color: var(--button-bg-hover);
border: 1px solid var(--button-border-hover);
background-color: var(--theme-button-pressed);
border: 1px solid var(--theme-button-border);
}
&:hover {
background-color: var(--button-bg-hover);
border: 1px solid var(--button-border-hover);
& > .icon { color: var(--caption-color); }
background-color: var(--theme-button-hovered);
border: 1px solid var(--theme-button-border);
& > .icon { color: var(--theme-caption-color); }
}
&:focus {
border: 1px solid var(--primary-button-focused-border);
box-shadow: 0 0 0 3px var(--primary-button-outline);
& > .icon { color: var(--caption-color); }
border: 1px solid var(--theme-button-border);
box-shadow: 0 0 0 2px var(--primary-button-focused-border);
& > .icon { color: var(--theme-caption-color); }
}
&.bordered { border-color: var(--button-border-color); }
&.bordered { border-color: var(--theme-button-border); }
}
.overflow-x-auto { overflow-x: auto; }
@ -817,6 +825,8 @@ a.no-line {
.background-primary-color { background-color: var(--primary-button-enabled); }
.background-content-accent-color { background-color: var(--accent-color); }
.content-trans-color { color: var(--theme-trans-color); }
.dark-color,
.content-dark-color { color: var(--dark-color); }
.content-color { color: var(--content-color); }

View File

@ -15,15 +15,16 @@
/* Panels */
* {
--app-panel-width: 4rem;
--app-panel-width: 4.25rem;
}
.antiPanel-application {
flex-shrink: 0;
display: flex;
justify-content: space-between;
align-items: center;
background-color: var(--board-bg-color);
background-color: var(--theme-navpanel-color);
border-right: 1px solid var(--theme-navpanel-divider);
&.vertical {
flex-direction: column;
min-width: var(--app-panel-width);
@ -43,37 +44,39 @@
flex-direction: column;
height: 100%;
overflow: hidden;
&.filled { background-color: var(--body-accent); }
&.border-left { border-left: 1px solid var(--divider-color); }
&.border-right { border-right: 1px solid var(--divider-color); }
&.filled { background-color: var(--theme-bg-color); }
&.border-left { border-left: 1px solid var(--theme-divider-color); }
&.border-right { border-right: 1px solid var(--theme-divider-color); }
}
.antiPanel-navigator {
position: relative;
min-width: 17.5rem;
max-width: 17.5rem;
width: 17.5rem;
background-color: var(--theme-navpanel-color);
border-right: 1px solid var(--theme-navpanel-border);
}
@media (max-width: 1024px) {
.antiPanel-navigator {
position: fixed;
background-color: var(--body-accent);
top: var(--status-bar-height);
height: calc(100% - var(--status-bar-height));
background-color: var(--theme-navpanel-color);
filter: drop-shadow(2px 0 1px rgba(0, 0, 0, .2));
z-index: 450;
&.portrait {
top: var(--status-bar-height);
left: 0;
}
&.landscape {
top: var(--status-bar-height);
left: var(--app-panel-width);
left: var(--app-panel-width);
}
}
}
.antiPanel-component:not(.aside) {
flex-grow: 1;
// background-color: var(--board-bg-color);
background-color: var(--theme-bg-color);
}
.antiPanel-component.aside {
min-width: 30rem;
@ -169,13 +172,13 @@
}
&:hover, &.hovered, &.selected {
background-color: var(--menu-bg-select);
// background-color: var(--theme-navpanel-hovered);
.an-element__icon,
.an-element__label { color: var(--caption-color); }
.an-element__icon-arrow { opacity: 1; }
}
&:hover, &.hovered { background-color: var(--highlight-hover); }
&.selected { background-color: var(--menu-bg-select); }
&:hover, &.hovered { background-color: var(--theme-navpanel-hovered); }
&.selected { background-color: var(--theme-navpanel-selected); }
&:hover .an-element__tool, &.hovered .an-element__tool { visibility: visible; }
&:not(.collapsed) .an-element__icon-arrow { opacity: 1; }
@ -220,7 +223,7 @@
margin: .5rem 0;
height: 1px;
&.line { background-color: var(--divider-color); }
&.line { background-color: var(--theme-navpanel-divider); }
&.short { margin: .25rem 1rem; }
}
.antiNav-space {
@ -231,7 +234,7 @@
flex-shrink: 0;
width: 100%;
height: 1px;
background-color: var(--divider-color);
background-color: var(--theme-navpanel-divider);
}
.antiNav-footer-grower {
flex-shrink: 10;
@ -297,7 +300,7 @@
margin: .25rem 0;
min-height: 1px;
height: 1px;
background-color: var(--divider-color);
background-color: var(--theme-divider-color);
&.dark { background-color: var(--body-accent); }
&.noMargin { margin: 0; }
@ -351,20 +354,7 @@
border-radius: .5rem .5rem 0 0;
}
&__counter {
display: flex;
align-items: center;
flex-wrap: nowrap;
flex-shrink: 0;
padding: 0.25rem 0.5rem;
min-width: 1.325rem;
text-align: center;
font-weight: 500;
font-size: 1rem;
line-height: 1rem;
color: var(--accent-color);
background-color: var(--body-color);
border: 1px solid var(--divider-color);
border-radius: 1rem;
color: var(--theme-darker-color);
}
&__tag {
display: flex;
@ -431,8 +421,8 @@
// Emphasized
.antiEmphasized {
padding: .75rem;
background-color: var(--body-accent);
border: 1px solid var(--button-border-color);
background-color: var(--theme-comp-header-color);
border: 1px solid var(--theme-divider-color);
border-radius: .5rem;
transition-property: border, background-color;
transition-duration: .15s;
@ -440,8 +430,8 @@
&:hover,
&:focus-within {
background-color: var(--body-color);
border-color: var(--button-border-hover);
// background-color: var(--body-color);
border-color: var(--theme-list-divider-color);
}
}

View File

@ -20,10 +20,15 @@
height: 100%;
.ac-header {
padding: 0.5rem 1.5rem 0.5rem 2.5rem;
padding: 0.5rem 2.25rem;
background-color: var(--theme-comp-header-color);
// height: 3.5rem;
// min-height: 2.5rem;
&.caption-height {
min-height: 3.25rem;
}
&.search-start { padding-left: 1.75rem; }
&.short {
display: flex;
align-items: center;
@ -31,21 +36,23 @@
}
&.full,
&-full {
display: grid;
grid-template-columns: auto;
grid-auto-flow: column;
grid-auto-columns: max-content;
gap: .75rem;
display: flex;
justify-content: space-between;
align-items: center;
min-width: 0;
&:not(.small-gap, .medium-gap) > *:not(:last-child) { margin-right: 1.25rem; }
&.small-gap > *:not(:last-child) { margin-right: .75rem; }
&.medium-gap > *:not(:last-child) { margin-right: 1rem; }
}
&.withSettings { padding-right: .75rem; }
// &.withSettings { padding-right: .75rem; }
&.mini {
display: flex;
flex-direction: column;
}
&.mirror {
justify-content: space-between;
padding: 0 1rem;
// padding: 0 1rem;
&-tool {
justify-content: space-between;
@ -53,7 +60,7 @@
}
}
&.divide {
border-bottom: 1px solid var(--divider-color);
border-bottom: 1px solid var(--theme-divider-color);
}
.secondRow {
align-self: flex-end;
@ -77,23 +84,30 @@
.ac-header__icon {
margin-right: 0.5rem;
color: var(--content-color);
color: var(--theme-content-color);
}
.ac-header__title {
flex-shrink: 1;
min-width: 0;
font-weight: 500;
font-size: 1rem;
color: var(--caption-color);
color: var(--theme-caption-color);
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
user-select: none;
}
.ac-header__counter {
flex-shrink: 0;
margin-left: .25rem;
min-width: 0;
font-size: 1rem;
color: var(--theme-darker-color);
}
.ac-header__description {
min-width: 0;
font-size: 0.75rem;
color: var(--dark-color);
color: var(--theme-dark-color);
overflow: hidden;
visibility: visible;
@ -316,14 +330,14 @@
// height: 1.5rem;
}
&__element {
fill: var(--accent-bg-color);
stroke: var(--divider-color);
fill: var(--theme-button-enabled);
stroke: var(--theme-button-border);
stroke-linecap: round;
stroke-linejoin: round;
&:hover { fill: var(--button-bg-color); }
&:hover { fill: var(--theme-button-hovered); }
}
&__selected { fill: var(--button-bg-hover); }
&__selected { fill: var(--theme-button-pressed); }
.asb-label__container {
position: absolute;
@ -338,11 +352,11 @@
height: 100%;
font-weight: 500;
font-size: 0.8125rem;
color: var(--dark-color);
color: var(--theme-dark-color);
pointer-events: none;
&.selected {
color: var(--caption-color);
color: var(--theme-caption-color);
}
}
}
@ -360,18 +374,24 @@
&:last-child { padding-right: 0; }
}
th {
height: 2.5rem;
font-weight: 500;
font-size: .75rem;
color: var(--dark-color);
box-shadow: inset 0 -1px 0 0 var(--divider-color);
height: 3rem;
font-weight: 600;
font-size: .625rem;
letter-spacing: .5px;
text-transform: uppercase;
color: var(--theme-dark-color);
box-shadow: inset 0 -1px 0 0 var(--theme-table-border-color);
user-select: none;
// z-index: 5;
&.sortable { cursor: pointer; }
&.sorted .icon {
margin-left: .25rem;
opacity: .6;
&.sorted {
color: var(--theme-caption-color);
.icon {
margin-left: .25rem;
opacity: .6;
}
}
&:hover .antiTable-cells__checkCell { visibility: visible; }
.checkall { visibility: visible; }
@ -379,7 +399,7 @@
&.editable {
th, td, tr {
border: 1px dashed var(--divider-color);
border: 1px dashed var(--theme-divider-color);
}
}
@ -424,10 +444,12 @@
}
.antiTable-body__row {
position: relative;
height: 3.25rem;
color: var(--caption-color);
color: var(--theme-caption-color);
background-color: var(--theme-table-row-color);
border-bottom: 1px solid var(--theme-divider-color);
&:not(:last-child) { border-bottom: 1px solid var(--accent-bg-color); }
&:hover .antiTable-cells__firstCell .antiTable-cells__firstCell-menuRow { visibility: visible; }
&:hover, &.checking {
.antiTable-cells__checkCell { visibility: visible; }
@ -442,14 +464,14 @@
}
.antiTable-body__border {
border: 1px solid var(--divider-color);
border: 1px solid var(--theme-divider-color);
}
&.highlightRows .antiTable-body__row {
&.selected { background-color: var(--highlight-hover); }
&.checking {
background-color: var(--highlight-select);
border-bottom-color: var(--highlight-select-border);
// border-bottom-color: var(--highlight-select-border);
&:hover { background-color: var(--highlight-select-hover); }
}
@ -460,8 +482,8 @@
position: sticky;
z-index: 2;
top: 0;
height: 2.5rem;
background-color: var(--body-color);
height: 3rem;
background-color: var(--theme-table-header-color);
}
.scroller-tfoot {
@ -469,10 +491,10 @@
z-index: 2;
bottom: 0;
height: 2.5rem;
background-color: var(--body-color);
background-color: var(--theme-table-header-color);
tr {
box-shadow: inset 0 1px 0 0 var(--divider-color);
box-shadow: inset 0 1px 0 0 var(--theme-divider-color);
}
}
@ -480,9 +502,22 @@
th, td {
&:first-child {
position: sticky;
z-index: 1;
padding: 0;
left: 0;
background-color: var(--body-color);
background-color: var(--theme-bg-color);
border-right: 1px solid transparent !important;
z-index: 1;
}
.fullfill {
display: flex;
align-items: center;
padding: .5rem;
width: 100%;
height: 100%;
background-color: var(--theme-bg-color);
border-right: 1px solid var(--theme-divider-color);
&.center { justify-content: center; }
}
}
}
@ -497,12 +532,12 @@
// Basic component view.
.antiComponentBox {
padding: 0.5rem;
background-color: var(--board-card-bg-color);
border: 1px solid var(--divider-color);
background-color: var(--theme-list-row-color);
border: 1px solid var(--theme-list-divider-color);
border-radius: .75rem;
&.antiComponentBoxFocused {
background-color: var(--board-card-bg-hover);
background-color: var(--theme-button-hovered);
}
}
@ -649,3 +684,46 @@
&.inter { font-size: 1em; }
}
}
/* ListView - global style */
.list-container .category-container .categoryHeader.subLevel.closed {
border-bottom: 1px solid var(--theme-list-border-color);
border-radius: 0 0 0.25rem 0.25rem;
}
.list-container .category-container .categoryHeader.closed:not(.subLevel) {
border-radius: 0 0 .25rem .25rem;
&::before {
border-bottom-color: var(--theme-list-border-color);
border-radius: 0.25rem;
}
}
.list-container .category-container .listGrid {
.fix-margin { margin-left: .875rem; }
.name { margin-left: .375rem; }
.optional-bar {
overflow: hidden;
display: flex;
align-items: center;
flex-shrink: 1;
min-width: 0;
.label-wrapper {
display: flex;
align-items: center;
flex-shrink: 10;
width: auto;
min-width: 0;
}
& > *:not(:last-child) {
flex-shrink: 10;
width: min-content;
}
& > *:last-child {
flex-shrink: 0;
width: max-content;
}
& > * { margin-left: .375rem; }
}
}

View File

@ -29,7 +29,8 @@
display: flex;
flex-direction: column;
min-height: 0;
background: var(--popup-bg-color);
background: var(--theme-list-row-color);
border: 1px solid var(--theme-divider-color);
border-radius: .5rem;
box-shadow: var(--card-shadow);
@ -49,7 +50,7 @@
min-width: 0;
font-weight: 500;
font-size: 1rem;
color: var(--accent-color);
color: var(--theme-caption-color);
}
&__error {
min-width: 0;
@ -83,13 +84,13 @@
display: flex;
flex-direction: column;
margin: 0 1rem .75rem;
color: var(--caption-color);
color: var(--theme-caption-color);
flex-wrap: wrap;
&__separator {
margin: 1rem 0;
height: 1px;
background-color: var(--divider-color);
background-color: var(--theme-divider-color);
}
}
@ -110,7 +111,7 @@
.antiCard-group {
padding: .5rem 1rem;
&:not(:last-child) { border-bottom: 1px solid var(--popup-divider); }
&:not(:last-child) { border-bottom: 1px solid var(--theme-divider-color); }
&.grid {
display: grid;
grid-template-columns: 5rem auto;
@ -124,7 +125,7 @@
font-weight: 500;
font-size: .75rem;
line-height: .75rem;
color: var(--content-color);
color: var(--theme-content-color);
}
.value {
display: flex;
@ -166,8 +167,8 @@
font-weight: 400;
font-size: .8125rem;
}
&__divider { color: var(--content-color); }
&__title { color: var(--accent-color); }
&__divider { color: var(--theme-content-color); }
&__title { color: var(--theme-caption-color); }
}
.antiCard-content { margin: .5rem 1.125rem 1rem; }
.antiCard-pool {
@ -185,7 +186,7 @@
align-items: center;
padding: .75rem;
height: auto;
border-top: 1px solid var(--divider-color);
border-top: 1px solid var(--theme-divider-color);
&.reverse { flex-direction: row-reverse; }
&__error {

View File

@ -115,7 +115,7 @@ body {
font-weight: 400;
font-size: var(--body-font-size);
color: var(--content-color);
background-color: var(--body-color);
background-color: var(--theme-bg-color);
user-select: none;
}

View File

@ -68,7 +68,7 @@
&:not(.embedded) {
border-radius: .5rem;
box-shadow: var(--popup-panel-shadow);
// box-shadow: var(--popup-panel-shadow);
}
.popupPanel-title {
@ -87,9 +87,9 @@
&__bordered {
min-width: 0;
min-height: 3rem;
background-color: var(--board-card-bg-color);
background-color: var(--theme-comp-header-color);
&:not(.embedded) {
border: 1px solid var(--divider-color);
border: 1px solid var(--theme-divider-color);
border-bottom: none;
border-radius: .5rem .5rem 0 0;
}
@ -116,8 +116,8 @@
min-height: 0;
width: 100%;
height: 100%;
background-color: var(--body-color);
border: 1px solid var(--divider-color);
background-color: var(--theme-bg-color);
border: 1px solid var(--theme-divider-color);
&:not(.embedded) {
border-radius: 0 0 .5rem .5rem;
}
@ -184,8 +184,8 @@
min-width: 320px;
}
&.bottom-divider { border-bottom: 1px solid var(--divider-color); }
&.top-divider { border-top: 1px solid var(--divider-color); }
&.bottom-divider { border-bottom: 1px solid var(--theme-divider-color); }
&.top-divider { border-top: 1px solid var(--theme-divider-color); }
.header-row {
display: flex;
align-items: center;
@ -214,7 +214,7 @@
bottom: 1rem;
left: 0;
width: 0;
border-left: 1px solid var(--divider-color);
border-left: 1px solid var(--theme-divider-color);
}
&.float {
@ -226,8 +226,8 @@
min-width: 0;
max-width: 320px;
height: 100%;
background-color: var(--board-card-bg-color);
border-left: 1px solid var(--divider-color);
background-color: var(--theme-list-row-color);
border-left: 1px solid var(--theme-divider-color);
border-bottom-right-radius: .45rem;
box-shadow: 0 0 0 0 rgba(0, 0, 0, 0);
transition: box-shadow 150ms ease 0s, transform 150ms cubic-bezier(0.175, 0.885, 0.32, 1.275);

View File

@ -422,7 +422,8 @@
flex-direction: column;
padding: .5rem;
min-height: 22rem;
background: var(--popup-bg-color);
background: var(--theme-list-row-color);
border: 1px solid var(--theme-divider-color);
border-radius: .5rem;
box-shadow: var(--popup-shadow);

View File

@ -106,3 +106,58 @@ export function numberToRGB (color: number, alpha?: number): string {
return `rgba(${r}, ${g}, ${b}, ${alpha === undefined ? '1' : alpha})`
}
/**
* @public
*/
export function hsvToRGB (h: number, s: number, v: number): { r: number, g: number, b: number, rgb: string } {
let r: number = 0
let g: number = 0
let b: number = 0
const i = Math.floor(h * 6)
const f = h * 6 - i
const p = v * (1 - s)
const q = v * (1 - f * s)
const t = v * (1 - (1 - f) * s)
switch (i % 6) {
case 0:
r = v
g = t
b = p
break
case 1:
r = q
g = v
b = p
break
case 2:
r = p
g = v
b = t
break
case 3:
r = p
g = q
b = v
break
case 4:
r = t
g = p
b = v
break
case 5:
r = v
g = p
b = q
break
}
r = Math.round(r * 255)
g = Math.round(g * 255)
b = Math.round(b * 255)
return {
r,
g,
b,
rgb: '#' + r.toString(16) + g.toString(16) + b.toString(16)
}
}

View File

@ -15,6 +15,7 @@
<script lang="ts">
import type { IntlString, Asset } from '@hcengineering/platform'
import type { AnySvelteComponent, TooltipAlignment } from '../types'
import { ComponentType } from 'svelte'
import Icon from './Icon.svelte'
import { tooltip } from '../tooltips'
@ -22,7 +23,7 @@
export let label: IntlString = '' as IntlString
export let labelProps: any = undefined
export let direction: TooltipAlignment | undefined = undefined
export let icon: Asset | AnySvelteComponent
export let icon: Asset | AnySvelteComponent | ComponentType
export let iconProps: any | undefined = undefined
export let size: 'x-small' | 'small' | 'medium' | 'large'
export let action: (ev: MouseEvent) => Promise<void> | void = async () => {}

View File

@ -17,7 +17,7 @@
import { onMount, ComponentType } from 'svelte'
import { registerFocus } from '../focus'
import { tooltip } from '../tooltips'
import type { AnySvelteComponent, ButtonKind, ButtonShape, ButtonSize, LabelAndProps } from '../types'
import type { AnySvelteComponent, ButtonKind, ButtonShape, ButtonSize, LabelAndProps, IconSize } from '../types'
import Icon from './Icon.svelte'
import Label from './Label.svelte'
import Spinner from './Spinner.svelte'
@ -29,6 +29,8 @@
export let shape: ButtonShape = undefined
export let icon: Asset | AnySvelteComponent | ComponentType | undefined = undefined
export let iconProps: any | undefined = undefined
export let iconRight: Asset | AnySvelteComponent | ComponentType | undefined = undefined
export let iconRightProps: any | undefined = undefined
export let justify: 'left' | 'center' = 'center'
export let disabled: boolean = false
export let loading: boolean = false
@ -45,10 +47,14 @@
export let id: string | undefined = undefined
export let input: HTMLButtonElement | undefined = undefined
export let showTooltip: LabelAndProps | undefined = undefined
export let iconSize: IconSize = size === 'inline' ? 'inline' : 'small'
export let iconRightSize: IconSize = 'x-small'
export let short: boolean = false
let iconSize: ButtonSize
$: iconSize = size === 'inline' ? 'inline' : 'small'
$: iconOnly = label === undefined && ($$slots.content === undefined || $$slots.icon !== undefined)
// $: iconSize = size === 'inline' ? 'inline' : 'small'
$: iconOnly =
label === undefined &&
($$slots.content === undefined || $$slots.icon !== undefined || $$slots.iconRight !== undefined)
onMount(() => {
if (focus && input) {
@ -95,6 +101,7 @@
class:selected
class:notSelected
disabled={disabled || loading}
class:short
style:width
style:height
{title}
@ -113,7 +120,7 @@
{/if}
{#if loading}
<div class="btn-icon pointer-events-none caption-color spinner" class:resetIconSize>
<Spinner size={iconSize} />
<Spinner size={iconSize === 'inline' ? 'inline' : 'small'} />
</div>
{/if}
{#if label}
@ -121,8 +128,14 @@
<Label {label} params={labelParams} />
</span>
{/if}
{#if iconRight}
<div class="btn-right-icon pointer-events-none" class:resetIconSize>
<Icon bind:icon={iconRight} size={iconRightSize} iconProps={iconRightProps} />
</div>
{/if}
{#if $$slots.icon}<slot name="icon" />{/if}
{#if $$slots.content}<slot name="content" />{/if}
{#if $$slots.iconRight}<slot name="iconRight" />{/if}
</button>
<style lang="scss">
@ -142,9 +155,9 @@
}
}
.medium {
height: 1.75rem;
height: 2rem;
&.only-icon {
width: 1.75rem;
width: 2rem;
}
}
.large {
@ -168,20 +181,29 @@
font-weight: 500;
min-width: 1.375rem;
white-space: nowrap;
color: var(--accent-color);
color: var(--theme-caption-color);
background-color: transparent;
border: 1px solid transparent;
transition-property: border, background-color, color, box-shadow;
transition-duration: 0.15s;
.btn-icon {
color: var(--content-color);
color: var(--theme-content-color);
transition: color 0.15s;
pointer-events: none;
}
.btn-right-icon {
margin-left: 0.5rem;
color: var(--theme-halfcontent-color);
transition: color 0.15s;
pointer-events: none;
}
&:not(.only-icon) .btn-icon:not(.spinner) {
margin-right: 0.5rem;
}
&:not(.only-icon) .btn-right-icon {
margin-left: 0.5rem;
}
&.no-border:not(.only-icon) .btn-icon,
&.link-bordered:not(.only-icon) .btn-icon,
&.list:not(.only-icon) .btn-icon,
@ -189,6 +211,9 @@
margin-right: 0.25rem;
}
&.short {
max-width: 7rem;
}
&.sh-no-shape {
border-radius: 0.25rem;
}
@ -217,25 +242,22 @@
}
&.highlight {
box-shadow: inset 0 0 1px 1px var(--primary-bg-color);
box-shadow: inset 0 0 1px 1px var(--primary-button-enabled);
&:hover {
box-shadow: inset 0 0 1px 1px var(--primary-bg-hover);
box-shadow: inset 0 0 1px 1px var(--primary-button-hovered);
}
}
&:hover {
color: var(--accent-color);
transition-duration: 0;
.btn-icon {
color: var(--caption-color);
color: var(--theme-caption-color);
}
}
&:focus {
border-color: var(--primary-edit-border-color) !important;
box-shadow: 0 0 0 2px var(--primary-button-focused-border);
}
&:disabled {
color: rgb(var(--caption-color) / 40%);
color: var(--theme-dark-color);
cursor: not-allowed;
.btn-icon {
@ -254,58 +276,64 @@
}
&.secondary {
background-color: var(--button-bg-color);
border-color: var(--button-border-color);
box-shadow: var(--button-shadow);
background-color: var(--theme-button-enabled);
border-color: var(--theme-button-border);
&.medium:not(.only-icon) {
padding: 0 0.75rem;
}
&:hover {
background-color: var(--button-bg-hover);
border-color: var(--button-border-hover);
background-color: var(--theme-button-hovered);
}
&:active {
background-color: var(--theme-button-pressed);
}
&:focus {
background-color: var(--theme-button-focused);
}
&:disabled {
background-color: var(--button-disabled-color);
border-color: transparent;
background-color: var(--theme-button-disabled);
}
&.selected {
background-color: var(--button-bg-hover);
border-color: var(--button-border-hover);
color: var(--caption-color);
background-color: var(--theme-button-hovered);
.btn-icon {
color: var(--accent-color);
color: var(--theme-caption-color);
}
}
}
&.no-border {
font-weight: 400;
color: var(--accent-color);
background-color: var(--noborder-bg-color);
color: var(--theme-content-color);
background-color: var(--theme-button-enabled);
box-shadow: var(--button-shadow);
&:hover {
color: var(--caption-color);
background-color: var(--noborder-bg-hover);
color: var(--theme-caption-color);
background-color: var(--theme-button-hovered);
.btn-icon {
color: var(--caption-color);
color: var(--theme-caption-color);
}
}
&:disabled {
color: var(--content-color);
background-color: var(--button-disabled-color);
color: var(--theme-trans-color);
background-color: var(--theme-list-button-color);
cursor: default;
.btn-icon {
color: var(--theme-trans-color);
}
&:hover {
color: var(--content-color);
color: var(--theme-trans-color);
.btn-icon {
color: var(--content-color);
color: var(--theme-trans-color);
}
}
}
}
&.transparent {
&:hover {
background-color: var(--highlight-hover);
background-color: var(--theme-button-hovered);
}
&.selected {
background-color: var(--highlight-select);
@ -317,72 +345,79 @@
&.link {
padding: 0 0.875rem;
&:hover {
color: var(--caption-color);
background-color: var(--body-color);
border-color: var(--divider-color);
color: var(--theme-caption-color);
background-color: var(--theme-bg-color);
border-color: var(--theme-divider-color);
.btn-icon {
color: var(--content-color);
color: var(--theme-content-color);
}
}
&:disabled {
color: var(--accent-color);
color: var(--theme-dark-color);
background-color: transparent;
border-color: transparent;
cursor: auto;
.btn-icon {
color: var(--content-color);
color: var(--theme-content-color);
}
}
}
&.link-bordered {
padding: 0 0.375rem;
color: var(--accent-color);
border-color: var(--divider-color);
padding: 0 0.5rem;
color: var(--theme-content-color);
border-color: var(--theme-divider-color);
&:hover {
color: var(--accent-color);
background-color: var(--button-bg-hover);
border-color: var(--button-border-hover);
color: var(--theme-caption-color);
background-color: var(--theme-button-hovered);
border-color: var(--theme-list-divider-color);
.btn-icon {
color: var(--accent-color);
color: var(--theme-caption-color);
}
}
}
&.list {
padding: 0 0.625em 0 0.5rem;
padding: 0 0.625em;
min-height: 1.75rem;
color: var(--content-color);
background-color: var(--body-color);
border: 1px solid var(--divider-color);
border-radius: 3rem;
transition-property: border, color, background-color;
transition-duration: 0.15s;
color: var(--theme-halfcontent-color);
background-color: var(--theme-list-button-color);
border: 1px solid var(--theme-button-border);
border-radius: 1.5rem;
// transition-property: border, color, background-color;
// transition-duration: 0.15s;
.btn-icon {
color: var(--theme-dark-color);
}
&:hover {
color: var(--caption-color);
background-color: var(--board-card-bg-color);
border-color: var(--button-border-color);
color: var(--theme-halfcontent-color);
background-color: var(--theme-list-button-color);
border-color: var(--theme-button-border);
}
&:focus {
box-shadow: none;
}
}
&.primary {
padding: 0 0.75rem;
color: var(--white-color);
background-color: var(--primary-bg-color);
border-color: var(--primary-bg-color);
box-shadow: var(--primary-shadow);
color: var(--primary-button-color);
background-color: var(--primary-button-enabled);
border-color: var(--primary-button-border);
.btn-icon {
color: var(--white-color);
}
&:hover {
background-color: var(--primary-bg-hover);
background-color: var(--primary-button-hovered);
}
&:active {
background-color: var(--primary-button-pressed);
}
&:focus {
border-color: var(--primary-edit-border-color);
background-color: var(--primary-button-focused);
}
&:disabled {
background-color: #5e6ad255;
border-color: #5e6ad255;
background-color: var(--primary-button-disabled);
}
}

View File

@ -17,6 +17,7 @@
export let checked: boolean = false
export let symbol: 'check' | 'minus' = 'check'
export let size: 'small' | 'medium' = 'small'
export let circle: boolean = false
export let primary: boolean = false
export let readonly = false
@ -34,7 +35,7 @@
}
</script>
<label class="checkbox" class:circle class:primary class:readonly class:checked>
<label class="checkbox {size}" class:circle class:primary class:readonly class:checked>
<input class="chBox" disabled={readonly} type="checkbox" bind:checked on:change={handleValueChanged} />
<svg class="checkSVG" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
{#if checked}
@ -53,27 +54,32 @@
display: inline-flex;
justify-content: center;
align-items: center;
width: 0.875rem;
height: 0.875rem;
border: 1px solid var(--dark-color);
background-color: var(--theme-button-hovered);
border: 1px solid var(--theme-checkbox-border);
border-radius: 0.25rem;
&.small {
width: 0.875rem;
height: 0.875rem;
}
&.medium {
width: 1rem;
height: 1rem;
}
&.circle {
width: 1rem;
height: 1rem;
border-radius: 50%;
}
&.checked {
background-color: var(--primary-bg-color);
border-color: transparent;
background-color: var(--theme-checkbox-bg-color);
}
&.primary.checked {
background-color: var(--primary-bg-color);
background-color: var(--primary-button-enabled);
border-color: transparent;
}
&.readonly.checked {
background-color: var(--dark-color);
border-color: transparent;
background-color: var(--theme-checkbox-disabled);
}
.chBox {
@ -89,7 +95,7 @@
&:checked + .checkSVG {
& .check {
visibility: visible;
fill: var(--white-color);
fill: var(--theme-checkbox-color);
&.primary {
fill: var(--primary-button-color);
}
@ -99,7 +105,7 @@
cursor: pointer;
}
&:disabled + .checkSVG .check {
fill: var(--content-color);
fill: var(--theme-checkbox-disabled);
}
}
.checkSVG {
@ -108,7 +114,7 @@
.check {
visibility: hidden;
fill: var(--button-bg-color);
fill: var(--theme-checkbox-color);
}
}
}

View File

@ -15,13 +15,13 @@
<script lang="ts">
import type { Asset, IntlString } from '@hcengineering/platform'
import { translate } from '@hcengineering/platform'
import { createEventDispatcher } from 'svelte'
import { createEventDispatcher, ComponentType } from 'svelte'
import plugin from '../plugin'
import type { AnySvelteComponent } from '../types'
import Icon from './Icon.svelte'
import IconClose from './icons/Close.svelte'
export let icon: Asset | AnySvelteComponent
export let icon: Asset | AnySvelteComponent | ComponentType
export let width: string | undefined = undefined
export let value: string | undefined = undefined
export let placeholder: IntlString = plugin.string.EditBoxPlaceholder
@ -65,9 +65,9 @@
.editbox {
padding: 0 0.5rem 0 0.5rem;
min-width: 10rem;
color: var(--caption-color);
background-color: var(--body-color);
border: 1px solid var(--button-border-color);
color: var(--theme-caption-color);
// background-color: var(--body-color);
border: 1px solid transparent;
border-radius: 0.25rem;
&.small {
@ -77,9 +77,11 @@
height: 2rem;
}
&:focus-within {
border-color: var(--primary-edit-border-color);
border-color: var(--theme-button-border);
box-shadow: 0 0 0 2px var(--primary-button-focused-border);
.icon {
color: var(--menu-icon-hover);
color: var(--theme-dark-color);
}
}
@ -89,19 +91,19 @@
border-radius: 0.25rem;
&::placeholder {
color: var(--content-color);
color: var(--theme-halfcontent-color);
}
}
.btn {
color: var(--content-color);
color: var(--theme-dark-color);
cursor: pointer;
&:hover {
color: var(--caption-color);
color: var(--theme-caption-color);
}
}
.icon {
color: var(--content-color);
color: var(--theme-dark-color);
}
}
</style>

View File

@ -71,8 +71,8 @@
position: relative;
width: 100%;
height: 1.5rem;
background-color: var(--board-bg-color);
border: 1px solid var(--accent-bg-color);
background-color: var(--theme-list-row-color);
border: 1px solid var(--theme-list-divider-color);
border-radius: 0.25rem;
.bar {

View File

@ -166,7 +166,7 @@
background-color: transparent;
&.bg {
background-color: var(--body-color);
background-color: var(--theme-back-color);
}
.panel-container {
padding: 0.5rem;

View File

@ -26,6 +26,7 @@
export let autoscroll: boolean = false
export let bottomStart: boolean = false
export let fade: FadeOptions = defaultSP
export let noFade: boolean = false
export let invertScroll: boolean = false
export let horizontal: boolean = false
export let contentDirection: 'vertical' | 'vertical-reverse' | 'horizontal' = 'vertical'
@ -74,10 +75,13 @@
let timerH: number
const inter = new Set<Element>()
let hasLastCategories: boolean = false
$: fz = $themeOptions.fontSize
$: shiftTop = fade.multipler?.top ? fade.multipler?.top * fz : 0
$: shiftBottom = fade.multipler?.bottom ? fade.multipler?.bottom * fz : 0
$: shiftLeft = fade.multipler?.left ? fade.multipler?.left * fz : 0
$: shiftRight = fade.multipler?.right ? fade.multipler?.right * fz : 0
$: orientir = contentDirection === 'horizontal' ? 'horizontal' : 'vertical'
const checkBar = (): void => {
@ -183,7 +187,7 @@
}
const renderFade = () => {
if (divScroll) {
if (divScroll && !noFade) {
const th = shiftTop + (topCrop === 'top' ? 2 * fz - topCropValue : 0)
const tf =
topCrop === 'full'
@ -205,10 +209,12 @@
if (divHScroll && horizontal) {
const gradientH = `linear-gradient(
90deg,
rgba(0, 0, 0, 0) 0,
rgba(0, 0, 0, 1) ${maskH === 'none' || maskH === 'left' ? '0px' : '2rem'},
rgba(0, 0, 0, 1) calc(100% - ${maskH === 'none' || maskH === 'right' ? '0px' : '2rem'}),
rgba(0, 0, 0, 0) 100%
rgba(0, 0, 0, 1) ${shiftLeft}px,
rgba(0, 0, 0, 0) ${shiftLeft}px,
rgba(0, 0, 0, 1) ${shiftLeft + (maskH === 'both' || maskH === 'right' ? 2 * fz : 0)}px,
rgba(0, 0, 0, 1) calc(100% - ${shiftRight + (maskH === 'both' || maskH === 'left' ? 2 * fz : 0)}px),
rgba(0, 0, 0, 0) calc(100% - ${shiftRight}px),
rgba(0, 0, 0, 1) calc(100% - ${shiftRight}px)
)`
divHScroll.style.webkitMaskImage = gradientH
}
@ -252,17 +258,47 @@
const checkIntersection = (entries: IntersectionObserverEntry[], observer: IntersectionObserver) => {
const interArr: Element[] = []
const catEntries: IntersectionObserverEntry[] = []
const lastCatEntries: IntersectionObserverEntry[] = []
entries.forEach((el) => {
if (el.isIntersecting) {
if (el.isIntersecting && el.target.classList.contains('categoryHeader')) {
inter.add(el.target)
interArr.push(el.target)
} else inter.delete(el.target)
if (hasLastCategories) {
if (el.isIntersecting && el.target.classList.contains('categoryHeader')) catEntries.push(el)
if (el.isIntersecting && el.target.classList.contains('lastCat')) lastCatEntries.push(el)
}
})
if (interArr.length > 0) {
dispatch('lastScrolledCategory', interArr[interArr.length - 1]?.getAttribute('id'))
dispatch('firstScrolledCategory', interArr[0]?.getAttribute('id'))
const interCats: string[] = interArr.map((it) => it.getAttribute('id') as string)
dispatch('scrolledCategories', interCats)
}
if (hasLastCategories) {
const targets = new Set<Element>()
const closed = new Set<Element>()
lastCatEntries.forEach((last) => {
catEntries.forEach((cat) => {
if (last.target !== cat.target) {
if (
last.boundingClientRect.top < cat.boundingClientRect.top + 8 &&
last.boundingClientRect.top >= cat.boundingClientRect.top
) {
targets.add(cat.target)
}
if (cat.target.classList.contains('closed') && !closed.has(cat.target)) closed.add(cat.target)
}
})
})
closed.forEach((el) => {
if (!targets.has(el)) el.classList.remove('closed')
})
targets.forEach((el) => el.classList.add('closed'))
}
}
const checkIntersectionFade = () => {
@ -323,6 +359,11 @@
const tempEls = divBox.querySelectorAll('.categoryHeader')
observer = new IntersectionObserver(checkIntersection, { root: null, rootMargin: '0px', threshold: 0.1 })
tempEls.forEach((el) => observer.observe(el))
const tempCats = divBox.querySelectorAll('.lastCat')
if (tempCats.length > 0) {
hasLastCategories = true
tempCats.forEach((el) => observer.observe(el))
} else hasLastCategories = false
}
})
@ -549,6 +590,7 @@
height: 100%;
}
.scroll {
will-change: opacity;
flex-grow: 1;
min-width: 0;
min-height: 0;

View File

@ -12,7 +12,6 @@
<EditWithIcon
icon={IconSearch}
size={'small'}
width={'12rem'}
placeholder={plugin.string.Search}
bind:value={_search}

View File

@ -78,9 +78,9 @@
word-wrap: none;
font-size: 0.75rem;
color: var(--caption-color);
background: var(--popup-bg-color);
border: 0.5px solid var(--popup-divider);
color: var(--theme-caption-color);
background: var(--theme-list-row-color);
border: 0.5px solid var(--theme-list-divider-color);
box-shadow: 0px 8px 15px rgba(0, 0, 0, 0.1);
border-radius: 2.5rem;
// z-index: 1;
@ -92,7 +92,7 @@
transform: translateX(-50%);
}
&:hover {
background: var(--popup-bg-hover);
background: var(--theme-list-button-color);
}
}
</style>

View File

@ -22,7 +22,7 @@
.container {
user-select: none;
font-size: 14px;
color: var(--content-color);
color: var(--theme-content-color);
&.WARNING {
color: yellow;
}

View File

@ -72,14 +72,14 @@
padding: 0;
min-width: 3rem;
height: 3.25rem;
background-color: var(--accent-bg-color);
border: 1px solid var(--button-border-color);
background-color: var(--theme-button-enabled);
border: 1px solid var(--theme-button-border);
border-radius: 0.75rem;
caret-color: var(--caret-color);
&:focus-within {
background-color: var(--body-accent);
border-color: var(--button-border-hover);
background-color: var(--theme-button-focused);
border-color: var(--theme-list-divider-color);
}
input {
height: 3.25rem;
@ -98,7 +98,7 @@
top: 1rem;
left: 1.25rem;
font-size: 0.75rem;
color: var(--caption-color);
color: var(--theme-caption-color);
opacity: 0.3;
transition: top 200ms;
pointer-events: none;

View File

@ -15,7 +15,7 @@
<script lang="ts">
import { createEventDispatcher } from 'svelte'
import { tooltip } from '../tooltips'
import type { TabItem } from '../types'
import type { TabItem, IconSize } from '../types'
import Icon from './Icon.svelte'
import Label from './Label.svelte'
@ -23,7 +23,7 @@
export let multiselect: boolean = false
export let items: TabItem[]
export let kind: 'normal' | 'secondary' = 'normal'
export let short: boolean = false
export let onlyIcons: boolean = false
export let size: 'small' | 'medium' = 'medium'
const dispatch = createEventDispatcher()
@ -38,6 +38,9 @@
return res
}
const tabs: HTMLElement[] = []
let iconSize: IconSize
$: iconSize = onlyIcons ? (size === 'small' ? 'small' : 'medium') : size === 'small' ? 'x-small' : 'small'
</script>
{#if items.length > 0}
@ -47,9 +50,10 @@
<div
bind:this={tabs[i]}
class="button"
class:short
class:onlyIcons
class:selected={getSelected(item.id)}
data-view={item.tooltip}
data-id={`tab-${item.id}`}
use:tooltip={{ label: item.tooltip ?? undefined, element: tabs[i] ?? undefined }}
on:click={() => {
if (multiselect) {
@ -64,7 +68,7 @@
>
{#if item.icon}
<div class="icon">
<Icon icon={item.icon} size={size === 'small' ? 'x-small' : 'small'} fill={item.color ?? 'currentColor'} />
<Icon icon={item.icon} size={iconSize} fill={item.color ?? 'currentColor'} />
</div>
{:else if item.color}
<div class="color" style:background-color={item.color} />
@ -110,10 +114,11 @@
}
&::before {
position: absolute;
top: 0.35rem;
top: 50%;
left: -1.5px;
height: 0.8rem;
height: 70%;
border-left: 1px solid var(--button-border-color);
transform: translateY(-50%);
}
}
.button:not(.selected) + .button:not(.selected)::before {
@ -123,6 +128,10 @@
&.small {
.button {
padding: 0 0.5rem;
&.onlyIcons {
padding: 0.375rem;
}
}
&.normal .button {
height: 1.5rem;
@ -132,29 +141,30 @@
}
}
&.medium .button {
height: 1.75rem;
height: 2rem;
padding: 0.25rem 0.75rem;
&.short {
padding: 0.5rem;
&.onlyIcons {
padding: 0.375rem;
}
}
&.normal {
background-color: var(--accent-bg-color);
border-radius: 0.5rem;
background-color: var(--theme-tablist-color);
border-radius: 0.25rem;
.button {
background-color: var(--accent-bg-color);
color: var(--theme-trans-color);
border: 1px solid transparent;
border-radius: calc(0.5rem - 1px);
border-radius: 0.25rem;
&:hover {
background-color: var(--button-bg-hover);
}
&.selected {
color: var(--caption-color);
background-color: var(--button-bg-color);
border-color: var(--button-border-color);
box-shadow: var(--accent-shadow);
color: var(--theme-caption-color);
background-color: var(--theme-button-enabled);
border-color: var(--theme-button-border);
&:hover {
background-color: var(--theme-button-hovered);
}
}
}
}

View File

@ -474,7 +474,7 @@
pointer-events: none;
&.normal {
color: var(--content-color);
color: var(--theme-content-color);
}
&.warning {
color: var(--warning-color);
@ -486,27 +486,31 @@
&.no-border {
font-weight: 400;
color: var(--accent-color);
background-color: var(--noborder-bg-color);
color: var(--theme-content-color);
background-color: var(--theme-button-enabled);
box-shadow: var(--button-shadow);
&:hover {
color: var(--caption-color);
background-color: var(--noborder-bg-hover);
color: var(--theme-caption-color);
background-color: var(--theme-button-hovered);
transition-duration: 0;
.btn-icon {
color: var(--caption-color);
color: var(--theme-caption-color);
}
}
&:disabled {
color: var(--content-color);
background-color: var(--button-disabled-color);
color: var(--theme-trans-color);
background-color: var(--theme-button-disabled);
cursor: default;
.btn-icon {
color: var(--theme-trans-color);
}
&:hover {
color: var(--content-color);
color: var(--theme-trans-color);
.btn-icon {
color: var(--content-color);
color: var(--theme-trans-color);
}
}
}
@ -515,7 +519,7 @@
cursor: pointer;
&:hover {
background-color: var(--noborder-bg-hover);
background-color: var(--theme-button-hovered);
.btn-icon {
&.normal {
color: var(--caption-color);
@ -528,14 +532,14 @@
}
}
.time-divider {
background-color: var(--button-border-hover);
background-color: var(--theme-divider-color);
}
}
&:focus-within {
background-color: var(--button-bg-color);
background-color: var(--theme-button-focused);
border-color: var(--primary-edit-border-color);
&:hover {
background-color: var(--button-bg-color);
background-color: var(--theme-button-hovered);
}
}
}
@ -554,12 +558,12 @@
padding: 0 0.875rem;
width: 100%;
height: 2.25rem;
color: var(--caption-color);
color: var(--theme-caption-color);
&:hover {
background-color: var(--body-color);
border-color: var(--divider-color);
background-color: var(--theme-bg-color);
border-color: var(--theme-divider-color);
.btn-icon {
color: var(--content-color);
color: var(--theme-content-color);
}
}
&.edit {
@ -574,15 +578,15 @@
margin: 0 0.25rem;
width: 0.75rem;
height: 0.75rem;
color: var(--content-color);
background-color: var(--button-bg-color);
color: var(--theme-content-color);
background-color: var(--theme-button-enabled);
outline: none;
border-radius: 50%;
cursor: pointer;
&:hover {
color: var(--accent-color);
background-color: var(--button-bg-hover);
background-color: var(--theme-button-hovered);
}
}
@ -614,7 +618,7 @@
width: 1px;
min-width: 1px;
height: 0.75rem;
background-color: var(--button-border-color);
background-color: var(--theme-divider-color);
}
.separator {
margin: 0 0.1rem;

View File

@ -87,9 +87,6 @@
grid-auto-columns: max-content;
grid-template-columns: repeat(7, minmax(0, 1fr));
}
.weekend {
background-color: var(--button-bg-color);
}
.cell {
height: calc(100% - 5px);
width: calc(100% - 5px);
@ -98,10 +95,16 @@
cursor: pointer;
}
.cell:hover {
background-color: var(--toggle-bg-hover);
color: var(--primary-button-color);
background-color: var(--highlight-hover);
}
.weekend {
background-color: var(--highlight-select);
&:hover {
background-color: var(--highlight-select-hover);
}
}
.wrongMonth {
color: var(--grayscale-grey-03);
color: var(--theme-trans-color);
}
</style>

View File

@ -43,6 +43,7 @@
{#each [...Array(displayedDaysCount).keys()] as dayOfWeek}
{@const day = getDay(weekMonday, dayOfWeek)}
<th>
<!-- svelte-ignore a11y-click-events-have-key-events -->
<div
class="antiTable-cells cursor-pointer uppercase flex-col-center"
class:today={areDatesEqual(todayDate, day)}
@ -88,7 +89,7 @@
width: 5rem;
}
.today {
color: var(--caption-color);
color: var(--theme-caption-color);
}
.calendar-td {
padding: 0;
@ -99,7 +100,7 @@
width: calc(calc(100% - 50px) / 7);
}
.cell:hover:not(.wrongMonth) {
background-color: var(--toggle-bg-hover);
color: var(--primary-button-color);
background-color: var(--highlight-hover);
}
</style>

View File

@ -37,8 +37,8 @@
<div class="year-erp-calendar">
{#each [...Array(12).keys()] as m}
<div class="antiComponentBox flex-grow flex-wrap" style={`min-width: ${minWidth};`}>
{getMonthName(month(currentDate, m))}
<div class="antiComponentBox flex-col flex-grow flex-wrap" style={`min-width: ${minWidth};`}>
<span class="month-caption">{getMonthName(month(currentDate, m))}</span>
<MonthCalendar
{cellHeight}
weekFormat="narrow"
@ -63,4 +63,11 @@
column-gap: 1rem;
border-collapse: collapse;
}
.month-caption {
margin: 0.5rem 0.75rem 0.75rem;
font-weight: 500;
font-size: 0.8125rem;
text-transform: uppercase;
color: var(--theme-dark-color);
}
</style>

View File

@ -0,0 +1,8 @@
<script lang="ts">
export let size: 'small' | 'medium' | 'large'
const fill: string = 'currentColor'
</script>
<svg class="svg-{size}" {fill} viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
<path d="M10.6572 8.00049L6.82861 4.17187L6.82861 11.8291L10.6572 8.00049Z" />
</svg>

View File

@ -16,6 +16,7 @@
import { getContext } from 'svelte'
import FontSize from './icons/FontSize.svelte'
import { popupstore } from '../../popups'
import { deviceOptionsStore as deviceInfo } from '../..'
const { currentFontSize, setFontSize } = getContext('fontsize') as {
currentFontSize: string
@ -31,6 +32,7 @@
setFontSize(fontsizes[current % fontsizes.length])
$popupstore = $popupstore
}
$: $deviceInfo.fontSize = fontsizes[current % fontsizes.length] === 'normal-font' ? 16 : 14
</script>
<!-- svelte-ignore a11y-click-events-have-key-events -->

View File

@ -175,7 +175,7 @@
// min-width: 600px;
font-size: 12px;
line-height: 150%;
background-color: var(--divider-color);
background-color: var(--theme-statusbar-color);
.status-info {
flex-grow: 1;

View File

@ -151,6 +151,7 @@ export { default as IconMaxWidth } from './components/icons/MaxWidth.svelte'
export { default as IconMixin } from './components/icons/Mixin.svelte'
export { default as IconCircles } from './components/icons/Circles.svelte'
export { default as IconLike } from './components/icons/Like.svelte'
export { default as IconCollapseArrow } from './components/icons/CollapseArrow.svelte'
export { default as PanelInstance } from './components/PanelInstance.svelte'
export { default as Panel } from './components/Panel.svelte'
@ -206,6 +207,7 @@ export const deviceOptionsStore = writable<DeviceOptions>({
docHeight: 0,
isPortrait: false,
isMobile: false,
fontSize: 0,
minWidth: false,
twoRows: false
})

View File

@ -307,7 +307,7 @@ export function fitPopupElement (
newProps.top = `${rect.top}px`
// newProps.bottom = `${Math.min(document.body.clientHeight - rect.bottom + 1, window.innerHeight - rect.top - 1)}px`
newProps.height = `${Math.min(rect.height, window.innerHeight - rect.top)}px`
newProps.left = `${rect.left + 1}px`
newProps.left = `${rect.left}px`
// newProps.right = `${Math.min(document.body.clientWidth - rect.right, window.innerWidth - rect.left - 5)}px`
newProps.width = `${Math.min(rect.width, window.innerWidth - rect.left)}px`
} else if (element === 'middle') {

View File

@ -167,7 +167,7 @@ export type TooltipAlignment = 'top' | 'bottom' | 'left' | 'right'
export type VerticalAlignment = 'top' | 'bottom'
export type HorizontalAlignment = 'left' | 'right'
export type IconSize = 'inline' | 'tiny' | 'x-small' | 'small' | 'medium' | 'large' | 'x-large' | 'full'
export type IconSize = 'inline' | 'tiny' | 'x-small' | 'smaller' | 'small' | 'medium' | 'large' | 'x-large' | 'full'
export interface DateOrShift {
date?: number
@ -233,10 +233,10 @@ export interface FadeOptions {
multipler?: Sides<number>
}
export const defaultSP: FadeOptions = { multipler: { top: 0, bottom: 0 } }
export const tableSP: FadeOptions = { multipler: { top: 2.5, bottom: 2.5 } }
export const tableSP: FadeOptions = { multipler: { top: 3, bottom: 2.5 } }
export const topSP: FadeOptions = { multipler: { top: 2.5, bottom: 0 } }
export const tableHRscheduleY: FadeOptions = { multipler: { top: 5, bottom: 0 } }
export const issueSP: FadeOptions = { multipler: { top: 3, bottom: 0 } }
export const issueSP: FadeOptions = { multipler: { top: 2.75, bottom: 0 } }
export const emojiSP: FadeOptions = { multipler: { top: 1.5, bottom: 0 } }
export interface DeviceOptions {
@ -244,6 +244,7 @@ export interface DeviceOptions {
docHeight: number
isPortrait: boolean
isMobile: boolean
fontSize: number
minWidth: boolean
twoRows: boolean
theme?: any

View File

@ -300,17 +300,17 @@
<style lang="scss">
.list {
padding: 0.5rem;
color: var(--caption-color);
color: var(--theme-caption-color);
overflow-x: auto;
overflow-y: hidden;
background-color: var(--accent-bg-color);
border: 1px solid var(--divider-color);
background-color: var(--theme-refinput-color);
border: 1px solid var(--theme-divider-color);
border-radius: 0.5rem 0.5rem 0 0;
border-bottom: none;
.item + .item {
padding-left: 1rem;
border-left: 1px solid var(--divider-color);
border-left: 1px solid var(--theme-divider-color);
}
}
</style>

View File

@ -17,7 +17,7 @@
import contact, { Employee, EmployeeAccount } from '@hcengineering/contact'
import core, { Class, getCurrentAccount, Ref, Space } from '@hcengineering/core'
import { getClient } from '@hcengineering/presentation'
import ui, { EditWithIcon, IconSearch, Label, Loading, location, navigate, TabList } from '@hcengineering/ui'
import { ActionIcon, IconMoreH, Label, Loading, location, navigate, TabList, SearchEdit } from '@hcengineering/ui'
import view from '@hcengineering/view'
import { get } from 'svelte/store'
import { dateFileBrowserFilters, FileBrowserSortMode, fileTypeFileBrowserFilters, sortModeToOptionObject } from '..'
@ -101,14 +101,30 @@
</script>
{#if withHeader}
<div class="ac-header full divide">
<div class="ac-header full divide caption-height">
<div class="ac-header__wrap-title">
<span class="ac-header__title"><Label label={attachment.string.FileBrowser} /></span>
</div>
<EditWithIcon icon={IconSearch} size={'small'} bind:value={search} placeholder={ui.string.SearchDots} />
<div class="mb-1 clear-mins">
<TabList
items={[
{ id: 'table', icon: view.icon.Table, tooltip: attachment.string.FileBrowserListView },
{ id: 'card', icon: view.icon.Card, tooltip: attachment.string.FileBrowserGridView }
]}
selected={isListDisplayMode ? 'table' : 'card'}
on:select={(result) => {
if (result.detail !== undefined) isListDisplayMode = result.detail === 'table' ?? false
}}
/>
</div>
</div>
{/if}
<div class="ac-header full">
<div class="ac-header full divide search-start">
<div class="ac-header-full small-gap">
<SearchEdit bind:value={search} on:change={() => {}} />
<ActionIcon icon={IconMoreH} size={'small'} />
<div class="buttons-divider" />
</div>
<FileBrowserFilters
{requestedSpaceClasses}
{spaceId}
@ -117,18 +133,6 @@
bind:selectedDateId
bind:selectedFileTypeId
/>
<TabList
items={[
{ id: 'table', icon: view.icon.Table, tooltip: attachment.string.FileBrowserListView },
{ id: 'card', icon: view.icon.Card, tooltip: attachment.string.FileBrowserGridView }
]}
kind={'secondary'}
size={'small'}
selected={isListDisplayMode ? 'table' : 'card'}
on:select={(result) => {
if (result.detail !== undefined) isListDisplayMode = result.detail === 'table' ?? false
}}
/>
</div>
<div class="group">
<div class="groupHeader">

View File

@ -29,54 +29,48 @@
export let selectedFileTypeId: string
</script>
<div class="filterBlockContainer">
<div class="simpleFilterButton">
<Component
is={contact.component.UserBoxList}
props={{
items: selectedParticipants,
label: attachment.string.FileBrowserFilterFrom
}}
on:update={(evt) => {
selectedParticipants = evt.detail
}}
/>
</div>
<div class="simpleFilterButton">
<SpaceMultiBoxList
_classes={requestedSpaceClasses}
label={attachment.string.FileBrowserFilterIn}
selectedItems={spaceId ? [spaceId] : []}
on:update={(evt) => {
selectedSpaces = evt.detail
}}
/>
</div>
<div class="simpleFilterButton">
<DropdownLabelsIntl
items={dateFileBrowserFilters}
label={attachment.string.FileBrowserFilterDate}
bind:selected={selectedDateId}
/>
</div>
<div class="simpleFilterButton">
<DropdownLabelsIntl
items={fileTypeFileBrowserFilters}
label={attachment.string.FileBrowserFilterFileType}
bind:selected={selectedFileTypeId}
/>
</div>
<div class="filterBlockContainer clear-mins gap-2">
<Component
is={contact.component.UserBoxList}
props={{
items: selectedParticipants,
label: attachment.string.FileBrowserFilterFrom,
kind: 'transparent',
size: 'medium'
}}
on:update={(evt) => {
selectedParticipants = evt.detail
}}
/>
<SpaceMultiBoxList
_classes={requestedSpaceClasses}
label={attachment.string.FileBrowserFilterIn}
selectedItems={spaceId ? [spaceId] : []}
kind={'transparent'}
size={'medium'}
on:update={(evt) => {
selectedSpaces = evt.detail
}}
/>
<DropdownLabelsIntl
items={dateFileBrowserFilters}
label={attachment.string.FileBrowserFilterDate}
bind:selected={selectedDateId}
kind={'transparent'}
size={'medium'}
/>
<DropdownLabelsIntl
items={fileTypeFileBrowserFilters}
label={attachment.string.FileBrowserFilterFileType}
bind:selected={selectedFileTypeId}
kind={'transparent'}
size={'medium'}
/>
</div>
<style lang="scss">
.filterBlockContainer {
display: flex;
flex-flow: row wrap;
margin-top: 10px;
margin-bottom: 10px;
}
.simpleFilterButton {
max-width: 12rem;
margin: 0.125rem 0.5rem 0.125rem 0;
}
</style>

View File

@ -26,7 +26,8 @@
Scroller,
showPopup,
WeekCalendar,
YearCalendar
YearCalendar,
defaultSP
} from '@hcengineering/ui'
import { BuildModelKey } from '@hcengineering/view'
import { CalendarMode } from '../index'
@ -166,173 +167,166 @@
let indexes = new Map<Ref<Event>, number>()
</script>
<div class="fs-title ml-10 mb-2 flex-row-center">
<div class="text-lg fs-bold px-10 my-4 flex-no-shrink clear-mins">
{label(currentDate, mode)}
</div>
<div class="flex gap-2 mb-4 ml-10">
<Button
size={'small'}
label={calendar.string.ModeDay}
on:click={() => {
mode = CalendarMode.Day
}}
/>
<Button
size={'small'}
label={calendar.string.ModeWeek}
on:click={() => {
mode = CalendarMode.Week
}}
/>
<Button
size={'small'}
label={calendar.string.ModeMonth}
on:click={() => {
mode = CalendarMode.Month
}}
/>
<Button
size={'small'}
label={calendar.string.ModeYear}
on:click={() => {
mode = CalendarMode.Year
}}
/>
<div class="flex ml-4 gap-2">
<div class="flex-between mb-4 px-10 flex-no-shrink clear-mins">
<div class="flex-row-center gap-2">
<Button
icon={IconBack}
size={'small'}
kind={'transparent'}
on:click={() => {
inc(-1)
}}
/>
<Button
size={'small'}
label={calendar.string.Today}
kind={'transparent'}
on:click={() => {
inc(0)
}}
/>
<Button
icon={IconForward}
size={'small'}
kind={'transparent'}
on:click={() => {
inc(1)
}}
/>
</div>
<div class="flex-row-center gap-2 clear-mins">
<Button
label={calendar.string.ModeDay}
on:click={() => {
mode = CalendarMode.Day
}}
/>
<Button
label={calendar.string.ModeWeek}
on:click={() => {
mode = CalendarMode.Week
}}
/>
<Button
label={calendar.string.ModeMonth}
on:click={() => {
mode = CalendarMode.Month
}}
/>
<Button
label={calendar.string.ModeYear}
on:click={() => {
mode = CalendarMode.Year
}}
/>
</div>
</div>
<div class="ml-10 mr-6 h-full clear-mins">
<Scroller
padding={'0 2.25rem'}
fade={mode === CalendarMode.Week || mode === CalendarMode.Day ? { multipler: { top: 3, bottom: 0 } } : defaultSP}
>
{#if mode === CalendarMode.Year}
<Scroller>
<YearCalendar
{mondayStart}
cellHeight={'2.5rem'}
bind:selectedDate
bind:currentDate
on:change={(e) => {
currentDate = e.detail
if (areDatesEqual(selectedDate, currentDate)) {
mode = CalendarMode.Month
}
selectedDate = e.detail
}}
>
<svelte:fragment slot="cell" let:date let:today let:selected let:wrongMonth>
<Day
events={findEvents(objects, date)}
{date}
{_class}
{baseMenuClass}
{options}
{config}
{today}
{selected}
{wrongMonth}
{query}
/>
</svelte:fragment>
</YearCalendar>
</Scroller>
<YearCalendar
{mondayStart}
cellHeight={'2.5rem'}
bind:selectedDate
bind:currentDate
on:change={(e) => {
currentDate = e.detail
if (areDatesEqual(selectedDate, currentDate)) {
mode = CalendarMode.Month
}
selectedDate = e.detail
}}
>
<svelte:fragment slot="cell" let:date let:today let:selected let:wrongMonth>
<Day
events={findEvents(objects, date)}
{date}
{_class}
{baseMenuClass}
{options}
{config}
{today}
{selected}
{wrongMonth}
{query}
/>
</svelte:fragment>
</YearCalendar>
{:else if mode === CalendarMode.Month}
<div class="flex flex-grow">
<MonthCalendar {mondayStart} cellHeight={'8.5rem'} bind:selectedDate bind:currentDate>
<svelte:fragment slot="cell" let:date let:today let:selected let:wrongMonth>
<Day
events={findEvents(objects, date)}
{date}
size={'huge'}
{_class}
{baseMenuClass}
{options}
{config}
{today}
{selected}
{wrongMonth}
{query}
on:select={(e) => {
currentDate = e.detail
if (areDatesEqual(selectedDate, currentDate)) {
mode = CalendarMode.Day
}
selectedDate = e.detail
}}
on:create={(e) => {
showCreateDialog(e.detail, false)
}}
/>
</svelte:fragment>
</MonthCalendar>
</div>
<MonthCalendar {mondayStart} cellHeight={'8.5rem'} bind:selectedDate bind:currentDate>
<svelte:fragment slot="cell" let:date let:today let:selected let:wrongMonth>
<Day
events={findEvents(objects, date)}
{date}
size={'huge'}
{_class}
{baseMenuClass}
{options}
{config}
{today}
{selected}
{wrongMonth}
{query}
on:select={(e) => {
currentDate = e.detail
if (areDatesEqual(selectedDate, currentDate)) {
mode = CalendarMode.Day
}
selectedDate = e.detail
}}
on:create={(e) => {
showCreateDialog(e.detail, false)
}}
/>
</svelte:fragment>
</MonthCalendar>
{:else if mode === CalendarMode.Week}
<Scroller>
<WeekCalendar
{mondayStart}
cellHeight={'4.5rem'}
bind:selectedDate
bind:currentDate
on:select={(e) => {
currentDate = e.detail
selectedDate = e.detail
mode = CalendarMode.Day
}}
>
<svelte:fragment slot="cell" let:date>
<Hour
events={findEvents(objects, date, true)}
{date}
bind:indexes
on:create={(e) => {
showCreateDialog(e.detail, true)
}}
/>
</svelte:fragment>
</WeekCalendar>
</Scroller>
<WeekCalendar
{mondayStart}
cellHeight={'4.5rem'}
bind:selectedDate
bind:currentDate
on:select={(e) => {
currentDate = e.detail
selectedDate = e.detail
mode = CalendarMode.Day
}}
>
<svelte:fragment slot="cell" let:date>
<Hour
events={findEvents(objects, date, true)}
{date}
bind:indexes
on:create={(e) => {
showCreateDialog(e.detail, true)
}}
/>
</svelte:fragment>
</WeekCalendar>
{:else if mode === CalendarMode.Day}
<Scroller>
<WeekCalendar
{mondayStart}
displayedDaysCount={1}
startFromWeekStart={false}
cellHeight={'4.5rem'}
bind:selectedDate
bind:currentDate
>
<svelte:fragment slot="cell" let:date>
<Hour
events={findEvents(objects, date, true)}
{date}
bind:indexes
wide
on:create={(e) => {
showCreateDialog(e.detail, true)
}}
/>
</svelte:fragment>
</WeekCalendar>
</Scroller>
<WeekCalendar
{mondayStart}
displayedDaysCount={1}
startFromWeekStart={false}
cellHeight={'4.5rem'}
bind:selectedDate
bind:currentDate
>
<svelte:fragment slot="cell" let:date>
<Hour
events={findEvents(objects, date, true)}
{date}
bind:indexes
wide
on:create={(e) => {
showCreateDialog(e.detail, true)
}}
/>
</svelte:fragment>
</WeekCalendar>
{/if}
</div>
</Scroller>
<div class="min-h-4 max-h-4 h-4 flex-no-shrink" />

View File

@ -21,13 +21,14 @@
AnyComponent,
Button,
Component,
Icon,
IconAdd,
ActionIcon,
Label,
Loading,
SearchEdit,
showPopup,
TabList
TabList,
IconMoreH,
IconAdd
} from '@hcengineering/ui'
import view, { Viewlet, ViewletPreference } from '@hcengineering/view'
import {
@ -38,7 +39,7 @@
viewOptionStore
} from '@hcengineering/view-resources'
import calendar from '../plugin'
import { deviceOptionsStore as deviceInfo } from '@hcengineering/ui'
// import { deviceOptionsStore as deviceInfo } from '@hcengineering/ui'
export let _class: Ref<Class<Event>> = calendar.class.Event
export let space: Ref<Space> | undefined = undefined
@ -107,45 +108,42 @@
}
})
$: twoRows = $deviceInfo.twoRows
// $: twoRows = $deviceInfo.twoRows
$: viewOptions = getViewOptions(selectedViewlet, $viewOptionStore)
</script>
<div class="ac-header withSettings" class:full={!twoRows} class:mini={twoRows}>
<div class:ac-header-full={!twoRows} class:flex-between={twoRows}>
<div class="ac-header__wrap-title mr-3">
<div class="ac-header__icon"><Icon icon={viewIcon} size={'small'} /></div>
<span class="ac-header__title"><Label label={viewLabel} /></span>
<div class="ml-4"><FilterButton {_class} /></div>
</div>
<SearchEdit
bind:value={search}
on:change={() => {
updateResultQuery(search)
}}
/>
<div class="ac-header full divide">
<div class="ac-header__wrap-title mr-3">
<span class="ac-header__title"><Label label={viewLabel} /></span>
</div>
<div class="ac-header-full" class:secondRow={twoRows}>
<Button icon={IconAdd} label={createLabel} kind={'primary'} size={'small'} on:click={showCreateDialog} />
<div class="ac-header-full medium-gap mb-1">
{#if viewlets.length > 1}
<TabList
items={viewslist}
multiselect={false}
selected={selectedViewlet?._id}
kind={'secondary'}
size={'small'}
on:select={(result) => {
if (result.detail !== undefined) selectedViewlet = viewlets.find((vl) => vl._id === result.detail.id)
}}
/>
{/if}
<ViewletSettingButton bind:viewOptions viewlet={selectedViewlet} />
<Button icon={IconAdd} label={createLabel} kind={'primary'} on:click={showCreateDialog} />
</div>
</div>
<div class="ac-header full divide search-start">
<div class="ac-header-full small-gap">
<SearchEdit bind:value={search} on:change={() => updateResultQuery(search)} />
<ActionIcon icon={IconMoreH} size={'small'} />
<div class="buttons-divider" />
<FilterButton {_class} />
</div>
<div class="ac-header-full medium-gap">
<ViewletSettingButton bind:viewOptions viewlet={selectedViewlet} />
<ActionIcon icon={IconMoreH} size={'small'} />
</div>
</div>
{#if selectedViewlet?.$lookup?.descriptor?.component}
{#if loading}
<Loading />

View File

@ -198,6 +198,7 @@
</script>
<div class="flex-col vScroll" bind:this={div} on:scroll={handleScroll}>
<div class="grower" />
{#if showFixed}
<div class="ml-2 pr-2 fixed">
<JumpToDateSelector {selectedDate} fixed on:jumpToDate={handleJumpToDate} />
@ -224,6 +225,10 @@
</div>
<style lang="scss">
.grower {
flex-grow: 10;
flex-shrink: 5;
}
.fixed {
position: absolute;
align-self: center;

View File

@ -38,7 +38,7 @@
}
</script>
<div class="ac-header divide full">
<div class="ac-header divide full caption-height">
{#if channel}
<Header
icon={channel.private ? Lock : classIcon(client, channel._class)}

View File

@ -48,7 +48,7 @@
</script>
<div class="flex-col h-full">
<div class="ac-header divide full">
<div class="ac-header divide full caption-height">
<Header icon={workbench.icon.Search} intlLabel={plugin.string.ChunterBrowser} />
</div>
<div class="h-full browser">

View File

@ -54,10 +54,11 @@
}
</script>
<div class="ac-header divide full">
<div class="ac-header divide full caption-height">
{#if dm}
{#await getDmName(client, dm) then name}
{#await getEmpolyeeIds() then empolyeeIds}
<!-- svelte-ignore a11y-click-events-have-key-events -->
<div class="ac-header__wrap-title" on:click={onSpaceEdit}>
<div class="ac-header__icon">
<CombineAvatars _class={contact.class.Employee} items={empolyeeIds} size={'x-small'} />

View File

@ -28,6 +28,7 @@
</script>
<div class="ac-header__wrap-description">
<!-- svelte-ignore a11y-click-events-have-key-events -->
<div class="ac-header__wrap-title" on:click>
{#if icon}<div class="ac-header__icon"><Icon {icon} size={'small'} /></div>{/if}
{#if label}

View File

@ -15,11 +15,11 @@
$: isCurrentYear = time ? new Date(time).getFullYear() === new Date().getFullYear() : undefined
</script>
<div id={fixed ? '' : time?.toString()} class="flex justify-center mt-5 pr-1 dateSelector">
<div id={fixed ? '' : time?.toString()} class="flex-center clear-mins dateSelector">
<!-- svelte-ignore a11y-click-events-have-key-events -->
<div
bind:this={div}
class="mb-1 p-1 border-radius-2 over-underline dateSelectorButton"
class="border-radius-4 over-underline dateSelectorButton clear-mins"
on:click={() => {
showPopup(DateRangePopup, {}, div, (v) => {
if (v) {
@ -30,28 +30,37 @@
}}
>
{#if time}
<div>
{new Date(time).toLocaleDateString('default', {
weekday: 'short',
month: 'long',
day: 'numeric',
year: isCurrentYear ? undefined : 'numeric'
})}
</div>
{new Date(time).toLocaleDateString('default', {
weekday: 'short',
month: 'long',
day: 'numeric',
year: isCurrentYear ? undefined : 'numeric'
})}
{/if}
</div>
</div>
<style lang="scss">
.dateSelector {
&:not(:first-child) {
border-top: 1px solid var(--divider-color);
position: relative;
flex-shrink: 0;
margin: 0.25rem 0;
&:not(:first-child)::after {
position: absolute;
content: '';
top: 50%;
left: 0;
width: 100%;
height: 1px;
background-color: var(--theme-divider-color);
}
.dateSelectorButton {
padding: 0.25rem 0.5rem;
height: max-content;
background-color: var(--theme-list-row-color);
border: 1px solid var(--theme-divider-color);
z-index: 10;
}
}
.dateSelectorButton {
margin-top: -1rem;
background-color: var(--body-color);
border: 1px solid var(--divider-color);
}
</style>

View File

@ -221,10 +221,10 @@
let loading = false
</script>
<div class="container" class:highlighted={isHighlighted} id={message._id}>
<div class="container clear-mins" class:highlighted={isHighlighted} id={message._id}>
<div class="avatar"><Avatar size={'medium'} avatar={employee?.avatar} /></div>
<div class="message">
<div class="header">
<div class="message clear-mins">
<div class="header clear-mins">
{#if employee}
<EmployeePresenter value={employee} shouldShowAvatar={false} inline />
{/if}
@ -270,7 +270,7 @@
</div>
{/if}
</div>
<div class="buttons" class:menuShowed>
<div class="buttons clear-mins" class:menuShowed>
<div class="tool">
<ActionIcon
icon={IconMoreH}
@ -305,6 +305,7 @@
.container {
position: relative;
display: flex;
flex-shrink: 0;
padding: 0.5rem 2rem;
&.highlighted {
@ -327,7 +328,7 @@
font-weight: 500;
font-size: 1rem;
line-height: 150%;
color: var(--caption-color);
color: var(--theme-caption-color);
margin-bottom: 0.25rem;
span {
@ -379,7 +380,7 @@
}
&:hover {
background-color: var(--board-card-bg-hover);
background-color: var(--highlight-hover);
}
}
</style>

View File

@ -85,7 +85,7 @@
}
</script>
<div class="ac-header full divide">
<div class="ac-header full divide caption-height">
<div class="ac-header__wrap-title">
<span class="ac-header__title"><Label label={chunter.string.SavedItems} /></span>
</div>
@ -93,7 +93,8 @@
<Scroller>
{#if savedMessages.length > 0 || savedAttachments.length > 0}
{#each savedMessages as message}
<div on:click={() => openMessageFromSpecial(message)}>
<!-- svelte-ignore a11y-click-events-have-key-events -->
<div class="clear-mins flex-no-shrink" on:click={() => openMessageFromSpecial(message)}>
<Message
{message}
on:openThread
@ -105,7 +106,8 @@
</div>
{/each}
{#each savedAttachments as att}
<div class="attachmentContainer" on:click={() => openAttachment(att)}>
<!-- svelte-ignore a11y-click-events-have-key-events -->
<div class="attachmentContainer flex-no-shrink clear-mins" on:click={() => openAttachment(att)}>
<AttachmentPreview value={att} isSaved={true} />
<div class="label">
<Label

View File

@ -163,7 +163,7 @@
let loading = false
</script>
<div class="ml-8 mt-4">
<div class="flex-col ml-8 mt-4 flex-no-shrink">
{#if parent}
{#await getChannel(parent.space) then channel}
{#if channel?._class === chunter.class.Channel}
@ -178,13 +178,13 @@
{/await}
{/if}
</div>
<div class="flex-col content">
<div class="flex-col content flex-no-shrink">
{#if parent}
<MsgView message={parent} thread {savedAttachmentsIds} />
{#if total > comments.length}
<!-- svelte-ignore a11y-click-events-have-key-events -->
<div
class="label pb-2 pt-2 pl-8 over-underline"
class="label pb-2 pt-2 pl-8 over-underline clear-mins"
on:click={() => {
showAll = true
}}
@ -195,7 +195,7 @@
{#each comments as comment (comment._id)}
<MsgView message={comment} thread {savedAttachmentsIds} />
{/each}
<div class="mr-4 ml-4 mb-4 mt-2">
<div class="mr-4 ml-4 pb-4 mt-2 clear-mins">
<AttachmentRefInput
space={parent.space}
_class={chunter.class.ThreadMessage}
@ -206,17 +206,19 @@
</div>
{/if}
</div>
<div class="min-h-4 max-h-4 h-4 flex-no-shrink" />
<style lang="scss">
.content {
overflow: hidden;
margin: 1rem 1rem 0px;
background-color: var(--board-bg-color);
border: 1px solid var(--divider-color);
margin: 1rem 1rem 0;
padding-top: 0.5rem;
background-color: var(--theme-list-row-color);
border: 1px solid var(--theme-divider-color);
border-radius: 0.75rem;
}
.label:hover {
background-color: var(--board-card-bg-hover);
background-color: var(--theme-button-hovered);
}
</style>

View File

@ -49,19 +49,16 @@
})
</script>
<div class="ac-header full divide">
<div class="ac-header full divide caption-height">
<div class="ac-header__wrap-title">
<span class="ac-header__title"><Label label={chunter.string.Threads} /></span>
</div>
</div>
<Scroller>
{#each threads as thread (thread)}
<div class="item"><Thread _id={thread} {savedAttachmentsIds} /></div>
{#each threads as thread, i (thread)}
<Thread _id={thread} {savedAttachmentsIds} />
{#if i < threads.length - 1}
<div class="antiDivider" />
{/if}
{/each}
</Scroller>
<style lang="scss">
.item + .item {
margin-top: 3rem;
}
</style>

View File

@ -16,7 +16,7 @@
"SelectFolder": "Select folder",
"OrganizationsFolder": "Companies folder",
"PersonsFolder": "Persons folder",
"ContactCreateLabel": "Contact",
"ContactCreateLabel": "Create contact",
"SearchEmployee": "Search for employee...",
"SearchPerson": "Search for person...",
"SearchOrganization": "Search for company...",

View File

@ -16,7 +16,7 @@
"SelectFolder": "Выбрать папку",
"OrganizationsFolder": "Папка с компаниями",
"PersonsFolder": "Папка с людьми",
"ContactCreateLabel": "Контакт",
"ContactCreateLabel": "Создать контакт",
"SearchEmployee": "Поиск сотрудника...",
"SearchPerson": "Поиск персоны...",
"SearchOrganization": "Поиск компании...",

View File

@ -126,6 +126,10 @@
width: 1.5rem; // 24
height: 1.5rem;
}
.ava-smaller {
width: 1.75rem; // 32
height: 1.75rem;
}
.ava-small {
width: 2rem; // 32
height: 2rem;
@ -157,6 +161,8 @@
.ava-inline.no-img,
.ava-x-small .ava-mask,
.ava-x-small.no-img,
.ava-smaller .ava-mask,
.ava-smaller.no-img,
.ava-small .ava-mask,
.ava-small.no-img,
.ava-medium .ava-mask,

View File

@ -16,7 +16,7 @@
<script lang="ts">
import { Doc, DocumentQuery } from '@hcengineering/core'
import { createQuery, getClient } from '@hcengineering/presentation'
import { Button, Icon, IconAdd, Label, Loading, SearchEdit, showPopup } from '@hcengineering/ui'
import { Button, Label, Loading, SearchEdit, showPopup, IconMoreH, ActionIcon } from '@hcengineering/ui'
import view, { Viewlet, ViewletPreference } from '@hcengineering/view'
import {
ActionContext,
@ -30,7 +30,7 @@
} from '@hcengineering/view-resources'
import contact from '../plugin'
import CreateContact from './CreateContact.svelte'
import { deviceOptionsStore as deviceInfo } from '@hcengineering/ui'
// import { deviceOptionsStore as deviceInfo } from '@hcengineering/ui'
let search = ''
let searchQuery: DocumentQuery<Doc> = {}
@ -74,7 +74,7 @@
showPopup(CreateContact, { space: contact.space.Contacts, targetElement: ev.target }, ev.target as HTMLElement)
}
$: twoRows = $deviceInfo.twoRows
// $: twoRows = $deviceInfo.twoRows
$: viewOptions = getViewOptions(viewlet, $viewOptionStore)
</script>
@ -85,30 +85,29 @@
}}
/>
<div class="antiPanel-component">
<div class="ac-header withSettings" class:full={!twoRows} class:mini={twoRows}>
<div class:ac-header-full={!twoRows} class:flex-between={twoRows}>
<div class="ac-header__wrap-title mr-3">
<div class="ac-header__icon"><Icon icon={contact.icon.Person} size={'small'} /></div>
<span class="ac-header__title"><Label label={contact.string.Contacts} /></span>
<div class="ml-4"><FilterButton _class={contact.class.Contact} /></div>
</div>
<SearchEdit
bind:value={search}
on:change={() => {
updateResultQuery(search)
}}
/>
<div class="ac-header full divide">
<div class="ac-header__wrap-title mr-3">
<span class="ac-header__title"><Label label={contact.string.Contacts} /></span>
</div>
<div class="ac-header-full" class:secondRow={twoRows}>
<div class="mb-1 clear-mins">
<Button
icon={IconAdd}
label={contact.string.ContactCreateLabel}
kind={'primary'}
size={'small'}
size={'medium'}
on:click={(ev) => showCreateDialog(ev)}
/>
</div>
</div>
<div class="ac-header full divide search-start">
<div class="ac-header-full small-gap">
<SearchEdit bind:value={search} on:change={() => updateResultQuery(search)} />
<ActionIcon icon={IconMoreH} size={'small'} />
<div class="buttons-divider" />
<FilterButton _class={contact.class.Contact} />
</div>
<div class="ac-header-full medium-gap">
<ViewletSettingButton bind:viewOptions {viewlet} />
<ActionIcon icon={IconMoreH} size={'small'} />
</div>
</div>

View File

@ -12,6 +12,8 @@
export let kind: ButtonKind = 'link'
export let tooltipLabels: PersonLabelTooltip | undefined = undefined
export let onChange: ((value: Ref<Employee>) => void) | undefined = undefined
export let colorInherit: boolean = false
export let accent: boolean = false
export let inline = false
$: employee = value ? $employeeByIdStore.get(value) : undefined
@ -47,7 +49,9 @@
shouldShowPlaceholder
defaultName={contact.string.NotSpecified}
shouldShowName={kind !== 'list'}
avatarSize={kind === 'list-header' ? 'small' : 'x-small'}
avatarSize={kind === 'list-header' ? 'smaller' : 'x-small'}
disableClick
{colorInherit}
{accent}
/>
{/if}

View File

@ -2,6 +2,7 @@
import { Employee } from '@hcengineering/contact'
import { WithLookup } from '@hcengineering/core'
import { IntlString } from '@hcengineering/platform'
import { IconSize } from '@hcengineering/ui'
import { PersonLabelTooltip } from '..'
import PersonPresenter from '../components/PersonPresenter.svelte'
import contact from '../plugin'
@ -12,10 +13,12 @@
export let shouldShowName: boolean = true
export let shouldShowPlaceholder = false
export let onEmployeeEdit: ((event: MouseEvent) => void) | undefined = undefined
export let avatarSize: 'inline' | 'tiny' | 'x-small' | 'small' | 'medium' | 'large' | 'x-large' = 'x-small'
export let avatarSize: IconSize = 'x-small'
export let isInteractive = true
export let inline = false
export let disableClick = false
export let colorInherit: boolean = false
export let accent: boolean = false
export let defaultName: IntlString | undefined = undefined
export let element: HTMLElement | undefined = undefined
</script>
@ -31,6 +34,8 @@
{shouldShowPlaceholder}
isInteractive={isInteractive && !disableClick}
{inline}
{colorInherit}
{accent}
{defaultName}
statusLabel={value?.active === false && shouldShowName ? contact.string.Inactive : undefined}
/>

View File

@ -9,17 +9,19 @@
export let kind: ButtonKind = 'link'
export let tooltipLabels: PersonLabelTooltip | undefined = undefined
export let onChange: ((value: Ref<Employee>) => void) | undefined = undefined
export let colorInherit: boolean = false
export let accent: boolean = false
export let inline = false
</script>
{#if Array.isArray(value)}
<div class="inline-content">
{#each value as employee}
<EmployeeAttributePresenter value={employee} {kind} {tooltipLabels} {onChange} {inline} />
<EmployeeAttributePresenter value={employee} {kind} {tooltipLabels} {onChange} {inline} {colorInherit} {accent} />
{/each}
</div>
{:else}
<EmployeeAttributePresenter {value} {kind} {tooltipLabels} {onChange} {inline} />
<EmployeeAttributePresenter {value} {kind} {tooltipLabels} {onChange} {inline} {colorInherit} {accent} />
{/if}
<style lang="scss">

View File

@ -16,6 +16,7 @@
import { Employee, getName, Person } from '@hcengineering/contact'
import { IntlString } from '@hcengineering/platform'
import { Label, LabelAndProps, tooltip } from '@hcengineering/ui'
import type { IconSize } from '@hcengineering/ui'
import { DocNavLink } from '@hcengineering/view-resources'
import Avatar from './Avatar.svelte'
@ -27,11 +28,13 @@
export let shouldShowPlaceholder = false
export let defaultName: IntlString | undefined = undefined
export let statusLabel: IntlString | undefined = undefined
export let avatarSize: 'inline' | 'tiny' | 'x-small' | 'small' | 'medium' | 'large' | 'x-large' = 'x-small'
export let avatarSize: IconSize = 'x-small'
export let onEdit: ((event: MouseEvent) => void) | undefined = undefined
export let showTooltip: LabelAndProps | undefined = undefined
export let enlargedText = false
export let element: HTMLElement | undefined = undefined
export let colorInherit: boolean = false
export let accent: boolean = false
const onEditClick = (evt: MouseEvent) => {
if (isInteractive) {
@ -41,7 +44,7 @@
</script>
{#if value}
<DocNavLink object={value} onClick={onEdit} disableClick={!isInteractive} {inline}>
<DocNavLink object={value} onClick={onEdit} disableClick={!isInteractive} {inline} {colorInherit}>
<span
use:tooltip={showTooltip}
class="contentPresenter"
@ -58,7 +61,7 @@
</span>
{/if}
{#if shouldShowName}
<span class="eContentPresenterLabel">{getName(value)}</span>
<span class="eContentPresenterLabel" class:colorInherit>{getName(value)}</span>
{/if}
</span>
</DocNavLink>
@ -80,7 +83,7 @@
</span>
{/if}
{#if shouldShowName && defaultName}
<span class="eContentPresenterLabel">
<span class="eContentPresenterLabel" class:colorInherit>
<Label label={defaultName} />
</span>
{#if statusLabel}
@ -109,7 +112,7 @@
min-width: 0;
font-weight: 500;
text-align: left;
color: var(--accent-color);
color: var(--theme-caption-color);
overflow: hidden;
visibility: visible;
@ -119,14 +122,18 @@
-webkit-line-clamp: 2;
line-clamp: 2;
user-select: none;
&.colorInherit {
color: inherit;
}
}
&:hover {
.eContentPresenterIcon {
color: var(--caption-color);
color: var(--theme-caption-color);
}
.eContentPresenterLabel {
text-decoration: underline;
color: var(--caption-color);
color: var(--theme-caption-color);
}
}
}

View File

@ -15,7 +15,7 @@
<script lang="ts">
import { getName, Person } from '@hcengineering/contact'
import { getEmbeddedLabel, IntlString } from '@hcengineering/platform'
import { LabelAndProps } from '@hcengineering/ui'
import type { LabelAndProps, IconSize } from '@hcengineering/ui'
import { PersonLabelTooltip } from '..'
import PersonContent from './PersonContent.svelte'
@ -29,9 +29,11 @@
export let defaultName: IntlString | undefined = undefined
export let statusLabel: IntlString | undefined = undefined
export let tooltipLabels: PersonLabelTooltip | undefined = undefined
export let avatarSize: 'inline' | 'tiny' | 'x-small' | 'small' | 'medium' | 'large' | 'x-large' = 'x-small'
export let avatarSize: IconSize = 'x-small'
export let onEdit: ((event: MouseEvent) => void) | undefined = undefined
export let element: HTMLElement | undefined = undefined
export let colorInherit: boolean = false
export let accent: boolean = false
function getTooltip (
tooltipLabels: PersonLabelTooltip | undefined,
@ -73,6 +75,8 @@
{shouldShowPlaceholder}
{enlargedText}
{statusLabel}
{colorInherit}
{accent}
bind:element
/>
{/if}

View File

@ -51,6 +51,10 @@
width: 1rem;
height: 1rem;
}
.smaller {
width: 1.125rem;
height: 1.125rem;
}
.small {
width: 1.25rem;
height: 1.25rem;

View File

@ -18,7 +18,7 @@
import { Doc, DocumentQuery } from '@hcengineering/core'
import { Document } from '@hcengineering/document'
import { createQuery, getClient } from '@hcengineering/presentation'
import { deviceOptionsStore as deviceInfo, Icon, Label, Loading, SearchEdit } from '@hcengineering/ui'
import { ActionIcon, IconMoreH, Label, Loading, SearchEdit } from '@hcengineering/ui'
import view, { Viewlet, ViewletPreference } from '@hcengineering/view'
import {
ActionContext,
@ -70,8 +70,8 @@
}
})
let twoRows: boolean
$: twoRows = $deviceInfo.docWidth <= 680
// let twoRows: boolean
// $: twoRows = $deviceInfo.docWidth <= 680
$: viewOptions = getViewOptions(viewlet, $viewOptionStore)
</script>
@ -82,23 +82,21 @@
}}
/>
<div class="antiPanel-component">
<div class="ac-header withSettings" class:full={!twoRows} class:mini={twoRows}>
<div class:ac-header-full={!twoRows} class:flex-between={twoRows}>
<div class="ac-header__wrap-title mr-3">
<div class="ac-header__icon"><Icon icon={document.icon.Document} size={'small'} /></div>
<span class="ac-header__title"><Label label={document.string.Documents} /></span>
<div class="ml-4"><FilterButton _class={document.class.Document} /></div>
</div>
<SearchEdit
bind:value={search}
on:change={() => {
updateResultQuery(search, query)
}}
/>
<div class="ac-header full divide caption-height">
<div class="ac-header__wrap-title mr-3">
<span class="ac-header__title"><Label label={document.string.Documents} /></span>
</div>
<div class="ac-header-full" class:secondRow={twoRows}>
</div>
<div class="ac-header full divide search-start">
<div class="ac-header-full small-gap">
<SearchEdit bind:value={search} on:change={() => updateResultQuery(search, query)} />
<ActionIcon icon={IconMoreH} size={'small'} />
<div class="buttons-divider" />
<FilterButton _class={document.class.Document} />
</div>
<div class="ac-header-full medium-gap">
<ViewletSettingButton bind:viewOptions {viewlet} />
<ActionIcon icon={IconMoreH} size={'small'} />
</div>
</div>

View File

@ -97,82 +97,82 @@
$: dragging = value._id === dragOver?._id && dragPersonId !== undefined
</script>
<div class="flex-center w-full px-4">
<!-- svelte-ignore a11y-click-events-have-key-events -->
<!-- svelte-ignore a11y-click-events-have-key-events -->
<div
class="w-full mt-2 mb-2 container flex"
class:cursor-pointer={currentDescendants.length}
on:click|stopPropagation={edit}
on:contextmenu|preventDefault={showMenu}
class:dragging
>
<div
class="w-full mt-2 mb-2 container flex"
class:cursor-pointer={currentDescendants.length}
on:click|stopPropagation={edit}
on:contextmenu|preventDefault={showMenu}
class:dragging
>
<div
class="flex-between pt-4 pb-4 pr-4 pl-2 w-full"
on:dragover|preventDefault|stopPropagation={(evt) => {
dragOver = value
}}
on:dragend|preventDefault|stopPropagation={() => {
class="flex-between pt-4 pb-4 pr-4 pl-2 w-full"
on:dragover|preventDefault|stopPropagation={(evt) => {
dragOver = value
}}
on:dragend|preventDefault|stopPropagation={() => {
dragPerson = undefined
closeTooltip()
}}
on:drop|preventDefault={(itm) => {
closeTooltip()
addMember(client, dragPerson, value).then(() => {
dragPerson = undefined
closeTooltip()
}}
on:drop|preventDefault={(itm) => {
closeTooltip()
addMember(client, dragPerson, value).then(() => {
dragPerson = undefined
dragOver = undefined
})
}}
>
<div class="flex-center">
<div class="mr-2">
<Button icon={IconAdd} kind={'list'} on:click={createChild} />
</div>
<Avatar size={'medium'} avatar={value.avatar} icon={hr.icon.Department} />
<div class="flex-row ml-2 mr-4">
<div class="fs-title">
{value.name}
</div>
<Label label={hr.string.MemberCount} params={{ count: value.members.length }} />
</div>
<PersonsPresenter value={values} bind:dragPerson showDragPerson={dragging} />
dragOver = undefined
})
}}
>
<div class="flex-center">
<div class="mr-2">
<Button icon={IconAdd} kind={'list'} on:click={createChild} />
</div>
<div class="flex-center mr-2">
<div class="mr-2">
<EmployeePresenter
value={value.$lookup?.teamLead}
avatarSize={'small'}
shouldShowAvatar
shouldShowPlaceholder
shouldShowName={false}
tooltipLabels={{
personLabel: hr.string.TeamLeadTooltip,
placeholderLabel: hr.string.AssignLead
}}
onEmployeeEdit={openLeadEditor}
/>
<Avatar size={'medium'} avatar={value.avatar} icon={hr.icon.Department} />
<div class="flex-row ml-2 mr-4">
<div class="fs-title">
{value.name}
</div>
<Label label={hr.string.MemberCount} params={{ count: value.members.length }} />
</div>
<PersonsPresenter value={values} bind:dragPerson showDragPerson={dragging} />
</div>
<div class="flex-center mr-2">
<div class="mr-2">
<EmployeePresenter
value={value.$lookup?.teamLead}
avatarSize={'small'}
shouldShowAvatar
shouldShowPlaceholder
shouldShowName={false}
tooltipLabels={{
personLabel: hr.string.TeamLeadTooltip,
placeholderLabel: hr.string.AssignLead
}}
onEmployeeEdit={openLeadEditor}
/>
</div>
</div>
</div>
</div>
<div class="ml-8">
{#each currentDescendants as nested}
<DepartmentCard value={nested} {descendants} {allEmployees} bind:dragPerson bind:dragOver />
{/each}
</div>
{#if currentDescendants.length > 0}
<div class="flex-col ml-8">
{#each currentDescendants as nested}
<DepartmentCard value={nested} {descendants} {allEmployees} bind:dragPerson bind:dragOver />
{/each}
</div>
{/if}
<style lang="scss">
.container {
background-color: var(--noborder-bg-color);
border: 1px solid transparent;
background-color: var(--theme-button-enabled);
border: 1px solid var(--theme-button-border);
border-radius: 0.5rem;
&:hover {
background-color: var(--noborder-bg-hover);
background-color: var(--theme-button-hovered);
cursor: pointer;
}
&.dragging {
border-color: var(--divider-color);
border-color: var(--primary-button-focused-border);
}
}
</style>

View File

@ -20,7 +20,8 @@
import { createQuery, getClient, SpaceSelector } from '@hcengineering/presentation'
import {
Button,
Icon,
ActionIcon,
IconMoreH,
IconBack,
IconForward,
Label,
@ -105,97 +106,80 @@
]
</script>
<div class="ac-header divide {twoRows ? 'flex-col-reverse' : 'full'} withSettings">
<div class="ac-header__wrap-title" class:mt-2={twoRows}>
{#if !twoRows}
<div class="ac-header__icon"><Icon icon={calendar.icon.Calendar} size={'small'} /></div>
<span class="ac-header__title"><Label label={hr.string.Schedule} /></span>
{:else}
<div class="fs-title mr-4 flex-row-center flex-grow firstLetter">
{#if mode === CalendarMode.Month}
<span class="mr-2 overflow-label">{getMonthName(currentDate)}</span>
{/if}
{currentDate.getFullYear()}
</div>
{/if}
<div class="flex-row-center gap-2 flex-no-shrink" class:ml-6={!twoRows}>
<TabList
items={[
{ id: 'ModeMonth', labelIntl: calendar.string.ModeMonth },
{ id: 'ModeYear', labelIntl: calendar.string.ModeYear }
]}
multiselect={false}
size={'small'}
on:select={handleSelect}
/>
<div class="buttons-divider" />
<Button
icon={IconBack}
size={'small'}
kind={'link-bordered'}
on:click={() => {
inc(-1)
}}
/>
<Button
size={'small'}
label={calendar.string.Today}
kind={'link-bordered'}
on:click={() => {
currentDate = new Date()
}}
/>
<Button
icon={IconForward}
size={'small'}
kind={'link-bordered'}
on:click={() => {
inc(1)
}}
/>
</div>
{#if !twoRows}
<div class="fs-title ml-4 flex-row-center firstLetter">
{#if mode === CalendarMode.Month}
<span class="overflow-label mr-2">{getMonthName(currentDate)}</span>
{/if}
{currentDate.getFullYear()}
</div>
{/if}
<div class="ac-header full divide caption-height">
<div class="ac-header__wrap-title mr-3">
<span class="ac-header__title"><Label label={hr.string.Schedule} /></span>
</div>
<div class="ac-header__wrap-title {twoRows ? 'mt-1' : 'ml-4'}">
{#if twoRows}
<div class="ac-header__icon flex-center"><Icon icon={calendar.icon.Calendar} size={'small'} /></div>
<span class="ac-header__title" class:flex-grow={twoRows}><Label label={hr.string.Schedule} /></span>
{/if}
<div class="flex-row-center gap-2">
{#if mode === CalendarMode.Month}
<TabList
items={viewslist}
multiselect={false}
selected={display}
kind={'secondary'}
size={'small'}
on:select={(result) => {
if (result.detail !== undefined) display = result.detail.id
}}
/>
{/if}
<SearchEdit
bind:value={search}
on:change={() => {
updateResultQuery(search)
<div class="ac-header-full medium-gap mb-1">
{#if mode === CalendarMode.Month}
<TabList
items={viewslist}
multiselect={false}
selected={display}
on:select={(result) => {
if (result.detail !== undefined) display = result.detail.id
}}
/>
<SpaceSelector
_class={hr.class.Department}
label={hr.string.Department}
bind:space={department}
kind={'secondary'}
/>
{/if}
<SpaceSelector
_class={hr.class.Department}
label={hr.string.Department}
bind:space={department}
size={'medium'}
kind={'secondary'}
/>
</div>
</div>
<div class="ac-header full divide search-start">
<div class="ac-header-full small-gap">
<SearchEdit bind:value={search} on:change={() => updateResultQuery(search)} />
<ActionIcon icon={IconMoreH} size={'small'} />
</div>
<div class="ac-header-full medium-gap">
<!-- <ViewletSettingButton bind:viewOptions {viewlet} /> -->
<!-- <ActionIcon icon={IconMoreH} size={'small'} /> -->
</div>
</div>
<div class="ac-header full divide">
<div class="ac-header-full small-gap">
<Button
icon={IconBack}
kind={'transparent'}
on:click={() => {
inc(-1)
}}
/>
<Button
label={calendar.string.Today}
kind={'transparent'}
on:click={() => {
currentDate = new Date()
}}
/>
<Button
icon={IconForward}
kind={'transparent'}
on:click={() => {
inc(1)
}}
/>
<div class="buttons-divider" />
<div class="fs-title flex-row-center flex-grow firstLetter">
{#if mode === CalendarMode.Month}
<span class="mr-2 overflow-label">{getMonthName(currentDate)}</span>
{/if}
{currentDate.getFullYear()}
</div>
</div>
<TabList
items={[
{ id: 'ModeMonth', labelIntl: calendar.string.ModeMonth },
{ id: 'ModeYear', labelIntl: calendar.string.ModeYear }
]}
multiselect={false}
on:select={handleSelect}
/>
</div>
<ScheduleView

View File

@ -21,12 +21,13 @@
Button,
deviceOptionsStore as deviceInfo,
eventToHTMLElement,
Icon,
IconAdd,
ActionIcon,
IconMoreH,
Label,
Scroller,
SearchEdit,
showPopup
showPopup,
IconAdd
} from '@hcengineering/ui'
import hr from '../plugin'
import CreateDepartment from './CreateDepartment.svelte'
@ -77,32 +78,23 @@
$: twoRows = $deviceInfo.twoRows
</script>
<div class="ac-header withSettings divide" class:full={!twoRows} class:mini={twoRows}>
<div class:ac-header-full={!twoRows} class:flex-between={twoRows}>
<div class="ac-header__wrap-title mr-3">
<div class="ac-header__icon"><Icon icon={hr.icon.Structure} size={'small'} /></div>
<span class="ac-header__title"><Label label={hr.string.Structure} /></span>
</div>
<SearchEdit
bind:value={search}
on:change={() => {
updateResultQuery(search)
}}
/>
<div class="ac-header full divide caption-height">
<div class="ac-header__wrap-title mr-3">
<span class="ac-header__title"><Label label={hr.string.Structure} /></span>
</div>
<div class="ac-header-full" class:secondRow={twoRows}>
<Button
label={hr.string.CreateDepartmentLabel}
icon={IconAdd}
kind={'primary'}
size={'small'}
on:click={showCreateDialog}
/>
<div class="mb-1 clear-mins">
<Button icon={IconAdd} label={hr.string.CreateDepartmentLabel} kind={'primary'} on:click={showCreateDialog} />
</div>
</div>
<div class="ac-header full divide search-start">
<div class="ac-header-full small-gap">
<SearchEdit bind:value={search} on:change={() => updateResultQuery(search)} />
<ActionIcon icon={IconMoreH} size={'small'} />
</div>
</div>
<Scroller>
<Scroller padding={'1rem 2.5rem'}>
{#if head}
<DepartmentCard value={head} {descendants} {allEmployees} dragOver={undefined} dragPerson={undefined} />
{/if}

View File

@ -18,12 +18,12 @@
import type { Request, RequestType, Staff } from '@hcengineering/hr'
import { getEmbeddedLabel } from '@hcengineering/platform'
import { createQuery, getClient } from '@hcengineering/presentation'
import { Button, Label, Loading, Scroller, showPopup, tableSP, tableToCSV } from '@hcengineering/ui'
import { Button, Label, Loading, showPopup, tableToCSV } from '@hcengineering/ui'
import view, { BuildModelKey, Viewlet, ViewletPreference } from '@hcengineering/view'
import {
getViewOptions,
setActiveViewletId,
Table,
TableBrowser,
viewOptionStore,
ViewletSettingButton
} from '@hcengineering/view-resources'
@ -398,31 +398,28 @@
</script>
{#if departmentStaff.length}
<Scroller fade={tableSP}>
<div class="p-2">
{#if descr}
{#if loading}
<Loading />
{:else}
<div class="flex-row-center flex-reverse">
<div class="ml-1">
<ViewletSettingButton bind:viewOptions viewlet={descr} />
</div>
<Button label={getEmbeddedLabel('Export')} size={'small'} on:click={(evt) => exportTable(evt)} />
</div>
{#await createConfig(descr, preference, month) then config}
<Table
tableId={'exportableData'}
_class={hr.mixin.Staff}
query={{ _id: { $in: departmentStaff.map((it) => it._id) } }}
{config}
options={descr.options}
/>
{/await}
{/if}
{/if}
</div>
</Scroller>
{#if descr}
{#if loading}
<Loading />
{:else}
<div class="ac-header full divide">
<div class="clear-mins" />
<div class="ac-header-full small-gap">
<Button label={getEmbeddedLabel('Export')} on:click={(evt) => exportTable(evt)} />
<ViewletSettingButton bind:viewOptions viewlet={descr} />
</div>
</div>
{#await createConfig(descr, preference, month) then config}
<TableBrowser
tableId={'exportableData'}
_class={hr.mixin.Staff}
query={{ _id: { $in: departmentStaff.map((it) => it._id) } }}
{config}
options={descr.options}
/>
{/await}
{/if}
{/if}
{:else}
<div class="flex-center h-full w-full flex-grow fs-title">
<Label label={hr.string.NoEmployeesInDepartment} />

View File

@ -23,7 +23,6 @@
day as getDay,
daysInMonth,
eventToHTMLElement,
FadeOptions,
floorFractionDigits,
getWeekDayName,
isWeekend,
@ -31,8 +30,8 @@
LabelAndProps,
Scroller,
showPopup,
tableSP,
tooltip
tooltip,
deviceOptionsStore as deviceInfo
} from '@hcengineering/ui'
import hr from '../../plugin'
import { EmployeeReports, getHolidayDatesForEmployee, getRequests, getTotal, isHoliday } from '../../utils'
@ -121,14 +120,6 @@
)
}
const fade: FadeOptions = {
...tableSP,
multipler: {
...tableSP.multipler,
bottom: 3.5
}
}
function showReportInfo (employee: Staff, rTime: EmployeeReports | undefined): void {
if (rTime === undefined) {
return
@ -142,15 +133,20 @@
export let staffDepartmentMap: Map<Ref<Staff>, Department[]>
export let holidays: Map<Ref<Department>, Date[]>
let colWidth: number
$: colWidthRem = colWidth / $deviceInfo.fontSize
</script>
{#if departmentStaff.length}
<Scroller {fade} horizontal>
<Scroller fade={{ multipler: { top: 3, bottom: 0, left: colWidthRem } }} horizontal>
<table class="scroller-first-column">
<thead class="scroller-thead">
<tr class="scroller-thead__tr">
<th>
<Label label={contact.string.Employee} />
<div class="fullfill center">
<Label label={contact.string.Employee} />
</div>
</th>
<th>#</th>
<th>##</th>
@ -180,8 +176,10 @@
{@const requests = employeeRequests.get(employee._id) ?? []}
{@const rTime = timeReports.get(employee._id)}
<tr>
<td>
<EmployeePresenter value={employee} />
<td bind:clientWidth={colWidth}>
<div class="fullfill">
<EmployeePresenter value={employee} />
</div>
</td>
<td
class="flex-center p-1 whitespace-nowrap text-center"
@ -258,7 +256,9 @@
<tfoot class="scroller-tfoot">
<tr>
<td class="summary">
<Label label={hr.string.Summary} />
<div class="fullfill">
<Label label={hr.string.Summary} />
</div>
</td>
<td class="flex-center p-1 whitespace-nowrap text-center summary">
{getTotal(
@ -316,7 +316,6 @@
border: none;
&:first-child {
width: 15rem;
padding: 0.5rem;
}
}
th {

View File

@ -15,12 +15,12 @@
-->
<script lang="ts">
import { DocumentQuery } from '@hcengineering/core'
import { Button, Icon, Label, Scroller, SearchEdit, showPopup, IconAdd } from '@hcengineering/ui'
import { Button, ActionIcon, Label, Scroller, SearchEdit, showPopup, IconMoreH, IconAdd } from '@hcengineering/ui'
import type { Category } from '@hcengineering/inventory'
import inventory from '../plugin'
import CreateCategory from './CreateCategory.svelte'
import HierarchyView from './HierarchyView.svelte'
import { deviceOptionsStore as deviceInfo } from '@hcengineering/ui'
// import { deviceOptionsStore as deviceInfo } from '@hcengineering/ui'
let search = ''
let resultQuery: DocumentQuery<Category> = {}
@ -33,31 +33,23 @@
showPopup(CreateCategory, { space: inventory.space.Category }, 'top')
}
$: twoRows = $deviceInfo.twoRows
// $: twoRows = $deviceInfo.twoRows
</script>
<div class="ac-header withSettings" class:full={!twoRows} class:mini={twoRows}>
<div class:ac-header-full={!twoRows} class:flex-between={twoRows}>
<div class="ac-header__wrap-title mr-3">
<div class="ac-header__icon"><Icon icon={inventory.icon.Categories} size={'small'} /></div>
<span class="ac-header__title"><Label label={inventory.string.Categories} /></span>
</div>
<SearchEdit
bind:value={search}
on:change={() => {
updateResultQuery(search)
}}
/>
<div class="ac-header full divide caption-height">
<div class="ac-header__wrap-title mr-3">
<span class="ac-header__title"><Label label={inventory.string.Categories} /></span>
</div>
<div class="ac-header-full" class:secondRow={twoRows}>
<Button
label={inventory.string.CategoryCreateLabel}
icon={IconAdd}
kind={'primary'}
size={'small'}
on:click={showCreateDialog}
/>
<div class="mb-1 clear-mins">
<Button icon={IconAdd} label={inventory.string.CategoryCreateLabel} kind={'primary'} on:click={showCreateDialog} />
</div>
</div>
<div class="ac-header full divide search-start">
<div class="ac-header-full small-gap">
<SearchEdit bind:value={search} on:change={() => updateResultQuery(search)} />
<ActionIcon icon={IconMoreH} size={'small'} />
<div class="buttons-divider" />
</div>
</div>

View File

@ -186,7 +186,7 @@
.title {
font-weight: 600;
font-size: 1.5rem;
color: var(--caption-color);
color: var(--theme-caption-color);
}
.status {
min-height: 7.5rem;
@ -214,13 +214,13 @@
.footer {
margin-top: 3.5rem;
font-size: 0.8rem;
color: var(--caption-color);
color: var(--theme-caption-color);
span {
opacity: 0.3;
}
a {
text-decoration: none;
color: var(--caption-color);
color: var(--theme-caption-color);
opacity: 0.8;
&:hover {
opacity: 1;

View File

@ -80,7 +80,7 @@
display: flex;
flex-direction: column;
height: 100%;
background: var(--popup-bg-color);
background: var(--theme-list-row-color);
box-shadow: var(--popup-aside-shadow);
&.minHeight {

View File

@ -79,6 +79,7 @@
<Scroller padding={'.125rem 0'}>
<div class="form">
{#each workspaces as workspace}
<!-- svelte-ignore a11y-click-events-have-key-events -->
<div
class="workspace flex-center fs-title cursor-pointer focused-button bordered form-row"
on:click={() => select(workspace.workspace)}
@ -120,7 +121,7 @@
.title {
font-weight: 600;
font-size: 1.5rem;
color: var(--caption-color);
color: var(--theme-caption-color);
}
.status {
min-height: 7.5rem;
@ -150,13 +151,13 @@
.footer {
margin-top: 3.5rem;
font-size: 0.8rem;
color: var(--caption-color);
color: var(--theme-caption-color);
span {
opacity: 0.3;
}
a {
text-decoration: none;
color: var(--caption-color);
color: var(--theme-caption-color);
opacity: 0.8;
&:hover {
opacity: 1;

View File

@ -30,15 +30,15 @@
<style lang="scss">
.container {
padding: 0.75rem 1rem;
background-color: var(--accent-bg-color);
border: 1px solid var(--divider-color);
background-color: var(--theme-comp-header-color);
border: 1px solid var(--theme-divider-color);
border-radius: 0.5rem;
}
.error {
color: var(--system-error-color);
fill: var(--system-error-color);
background-color: var(--accent-bg-color);
background-color: var(--theme-comp-header-color);
border-color: var(--system-error-60-color);
}
</style>

View File

@ -585,6 +585,8 @@
focusIndex={10}
bind:value={object.channels}
highlighted={matchedChannels.map((it) => it.provider)}
kind={'link-bordered'}
size={'large'}
/>
<YesNo
disabled={loading}
@ -592,6 +594,8 @@
label={recruit.string.Onsite}
tooltip={recruit.string.WorkLocationPreferences}
bind:value={object.onsite}
kind={'link-bordered'}
size={'large'}
/>
<YesNo
disabled={loading}
@ -599,6 +603,8 @@
label={recruit.string.Remote}
tooltip={recruit.string.WorkLocationPreferences}
bind:value={object.remote}
kind={'link-bordered'}
size={'large'}
/>
<Component
is={tags.component.TagsDropdownEditor}
@ -611,7 +617,9 @@
showTitle: false,
elements,
newElements,
countLabel: recruit.string.NumberSkills
countLabel: recruit.string.NumberSkills,
kind: 'link-bordered',
size: 'large'
}}
on:open={(evt) => {
addTagRef(evt.detail)
@ -621,8 +629,7 @@
}}
/>
{#if object.skills.length > 0}
<div class="flex-break" />
<div class="antiComponent antiEmphasized flex-grow mt-2">
<div class="antiComponent antiEmphasized w-full flex-grow mt-2">
<Component
is={tags.component.TagsEditor}
props={{
@ -730,8 +737,8 @@
.resume {
margin: -0.375rem 0rem -0.375rem -0.375rem;
padding: 0.375rem;
background: var(--accent-bg-color);
border: 1px dashed var(--divider-color);
background: var(--theme-comp-header-color);
border: 1px dashed var(--theme-divider-color);
border-radius: 0.5rem;
&.solid {
@ -740,8 +747,8 @@
}
.skills-box {
padding: 0.5rem 0.75rem;
background: var(--accent-bg-color);
border: 1px dashed var(--divider-color);
background: var(--theme-comp-header-color);
border: 1px dashed var(--theme-divider-color);
border-radius: 0.5rem;
}
</style>

View File

@ -17,16 +17,7 @@
import core, { Doc, DocumentQuery, Ref } from '@hcengineering/core'
import { createQuery, getClient } from '@hcengineering/presentation'
import { Applicant, Vacancy } from '@hcengineering/recruit'
import {
Button,
deviceOptionsStore as deviceInfo,
Icon,
IconAdd,
Label,
Loading,
SearchEdit,
showPopup
} from '@hcengineering/ui'
import { Button, ActionIcon, IconMoreH, Label, Loading, SearchEdit, showPopup, IconAdd } from '@hcengineering/ui'
import view, { BuildModelKey, Viewlet, ViewletPreference } from '@hcengineering/view'
import {
FilterBar,
@ -230,34 +221,29 @@
return result
}
$: twoRows = $deviceInfo.twoRows
// $: twoRows = $deviceInfo.twoRows
$: viewOptions = getViewOptions(descr, $viewOptionStore)
</script>
<div class="ac-header withSettings" class:full={!twoRows} class:mini={twoRows}>
<div class:ac-header-full={!twoRows} class:flex-between={twoRows}>
<div class="ac-header__wrap-title mr-3">
<div class="ac-header__icon"><Icon icon={recruit.icon.Vacancy} size={'small'} /></div>
<span class="ac-header__title"><Label label={recruit.string.Organizations} /></span>
<div class="ml-4"><FilterButton _class={recruit.class.Vacancy} /></div>
</div>
<SearchEdit
bind:value={search}
on:change={(e) => {
search = e.detail
}}
/>
<div class="ac-header full divide">
<div class="ac-header__wrap-title mr-3">
<span class="ac-header__title"><Label label={recruit.string.Organizations} /></span>
</div>
<div class="ac-header-full" class:secondRow={twoRows}>
<Button
icon={IconAdd}
label={recruit.string.CompanyCreateLabel}
size={'small'}
kind={'primary'}
on:click={showCreateDialog}
/>
<div class="clear-mins mb-1">
<Button icon={IconAdd} label={recruit.string.CompanyCreateLabel} kind={'primary'} on:click={showCreateDialog} />
</div>
</div>
<div class="ac-header full divide search-start">
<div class="ac-header-full small-gap">
<SearchEdit bind:value={search} on:change={(e) => (search = e.detail)} />
<ActionIcon icon={IconMoreH} size={'small'} />
<div class="buttons-divider" />
<FilterButton _class={recruit.class.Vacancy} />
</div>
<div class="ac-header-full medium-gap">
<ViewletSettingButton bind:viewOptions viewlet={descr} />
<ActionIcon icon={IconMoreH} size={'small'} />
</div>
</div>

View File

@ -18,14 +18,14 @@
import { Vacancy } from '@hcengineering/recruit'
import {
Button,
Icon,
IconAdd,
ActionIcon,
IconMoreH,
Label,
Loading,
SearchEdit,
deviceOptionsStore as deviceInfo,
showPopup,
tableToCSV
tableToCSV,
IconAdd
} from '@hcengineering/ui'
import view, { BuildModelKey, Viewlet, ViewletPreference } from '@hcengineering/view'
import {
@ -157,37 +157,18 @@
return result
}
$: twoRows = $deviceInfo.twoRows
// $: twoRows = $deviceInfo.twoRows
$: viewOptions = getViewOptions(descr, $viewOptionStore)
</script>
<div class="ac-header withSettings" class:full={!twoRows} class:mini={twoRows}>
<div class:ac-header-full={!twoRows} class:flex-between={twoRows}>
<div class="ac-header__wrap-title mr-3">
<div class="ac-header__icon"><Icon icon={recruit.icon.Vacancy} size={'small'} /></div>
<span class="ac-header__title"><Label label={recruit.string.Vacancies} /></span>
<div class="ml-4"><FilterButton _class={recruit.class.Vacancy} /></div>
</div>
<SearchEdit
bind:value={search}
on:change={(e) => {
search = e.detail
}}
/>
<div class="ac-header full divide">
<div class="ac-header__wrap-title mr-3">
<span class="ac-header__title"><Label label={recruit.string.Vacancies} /></span>
</div>
<div class="ac-header-full" class:secondRow={twoRows}>
<Button
icon={IconAdd}
label={recruit.string.VacancyCreateLabel}
size={'small'}
kind={'primary'}
on:click={showCreateDialog}
/>
<ViewletSettingButton bind:viewOptions viewlet={descr} />
<div class="ac-header-full medium-gap mb-1">
<Button
label={recruit.string.Export}
size={'small'}
on:click={() => {
// Download it
const filename = 'vacancies' + new Date().toLocaleDateString() + '.csv'
@ -204,6 +185,19 @@
document.body.removeChild(link)
}}
/>
<Button icon={IconAdd} label={recruit.string.VacancyCreateLabel} kind={'primary'} on:click={showCreateDialog} />
</div>
</div>
<div class="ac-header full divide search-start">
<div class="ac-header-full small-gap">
<SearchEdit bind:value={search} on:change={(e) => (search = e.detail)} />
<ActionIcon icon={IconMoreH} size={'small'} />
<div class="buttons-divider" />
<FilterButton _class={recruit.class.Vacancy} />
</div>
<div class="ac-header-full medium-gap">
<ViewletSettingButton bind:viewOptions viewlet={descr} />
<ActionIcon icon={IconMoreH} size={'small'} />
</div>
</div>

View File

@ -154,7 +154,7 @@
</script>
{#if visibleCategories.length > 0}
<div class="flex-between header">
<div class="ac-header full divide">
<div class="buttons-group small-gap">
<Button
label={tags.string.AllCategories}

View File

@ -11,7 +11,7 @@
export let object: WithLookup<Doc>
export let full: boolean
export let ckeckFilled: boolean = false
export let kind: 'short' | 'full' = 'short'
export let kind: 'short' | 'full' | 'list' = 'short'
export let isEditable: boolean = false
export let action: (evt: MouseEvent) => Promise<void> | void = async () => {}
export let compression: boolean = false
@ -46,27 +46,35 @@
})
</script>
<!-- svelte-ignore a11y-click-events-have-key-events -->
<div
class="labels-container"
style:justify-content={kind === 'short' ? 'space-between' : 'flex-start'}
class:w-full={kind === 'full'}
style:flex-wrap={kind === 'short' || compression ? 'nowrap' : 'wrap'}
style:flex-shrink={compression ? 1 : 0}
use:resizeObserver={(element) => {
allWidth = element.clientWidth
}}
on:click|stopPropagation={(evt) => {
if (isEditable) tagsHandler(evt)
else action(evt)
}}
>
{#each items as value, i}
<div class="label-box wrap-{kind}" title={value.title}>
<TagReferencePresenter attr={undefined} {value} kind={'kanban-labels'} bind:realWidth={widths[i]} />
{#if kind === 'list'}
{#each items as value}
<div class="label-box no-shrink" title={value.title}>
<TagReferencePresenter attr={undefined} {value} kind={'labels'} />
</div>
{/each}
</div>
{:else}
<!-- svelte-ignore a11y-click-events-have-key-events -->
<div
class="labels-container"
style:justify-content={kind === 'short' ? 'space-between' : 'flex-start'}
class:w-full={kind === 'full'}
style:flex-wrap={kind === 'short' || compression ? 'nowrap' : 'wrap'}
style:flex-shrink={compression ? 1 : 0}
use:resizeObserver={(element) => {
allWidth = element.clientWidth
}}
on:click|stopPropagation={(evt) => {
if (isEditable) tagsHandler(evt)
else action(evt)
}}
>
{#each items as value, i}
<div class="label-box wrap-{kind}" title={value.title}>
<TagReferencePresenter attr={undefined} {value} kind={'kanban-labels'} bind:realWidth={widths[i]} />
</div>
{/each}
</div>
{/if}
<style lang="scss">
.labels-container {
@ -87,7 +95,7 @@
border-radius: 0.25rem;
transition: box-shadow 0.15s ease-in-out;
&:last-child {
&:not(.no-shrink):last-child {
flex-shrink: 0;
}
}

View File

@ -74,11 +74,12 @@
align-items: center;
flex-shrink: 0;
padding-left: 0.5rem;
height: 1.5rem;
height: 1.75rem;
min-width: 0;
min-height: 0;
border: 1px solid var(--divider-color);
border-radius: 0.75rem;
background-color: var(--theme-list-button-color);
border: 1px solid var(--theme-button-border);
border-radius: 1.5rem;
.btn-close {
flex-shrink: 0;

View File

@ -17,12 +17,21 @@
import { Asset, IntlString, translate } from '@hcengineering/platform'
import { createQuery } from '@hcengineering/presentation'
import { TagCategory, TagElement } from '@hcengineering/tags'
import { AnySvelteComponent, Button, Icon, IconAdd, Label, SearchEdit, showPopup } from '@hcengineering/ui'
import {
AnySvelteComponent,
Button,
ActionIcon,
IconMoreH,
Label,
SearchEdit,
showPopup,
IconAdd
} from '@hcengineering/ui'
import { TableBrowser } from '@hcengineering/view-resources'
import tags from '../plugin'
import CategoryBar from './CategoryBar.svelte'
import CreateTagElement from './CreateTagElement.svelte'
import { deviceOptionsStore as deviceInfo } from '@hcengineering/ui'
// import { deviceOptionsStore as deviceInfo } from '@hcengineering/ui'
export let title: IntlString = tags.string.Tags
export let icon: Asset | AnySvelteComponent = tags.icon.Tags
@ -86,25 +95,22 @@
(tagElements?.get(b._id as Ref<TagElement>)?.count ?? 0) -
(tagElements?.get(a._id as Ref<TagElement>)?.count ?? 0) ?? 0
$: twoRows = $deviceInfo.twoRows
// $: twoRows = $deviceInfo.twoRows
</script>
<div class="ac-header withSettings" class:full={!twoRows} class:mini={twoRows}>
<div class:ac-header-full={!twoRows} class:flex-between={twoRows}>
<div class="ac-header__wrap-title mr-3">
<div class="ac-header__icon"><Icon {icon} size={'small'} /></div>
<span class="ac-header__title"><Label label={title} /></span>
</div>
<SearchEdit
bind:value={search}
on:change={() => {
updateResultQuery(search, category)
}}
/>
<div class="ac-header full divide">
<div class="ac-header__wrap-title mr-3">
<span class="ac-header__title"><Label label={title} /></span>
</div>
<div class="ac-header-full" class:secondRow={twoRows}>
<Button icon={IconAdd} label={сreateItemLabel} kind={'primary'} size={'small'} on:click={showCreateDialog} />
<div class="clear-mins mb-1">
<Button icon={IconAdd} label={сreateItemLabel} kind={'primary'} on:click={showCreateDialog} />
</div>
</div>
<div class="ac-header full divide search-start">
<div class="ac-header-full small-gap">
<SearchEdit bind:value={search} on:change={() => updateResultQuery(search, category)} />
<ActionIcon icon={IconMoreH} size={'small'} />
</div>
</div>

View File

@ -5,13 +5,8 @@
<path d="M19.2,11.4c-0.3,0-0.6,0.3-0.6,0.6v6.6c0,0.7-0.5,1.3-1.2,1.3H4.8c-0.7,0-1.2-0.6-1.2-1.3V5.4 c0-0.7,0.5-1.3,1.2-1.3h9.9c0.3,0,0.6-0.3,0.6-0.6S15,2.9,14.7,2.9H4.8C3.5,2.9,2.4,4,2.4,5.4v13.2c0,1.4,1.1,2.5,2.4,2.5h12.6 c1.3,0,2.4-1.1,2.4-2.5V12C19.8,11.7,19.5,11.4,19.2,11.4z"/>
</g>
</symbol>
<symbol id="kanban" viewBox="0 0 16 16">
<path d="M1 2.6C1 2.03995 1 1.75992 1.10899 1.54601C1.20487 1.35785 1.35785 1.20487 1.54601 1.10899C1.75992 1 2.03995 1 2.6 1H5.4C5.96005 1 6.24008 1 6.45399 1.10899C6.64215 1.20487 6.79513 1.35785 6.89101 1.54601C7 1.75992 7 2.03995 7 2.6V3.4C7 3.96005 7 4.24008 6.89101 4.45399C6.79513 4.64215 6.64215 4.79513 6.45399 4.89101C6.24008 5 5.96005 5 5.4 5H2.6C2.03995 5 1.75992 5 1.54601 4.89101C1.35785 4.79513 1.20487 4.64215 1.10899 4.45399C1 4.24008 1 3.96005 1 3.4V2.6Z" />
<path d="M9 2.6C9 2.03995 9 1.75992 9.10899 1.54601C9.20487 1.35785 9.35785 1.20487 9.54601 1.10899C9.75992 1 10.0399 1 10.6 1H13.4C13.9601 1 14.2401 1 14.454 1.10899C14.6422 1.20487 14.7951 1.35785 14.891 1.54601C15 1.75992 15 2.03995 15 2.6V3.4C15 3.96005 15 4.24008 14.891 4.45399C14.7951 4.64215 14.6422 4.79513 14.454 4.89101C14.2401 5 13.9601 5 13.4 5H10.6C10.0399 5 9.75992 5 9.54601 4.89101C9.35785 4.79513 9.20487 4.64215 9.10899 4.45399C9 4.24008 9 3.96005 9 3.4V2.6Z" />
<path d="M1 7.6C1 7.03995 1 6.75992 1.10899 6.54601C1.20487 6.35785 1.35785 6.20487 1.54601 6.10899C1.75992 6 2.03995 6 2.6 6H5.4C5.96005 6 6.24008 6 6.45399 6.10899C6.64215 6.20487 6.79513 6.35785 6.89101 6.54601C7 6.75992 7 7.03995 7 7.6V8.4C7 8.96005 7 9.24008 6.89101 9.45399C6.79513 9.64215 6.64215 9.79513 6.45399 9.89101C6.24008 10 5.96005 10 5.4 10H2.6C2.03995 10 1.75992 10 1.54601 9.89101C1.35785 9.79513 1.20487 9.64215 1.10899 9.45399C1 9.24008 1 8.96005 1 8.4V7.6Z" />
<path d="M9 7.6C9 7.03995 9 6.75992 9.10899 6.54601C9.20487 6.35785 9.35785 6.20487 9.54601 6.10899C9.75992 6 10.0399 6 10.6 6H13.4C13.9601 6 14.2401 6 14.454 6.10899C14.6422 6.20487 14.7951 6.35785 14.891 6.54601C15 6.75992 15 7.03995 15 7.6V8.4C15 8.96005 15 9.24008 14.891 9.45399C14.7951 9.64215 14.6422 9.79513 14.454 9.89101C14.2401 10 13.9601 10 13.4 10H10.6C10.0399 10 9.75992 10 9.54601 9.89101C9.35785 9.79513 9.20487 9.64215 9.10899 9.45399C9 9.24008 9 8.96005 9 8.4V7.6Z" />
<path d="M1 12.6C1 12.0399 1 11.7599 1.10899 11.546C1.20487 11.3578 1.35785 11.2049 1.54601 11.109C1.75992 11 2.03995 11 2.6 11H5.4C5.96005 11 6.24008 11 6.45399 11.109C6.64215 11.2049 6.79513 11.3578 6.89101 11.546C7 11.7599 7 12.0399 7 12.6V13.4C7 13.9601 7 14.2401 6.89101 14.454C6.79513 14.6422 6.64215 14.7951 6.45399 14.891C6.24008 15 5.96005 15 5.4 15H2.6C2.03995 15 1.75992 15 1.54601 14.891C1.35785 14.7951 1.20487 14.6422 1.10899 14.454C1 14.2401 1 13.9601 1 13.4V12.6Z" />
<path d="M9 12.6C9 12.0399 9 11.7599 9.10899 11.546C9.20487 11.3578 9.35785 11.2049 9.54601 11.109C9.75992 11 10.0399 11 10.6 11H13.4C13.9601 11 14.2401 11 14.454 11.109C14.6422 11.2049 14.7951 11.3578 14.891 11.546C15 11.7599 15 12.0399 15 12.6V13.4C15 13.9601 15 14.2401 14.891 14.454C14.7951 14.6422 14.6422 14.7951 14.454 14.891C14.2401 15 13.9601 15 13.4 15H10.6C10.0399 15 9.75992 15 9.54601 14.891C9.35785 14.7951 9.20487 14.6422 9.10899 14.454C9 14.2401 9 13.9601 9 13.4V12.6Z" />
<symbol id="kanban" viewBox="0 0 20 20">
<path fill-rule="evenodd" clip-rule="evenodd" d="M7.5 12.5H3.75L3.75 16.25H7.5V12.5ZM7.5 3.75H3.75L3.75 7.5H7.5V3.75ZM16.25 12.5H12.5V16.25H16.25V12.5ZM16.25 3.75H12.5V7.5H16.25V3.75ZM3.75 2.5C3.05964 2.5 2.5 3.05964 2.5 3.75V7.5C2.5 8.19036 3.05964 8.75 3.75 8.75H7.5C8.19036 8.75 8.75 8.19036 8.75 7.5V3.75C8.75 3.05964 8.19036 2.5 7.5 2.5H3.75ZM3.75 11.25C3.05964 11.25 2.5 11.8096 2.5 12.5V16.25C2.5 16.9404 3.05964 17.5 3.75 17.5H7.5C8.19036 17.5 8.75 16.9404 8.75 16.25V12.5C8.75 11.8096 8.19036 11.25 7.5 11.25H3.75ZM11.25 12.5C11.25 11.8096 11.8096 11.25 12.5 11.25H16.25C16.9404 11.25 17.5 11.8096 17.5 12.5V16.25C17.5 16.9404 16.9404 17.5 16.25 17.5H12.5C11.8096 17.5 11.25 16.9404 11.25 16.25V12.5ZM12.5 2.5C11.8096 2.5 11.25 3.05964 11.25 3.75V7.5C11.25 8.19036 11.8096 8.75 12.5 8.75H16.25C16.9404 8.75 17.5 8.19036 17.5 7.5V3.75C17.5 3.05964 16.9404 2.5 16.25 2.5H12.5Z" />
</symbol>
<symbol id='todo-check' viewBox="0 0 16 16">
<path d="M8,14.5c-3.6,0-6.5-2.9-6.5-6.5S4.4,1.5,8,1.5s6.5,2.9,6.5,6.5S11.6,14.5,8,14.5z M8,2.5C5,2.5,2.5,5,2.5,8 c0,3,2.5,5.5,5.5,5.5c3,0,5.5-2.5,5.5-5.5C13.5,5,11,2.5,8,2.5z"/>

Before

Width:  |  Height:  |  Size: 5.7 KiB

After

Width:  |  Height:  |  Size: 3.8 KiB

View File

@ -18,7 +18,7 @@
import { createQuery, getClient } from '@hcengineering/presentation'
import tags, { selectedTagElements, TagCategory, TagElement } from '@hcengineering/tags'
import { DoneState, Task } from '@hcengineering/task'
import { Component, Icon, Label, SearchEdit } from '@hcengineering/ui'
import { Component, Label, SearchEdit } from '@hcengineering/ui'
import { TableBrowser } from '@hcengineering/view-resources'
import task from '../plugin'
@ -70,9 +70,8 @@
const handleChange = (evt: any) => updateCategory(evt.detail)
</script>
<div class="ac-header full">
<div class="ac-header full divide caption-height">
<div class="ac-header__wrap-title">
<div class="ac-header__icon"><Icon icon={task.icon.Task} size={'small'} /></div>
<span class="ac-header__title"><Label label={labelTasks} /></span>
</div>

View File

@ -143,8 +143,9 @@
$: updateDocs(_class, states, resultQuery)
</script>
<div class="min-h-4 max-h-4 h-4 flex-no-shrink" />
<CreateFilter bind:value={modified} />
<div class="ml-10 mt-4">
<div class="mx-10 mt-4">
<BarDashboard {items} />
</div>

View File

@ -145,18 +145,17 @@
}
</script>
<div class="header">
<div class="ac-header full divide">
<TabList
items={[
{ id: 'AllStates', labelIntl: task.string.AllStates },
{ id: 'DoneStates', labelIntl: task.string.DoneStates }
]}
multiselect={false}
size={'small'}
on:select={handleSelect}
/>
{#if doneStatusesView}
<TabList items={itemsDS} bind:selected={selectedDS} multiselect on:select={handleDoneSelect} size={'small'} />
<TabList items={itemsDS} bind:selected={selectedDS} multiselect on:select={handleDoneSelect} />
{:else}
<StatesBar bind:state {space} gap={'none'} on:change={() => updateQuery(query, selectedDoneStates)} />
{/if}
@ -171,20 +170,4 @@
min-height: 0;
height: 100%;
}
.header {
display: grid;
grid-template-columns: auto auto;
justify-content: space-between;
align-items: center;
column-gap: 1rem;
padding: 0.75rem 0.75rem 0.75rem 2.5rem;
width: 100%;
min-height: 3.25rem;
min-width: 0;
background-color: var(--board-bg-color);
border-top: 1px solid var(--divider-color);
// border-bottom: 1px solid var(--divider-color);
}
</style>

View File

@ -84,29 +84,27 @@
<path style="fill-rule:evenodd;clip-rule:evenodd;" d="M7,14c3.9,0,7-3.1,7-7c0-3.9-3.1-7-7-7C3.1,0,0,3.1,0,7C0,10.9,3.1,14,7,14z M5,4C4.7,3.7,4.3,3.7,4,4S3.7,4.7,4,5l2,2L4,9C3.7,9.3,3.7,9.7,4,10c0.3,0.3,0.8,0.3,1.1,0l2-2l2,2c0.3,0.3,0.8,0.3,1.1,0c0.3-0.3,0.3-0.8,0-1.1l-2-2l2-2c0.3-0.3,0.3-0.8,0-1.1C9.7,3.7,9.3,3.7,9,4l-2,2L5,4z" />
</symbol>
<symbol id="priority-nopriority" viewBox="0 0 14 14">
<rect width="2" height="2" rx="1" transform="matrix(-1 0 0 1 5 6)" />
<rect width="2" height="2" rx="1" transform="matrix(-1 0 0 1 8 6)" />
<rect width="2" height="2" rx="1" transform="matrix(-1 0 0 1 11 6)" />
<symbol id="priority-nopriority" viewBox="0 0 16 16">
<rect opacity="0.6" x="2" y="7.5" width="12" height="1" rx="0.5" />
</symbol>
<symbol id="priority-urgent" viewBox="-1 -1 16 16">
<path fill="var(--warning-color)" d="M2 0a2 2 0 00-2 2v10a2 2 0 002 2h10a2 2 0 002-2V2a2 2 0 00-2-2H2zm3.914 3h1.738L7.5 8.602H6.07L5.914 3zm1.809 7.164a.95.95 0 01-.938.938.934.934 0 110-1.867c.5 0 .934.417.938.93z" />
</symbol>
<symbol id="priority-high" viewBox="0 0 16 16">
<rect x="1" y="8" width="3" height="6" rx="1" />
<rect x="6" y="5" width="3" height="9" rx="1" />
<rect x="11" y="2" width="3" height="12" rx="1" />
</symbol>
<symbol id="priority-medium" viewBox="0 0 16 16">
<rect x="1" y="8" width="3" height="6" rx="1" />
<rect x="6" y="5" width="3" height="9" rx="1" />
<rect x="11" y="2" width="3" height="12" rx="1" fill-opacity=".4" />
</symbol>
<symbol id="priority-low" viewBox="0 0 16 16">
<rect x="1" y="8" width="3" height="6" rx="1" />
<rect x="1" y="8" width="3" height="6" rx="1" fill-opacity=".4" />
<rect x="6" y="5" width="3" height="9" rx="1" fill-opacity=".4" />
<rect x="11" y="2" width="3" height="12" rx="1" fill-opacity=".4" />
</symbol>
<symbol id="priority-medium" viewBox="0 0 16 16">
<rect x="1" y="8" width="3" height="6" rx="1" fill-opacity=".4" />
<rect x="6" y="5" width="3" height="9" rx="1" fill-opacity=".4" />
<rect x="11" y="2" width="3" height="12" rx="1" fill-opacity=".15" />
</symbol>
<symbol id="priority-low" viewBox="0 0 16 16">
<rect x="1" y="8" width="3" height="6" rx="1" fill-opacity=".4" />
<rect x="6" y="5" width="3" height="9" rx="1" fill-opacity=".15" />
<rect x="11" y="2" width="3" height="12" rx="1" fill-opacity=".15" />
</symbol>
<symbol id="list" viewBox="0 0 16 16">
<path d="M1 1.8C1 1.51997 1 1.37996 1.0545 1.273C1.10243 1.17892 1.17892 1.10243 1.273 1.0545C1.37996 1 1.51997 1 1.8 1H14.2C14.48 1 14.62 1 14.727 1.0545C14.8211 1.10243 14.8976 1.17892 14.9455 1.273C15 1.37996 15 1.51997 15 1.8V2.2C15 2.48003 15 2.62004 14.9455 2.727C14.8976 2.82108 14.8211 2.89757 14.727 2.9455C14.62 3 14.48 3 14.2 3H1.8C1.51997 3 1.37996 3 1.273 2.9455C1.17892 2.89757 1.10243 2.82108 1.0545 2.727C1 2.62004 1 2.48003 1 2.2V1.8Z" />

Before

Width:  |  Height:  |  Size: 32 KiB

After

Width:  |  Height:  |  Size: 32 KiB

View File

@ -32,7 +32,8 @@
export let justify: 'left' | 'center' = 'center'
export let width: string | undefined = 'min-content'
export let onlyIcon: boolean = false
export let enlargedText = false
export let enlargedText: boolean = false
export let short: boolean = false
let selectedComponent: Component | undefined
let defaultComponentLabel = ''
@ -105,6 +106,7 @@
icon={tracker.icon.Components}
disabled={!isEditable}
{loading}
{short}
on:click={handleComponentEditorOpened}
/>
{:else}
@ -117,6 +119,7 @@
icon={tracker.icon.Components}
disabled={!isEditable}
{loading}
{short}
on:click={handleComponentEditorOpened}
><svelte:fragment slot="content">
<span

View File

@ -1,51 +1,29 @@
<script lang="ts">
import { IntlString } from '@hcengineering/platform'
import { Button } from '@hcengineering/ui'
import { TabList } from '@hcengineering/ui'
export let mode: string
export let config: [string, IntlString, object][]
export let onChange: (_mode: string) => void
function getButtonShape (i: number) {
if (config.length === 1) return 'round'
switch (i) {
case 0:
return 'rectangle-right'
case config.length - 1:
return 'rectangle-left'
default:
return 'rectangle'
$: modeList = config.map((c) => {
return {
id: c[0],
labelIntl: c[1],
action: () => onChange(c[0])
}
}
})
</script>
<div class="itemsContainer">
{#each config as [_mode, label, params], i}
<div class="buttonWrapper">
<Button
{label}
labelParams={params}
size="small"
on:click={() => onChange(_mode)}
selected={_mode === mode}
shape={getButtonShape(i)}
/>
</div>
{/each}
<div class="ac-header full divide search-start">
<div class="ac-header-full small-gap">
<TabList
items={modeList}
selected={mode}
kind={'normal'}
on:select={(result) => {
if (result.detail !== undefined && result.detail.action) result.detail.action()
}}
/>
</div>
</div>
<style lang="scss">
.itemsContainer {
display: flex;
align-items: center;
padding: 0.65rem 1.35rem 0.65rem 2.25rem;
border-top: 1px solid var(--divider-color);
}
.buttonWrapper {
margin-right: 1px;
&:last-child {
margin-right: 0;
}
}
</style>

View File

@ -90,17 +90,27 @@
const retrieveMembers = (p: Component) => p.members
</script>
<div class="fs-title flex-between header">
<div class="flex-center">
<Label {label} />
<div class="componentTitle">
<div class="ac-header full divide caption-height">
<div class="ac-header__wrap-title mr-3">
<span class="ac-header__title"><Label {label} /></span>
<span class="componentTitle">
<Label label={title} />
</div>
</span>
</div>
<div class="ac-header-full medium-gap mb-1">
<TabList
items={viewList}
selected={viewMode}
on:select={(result) => {
if (result.detail !== undefined && result.detail.id !== viewMode) viewMode = result.detail.id
}}
/>
<Button icon={IconAdd} label={tracker.string.Component} kind={'primary'} on:click={showCreateDialog} />
</div>
<Button size="small" icon={IconAdd} label={tracker.string.Component} kind={'primary'} on:click={showCreateDialog} />
</div>
<div class="itemsContainer">
<div class="flex-row-center">
<div class="ac-header full divide search-start">
<div class="ac-header-full small-gap">
<TabList
items={modeList}
selected={mode}
@ -109,26 +119,9 @@
if (result.detail !== undefined && result.detail.action) result.detail.action()
}}
/>
<!-- <div class="ml-3 filterButton">
<BuComponet size="small"
icon={IconAdd}
kind={'link-bordered'}
borderStyle={'dashed'}
label={tracker.string.Filter}
on:click={() => {}}
/>
</div> -->
</div>
<TabList
items={viewList}
selected={viewMode}
kind={'secondary'}
size={'small'}
on:select={(result) => {
if (result.detail !== undefined && result.detail.id !== viewMode) viewMode = result.detail.id
}}
/>
</div>
<ComponentsListBrowser
_class={tracker.class.Component}
itemsConfig={[

View File

@ -52,7 +52,7 @@
<div
class="clear-mins"
class:minus-margin={kind === 'list-header'}
class:compression
class:label-wrapper={compression}
use:tooltip={{ label: value.component ? tracker.string.MoveToComponent : tracker.string.AddToComponent }}
>
<ComponentSelector
@ -67,6 +67,7 @@
{onlyIcon}
{enlargedText}
value={value.component}
short={compression}
onChange={handleComponentIdChanged}
/>
</div>
@ -76,8 +77,4 @@
.minus-margin {
margin-left: -0.5rem;
}
.compression {
flex-shrink: 5;
min-width: 1rem;
}
</style>

View File

@ -17,41 +17,57 @@
{fill}
id={category._id}
style:transform={category._id === tracker.issueStatusCategory.Started ? 'rotate(-90deg)' : ''}
viewBox="0 0 14 14"
viewBox="0 0 16 16"
xmlns="http://www.w3.org/2000/svg"
>
{#if category._id === tracker.issueStatusCategory.Backlog}
<path
d="M13.9,7.9l-2-0.3c0-0.2,0-0.4,0-0.7s0-0.4,0-0.7l2-0.3C14,6.4,14,6.7,14,7S14,7.6,13.9,7.9z M13.5,4.3c-0.2-0.6-0.5-1.1-0.9-1.6L11,4c0.3,0.3,0.5,0.7,0.7,1.1L13.5,4.3z M11.3,1.4L10,3C9.7,2.8,9.3,2.5,8.9,2.4l0.8-1.8C10.2,0.8,10.8,1.1,11.3,1.4z M7.9,0.1L7.7,2C7.4,2,7.2,2,7,2S6.6,2,6.3,2l-0.3-2C6.4,0,6.7,0,7,0S7.6,0,7.9,0.1z M4.3,0.5l0.8,1.8C4.7,2.5,4.3,2.8,4,3L2.7,1.4C3.2,1.1,3.8,0.8,4.3,0.5z M1.4,2.7L3,4C2.8,4.3,2.5,4.7,2.4,5.1L0.5,4.3C0.8,3.8,1.1,3.2,1.4,2.7z M0.1,6.1C0,6.4,0,6.7,0,7s0,0.6,0.1,0.9l2-0.3C2,7.4,2,7.2,2,7s0-0.4,0-0.7L0.1,6.1z M0.5,9.7l1.8-0.8C2.5,9.3,2.8,9.7,3,10l-1.6,1.2C1.1,10.8,0.8,10.2,0.5,9.7z M2.7,12.6L4,11c0.3,0.3,0.7,0.5,1.1,0.7l-0.8,1.8C3.8,13.2,3.2,12.9,2.7,12.6z M6.1,13.9l0.3-2c0.2,0,0.4,0,0.7,0s0.4,0,0.7,0l0.3,2C7.6,14,7.3,14,7,14S6.4,14,6.1,13.9z M9.7,13.5l-0.8-1.8c0.4-0.2,0.8-0.4,1.1-0.7l1.2,1.6C10.8,12.9,10.2,13.2,9.7,13.5z M12.6,11.3L11,10c0.3-0.3,0.5-0.7,0.7-1.1l1.8,0.8C13.2,10.2,12.9,10.8,12.6,11.3z"
fill-rule="evenodd"
clip-rule="evenodd"
d="M6.97975 1.07389C3.92356 1.52014 1.50831 3.94118 1.0708 7.0002H2.08287C2.50337 4.49345 4.47822 2.51374 6.9825 2.08599L6.97975 1.07389ZM8.98249 2.08014L8.97974 1.06812C12.055 1.49885 14.4896 3.92773 14.9291 7.0002H13.917C13.4945 4.48183 11.5033 2.4954 8.98249 2.08014ZM9.01467 13.9146C11.5201 13.4879 13.4962 11.5077 13.917 9.00019H14.929C14.4913 12.06 12.0748 14.4815 9.01742 14.9267L9.01467 13.9146ZM2.0829 9.0002C2.50529 11.5176 4.49522 13.5034 7.01468 13.9196L7.01743 14.9317C3.94351 14.4999 1.51022 12.0717 1.07083 9.0002H2.0829Z"
/>
{:else if category._id === tracker.issueStatusCategory.Unstarted}
<path
d="M7,0C3.1,0,0,3.1,0,7c0,3.9,3.1,7,7,7c3.9,0,7-3.1,7-7C14,3.1,10.9,0,7,0z M7,12c-2.8,0-5-2.2-5-5s2.2-5,5-5s5,2.2,5,5S9.8,12,7,12z"
fill-rule="evenodd"
clip-rule="evenodd"
d="M8 14C11.3137 14 14 11.3137 14 8C14 4.68629 11.3137 2 8 2C4.68629 2 2 4.68629 2 8C2 11.3137 4.68629 14 8 14ZM8 15C11.866 15 15 11.866 15 8C15 4.13401 11.866 1 8 1C4.13401 1 1 4.13401 1 8C1 11.866 4.13401 15 8 15Z"
/>
{:else if category._id === tracker.issueStatusCategory.Started}
<path
d="M7,0C3.1,0,0,3.1,0,7c0,3.9,3.1,7,7,7c3.9,0,7-3.1,7-7C14,3.1,10.9,0,7,0z M7,12c-2.8,0-5-2.2-5-5s2.2-5,5-5s5,2.2,5,5S9.8,12,7,12z"
fill-rule="evenodd"
clip-rule="evenodd"
d="M8 14C11.3137 14 14 11.3137 14 8C14 4.68629 11.3137 2 8 2C4.68629 2 2 4.68629 2 8C2 11.3137 4.68629 14 8 14ZM8 15C11.866 15 15 11.866 15 8C15 4.13401 11.866 1 8 1C4.13401 1 1 4.13401 1 8C1 11.866 4.13401 15 8 15Z"
/>
{#if statusIcon.count && statusIcon.index}
<path
d="M 3.5 3.5 L 7 3.5 A 3.5 3.5 0 {statusIcon.index > (statusIcon.count - 1) / 2 ? 1 : 0} 1 {Math.cos(
d="M 4.5 4.5 L 9 4.5 A 4.5 4.5 0 {statusIcon.index > (statusIcon.count - 1) / 2 ? 1 : 0} 1 {Math.cos(
((2 * Math.PI) / statusIcon.count) * statusIcon.index - 0.01
) *
3.5 +
3.5} {Math.sin(((2 * Math.PI) / statusIcon.count) * statusIcon.index - 0.01) * 3.5 + 3.5} Z"
4.5 +
4.5} {Math.sin(((2 * Math.PI) / statusIcon.count) * statusIcon.index - 0.01) * 4.5 + 4.5} Z"
transform="translate(3.5,3.5)"
/>
{:else}
<circle cx="7" cy="7" r="3.5" fill="var(--error-color)" opacity=".15" />
<circle cx="8" cy="8" r="4" fill="var(--error-color)" opacity=".15" />
{/if}
{:else if category._id === tracker.issueStatusCategory.Completed}
<path
d="M7,0C3.1,0,0,3.1,0,7c0,3.9,3.1,7,7,7c3.9,0,7-3.1,7-7C14,3.1,10.9,0,7,0z M9.9,3.9c0.3-0.3,0.8-0.3,1.2,0l0,0c0.3,0.3,0.3,0.9,0,1.2l-5,5c-0.3,0.3-0.9,0.3-1.2,0l-2-2c-0.3-0.3-0.3-0.9,0-1.2c0.2-0.2,0.4-0.2,0.6-0.2s0.4,0.1,0.6,0.2l1.4,1.4l4-4v0L9.9,3.9z"
d="M8,1C4.1,1,1,4.1,1,8c0,3.9,3.1,7,7,7c3.9,0,7-3.1,7-7C15,4.1,11.9,1,8,1z M8,14c-3.3,0-6-2.7-6-6s2.7-6,6-6s6,2.7,6,6S11.3,14,8,14z"
/>
<path
d="M10.6,6.1L7.5,9.2L5.9,7.6c-0.2-0.2-0.6-0.2-0.8,0s-0.2,0.6,0,0.8l2,2c0.1,0.1,0.3,0.2,0.4,0.2s0.3-0.1,0.4-0.2l3.5-3.5c0.2-0.2,0.2-0.6,0-0.8S10.8,5.8,10.6,6.1z"
/>
{:else if category._id === tracker.issueStatusCategory.Canceled}
<path
style="fill-rule:evenodd;clip-rule:evenodd;"
d="M7,14c3.9,0,7-3.1,7-7c0-3.9-3.1-7-7-7C3.1,0,0,3.1,0,7C0,10.9,3.1,14,7,14z M5,4C4.7,3.7,4.3,3.7,4,4S3.7,4.7,4,5l2,2L4,9C3.7,9.3,3.7,9.7,4,10c0.3,0.3,0.8,0.3,1.1,0l2-2l2,2c0.3,0.3,0.8,0.3,1.1,0c0.3-0.3,0.3-0.8,0-1.1l-2-2l2-2c0.3-0.3,0.3-0.8,0-1.1C9.7,3.7,9.3,3.7,9,4l-2,2L5,4z"
fill-rule="evenodd"
clip-rule="evenodd"
d="M8,1C4.1,1,1,4.1,1,8c0,3.9,3.1,7,7,7c3.9,0,7-3.1,7-7C15,4.1,11.9,1,8,1z M8,14c-3.3,0-6-2.7-6-6s2.7-6,6-6s6,2.7,6,6S11.3,14,8,14z"
/>
<path
fill-rule="evenodd"
clip-rule="evenodd"
d="M10.5,5.5c-0.2-0.2-0.6-0.2-0.8,0L8,7.2L6.3,5.5c-0.2-0.2-0.6-0.2-0.8,0s-0.2,0.6,0,0.8L7.2,8L5.5,9.7c-0.2,0.2-0.2,0.6,0,0.8s0.6,0.2,0.8,0L8,8.8l1.7,1.7c0.2,0.2,0.6,0.2,0.8,0c0.2-0.2,0.2-0.6,0-0.8L8.8,8l1.7-1.7C10.8,6.1,10.8,5.7,10.5,5.5z"
/>
{/if}
</svg>

View File

@ -26,6 +26,7 @@
export let shouldShowAvatar: boolean = false
export let noUnderline = false
export let inline = false
export let kind: 'list' | undefined = undefined
// Extra properties
export let projects: Map<Ref<Project>, Project> | undefined = undefined
@ -48,7 +49,7 @@
{#if value}
<DocNavLink object={value} {onClick} {disableClick} {noUnderline} {inline} component={tracker.component.EditIssue}>
<span class="issuePresenterRoot" class:inline>
<span class="issuePresenterRoot" class:inline class:list={kind === 'list'}>
{#if !inline && shouldShowAvatar}
<div class="icon" use:tooltip={{ label: tracker.string.Issue }}>
<Icon icon={tracker.icon.Issues} size={'small'} />
@ -67,12 +68,17 @@
align-items: center;
flex-shrink: 0;
max-width: 5rem;
color: var(--content-color);
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
cursor: pointer;
&:not(.list) {
color: var(--theme-content-color);
}
&.list {
color: var(--theme-halfcontent-color);
}
.icon {
margin-right: 0.5rem;
color: var(--dark-color);

View File

@ -1,11 +1,11 @@
<script lang="ts">
import { Ref, Space } from '@hcengineering/core'
import { Icon, TabList, SearchEdit } from '@hcengineering/ui'
import { ActionIcon, TabList, SearchEdit, IconMoreH } from '@hcengineering/ui'
import { Viewlet } from '@hcengineering/view'
import { FilterButton, setActiveViewletId } from '@hcengineering/view-resources'
import tracker from '../../plugin'
import { WithLookup } from '@hcengineering/core'
import { deviceOptionsStore as deviceInfo } from '@hcengineering/ui'
// import { deviceOptionsStore as deviceInfo } from '@hcengineering/ui'
export let space: Ref<Space> | undefined = undefined
export let viewlet: WithLookup<Viewlet> | undefined
@ -22,30 +22,24 @@
}
})
$: twoRows = $deviceInfo.twoRows
// $: twoRows = $deviceInfo.twoRows
</script>
<div class="ac-header withSettings" class:full={!twoRows} class:mini={twoRows}>
<div class:ac-header-full={!twoRows} class:flex-between={twoRows}>
<div class="ac-header__wrap-title mr-3">
{#if showLabelSelector}
<slot name="label_selector" />
{:else}
<div class="ac-header__icon"><Icon icon={tracker.icon.Issues} size={'small'} /></div>
<span class="ac-header__title">{label}</span>
{/if}
<div class="ml-4"><FilterButton _class={tracker.class.Issue} {space} /></div>
</div>
<SearchEdit bind:value={search} on:change={() => {}} />
<div class="ac-header full divide">
<div class="ac-header__wrap-title">
{#if showLabelSelector}
<slot name="label_selector" />
{:else}
<span class="ac-header__title">{label}</span>
{/if}
</div>
<div class="ac-header-full" class:secondRow={twoRows}>
<div class="mb-1 clear-mins">
{#if viewlets.length > 1}
<TabList
items={viewslist}
multiselect={false}
selected={viewlet?._id}
kind={'secondary'}
size={'small'}
onlyIcons
on:select={(result) => {
if (result.detail !== undefined) {
if (viewlet?._id === result.detail.id) return
@ -56,6 +50,18 @@
}}
/>
{/if}
<slot name="extra" />
<slot name="header-tools" />
</div>
</div>
<div class="ac-header full divide search-start">
<div class="ac-header-full small-gap">
<SearchEdit bind:value={search} on:change={() => {}} />
<ActionIcon icon={IconMoreH} size={'small'} />
<div class="buttons-divider" />
<FilterButton _class={tracker.class.Issue} {space} />
</div>
<div class="ac-header-full medium-gap">
<slot name="extra" />
<ActionIcon icon={IconMoreH} size={'small'} />
</div>
</div>

View File

@ -110,8 +110,8 @@
{/if}
</svelte:fragment>
</IssuesHeader>
<slot name="afterHeader" />
<FilterBar _class={tracker.class.Issue} query={searchQuery} {viewOptions} on:change={(e) => (resultQuery = e.detail)} />
<slot name="afterHeader" />
<div class="flex w-full h-full clear-mins">
{#if viewlet}
<IssuesContent {viewlet} query={resultQuery} {space} {viewOptions} />

View File

@ -386,12 +386,12 @@
.header {
padding-bottom: 0.75rem;
border-bottom: 1px solid var(--divider-color);
border-bottom: 1px solid var(--theme-divider-color);
.label {
color: var(--caption-color);
color: var(--theme-caption-color);
.counter {
color: rgba(var(--caption-color), 0.8);
color: rgba(var(--theme-caption-color), 0.8);
}
}
}

View File

@ -118,11 +118,11 @@
flex-shrink: 0;
width: 1rem;
height: 1rem;
color: var(--content-color);
color: var(--theme-caption-color);
}
&:hover {
.icon {
color: var(--caption-color) !important;
color: var(--theme-caption-color) !important;
}
}
}

View File

@ -19,6 +19,8 @@
export let value: IssuePriority
export let size: 'small' | 'medium' = 'small'
export let colorInherit: boolean = false
export let accent: boolean = false
export let inline: boolean = false
$: icon = issuePriorities[value]?.icon
@ -27,9 +29,14 @@
<div class="flex-presenter cursor-default">
{#if !inline && icon}
<Icon {icon} {size} />
<Icon {icon} {size} fill={'var(--theme-caption-color)'} />
{/if}
<span class="overflow-label" class:ml-2={!inline && icon}>
<span
class="overflow-label"
class:ml-2={!inline && icon}
style:color={colorInherit ? 'inherit' : 'var(--theme-content-color)'}
class:fs-bold={accent}
>
<Label {label} />
</span>
</div>

View File

@ -99,9 +99,14 @@
{#if value && statuses}
{#if kind === 'list' || kind === 'list-header'}
<!-- svelte-ignore a11y-click-events-have-key-events -->
<div class="flex-row-center flex-no-shrink" class:cursor-pointer={isEditable} on:click={handleStatusEditorOpened}>
<div
class="flex-row-center flex-no-shrink"
class:fix-margin={kind === 'list'}
class:cursor-pointer={isEditable}
on:click={handleStatusEditorOpened}
>
<div class="flex-center flex-no-shrink square-4">
{#if selectedStatus}<IssueStatusIcon value={selectedStatus} size={kind === 'list' ? 'inline' : 'medium'} />{/if}
{#if selectedStatus}<IssueStatusIcon value={selectedStatus} size={kind === 'list' ? 'small' : 'medium'} />{/if}
</div>
{#if selectedStatusLabel}
<span

View File

@ -18,16 +18,34 @@
export let value: IssueStatus | undefined
export let size: 'small' | 'medium' = 'small'
export let kind: 'list-header' | undefined = undefined
export let colorInherit: boolean = false
export let accent: boolean = false
export let inline: boolean = false
</script>
{#if value}
<div class="flex-presenter cursor-default">
<div class="flex-presenter cursor-default" style:color={'inherit'}>
{#if !inline}
<IssueStatusIcon {value} {size} />
{/if}
<span class="overflow-label" class:ml-2={!inline}>
<span
class="overflow-label"
class:ml-2={!inline}
class:list-header={kind === 'list-header'}
class:colorInherit
class:fs-bold={accent}
>
{value.name}
</span>
</div>
{/if}
<style lang="scss">
.list-header:not(.colorInherit) {
color: var(--theme-content-color);
}
.list-header.colorInherit {
color: inherit;
}
</style>

View File

@ -19,8 +19,17 @@
export let value: Ref<Status> | StatusValue | undefined
export let size: 'small' | 'medium' = 'medium'
export let kind: 'list-header' | undefined = undefined
export let colorInherit: boolean = false
export let accent: boolean = false
</script>
{#if value}
<StatusPresenter value={$statusStore.get(typeof value === 'string' ? value : value.values?.[0]?._id)} {size} />
<StatusPresenter
value={$statusStore.get(typeof value === 'string' ? value : value.values?.[0]?._id)}
{size}
{kind}
{colorInherit}
{accent}
/>
{/if}

Some files were not shown because too many files have changed in this diff Show More