UBER-675: updated pop-ups and components layout (#3631)

Signed-off-by: Alexander Platov <sas_lord@mail.ru>
This commit is contained in:
Alexander Platov
2023-08-25 16:49:14 +07:00
committed by GitHub
parent 15b61ce2fa
commit 97abd2fc12
42 changed files with 864 additions and 509 deletions
+1 -1
View File
@@ -1 +1 @@
{ "major": 0, "minor": 6, "patch": 120 }
{ "major": 0, "minor": 6, "patch": 120 }
+2
View File
@@ -144,6 +144,7 @@
--theme-editbox-focus-color: rgba(255, 255, 255, .04);
--theme-editbox-focus-border: #5190EC;
--theme-editbox-default-focus-border: #205DC2; // Light
--theme-tablist-color: rgba(0, 0, 0, .02);
--theme-tablist-plain-color: #2A64C4; // Light
--theme-tablist-plain-divider: rgba(255, 255, 255, .07); // Light invert
@@ -339,6 +340,7 @@
--theme-editbox-focus-color: rgba(0, 0, 0, .08);
--theme-editbox-focus-border: #5190EC;
--theme-editbox-default-focus-border: #205DC2;
--theme-tablist-color: rgba(0, 0, 0, .02);
--theme-tablist-plain-color: #2A64C4;
--theme-tablist-plain-divider: rgba(0, 0, 0, .07);
+16 -1
View File
@@ -265,8 +265,11 @@ input.search {
.justify-center { justify-content: center; }
.justify-stretch { justify-content: stretch; }
.items-baseline { align-items: baseline; }
.items-start { align-items: flex-start; }
.items-center { align-items: center; }
.self-end { align-self: end; }
.items-stretch { align-items: stretch; }
.self-start { align-self: flex-start; }
.self-end { align-self: flex-end; }
.flex-gap-4 { gap: 1rem; }
.flex-gap-3 { gap: .75rem; }
@@ -465,6 +468,7 @@ input.search {
.ml-2 { margin-left: .5rem; }
.ml-3 { margin-left: .75rem; }
.ml-4 { margin-left: 1rem; }
.ml-5-5 { margin-left: 1.375rem; }
.ml-6 { margin-left: 1.5rem; }
.ml-8 { margin-left: 2rem; }
.ml-10 { margin-left: 2.5rem; }
@@ -524,6 +528,7 @@ input.search {
.pl-2 { padding-left: .5rem; }
.pl-3 { padding-left: .75rem; }
.pl-4 { padding-left: 1rem; }
.pl-5-5 { padding-left: 1.375rem; }
.pl-7 { padding-left: 1.75rem; }
.pl-8 { padding-left: 2rem; }
.pl-9 { padding-left: 2.25rem; }
@@ -534,10 +539,12 @@ input.search {
.pr-4 { padding-right: 1rem; }
.pr-8 { padding-right: 2rem; }
.pr-24 { padding-right: 6rem; }
.pt-1 { padding-top: .25rem; }
.pt-2 { padding-top: .5rem; }
.pt-3 { padding-top: .75rem; }
.pt-4 { padding-top: 1rem; }
.pt-6 { padding-top: 1.5rem; }
.pb-0-5 { padding-bottom: .125rem; }
.pb-1 { padding-bottom: .25rem !important; }
.pb-2 { padding-bottom: .5rem; }
.pb-3 { padding-bottom: .75rem; }
@@ -550,6 +557,7 @@ input.search {
.px-4 { padding: 0 1rem; }
.px-6 { padding: 0 1.5rem; }
.px-10 { padding: 0 2.5rem; }
.py-0-5 { padding: 0.125rem 0; }
.py-1 { padding: 0.25rem 0; }
.py-4 { padding: 1rem 0; }
.py-8 { padding: 2rem 0; }
@@ -560,6 +568,7 @@ input.search {
.p-2 { padding: .5rem; }
.p-3 { padding: .75rem; }
.p-4 { padding: 1rem; }
.p-5 { padding: 1.25rem; }
.p-6 { padding: 1.5rem; }
.p-10 { padding: 2.5rem; }
@@ -568,6 +577,8 @@ input.search {
.step-lr25 + .step-lr25 { margin-left: .25rem; }
.step-lr75 + .step-lr75 { margin-left: .75rem; }
.step-tb25 + .step-tb25 { margin-top: .25rem; }
.step-tb375 + .step-tb375 { margin-top: .375rem; }
.step-tb75 + .step-tb75 { margin-top: .75rem; }
.step-tb-6 + .step-tb-6 { margin-top: 1.5rem; }
.step-tb-12 + .step-tb-12 { margin-top: 3rem; }
@@ -640,6 +651,7 @@ input.search {
.h-18 { height: 4.5rem; }
.h-50 { height: 12.5rem; }
.h-60 { height: 15.0rem; }
.w-min { width: min-content; }
.w-full { width: 100%; }
.w-2 { width: .5rem; }
.w-4 { width: 1rem; }
@@ -659,6 +671,7 @@ input.search {
.min-w-4 { min-width: 1rem; }
.min-w-8 { min-width: 2rem; }
.min-w-9 { min-width: 2.25rem; }
.min-w-12 { min-width: 3rem; }
.min-w-60 { min-width: 15rem; }
.min-w-80 { min-width: 20rem; }
.min-w-100 { min-width: 25rem; }
@@ -669,6 +682,7 @@ input.search {
.min-h-4 { min-height: 1rem; }
.min-h-5 { min-height: 1.25rem; }
.min-h-7 { min-height: 1.75rem; }
.min-h-8 { min-height: 2rem; }
.min-h-30 { min-height: 7.5rem; }
.min-h-60 { min-height: 15rem; }
.max-w-2 { max-width: .5rem; }
@@ -786,6 +800,7 @@ a.no-line {
user-select: none;
}
.text-xs { font-size: .625rem; }
.text-11px { font-size: .6875rem; }
.text-sm { font-size: .75rem; }
.text-md { font-size: .8125rem; }
.text-normal { font-size: var(--body-font-size); }
+13 -3
View File
@@ -27,7 +27,7 @@
font-size: .8125rem;
&.only-icon { width: 1.75rem; }
}
&.medium {
&.medium:not(.stepper) {
height: 2rem;
&.only-icon { width: 2rem; }
}
@@ -59,6 +59,7 @@
&.short { max-width: 8.5rem; }
&.accent { font-weight: 500; }
&.sh-no-shape { border-radius: .25rem; }
&.sh-round-sm { border-radius: .375rem; }
&.sh-round { border-radius: .5rem; }
&.sh-round2 { border-radius: .75rem; }
&.sh-circle { border-radius: 1rem; }
@@ -89,7 +90,8 @@
&.jf-center { justify-content: center; }
&.only-icon {
flex-shrink: 0 !important;
padding: 0;
&:not(.stepper) { padding: 0; }
}
&.regular {
@@ -133,7 +135,7 @@
}
}
}
&.ghost {
&.ghost, &.stepper {
&:hover { background-color: var(--theme-button-hovered); }
&:active { background-color: var(--theme-button-pressed); }
&.selected { background-color: var(--highlight-select); }
@@ -265,6 +267,14 @@
background-color: var(--theme-button-contrast-disabled);
}
}
&.stepper {
padding: 0;
width: 1rem;
height: .8125rem;
min-width: 1rem;
&:focus { box-shadow: 0 0 0 1px var(--accented-button-outline); }
}
&.notSelected {
color: var(--theme-dark-color);
+1
View File
@@ -403,6 +403,7 @@
&:not(.withMargins) { margin: 0 !important; }
&.x0-5 { height: .125rem; }
&.x1-5 { height: .375rem; }
&.x2 { height: .5rem; }
&.x3 { height: .75rem; }
+35
View File
@@ -788,6 +788,41 @@
}
}
/* Option */
.antiOption {
position: relative;
display: flex;
justify-content: space-between;
align-items: center;
padding: 0 .25rem;
height: 2rem;
min-width: 0;
font-size: .8125rem;
border-radius: .375rem;
outline: none;
z-index: 1;
.tools { opacity: 0; }
&.leftPadding { padding-left: 0.625rem; }
&::before {
position: absolute;
top: -.125rem;
bottom: -.125rem;
left: -.125rem;
right: -.125rem;
border: 1px solid var(--theme-editbox-default-focus-border);
border-radius: .5rem;
z-index: -1;
}
&:hover {
background-color: var(--theme-button-hovered);
.tools { opacity: 1; }
}
&:focus-within::before, &:focus::before { content: ''; }
}
/* Wraps */
.antiWrapper {
position: relative;
+97
View File
@@ -0,0 +1,97 @@
.antiEditBox {
display: inline-flex;
flex-direction: column;
align-items: flex-start;
min-width: 0;
.large-style {
font-weight: 400;
font-size: 1.25rem;
}
.small-style {
font-weight: 400;
font-size: 0.75rem;
}
.search-style {
font-weight: 400;
padding: 0.625rem 0.75rem;
}
.underline {
font-weight: 500;
input {
padding: 0.25rem 0.5rem;
background-color: var(--theme-editbox-focus-color);
border-radius: 0.25rem;
&:focus { box-shadow: 0 0 0 1px var(--theme-editbox-focus-border); }
}
}
.focusable:not(.default, .default-large, .ghost, .ghost-large) {
margin: 0 -0.75rem;
padding: 0.625rem 0.75rem;
width: calc(100% + 1.5rem);
border-radius: 0.25rem;
transition: border-color 0.15s ease-in-out;
&:focus-within { box-shadow: 0 0 0 1px var(--theme-editbox-focus-border); }
}
input {
margin: 0;
padding: 0;
min-width: 0;
color: var(--theme-caption-color);
border: none;
border-radius: 2px;
&::-webkit-contacts-auto-fill-button,
&::-webkit-credentials-auto-fill-button {
visibility: hidden;
display: none !important;
pointer-events: none;
height: 0;
width: 0;
margin: 0;
}
&.number::-webkit-outer-spin-button,
&.number::-webkit-inner-spin-button { -webkit-appearance: none; }
}
input[type='number'] { -moz-appearance: textfield; }
&.uppercase .hidden-text,
&.uppercase input { text-transform: uppercase; }
.default, .ghost {
font-weight: 400;
font-size: .8125rem;
}
.default-large, .ghost-large {
font-weight: 500;
font-size: 1rem;
}
.default, .ghost { padding: 0.3125rem 0.5rem; }
.default-large, .ghost-large { padding: 0.4375rem 0.5rem; }
.default, .ghost, .default-large, .ghost-large {
box-sizing: border-box;
line-height: 1.25rem;
border-radius: .375rem;
border: 1px solid transparent;
input {
color: inherit;
&::placeholder { color: var(--theme-darker-color); }
}
&:hover { background-color: var(--theme-button-hovered); }
&.focusable:focus-within {
background-color: var(--theme-button-focused);
border-color: var(--theme-editbox-default-focus-border);
}
&.disabled {
color: var(--theme-dark-color);
background-color: transparent;
border-color: var(--theme-divider-color);
}
}
.default, .default-large { border-color: var(--theme-divider-color); }
}
+1
View File
@@ -17,6 +17,7 @@
@import "./_layouts.scss";
@import "./common.scss";
@import "./button.scss";
@import "./editors.scss";
@import "./components.scss";
@import "./dialogs.scss";
@import "./popups.scss";
+20 -2
View File
@@ -222,6 +222,7 @@
.ap-space {
flex-shrink: 0;
height: .25rem;
&.x1-5 { height: .375rem; }
&.x2 { height: .5rem; }
&.x3 { height: .75rem; }
}
@@ -255,11 +256,13 @@
cursor: pointer;
&:not(.separator) {
margin: 0 .5rem;
min-height: 2.25rem;
border-radius: .25rem;
}
&:not(.separator, .withComp) { padding: .25rem .5rem; }
&:not(.separator, .noMargin) {
margin-left: .5rem;
margin-right: .5rem;
}
&.withComp {
display: flex;
align-items: center;
@@ -340,6 +343,21 @@
&.halfMargin { margin: .25rem 0; }
}
}
&:not(.thinStyle) .ap-menuItem:not(.separator, .withComp) { padding: .25rem .5rem; }
&.thinStyle {
border-radius: .75rem;
.ap-menuItem:not(.separator) {
padding: 0 .5rem;
min-height: 2rem;
font-size: .8125rem;
border-radius: .375rem;
}
.ap-menuItem:not(.separator, .noMargin) {
margin-left: .375rem;
margin-right: .375rem;
}
}
.ap-check {
flex-shrink: 0;
margin-left: 1rem;
+3
View File
@@ -9,6 +9,9 @@
"Days": "{days, plural, =0 {today} =1 {yesterday} other {# days ago}}",
"Months": "{months, plural, =0 {this month} =1 {a month ago} other {# months ago}}",
"Years": "{years, plural, =0 {this year} =1 {a year ago} other {# years ago}}",
"MinutesShort": "{value}m",
"HoursShort": "{value}h",
"DaysShort": "{value}d",
"ShowMore": "Show more",
"ShowLess": "Show less",
"Search": "Search",
+3
View File
@@ -9,6 +9,9 @@
"Days": "{days, plural, =0 {сегодня} =1 {вчера} one {# день назад} few {# дня назад} other {# дней назад}}",
"Months": "{months, plural, =0 {в этом месяце} =1 {месяц назад} one {# месяц назад} few {# месяца назад} other {# месяцев назад}}",
"Years": "{years, plural, =0 {в этом году} =1 {год назад} one {# год назад} few {# год назад} other {# лет назад}}",
"MinutesShort": "{value}м",
"HoursShort": "{value}ч",
"DaysShort": "{value}д",
"ShowMore": "Показать больше",
"ShowLess": "Показать меньше",
"Search": "Поиск",
+2 -77
View File
@@ -133,7 +133,7 @@
<!-- svelte-ignore a11y-click-events-have-key-events -->
<div
class="editbox-container"
class="antiEditBox"
class:flex-grow={fullSize}
class:w-full={focusable || fullSize}
class:uppercase
@@ -152,7 +152,7 @@
{#if required}<span class="error-color">&ast</span>{/if}
</div>
{/if}
<div class="{kind} flex-row-center clear-mins" class:focusable>
<div class="{kind} flex-row-center clear-mins" class:focusable class:disabled class:w-full={fullSize}>
{#if icon}
<div class="dark-color mr-1">
<Icon {icon} size={'small'} />
@@ -205,78 +205,3 @@
{/if}
</div>
</div>
<style lang="scss">
.editbox-container {
display: inline-flex;
flex-direction: column;
align-items: flex-start;
.large-style {
font-weight: 400;
font-size: 1.25rem;
}
.small-style {
font-weight: 400;
font-size: 0.75rem;
}
.search-style {
font-weight: 400;
padding: 0.625rem 0.75rem;
}
.underline {
font-weight: 500;
input {
padding: 0.25rem 0.5rem;
background-color: var(--theme-editbox-focus-color);
border-radius: 0.25rem;
&:focus {
box-shadow: 0 0 0 1px var(--theme-editbox-focus-border);
}
}
}
.focusable {
margin: 0 -0.75rem;
padding: 0.625rem 0.75rem;
width: calc(100% + 1.5rem);
border-radius: 0.25rem;
transition: border-color 0.15s ease-in-out;
&:focus-within {
box-shadow: 0 0 0 1px var(--theme-editbox-focus-border);
}
}
input {
margin: 0;
padding: 0;
min-width: 0;
color: var(--theme-caption-color);
border: none;
border-radius: 2px;
&::-webkit-contacts-auto-fill-button,
&::-webkit-credentials-auto-fill-button {
visibility: hidden;
display: none !important;
pointer-events: none;
height: 0;
width: 0;
margin: 0;
}
&.number::-webkit-outer-spin-button,
&.number::-webkit-inner-spin-button {
-webkit-appearance: none;
}
}
input[type='number'] {
-moz-appearance: textfield;
}
&.uppercase .hidden-text,
&.uppercase input {
text-transform: uppercase;
}
}
</style>
+11 -1
View File
@@ -20,6 +20,7 @@
export let count: number
export let addClass: string | undefined = undefined
export let noScroll: boolean = false
export let kind: 'default' | 'thin' = 'default'
const refs: HTMLElement[] = []
@@ -60,7 +61,7 @@
{#if count}
<div
class="list-container flex-col flex-grow"
class="list-container {kind} flex-col flex-grow"
style:overflow={noScroll ? 'visible' : 'auto'}
use:resizeObserver={() => {
dispatch('changeContent')
@@ -95,6 +96,15 @@
min-width: 0;
border-radius: 0.25rem;
}
&.thin {
.list-item {
margin: 0 0.375rem;
border-radius: 0.375rem;
}
.list-item + .list-item {
margin-top: 0.375rem;
}
}
.selection {
background-color: var(--theme-popup-hover);
}
@@ -23,6 +23,7 @@
import { floorFractionDigits } from '../utils'
import DownOutline from './icons/DownOutline.svelte'
import UpOutline from './icons/UpOutline.svelte'
import Button from './Button.svelte'
export let maxWidth: string | undefined = undefined
export let value: number = 0
@@ -145,13 +146,9 @@
on:keypress
on:blur
/>
<div class="flex-col-center">
<div on:click={() => value++}>
<UpOutline size="small" />
</div>
<div on:click={() => value--}>
<DownOutline size="small" />
</div>
<div class="flex-col-center py-0-5">
<Button icon={UpOutline} kind={'stepper'} padding={'0'} {disabled} on:click={() => value++} />
<Button icon={DownOutline} kind={'stepper'} padding={'0'} {disabled} on:click={() => value--} />
</div>
</div>
</div>
@@ -161,9 +158,9 @@
display: inline-flex;
flex-direction: column;
align-items: flex-start;
padding: 0rem 0.125rem 0 0.5rem;
border: 1px solid var(--theme-divider-color);
border-radius: 0.375rem;
border: 1px solid var(--theme-table-border-color);
padding: 0rem 0.5rem;
input {
margin: 0;
@@ -181,6 +178,9 @@
width: 0;
margin: 0;
}
&:disabled {
color: var(--theme-darker-color);
}
&.number::-webkit-outer-spin-button,
&.number::-webkit-inner-spin-button {
@@ -19,17 +19,27 @@
import { DAY, HOUR, MINUTE } from '../types'
export let value: number
export let exact: boolean = false
let time: string = ''
async function formatTime (value: number) {
if (value > 0) {
if (value < HOUR) {
time = await translate(ui.string.MinutesAfter, { minutes: Math.floor(value / MINUTE) }, $themeStore.language)
} else if (value < DAY) {
time = await translate(ui.string.HoursAfter, { hours: Math.floor(value / HOUR) }, $themeStore.language)
if (exact) {
const d = Math.floor(value / DAY)
time = d ? await translate(ui.string.DaysShort, { value: d }, $themeStore.language) : ''
const h = Math.floor((value - d * DAY) / HOUR)
time += h ? ` ${await translate(ui.string.HoursShort, { value: h }, $themeStore.language)}` : ''
const m = Math.floor((value - d * DAY - h * HOUR) / MINUTE)
time += m ? ` ${await translate(ui.string.MinutesShort, { value: m }, $themeStore.language)}` : ''
} else {
time = await translate(ui.string.DaysAfter, { days: Math.floor(value / DAY) }, $themeStore.language)
if (value < HOUR) {
time = await translate(ui.string.MinutesAfter, { minutes: Math.floor(value / MINUTE) }, $themeStore.language)
} else if (value < DAY) {
time = await translate(ui.string.HoursAfter, { hours: Math.floor(value / HOUR) }, $themeStore.language)
} else {
time = await translate(ui.string.DaysAfter, { days: Math.floor(value / DAY) }, $themeStore.language)
}
}
} else {
const abs = Math.abs(value)
@@ -142,7 +142,7 @@
selected = index === 0 ? edits[1].id : edits[index - 1].id
}
if (ev.code === 'ArrowRight' && edits[index].el) {
selected = index === 4 ? edits[0].id : edits[index + 1].id
selected = index === 1 ? edits[0].id : edits[index + 1].id
}
if (ev.code === 'Tab') {
if (ed === 'min') dispatch('save')
@@ -3,8 +3,8 @@
export let fill: string = 'currentColor'
</script>
<svg class="svg-{size}" {fill} viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg">
<svg class="svg-{size}" {fill} viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
<path
d="M5.18306 5.18306C4.93898 5.42714 4.93898 5.82286 5.18306 6.06694L9.11612 10L5.18306 13.9331C4.93898 14.1771 4.93898 14.5729 5.18306 14.8169C5.42714 15.061 5.82286 15.061 6.06694 14.8169L10 10.8839L13.9331 14.8169C14.1771 15.061 14.5729 15.061 14.8169 14.8169C15.061 14.5729 15.061 14.1771 14.8169 13.9331L10.8839 10L14.8169 6.06694C15.061 5.82286 15.061 5.42714 14.8169 5.18306C14.5729 4.93898 14.1771 4.93898 13.9331 5.18306L10 9.11612L6.06694 5.18306C5.82286 4.93898 5.42714 4.93898 5.18306 5.18306Z"
d="M3.14645 3.14645C2.95118 3.34171 2.95118 3.65829 3.14645 3.85355L7.29289 8L3.14645 12.1464C2.95118 12.3417 2.95118 12.6583 3.14645 12.8536C3.34171 13.0488 3.65829 13.0488 3.85355 12.8536L8 8.70711L12.1464 12.8536C12.3417 13.0488 12.6583 13.0488 12.8536 12.8536C13.0488 12.6583 13.0488 12.3417 12.8536 12.1464L8.70711 8L12.8536 3.85355C13.0488 3.65829 13.0488 3.34171 12.8536 3.14645C12.6583 2.95118 12.3417 2.95118 12.1464 3.14645L8 7.29289L3.85355 3.14645C3.65829 2.95118 3.34171 2.95118 3.14645 3.14645Z"
/>
</svg>
+10 -4
View File
@@ -3,8 +3,14 @@
const fill: string = 'currentColor'
</script>
<svg class="svg-{size}" {fill} viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
<circle cx="8" cy="8" r="1" />
<circle cx="4" cy="8" r="1" />
<circle cx="12" cy="8" r="1" />
<svg class="svg-{size}" {fill} viewBox="0 0 32 32" xmlns="http://www.w3.org/2000/svg">
<path
d="M8 18C9.10457 18 10 17.1046 10 16C10 14.8954 9.10457 14 8 14C6.89543 14 6 14.8954 6 16C6 17.1046 6.89543 18 8 18Z"
/>
<path
d="M16 18C17.1046 18 18 17.1046 18 16C18 14.8954 17.1046 14 16 14C14.8954 14 14 14.8954 14 16C14 17.1046 14.8954 18 16 18Z"
/>
<path
d="M26 16C26 17.1046 25.1046 18 24 18C22.8954 18 22 17.1046 22 16C22 14.8954 22.8954 14 24 14C25.1046 14 26 14.8954 26 16Z"
/>
</svg>
+10 -4
View File
@@ -3,8 +3,14 @@
const fill: string = 'currentColor'
</script>
<svg class="svg-{size}" {fill} viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
<path d="M8,6.6C7.3,6.6,6.7,7.2,6.7,8S7.3,9.4,8,9.4S9.4,8.8,9.4,8S8.8,6.6,8,6.6z" />
<path d="M8,4.6c0.8,0,1.4-0.6,1.4-1.4S8.8,1.8,8,1.8S6.7,2.4,6.7,3.2S7.3,4.6,8,4.6z" />
<path d="M8,11.4c-0.8,0-1.4,0.6-1.4,1.4c0,0.8,0.6,1.4,1.4,1.4s1.4-0.6,1.4-1.4C9.4,12,8.8,11.4,8,11.4z" />
<svg class="svg-{size}" {fill} viewBox="0 0 32 32" xmlns="http://www.w3.org/2000/svg">
<path
d="M14 8C14 9.10457 14.8954 10 16 10C17.1046 10 18 9.10457 18 8C18 6.89543 17.1046 6 16 6C14.8954 6 14 6.89543 14 8Z"
/>
<path
d="M14 16C14 17.1046 14.8954 18 16 18C17.1046 18 18 17.1046 18 16C18 14.8954 17.1046 14 16 14C14.8954 14 14 14.8954 14 16Z"
/>
<path
d="M16 26C14.8954 26 14 25.1046 14 24C14 22.8954 14.8954 22 16 22C17.1046 22 18 22.8954 18 24C18 25.1046 17.1046 26 16 26Z"
/>
</svg>
+3
View File
@@ -34,6 +34,9 @@ export const uis = plugin(uiId, {
Days: '' as IntlString,
Months: '' as IntlString,
Years: '' as IntlString,
MinutesShort: '' as IntlString,
HoursShort: '' as IntlString,
DaysShort: '' as IntlString,
ShowMore: '' as IntlString,
ShowLess: '' as IntlString,
Search: '' as IntlString,
+12 -1
View File
@@ -139,17 +139,28 @@ export type ButtonKind =
| 'list'
| 'list-header'
| 'contrast'
| 'stepper'
export type ButtonSize = 'inline' | 'x-small' | 'small' | 'medium' | 'large' | 'x-large'
export type ButtonShape =
| 'rectangle'
| 'rectangle-left'
| 'rectangle-right'
| 'circle'
| 'round-sm'
| 'round'
| 'round2'
| 'filter'
| undefined
export type EditStyle = 'editbox' | 'large-style' | 'small-style' | 'search-style' | 'underline'
export type EditStyle =
| 'editbox'
| 'large-style'
| 'small-style'
| 'search-style'
| 'underline'
| 'default'
| 'ghost'
| 'default-large'
| 'ghost-large'
export interface PopupPositionElement {
getBoundingClientRect: () => DOMRect
position?: {
+14 -14
View File
@@ -19,22 +19,22 @@
<path d="M8 4C8 3.72386 7.77614 3.5 7.5 3.5C7.22386 3.5 7 3.72386 7 4V8.5C7 8.77614 7.22386 9 7.5 9H10.5C10.7761 9 11 8.77614 11 8.5C11 8.22386 10.7761 8 10.5 8L8 8V4Z" />
<path fill-rule="evenodd" clip-rule="evenodd" d="M15 8C15 11.866 11.866 15 8 15C4.13401 15 1 11.866 1 8C1 4.13401 4.13401 1 8 1C11.866 1 15 4.13401 15 8ZM14 8C14 11.3137 11.3137 14 8 14C4.68629 14 2 11.3137 2 8C2 4.68629 4.68629 2 8 2C11.3137 2 14 4.68629 14 8Z" />
</symbol>
<symbol id="description" viewBox="0 0 16 16">
<path d="M2 4.5C2 4.22386 2.22386 4 2.5 4H13.5C13.7761 4 14 4.22386 14 4.5C14 4.77614 13.7761 5 13.5 5H2.5C2.22386 5 2 4.77614 2 4.5Z" fill-opacity="0.6"/>
<path d="M2 8C2 7.72386 2.22386 7.5 2.5 7.5H9.5C9.77614 7.5 10 7.72386 10 8C10 8.27614 9.77614 8.5 9.5 8.5H2.5C2.22386 8.5 2 8.27614 2 8Z" fill-opacity="0.6"/>
<path d="M2 11.5C2 11.2239 2.22386 11 2.5 11H11.5C11.7761 11 12 11.2239 12 11.5C12 11.7761 11.7761 12 11.5 12H2.5C2.22386 12 2 11.7761 2 11.5Z" fill-opacity="0.6"/>
<symbol id="description" viewBox="0 0 32 32">
<path d="M4 9.00024C4 8.44796 4.44772 8.00024 5 8.00024H27C27.5523 8.00024 28 8.44796 28 9.00024C28 9.55253 27.5523 10.0002 27 10.0002H5C4.44772 10.0002 4 9.55253 4 9.00024Z" />
<path d="M4 16.0002C4 15.448 4.44772 15.0002 5 15.0002H19C19.5523 15.0002 20 15.448 20 16.0002C20 16.5525 19.5523 17.0002 19 17.0002H5C4.44772 17.0002 4 16.5525 4 16.0002Z" />
<path d="M4 23.0002C4 22.448 4.44772 22.0002 5 22.0002H23C23.5523 22.0002 24 22.448 24 23.0002C24 23.5525 23.5523 24.0002 23 24.0002H5C4.44772 24.0002 4 23.5525 4 23.0002Z" />
</symbol>
<symbol id="participants" viewBox="0 0 16 16">
<path fill-rule="evenodd" clip-rule="evenodd" d="M2 5.5C2 3.567 3.567 2 5.5 2C7.433 2 9 3.567 9 5.5C9 7.433 7.433 9 5.5 9C3.567 9 2 7.433 2 5.5ZM5.5 3C4.11929 3 3 4.11929 3 5.5C3 6.88071 4.11929 8 5.5 8C6.88071 8 8 6.88071 8 5.5C8 4.11929 6.88071 3 5.5 3Z" fill-opacity="0.6"/>
<path d="M10.5 10C10.2239 10 10 10.2239 10 10.5C10 10.7761 10.2239 11 10.5 11H11.5C12.8807 11 14 12.1193 14 13.5C14 13.7761 14.2239 14 14.5 14C14.7761 14 15 13.7761 15 13.5C15 11.567 13.433 10 11.5 10H10.5Z" fill-opacity="0.6"/>
<path d="M4.5 11C3.11929 11 2 12.1193 2 13.5C2 13.7761 1.77614 14 1.5 14C1.22386 14 1 13.7761 1 13.5C1 11.567 2.567 10 4.5 10H6.5C8.433 10 10 11.567 10 13.5C10 13.7761 9.77614 14 9.5 14C9.22386 14 9 13.7761 9 13.5C9 12.1193 7.88071 11 6.5 11H4.5Z" fill-opacity="0.6"/>
<path d="M10.5 2.99988C10.2238 2.99988 9.99995 3.22374 9.99995 3.49988C9.99995 3.77602 10.2238 3.99988 10.5 3.99988C10.7846 3.99988 11.0661 4.06066 11.3254 4.17815C11.5847 4.29564 11.8159 4.46714 12.0036 4.68119C12.1913 4.89523 12.3312 5.14688 12.4138 5.41931C12.4965 5.69174 12.52 5.97868 12.4828 6.26093C12.4457 6.54318 12.3487 6.81425 12.1984 7.05601C12.048 7.29777 11.8478 7.50465 11.6111 7.66282C11.3744 7.82098 11.1066 7.92679 10.8257 7.97316C10.5449 8.01954 10.2573 8.00541 9.98232 7.93173C9.71558 7.86026 9.44141 8.01855 9.36994 8.28528C9.29847 8.55202 9.45677 8.82618 9.7235 8.89766C10.136 9.00818 10.5673 9.02937 10.9886 8.95981C11.41 8.89025 11.8116 8.73153 12.1667 8.49429C12.5217 8.25704 12.8221 7.94672 13.0476 7.58408C13.2731 7.22144 13.4186 6.81484 13.4743 6.39146C13.53 5.96807 13.4947 5.53767 13.3708 5.12902C13.2468 4.72038 13.037 4.3429 12.7555 4.02184C12.4739 3.70078 12.127 3.44353 11.7381 3.26729C11.3491 3.09105 10.927 2.99988 10.5 2.99988Z" fill-opacity="0.6"/>
<symbol id="participants" viewBox="0 0 32 32">
<path fill-rule="evenodd" clip-rule="evenodd" d="M4 11.0002C4 7.13425 7.13401 4.00024 11 4.00024C14.866 4.00024 18 7.13425 18 11.0002C18 14.8662 14.866 18.0002 11 18.0002C7.13401 18.0002 4 14.8662 4 11.0002ZM11 6.00024C8.23858 6.00024 6 8.23882 6 11.0002C6 13.7617 8.23858 16.0002 11 16.0002C13.7614 16.0002 16 13.7617 16 11.0002C16 8.23882 13.7614 6.00024 11 6.00024Z" />
<path d="M21 20.0002C20.4477 20.0002 20 20.448 20 21.0002C20 21.5525 20.4477 22.0002 21 22.0002H23C25.7614 22.0002 28 24.2388 28 27.0002C28 27.5525 28.4477 28.0002 29 28.0002C29.5523 28.0002 30 27.5525 30 27.0002C30 23.1343 26.866 20.0002 23 20.0002H21Z" />
<path d="M9 22.0002C6.23858 22.0002 4 24.2388 4 27.0002C4 27.5525 3.55228 28.0002 3 28.0002C2.44772 28.0002 2 27.5525 2 27.0002C2 23.1343 5.13401 20.0002 9 20.0002H13C16.866 20.0002 20 23.1343 20 27.0002C20 27.5525 19.5523 28.0002 19 28.0002C18.4477 28.0002 18 27.5525 18 27.0002C18 24.2388 15.7614 22.0002 13 22.0002H9Z" />
<path d="M20.9999 6C20.4476 6 19.9999 6.44772 19.9999 7C19.9999 7.55228 20.4476 8 20.9999 8C21.5693 8 22.1321 8.12156 22.6507 8.35654C23.1694 8.59153 23.6318 8.93453 24.0073 9.36262C24.3827 9.7907 24.6624 10.294 24.8277 10.8389C24.993 11.3837 25.04 11.9576 24.9657 12.5221C24.8914 13.0866 24.6974 13.6288 24.3967 14.1123C24.096 14.5958 23.6956 15.0095 23.2222 15.3259C22.7488 15.6422 22.2133 15.8538 21.6515 15.9466C21.0897 16.0393 20.5146 16.0111 19.9646 15.8637C19.4312 15.7208 18.8828 16.0373 18.7399 16.5708C18.5969 17.1043 18.9135 17.6526 19.447 17.7956C20.272 18.0166 21.1346 18.059 21.9773 17.9199C22.8199 17.7807 23.6232 17.4633 24.3333 16.9888C25.0435 16.5143 25.6441 15.8937 26.0951 15.1684C26.5461 14.4431 26.8371 13.6299 26.9486 12.7832C27.0601 11.9364 26.9895 11.0756 26.7416 10.2583C26.4936 9.441 26.0741 8.68605 25.5109 8.04392C24.9478 7.4018 24.2541 6.8873 23.4762 6.53482C22.6982 6.18234 21.854 6 20.9999 6Z" />
</symbol>
<symbol id="repeat" viewBox="0 0 16 16">
<path d="M10.0003 4.99986H12.6103C11.9636 4.00602 11.0131 3.24777 9.90035 2.83815C8.78765 2.42852 7.57236 2.38944 6.43564 2.72675C5.29892 3.06405 4.30164 3.75967 3.59247 4.70992C2.98332 5.52613 2.61475 6.49266 2.52293 7.50049C2.49788 7.7755 2.27614 7.99986 1.99998 7.99986C1.72404 7.99986 1.49802 7.77598 1.51892 7.50083C1.60709 6.33998 2.00581 5.22075 2.67752 4.26241C3.44506 3.16736 4.53166 2.33568 5.78917 1.88079C7.04668 1.4259 8.41389 1.36994 9.70437 1.72053C10.9948 2.07112 12.1458 2.8112 13.0003 3.83986V1.99986H14.0003V5.99986H10.0003V4.99986Z" fill-opacity="0.6"/>
<path d="M6.00026 10.9999H3.39026C4.03693 11.9937 4.98746 12.7519 6.10016 13.1616C7.21287 13.5712 8.42816 13.6103 9.56487 13.273C10.7016 12.9357 11.6989 12.24 12.408 11.2898C13.0172 10.4736 13.3858 9.50706 13.4776 8.49923C13.5026 8.22421 13.7244 7.99986 14.0005 7.99986C14.2765 7.99986 14.5025 8.22373 14.4816 8.49888C14.3934 9.65973 13.9947 10.779 13.323 11.7373C12.5555 12.8324 11.4689 13.664 10.2113 14.1189C8.95384 14.5738 7.58663 14.6298 6.29615 14.2792C5.00567 13.9286 3.85472 13.1885 3.00026 12.1599V13.9999H2.00026V9.99986H6.00026V10.9999Z" fill-opacity="0.6"/>
<symbol id="repeat" viewBox="0 0 32 32">
<path d="M20 9.99996H25.22C23.9267 8.01228 22.0256 6.49579 19.8002 5.67653C17.5748 4.85728 15.1442 4.77913 12.8708 5.45374C10.5974 6.12835 8.6028 7.51959 7.18444 9.42008C5.96615 11.0525 5.229 12.9856 5.04538 15.0012C4.99528 15.5513 4.55179 16 3.99948 16C3.4476 16 2.99556 15.5522 3.03735 15.0019C3.21369 12.6802 4.01114 10.4417 5.35455 8.52507C6.88962 6.33496 9.06283 4.67161 11.5778 3.76183C14.0929 2.85205 16.8273 2.74012 19.4082 3.4413C21.9892 4.14248 24.2911 5.62264 26 7.67996V3.99996H28V12H20V9.99996Z" />
<path d="M12 22H6.78002C8.07337 23.9876 9.97444 25.5041 12.1998 26.3234C14.4252 27.1426 16.8558 27.2208 19.1293 26.5462C21.4027 25.8716 23.3972 24.4803 24.8156 22.5798C26.0339 20.9474 26.771 19.0144 26.9547 16.9987C27.0048 16.4487 27.4483 16 28.0006 16C28.5525 16 29.0045 16.4477 28.9627 16.998C28.7864 19.3197 27.9889 21.5582 26.6455 23.4749C25.1104 25.665 22.9372 27.3283 20.4222 28.2381C17.9072 29.1479 15.1728 29.2598 12.5918 28.5586C10.0108 27.8574 7.70896 26.3773 6.00002 24.32V28H4.00002V20H12V22Z" />
</symbol>
<symbol id="globe" viewBox="0 0 16 16">
<path d="M8 1C6.61553 1 5.26216 1.41054 4.11101 2.17971C2.95987 2.94888 2.06266 4.04213 1.53285 5.32122C1.00303 6.6003 0.86441 8.00776 1.13451 9.36563C1.4046 10.7235 2.07129 11.9708 3.05026 12.9497C4.02922 13.9287 5.2765 14.5954 6.63437 14.8655C7.99224 15.1356 9.3997 14.997 10.6788 14.4672C11.9579 13.9373 13.0511 13.0401 13.8203 11.889C14.5895 10.7378 15 9.38447 15 8C15 6.14348 14.2625 4.36301 12.9497 3.05025C11.637 1.7375 9.85652 1 8 1ZM14 7.5H11C10.9416 5.65854 10.4646 3.85458 9.605 2.225C10.7893 2.54895 11.8457 3.22842 12.6316 4.17171C13.4175 5.115 13.8952 6.27669 14 7.5ZM8 14C7.88846 14.0075 7.77654 14.0075 7.665 14C6.62915 12.3481 6.05426 10.4491 6 8.5H10C9.95026 10.4477 9.38058 12.3466 8.35 14C8.23348 14.0082 8.11653 14.0082 8 14ZM6 7.5C6.04975 5.55234 6.61942 3.65341 7.65 2C7.87264 1.97498 8.09737 1.97498 8.32 2C9.36114 3.6504 9.94124 5.54953 10 7.5H6ZM6.38 2.225C5.52565 3.85582 5.05373 5.65972 5 7.5H2C2.10485 6.27669 2.58247 5.115 3.3684 4.17171C4.15432 3.22842 5.21072 2.54895 6.395 2.225H6.38ZM2.025 8.5H5.025C5.07718 10.3399 5.54739 12.1438 6.4 13.775C5.21943 13.4476 4.16739 12.7666 3.38528 11.8236C2.60317 10.8806 2.12848 9.72076 2.025 8.5ZM9.605 13.775C10.4646 12.1454 10.9416 10.3415 11 8.5H14C13.8952 9.72331 13.4175 10.885 12.6316 11.8283C11.8457 12.7716 10.7893 13.4511 9.605 13.775Z" fill-opacity="0.6"/>
<symbol id="globe" viewBox="0 0 32 32">
<path d="M16 2.00024C13.2311 2.00024 10.5243 2.82133 8.22202 4.35967C5.91973 5.89801 4.12532 8.08451 3.06569 10.6427C2.00607 13.2008 1.72882 16.0158 2.26901 18.7315C2.80921 21.4472 4.14258 23.9418 6.10051 25.8997C8.05845 27.8577 10.553 29.191 13.2687 29.7312C15.9845 30.2714 18.7994 29.9942 21.3576 28.9346C23.9157 27.8749 26.1022 26.0805 27.6406 23.7782C29.1789 21.4759 30 18.7692 30 16.0002C30 12.2872 28.525 8.72626 25.8995 6.10075C23.274 3.47524 19.713 2.00024 16 2.00024ZM28 15.0002H22C21.8833 11.3173 20.9291 7.70939 19.21 4.45024C21.5786 5.09814 23.6914 6.45709 25.2632 8.34367C26.8351 10.2302 27.7903 12.5536 28 15.0002ZM16 28.0002C15.7769 28.0152 15.5531 28.0152 15.33 28.0002C13.2583 24.6964 12.1085 20.8984 12 17.0002H20C19.9005 20.8956 18.7612 24.6934 16.7 28.0002C16.467 28.0166 16.2331 28.0166 16 28.0002ZM12 15.0002C12.0995 11.1049 13.2388 7.30707 15.3 4.00024C15.7453 3.95021 16.1947 3.95021 16.64 4.00024C18.7223 7.30104 19.8825 11.0993 20 15.0002H12ZM12.76 4.45024C11.0513 7.71189 10.1075 11.3197 10 15.0002H4.00001C4.20971 12.5536 5.16495 10.2302 6.7368 8.34367C8.30865 6.45709 10.4214 5.09814 12.79 4.45024H12.76ZM4.05001 17.0002H10.05C10.1544 20.68 11.0948 24.2878 12.8 27.5502C10.4389 26.8954 8.33478 25.5334 6.77056 23.6474C5.20634 21.7614 4.25695 19.4418 4.05001 17.0002ZM19.21 27.5502C20.9291 24.2911 21.8833 20.6832 22 17.0002H28C27.7903 19.4469 26.8351 21.7702 25.2632 23.6568C23.6914 25.5434 21.5786 26.9023 19.21 27.5502Z" />
</symbol>
</svg>

Before

Width:  |  Height:  |  Size: 10 KiB

After

Width:  |  Height:  |  Size: 10 KiB

+3 -1
View File
@@ -76,6 +76,8 @@
"AddParticipants": "Add participants",
"Sync": "Synchronization",
"Busy": "Busy",
"AddReminder": "Add reminder"
"AddReminder": "Add reminder",
"SeeAllNumberParticipants": "{value, plural, other {See all # participants}}",
"SeeAllNumberReminders": "{value, plural, other {See all # reminders}}"
}
}
+3 -1
View File
@@ -76,6 +76,8 @@
"AddParticipants": "Добавить участников",
"Sync": "Синхронизация",
"Busy": "Занято",
"AddReminder": "Добавить напоминание"
"AddReminder": "Добавить напоминание",
"SeeAllNumberParticipants": "{value, plural, other {Увидеть всех # участников}}",
"SeeAllNumberReminders": "{value, plural, other {Просмотреть все # напоминаний}}"
}
}
@@ -33,6 +33,7 @@
export let focusable: boolean = false
export let disabled: boolean = false
export let excluded: Ref<Person>[] = []
export let fullSize: boolean = false
const dispatch = createEventDispatcher()
@@ -163,7 +164,8 @@
<!-- svelte-ignore a11y-click-events-have-key-events -->
<div
class="editbox-container"
class="antiEditBox"
class:flex-grow={fullSize}
class:w-full={focusable}
on:click={() => {
input.focus()
@@ -181,7 +183,7 @@
}}
>
<div class="hidden-text" bind:this={text} />
<div class="flex-row-center clear-mins" class:focusable>
<div class="ghost flex-row-center clear-mins" class:focusable class:w-full={fullSize}>
<input
{disabled}
bind:this={input}
@@ -197,42 +199,3 @@
/>
</div>
</div>
<style lang="scss">
.editbox-container {
display: inline-flex;
flex-direction: column;
align-items: flex-start;
.focusable {
margin: 0 -0.75rem;
padding: 0.625rem 0.75rem;
width: calc(100% + 1.5rem);
border-radius: 0.25rem;
transition: border-color 0.15s ease-in-out;
&:focus-within {
box-shadow: 0 0 0 1px var(--theme-editbox-focus-border);
}
}
input {
margin: 0;
padding: 0;
min-width: 0;
color: var(--theme-caption-color);
border: none;
border-radius: 2px;
&::-webkit-contacts-auto-fill-button,
&::-webkit-credentials-auto-fill-button {
visibility: hidden;
display: none !important;
pointer-events: none;
height: 0;
width: 0;
margin: 0;
}
}
}
</style>
@@ -17,15 +17,15 @@
import { Person, PersonAccount } from '@hcengineering/contact'
import { Class, Doc, Ref, getCurrentAccount } from '@hcengineering/core'
import presentation, { getClient } from '@hcengineering/presentation'
import { Button, CheckBox, EditBox, Icon, IconClose, Label, showPopup } from '@hcengineering/ui'
import { Button, EditBox, Icon, IconClose, showPopup, IconMoreH } from '@hcengineering/ui'
import { createEventDispatcher } from 'svelte'
import calendar from '../plugin'
import { saveUTC } from '../utils'
import EventParticipants from './EventParticipants.svelte'
import EventTimeEditor from './EventTimeEditor.svelte'
import RRulePresenter from './RRulePresenter.svelte'
import ReccurancePopup from './ReccurancePopup.svelte'
import EventReminders from './EventReminders.svelte'
import EventTimeExtraButton from './EventTimeExtraButton.svelte'
export let attachedTo: Ref<Doc> = calendar.ids.NoAttached
export let attachedToClass: Ref<Class<Doc>> = calendar.class.Event
@@ -36,6 +36,7 @@
const now = new Date()
const defaultDuration = 60 * 60 * 1000
const allDayDuration = 24 * 60 * 60 * 1000 - 1
// const offsetTZ = new Date().getTimezoneOffset() * 60 * 1000
let startDate =
date === undefined ? now.getTime() : withTime ? date.getTime() : date.setHours(now.getHours(), now.getMinutes())
@@ -118,117 +119,83 @@
}
</script>
<div class="container">
<div class="eventPopup-container">
<div class="header flex-between">
<EditBox bind:value={title} placeholder={calendar.string.NewEvent} />
<Button
id="card-close"
focusIndex={10002}
icon={IconClose}
iconProps={{ size: 'medium', fill: 'var(--theme-dark-color)' }}
kind={'ghost'}
size={'small'}
on:click={() => {
dispatch('close')
}}
<EditBox
bind:value={title}
placeholder={calendar.string.NewEvent}
kind={'ghost-large'}
fullSize
focusable
focusIndex={10001}
/>
</div>
<div class="time">
<EventTimeEditor {allDay} bind:startDate bind:dueDate />
<div>
{#if !allDay && rules.length === 0}
<div class="flex-row-center flex-gap-3 ext">
<div class="cursor-pointer" on:click={() => (allDay = true)}>
<Label label={calendar.string.AllDay} />
</div>
<div>
<Label label={calendar.string.TimeZone} />
</div>
<div class="cursor-pointer" on:click={setRecurrance}>
<Label label={calendar.string.Repeat} />
</div>
</div>
{:else}
<div>
<div class="flex-row-center flex-gap-2 mt-1">
<CheckBox bind:checked={allDay} accented on:value={allDayChangeHandler} />
<Label label={calendar.string.AllDay} />
</div>
<div class="flex-row-center flex-gap-2 mt-1">
<Icon size="small" icon={calendar.icon.Globe} />
<Label label={calendar.string.TimeZone} />
</div>
<div class="flex-row-center flex-gap-2 mt-1" on:click={setRecurrance}>
<Icon size="small" icon={calendar.icon.Repeat} />
{#if rules.length > 0}
<RRulePresenter {rules} />
{:else}
<Label label={calendar.string.Repeat} />
{/if}
</div>
</div>
{/if}
<div class="flex-row-center gap-1 flex-no-shrink ml-3">
<Button id="card-more" focusIndex={10002} icon={IconMoreH} kind={'ghost'} size={'small'} on:click={() => {}} />
<Button
id="card-close"
focusIndex={10003}
icon={IconClose}
kind={'ghost'}
size={'small'}
on:click={() => {
dispatch('close')
}}
/>
</div>
</div>
<div class="divider" />
<div>
<div class="block first flex-no-shrink">
<EventTimeEditor {allDay} bind:startDate bind:dueDate />
<EventTimeExtraButton bind:allDay bind:rules on:repeat={setRecurrance} on:allday={allDayChangeHandler} />
</div>
<div class="block rightCropPadding">
<EventParticipants bind:participants bind:externalParticipants />
</div>
<div class="divider" />
<div class="block">
<div class="flex-row-center flex-gap-2">
<Icon icon={calendar.icon.Description} size="small" />
<EditBox bind:value={description} placeholder={calendar.string.Description} />
<div class="block flex-no-shrink">
<div class="flex-row-center gap-1-5">
<Icon icon={calendar.icon.Description} size={'small'} />
<EditBox bind:value={description} placeholder={calendar.string.Description} kind={'ghost'} fullSize focusable />
</div>
</div>
<div class="divider" />
<div class="block">
<div class="block rightCropPadding">
<EventReminders bind:reminders />
</div>
<div class="divider" />
<div class="flex-between pool">
<div class="flex-between p-5 flex-no-shrink">
<div />
<Button kind="accented" label={presentation.string.Create} on:click={saveEvent} disabled={title === ''} />
</div>
</div>
<style lang="scss">
.container {
.eventPopup-container {
display: flex;
flex-direction: column;
max-width: 25rem;
min-width: 25rem;
min-height: 0;
background: var(--theme-popup-color);
box-shadow: var(--theme-popup-shadow);
width: 25rem;
border-radius: 1rem;
box-shadow: var(--theme-popup-shadow);
.header {
margin: 0.75rem 0.75rem 0 0.75rem;
padding: 0.5rem;
flex-shrink: 0;
padding: 0.75rem 0.75rem 0.5rem;
}
.block {
padding-left: 1.25rem;
padding-right: 1.25rem;
}
display: flex;
flex-direction: column;
min-width: 0;
min-height: 0;
border-bottom: 1px solid var(--theme-divider-color);
.divider {
margin-top: 0.75rem;
margin-bottom: 0.75rem;
border-bottom: 1px solid var(--border-color, rgba(0, 0, 0, 0.1));
}
.pool {
margin-top: 0.5rem;
margin: 1.25rem;
}
.time {
margin-left: 1.25rem;
margin-right: 1.25rem;
.ext {
color: var(--theme-dark-color);
&.first {
padding-top: 0;
}
&:not(.rightCropPadding) {
padding: 0.75rem 1.25rem;
}
&.rightCropPadding {
padding: 0.75rem 1rem 0.75rem 1.25rem;
}
}
}
@@ -21,12 +21,14 @@
SimpleDatePopup,
eventToHTMLElement,
showPopup,
TimeInputBox
TimeInputBox,
TimeShiftPresenter
} from '@hcengineering/ui'
import { createEventDispatcher } from 'svelte'
import DateLocalePresenter from './DateLocalePresenter.svelte'
export let date: number
export let difference: number = 0
export let direction: 'vertical' | 'horizontal' = 'vertical'
export let showDate: boolean = true
export let withoutTime: boolean
@@ -69,18 +71,27 @@
}
</script>
<div class="dateEditor-container {direction}">
<div
class="dateEditor-container {direction}"
class:difference={difference > 0}
class:gap-1-5={direction === 'horizontal'}
>
{#if showDate || withoutTime}
<Button {kind} {size} padding={'0 .5rem'} on:click={dateClick} {disabled}>
<div slot="content">
<Button {kind} {size} padding={'0 .5rem'} shape={'round-sm'} on:click={dateClick} {disabled}>
<svelte:fragment slot="content">
<DateLocalePresenter date={currentDate.getTime()} />
</div>
</svelte:fragment>
</Button>
{/if}
{#if !withoutTime}
<Button {kind} {size} padding={'0 .5rem'} on:click={timeClick} {disabled}>
<Button {kind} {size} padding={'0 .5rem'} shape={'round-sm'} on:click={timeClick} {disabled}>
<svelte:fragment slot="content">
<TimeInputBox bind:currentDate noBorder size={'small'} on:update={(date) => updateTime(date.detail)} />
{#if difference > 0}
<div class="ml-2 flex-no-shrink content-darker-color overflow-label">
<TimeShiftPresenter value={date - difference} exact />
</div>
{/if}
</svelte:fragment>
</Button>
{/if}
@@ -96,6 +107,13 @@
}
&.vertical {
flex-direction: column;
&.difference {
align-items: start;
}
&:not(.difference) {
align-items: stretch;
}
}
}
</style>
@@ -17,17 +17,17 @@
import { Person } from '@hcengineering/contact'
import { DocumentUpdate, Ref } from '@hcengineering/core'
import presentation, { getClient } from '@hcengineering/presentation'
import { Button, CheckBox, DAY, EditBox, Icon, IconClose, Label, closePopup, showPopup } from '@hcengineering/ui'
import { Button, DAY, EditBox, Icon, IconClose, IconMoreH, closePopup, showPopup } from '@hcengineering/ui'
import { createEventDispatcher } from 'svelte'
import calendar from '../plugin'
import { isReadOnly, saveUTC } from '../utils'
import EventParticipants from './EventParticipants.svelte'
import EventTimeEditor from './EventTimeEditor.svelte'
import RRulePresenter from './RRulePresenter.svelte'
import ReccurancePopup from './ReccurancePopup.svelte'
import UpdateRecInstancePopup from './UpdateRecInstancePopup.svelte'
import { deepEqual } from 'fast-equals'
import EventReminders from './EventReminders.svelte'
import EventTimeExtraButton from './EventTimeExtraButton.svelte'
export let object: Event
$: readOnly = isReadOnly(object)
@@ -207,124 +207,94 @@
}
</script>
<div class="container">
<div class="eventPopup-container">
<div class="header flex-between">
<EditBox bind:value={title} placeholder={calendar.string.NewEvent} disabled={readOnly} />
<Button
id="card-close"
focusIndex={10002}
icon={IconClose}
iconProps={{ size: 'medium', fill: 'var(--theme-dark-color)' }}
kind={'ghost'}
size={'small'}
on:click={() => {
dispatch('close')
}}
<EditBox
bind:value={title}
placeholder={calendar.string.NewEvent}
disabled={readOnly}
kind={'ghost-large'}
fullSize
focusable
focusIndex={10001}
/>
</div>
<div class="time">
<EventTimeEditor {allDay} bind:startDate bind:dueDate disabled={readOnly} />
<div>
{#if !allDay && rules.length === 0}
<div class="flex-row-center flex-gap-3 ext">
<!-- svelte-ignore a11y-click-events-have-key-events -->
<div class="cursor-pointer" on:click={() => (allDay = true)}>
<Label label={calendar.string.AllDay} />
</div>
<div>
<Label label={calendar.string.TimeZone} />
</div>
{#if rules.length > 0}
<!-- svelte-ignore a11y-click-events-have-key-events -->
<div class="cursor-pointer" on:click={setRecurrance}>
<Label label={calendar.string.Repeat} />
</div>
{/if}
</div>
{:else}
<div>
<div class="flex-row-center flex-gap-2 mt-1">
<CheckBox bind:checked={allDay} accented on:value={allDayChangeHandler} readonly={readOnly} />
<Label label={calendar.string.AllDay} />
</div>
<div class="flex-row-center flex-gap-2 mt-1">
<Icon size="small" icon={calendar.icon.Globe} />
<Label label={calendar.string.TimeZone} />
</div>
{#if rules.length > 0}
<!-- svelte-ignore a11y-click-events-have-key-events -->
<div class="flex-row-center flex-gap-2 mt-1" on:click={setRecurrance}>
<Icon size="small" icon={calendar.icon.Repeat} />
{#if rules.length > 0}
<RRulePresenter {rules} />
{:else}
<Label label={calendar.string.Repeat} />
{/if}
</div>
{/if}
</div>
{/if}
<div class="flex-row-center gap-1 flex-no-shrink ml-3">
<Button id="card-more" focusIndex={10002} icon={IconMoreH} kind={'ghost'} size={'small'} on:click={() => {}} />
<Button
id="card-close"
focusIndex={10003}
icon={IconClose}
kind={'ghost'}
size={'small'}
on:click={() => {
dispatch('close')
}}
/>
</div>
</div>
<div class="divider" />
<div>
<div class="block first flex-no-shrink">
<EventTimeEditor {allDay} bind:startDate bind:dueDate disabled={readOnly} />
<EventTimeExtraButton bind:allDay bind:rules on:repeat={setRecurrance} on:allday={allDayChangeHandler} noRepeat />
</div>
<div class="block rightCropPadding">
<EventParticipants bind:participants bind:externalParticipants disabled={readOnly} />
</div>
<div class="divider" />
<div class="block">
<div class="flex-row-center flex-gap-2">
<Icon icon={calendar.icon.Description} size="small" />
<EditBox bind:value={description} placeholder={calendar.string.Description} disabled={readOnly} />
<div class="block flex-no-shrink">
<div class="flex-row-center gap-1-5">
<Icon icon={calendar.icon.Description} size={'small'} />
<EditBox
bind:value={description}
placeholder={calendar.string.Description}
kind={'ghost'}
fullSize
focusable
disabled={readOnly}
/>
</div>
</div>
<div class="divider" />
<div class="block">
<div class="block rightCropPadding">
<EventReminders bind:reminders />
</div>
<div class="divider" />
<div class="flex-between pool">
<div class="flex-between p-5 flex-no-shrink">
<div />
<Button kind="accented" label={presentation.string.Save} disabled={readOnly} on:click={saveEvent} />
</div>
</div>
<style lang="scss">
.container {
.eventPopup-container {
display: flex;
flex-direction: column;
max-width: 25rem;
min-width: 25rem;
min-height: 0;
background: var(--theme-popup-color);
box-shadow: var(--theme-popup-shadow);
min-width: 25rem;
border-radius: 1rem;
box-shadow: var(--theme-popup-shadow);
.header {
margin: 0.75rem 0.75rem 0 0.75rem;
padding: 0.5rem;
flex-shrink: 0;
padding: 0.75rem 0.75rem 0.5rem;
}
.block {
padding-left: 1.25rem;
padding-right: 1.25rem;
}
display: flex;
flex-direction: column;
padding: 0.75rem 1.25rem;
min-width: 0;
min-height: 0;
border-bottom: 1px solid var(--theme-divider-color);
.divider {
margin-top: 0.75rem;
margin-bottom: 0.75rem;
border-bottom: 1px solid var(--border-color, rgba(0, 0, 0, 0.1));
}
.pool {
margin-top: 0.5rem;
margin: 1.25rem;
}
.time {
margin-left: 1.25rem;
margin-right: 1.25rem;
.ext {
color: var(--theme-dark-color);
&.first {
padding-top: 0;
}
&:not(.rightCropPadding) {
padding: 0.75rem 1.25rem;
}
&.rightCropPadding {
padding: 0.75rem 1rem 0.75rem 1.25rem;
}
}
}
@@ -0,0 +1,66 @@
<!--
// Copyright © 2023 Hardcore Engineering Inc.
//
// Licensed under the Eclipse Public License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License. You may
// obtain a copy of the License at https://www.eclipse.org/legal/epl-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//
// See the License for the specific language governing permissions and
// limitations under the License.
-->
<script lang="ts">
import { createEventDispatcher } from 'svelte'
import { Person } from '@hcengineering/contact'
import { ContactRefPresenter } from '@hcengineering/contact-resources'
import { Ref } from '@hcengineering/core'
import { Button, IconClose } from '@hcengineering/ui'
export let participant: Ref<Person> | undefined = undefined
export let externalParticipant: string | undefined = undefined
export let disabled: boolean = false
export let focusIndex: number = -1
const dispatch = createEventDispatcher()
</script>
{#if participant !== undefined}
<!-- svelte-ignore a11y-no-noninteractive-tabindex -->
<div class="antiOption step-tb25" tabindex={focusIndex}>
<ContactRefPresenter disabled value={participant} />
<div class="tools">
<Button
icon={IconClose}
kind={'ghost'}
size={'x-small'}
padding={'0 .5rem'}
focusIndex={-1}
noFocus
on:click={() => {
dispatch('removeParticipant', participant)
}}
/>
</div>
</div>
{:else if externalParticipant !== undefined}
<!-- svelte-ignore a11y-no-noninteractive-tabindex -->
<div class="antiOption step-tb25" tabindex={focusIndex}>
<span class="ml-8 overflow-label">{externalParticipant}</span>
<div class="tools">
<Button
icon={IconClose}
kind={'ghost'}
size={'x-small'}
padding={'0 .5rem'}
focusIndex={-1}
noFocus
on:click={() => {
dispatch('removeExtParticipant', externalParticipant)
}}
/>
</div>
</div>
{/if}
@@ -14,16 +14,36 @@
-->
<script lang="ts">
import { Person } from '@hcengineering/contact'
import { ContactRefPresenter } from '@hcengineering/contact-resources'
import { Ref } from '@hcengineering/core'
import { Button, Icon, IconClose } from '@hcengineering/ui'
import { Button, Icon, Label, IconMoreV, Scroller } from '@hcengineering/ui'
import calendar from '../plugin'
import AddParticipant from './AddParticipant.svelte'
import EventParticipantItem from './EventParticipantItem.svelte'
export let participants: Ref<Person>[]
export let externalParticipants: string[]
export let disabled: boolean = false
interface IParticipants {
participant: Ref<Person> | undefined
externalParticipant: string | undefined
}
const shortListLength: number = 4
let shown: boolean = false
let needShort: boolean = false
let allParticipants: IParticipants[]
let shortParticipants: IParticipants[]
$: if (participants || externalParticipants) {
allParticipants = []
participants.forEach((p) => allParticipants.push({ participant: p, externalParticipant: undefined }))
externalParticipants.forEach((p) => allParticipants.push({ participant: undefined, externalParticipant: p }))
needShort = allParticipants.length > shortListLength
if (needShort) {
shortParticipants = []
for (let i = 0; i < shortListLength - 2; i++) shortParticipants.push(allParticipants[i])
}
}
$: placeholder =
participants.length > 0 || externalParticipants.length > 0
? calendar.string.AddParticipants
@@ -62,66 +82,66 @@
}
</script>
<div class="container flex-col">
<div class="header flex-row-center flex-gap-3">
<Icon icon={calendar.icon.Participants} size="small" />
<AddParticipant {placeholder} excluded={participants} on:ref={ref} on:enter={enter} />
</div>
<div class="content">
{#each participants as participant}
<div class="flex-between item">
<ContactRefPresenter disabled value={participant} />
<div class="tool">
<Button
icon={IconClose}
iconProps={{ size: 'medium', fill: 'var(--theme-dark-color)' }}
kind={'ghost'}
size={'small'}
on:click={() => {
removeParticipant(participant)
}}
/>
</div>
</div>
{/each}
{#each externalParticipants as participant}
<div class="flex-between item overflow-label">
{participant}
<div class="tool">
<Button
icon={IconClose}
iconProps={{ size: 'medium', fill: 'var(--theme-dark-color)' }}
kind={'ghost'}
size={'small'}
on:click={() => {
removeExtParticipant(participant)
}}
/>
</div>
</div>
{/each}
</div>
<div class="flex-row-center gap-1-5 pb-0-5 pr-1">
<Icon icon={calendar.icon.Participants} size="small" />
<AddParticipant {placeholder} excluded={participants} focusable fullSize on:ref={ref} on:enter={enter} />
</div>
<style lang="scss">
.container {
margin: 0 1.25rem;
.content {
margin-top: 0.25rem;
margin-left: 1.75rem;
}
.item {
.tool {
opacity: 0;
}
&:hover {
.tool {
opacity: 1;
}
}
}
}
</style>
{#if allParticipants.length}
<Scroller padding={'.125rem .375rem 0 1.5rem'} shrink>
{#if needShort && !shown}
{#each shortParticipants as p, i}
<EventParticipantItem
participant={p.participant}
externalParticipant={p.externalParticipant}
focusIndex={10010 + i}
on:removeParticipant={() => {
if (p.participant) removeParticipant(p.participant)
}}
on:removeExtParticipant={() => {
if (p.externalParticipant) removeExtParticipant(p.externalParticipant)
}}
/>
{/each}
<!-- svelte-ignore a11y-no-noninteractive-tabindex -->
<div class="antiOption step-tb25" tabindex={10010 + shortListLength - 2}>
<Button
icon={IconMoreV}
kind={'ghost'}
size={'x-small'}
padding={'0 .5rem'}
focusIndex={-1}
on:click={() => (shown = true)}
/>
<span class="overflow-label flex-grow ml-2">
<Label label={calendar.string.SeeAllNumberParticipants} params={{ value: allParticipants.length }} />
</span>
</div>
<EventParticipantItem
participant={allParticipants[allParticipants.length - 1].participant}
externalParticipant={allParticipants[allParticipants.length - 1].externalParticipant}
focusIndex={10010 + shortListLength - 1}
on:removeParticipant={(event) => {
if (event.detail !== undefined) removeParticipant(event.detail)
}}
on:removeExtParticipant={(event) => {
if (event.detail !== undefined) removeExtParticipant(event.detail)
}}
/>
{:else}
{#each allParticipants as p, i}
<EventParticipantItem
participant={p.participant}
externalParticipant={p.externalParticipant}
focusIndex={10010 + i}
on:removeParticipant={() => {
if (p.participant) removeParticipant(p.participant)
}}
on:removeExtParticipant={() => {
if (p.externalParticipant) removeExtParticipant(p.externalParticipant)
}}
/>
{/each}
{/if}
<div class="antiVSpacer x0-5" />
</Scroller>
{/if}
@@ -0,0 +1,47 @@
<!--
// Copyright © 2023 Hardcore Engineering Inc.
//
// Licensed under the Eclipse Public License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License. You may
// obtain a copy of the License at https://www.eclipse.org/legal/epl-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//
// See the License for the specific language governing permissions and
// limitations under the License.
-->
<script lang="ts">
import { createEventDispatcher } from 'svelte'
import { Button, IconClose, IconMoreH, TimeShiftPresenter } from '@hcengineering/ui'
export let reminder: number
const dispatch = createEventDispatcher()
</script>
<!-- svelte-ignore a11y-no-noninteractive-tabindex -->
<div class="antiOption leftPadding cursor-pointer step-tb25" tabindex={0}>
<TimeShiftPresenter value={reminder * -1} />
<div class="tools flex-row-center flex-no-shrink gap-1">
<Button
icon={IconMoreH}
kind={'ghost'}
size={'x-small'}
padding={'0 .5rem'}
focusIndex={-1}
noFocus
on:click={(e) => dispatch('edit', e)}
/>
<Button
icon={IconClose}
kind={'ghost'}
size={'x-small'}
padding={'0 .5rem'}
focusIndex={-1}
noFocus
on:click={() => dispatch('remove')}
/>
</div>
</div>
@@ -13,14 +13,20 @@
// limitations under the License.
-->
<script lang="ts">
import { Button, eventToHTMLElement, Icon, IconClose, Label, showPopup, TimeShiftPresenter } from '@hcengineering/ui'
import { Button, eventToHTMLElement, Icon, Scroller, IconMoreV, showPopup, Label } from '@hcengineering/ui'
import calendar from '../plugin'
import ReminderPopup from './ReminderPopup.svelte'
import EventReminderItem from './EventReminderItem.svelte'
export let reminders: number[]
function addReminder () {
reminders = [...reminders, 30 * 60 * 1000]
const maxReminders: number = 4
let shown: boolean = false
function addReminder (e: MouseEvent) {
showPopup(ReminderPopup, { value: 0 }, eventToHTMLElement(e), (event) => {
if (event) reminders = [...reminders, event]
})
}
function edit (e: MouseEvent, value: number, index: number) {
@@ -36,40 +42,60 @@
}
</script>
<div class="flex-row-center flex-gap-2">
<div class="flex-row-center gap-1-5 pr-1" class:pb-0-5={reminders.length}>
<Icon icon={calendar.icon.Notifications} size="small" />
<Button kind="ghost" on:click={addReminder}>
<div slot="content">
<Label label={reminders.length ? calendar.string.AddReminder : calendar.string.Reminders} />
</div>
</Button>
<Button
label={reminders.length ? calendar.string.AddReminder : calendar.string.Reminders}
kind={'ghost'}
padding={'0 .5rem'}
shape={'round-sm'}
on:click={(e) => addReminder(e)}
/>
</div>
{#each reminders as reminder, i}
<div class="ml-6 flex-row-center item">
<Button kind="ghost" on:click={(e) => edit(e, reminder, i)}>
<div slot="content"><TimeShiftPresenter value={reminder * -1} /></div>
</Button>
<div class="tool">
<Button
kind="ghost"
icon={IconClose}
iconProps={{ size: 'medium', fill: 'var(--theme-dark-color)' }}
on:click={() => remove(i)}
{#if reminders.length}
<Scroller padding={'.125rem .25rem 0 1.5rem'} shrink>
{#if reminders.length > maxReminders && !shown}
{#each reminders.slice(0, maxReminders - 2) as reminder, i}
<EventReminderItem
{reminder}
on:edit={(event) => {
if (event.detail) edit(event.detail, reminder, i)
}}
on:remove={() => remove(i)}
/>
{/each}
<!-- svelte-ignore a11y-no-noninteractive-tabindex -->
<div class="antiOption cursor-pointer step-tb25" tabindex={0}>
<Button
icon={IconMoreV}
kind={'ghost'}
size={'x-small'}
padding={'0 .5rem'}
focusIndex={-1}
on:click={() => (shown = true)}
/>
<span class="overflow-label flex-grow ml-2">
<Label label={calendar.string.SeeAllNumberReminders} params={{ value: reminders.length }} />
</span>
</div>
<EventReminderItem
reminder={reminders[reminders.length - 1]}
on:edit={(event) => {
if (event.detail) edit(event.detail, reminders[reminders.length - 1], reminders.length - 1)
}}
on:remove={() => remove(reminders.length - 1)}
/>
</div>
</div>
{/each}
<style lang="scss">
.item {
.tool {
opacity: 0;
}
&:hover {
.tool {
opacity: 1;
}
}
}
</style>
{:else}
{#each reminders as reminder, i}
<EventReminderItem
{reminder}
on:edit={(event) => {
if (event.detail) edit(event.detail, reminder, i)
}}
on:remove={() => remove(i)}
/>
{/each}
{/if}
<div class="antiVSpacer x0-5" />
</Scroller>
{/if}
@@ -43,26 +43,27 @@
}
</script>
<div class="flex-row-center flex-gap-1 mt-2 mb-2">
<Icon icon={calendar.icon.Watch} size="small" />
{#if sameDate}
<DateEditor bind:date={startDate} direction="horizontal" withoutTime={allDay} on:update={dateChange} {disabled} />
<div class="content-dark-color">
<IconArrowRight size="small" />
</div>
<DateEditor
bind:date={dueDate}
direction="horizontal"
withoutTime={allDay}
showDate={false}
{disabled}
on:update={dueChange}
/>
{:else}
<DateEditor bind:date={startDate} direction="vertical" withoutTime={allDay} on:update={dateChange} {disabled} />
<div class="content-dark-color">
<IconArrowRight size="small" />
</div>
<DateEditor bind:date={dueDate} direction="vertical" withoutTime={allDay} on:update={dueChange} {disabled} />
{/if}
<div class="flex-row-center">
<div class="self-start flex-no-shrink mt-2 mr-1-5 content-dark-color">
<Icon icon={calendar.icon.Watch} size={'small'} />
</div>
<DateEditor
bind:date={startDate}
direction={sameDate ? 'horizontal' : 'vertical'}
withoutTime={allDay}
on:update={dateChange}
{disabled}
/>
<div class="self-end flex-no-shrink mb-2 ml-1-5 mr-1-5 content-darker-color">
<IconArrowRight size={'small'} />
</div>
<DateEditor
bind:date={dueDate}
direction={sameDate ? 'horizontal' : 'vertical'}
withoutTime={allDay}
showDate={!sameDate}
difference={startDate}
{disabled}
on:update={dueChange}
/>
</div>
@@ -0,0 +1,91 @@
<!--
// Copyright © 2023 Hardcore Engineering Inc.
//
// Licensed under the Eclipse Public License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License. You may
// obtain a copy of the License at https://www.eclipse.org/legal/epl-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//
// See the License for the specific language governing permissions and
// limitations under the License.
-->
<script lang="ts">
import { RecurringRule } from '@hcengineering/calendar'
import { Button, CheckBox, Icon, Label, MILLISECONDS_IN_MINUTE } from '@hcengineering/ui'
import { createEventDispatcher } from 'svelte'
import calendar from '../plugin'
import RRulePresenter from './RRulePresenter.svelte'
export let allDay: boolean
export let rules: RecurringRule[] = []
export let noRepeat: boolean = false
const dispatch = createEventDispatcher()
const offsetTZ = new Date().getTimezoneOffset() * 60 * 1000
</script>
{#if !allDay && rules.length === 0}
<div class="antiButton ghost x-small sh-round-sm text-11px pl-2 pr-2 pt-1 pb-1 mt-1 ml-5-5 gap-3 w-min">
<!-- svelte-ignore a11y-click-events-have-key-events -->
<div class="overflow-label cursor-pointer" on:click={() => (allDay = true)}>
<Label label={calendar.string.AllDay} />
</div>
<div class="overflow-label cursor-default">
<Label label={calendar.string.TimeZone} />
</div>
{#if !noRepeat}
<!-- svelte-ignore a11y-click-events-have-key-events -->
<div class="overflow-label cursor-pointer" on:click={() => dispatch('repeat')}>
<Label label={calendar.string.Repeat} />
</div>
{/if}
</div>
{:else}
<div class="flex-row-center gap-1-5 mt-1">
<CheckBox bind:checked={allDay} accented on:value={() => dispatch('allday')} />
<Button
label={calendar.string.AllDay}
kind={'ghost'}
padding={'0 .5rem'}
shape={'round-sm'}
justify={'left'}
on:click={() => {
allDay = !allDay
dispatch('allday')
}}
/>
</div>
<div class="flex-row-center gap-1-5 mt-1">
<Icon icon={calendar.icon.Globe} size={'small'} fill={'var(--theme-dark-color)'} />
<Button label={calendar.string.TimeZone} kind={'ghost'} padding={'0 .5rem'} shape={'round-sm'} justify={'left'}>
<svelte:fragment slot="content">
<span class="ml-2 content-darker-color">
GMT{(offsetTZ > 0 ? '-' : '+') + Math.abs(offsetTZ / MILLISECONDS_IN_MINUTE / 60)}
</span>
</svelte:fragment>
</Button>
</div>
{#if !noRepeat}
<div class="flex-row-center gap-1-5 mt-1">
<Icon icon={calendar.icon.Repeat} size={'small'} fill={'var(--theme-dark-color)'} />
<Button
label={rules.length > 0 ? undefined : calendar.string.Repeat}
kind={'ghost'}
padding={'0 .5rem'}
shape={'round-sm'}
justify={'left'}
on:click={() => dispatch('repeat')}
>
<svelte:fragment slot="content">
{#if rules.length > 0}
<RRulePresenter {rules} />
{/if}
</svelte:fragment>
</Button>
</div>
{/if}
{/if}
@@ -57,18 +57,20 @@
}
</script>
<div class="antiPopup" on:keydown={onKeyDown}>
<div class="antiPopup thinStyle" on:keydown={onKeyDown}>
<div class="ap-space x1-5" />
<div class="ap-scroll">
<div class="ap-box">
<!-- svelte-ignore a11y-click-events-have-key-events -->
<ListView bind:this={list} count={participants.length}>
<ListView bind:this={list} count={participants.length} kind={'thin'}>
<svelte:fragment slot="item" let:item>
{@const doc = participants[item]}
<div class="ap-menuItem withComp" on:click={() => select(doc)}>
<div class="ap-menuItem withComp noMargin" on:click={() => select(doc)}>
<PersonRefPresenter disabled value={doc} />
</div>
</svelte:fragment>
</ListView>
</div>
</div>
<div class="ap-space x1-5" />
</div>
@@ -56,14 +56,14 @@
<Label label={calendar.string.Every} />
{rule.interval ?? 1}
<Label label={periods[rule.freq]} params={{ count: rule.interval ?? 1 }} />
<span class="content-darker-color">
<span class="ml-2 content-darker-color">
{#if rule.freq === 'WEEKLY' && rule.byDay}
{#await getDays(rule.byDay ?? [], $themeStore.language) then str}
{str}
{/await}
{/if}
{#if rule.endDate}
<Label label={calendar.string.OnUntil} />
<span class="lower"><Label label={calendar.string.OnUntil} /></span>
<DateLocalePresenter date={rule.endDate} />
{/if}
{#if rule.count}
@@ -107,21 +107,21 @@
let until: number = rules[0]?.endDate ?? Date.now()
</script>
<div class="container">
<div class="header fs-title">
<div class="repeatPopup-container">
<div class="header">
<Label label={calendar.string.Repeat} />
{selected}
</div>
<div class="content">
<div class="flex-row-center flex-gap-2">
<Label label={calendar.string.Every} />
<NumberInput bind:value={interval} maxWidth={'3rem'} maxDigitsAfterPoint={0} minValue={1} />
<div class="content flex-col">
<div class="flex-row-center gap-1-5">
<span class="min-w-12"><Label label={calendar.string.Every} /></span>
<NumberInput bind:value={interval} maxWidth={'4rem'} maxDigitsAfterPoint={0} minValue={1} />
<DropdownLabelsIntl bind:selected={periodType} items={ddItems} size="medium" params={{ count: interval }} />
</div>
{#if periodType === 'WEEKLY'}
<div class="flex-row-center mt-4">
<Label label={calendar.string.On} />
<div class="flex-row-center flex-gap-2 ml-6">
<div class="flex-row-center mt-3">
<span class="min-w-12"><Label label={calendar.string.On} /></span>
<div class="flex-row-center flex-gap-2 ml-1-5">
{#each weekdays as day}
<CircleButton
size="medium"
@@ -136,10 +136,10 @@
</div>
</div>
{/if}
<div class="mt-4 mb-6">
<div class="flex-row-center mt-3 mb-3 min-h-8">
<Label label={calendar.string.Ends} />
</div>
<Grid columnGap={1} rowGap={1}>
<Grid columnGap={0.375} rowGap={0.75}>
<RadioButton
labelIntl={calendar.string.Never}
value={'never'}
@@ -157,7 +157,7 @@
selected = 'on'
}}
/>
<div class="flex">
<div class="flex-row-center">
<DateEditor bind:date={until} withoutTime kind="regular" disabled={selected !== 'on'} />
</div>
<RadioButton
@@ -168,7 +168,7 @@
selected = 'after'
}}
/>
<div class="flex-row-center flex-gap-2">
<div class="flex-row-center">
<NumberInput
bind:value={count}
maxWidth={'3rem'}
@@ -176,7 +176,9 @@
minValue={1}
disabled={selected !== 'after'}
/>
<Label label={calendar.string.Times} params={{ count }} />
<span class="ml-1-5" class:content-dark-color={selected !== 'after'}>
<Label label={calendar.string.Times} params={{ count }} />
</span>
</div>
</Grid>
</div>
@@ -192,7 +194,7 @@
</div>
<style lang="scss">
.container {
.repeatPopup-container {
display: flex;
flex-direction: column;
min-height: 0;
@@ -202,12 +204,13 @@
border-radius: 1rem;
.header {
margin: 1.25rem;
margin-bottom: 0;
padding: 1.25rem;
font-weight: 500;
font-size: 1rem;
}
.content {
margin: 1.25rem;
padding: 0 1.25rem 1.25rem;
}
.weekday {
@@ -216,8 +219,8 @@
}
.pool {
border-top: 1px solid var(--border-color, rgba(0, 0, 0, 0.1));
padding: 1.25rem;
border-top: 1px solid var(--theme-divider-color);
}
}
</style>
@@ -13,7 +13,7 @@
// limitations under the License.
-->
<script lang="ts">
import { DAY, HOUR, MINUTE, TimeShiftPresenter } from '@hcengineering/ui'
import { DAY, HOUR, MINUTE, TimeShiftPresenter, IconCheck } from '@hcengineering/ui'
import { createEventDispatcher } from 'svelte'
export let value: number
@@ -31,16 +31,25 @@
const dispatch = createEventDispatcher()
</script>
<div class="antiPopup">
<div class="antiPopup thinStyle">
<div class="ap-space x1-5" />
{#each values as val}
<!-- svelte-ignore a11y-click-events-have-key-events -->
<div
class="ap-menuItem flex-row-center hoverable"
class:selected={value === val}
class="ap-menuItem flex-row-center withCheck hoverable step-tb375"
on:click={() => {
dispatch('close', val)
}}
>
<TimeShiftPresenter value={val * -1} />
<span class="overflow-label flex-grow">
<TimeShiftPresenter value={val * -1} />
</span>
<div class="ap-check">
{#if value === val}
<IconCheck size={'small'} />
{/if}
</div>
</div>
{/each}
<div class="ap-space x1-5" />
</div>
+10 -1
View File
@@ -36,13 +36,22 @@ import CalendarEventPresenter from './components/CalendarEventPresenter.svelte'
import DayCalendar from './components/DayCalendar.svelte'
import EventParticipants from './components/EventParticipants.svelte'
import EventTimeEditor from './components/EventTimeEditor.svelte'
import EventTimeExtraButton from './components/EventTimeExtraButton.svelte'
import IntegrationConfigure from './components/IntegrationConfigure.svelte'
import EventReminders from './components/EventReminders.svelte'
import calendar from './plugin'
import contact from '@hcengineering/contact'
import { deleteObjects } from '@hcengineering/view-resources'
export { EventElement, CalendarView, DayCalendar, EventParticipants, EventTimeEditor, EventReminders }
export {
EventElement,
CalendarView,
DayCalendar,
EventParticipants,
EventTimeEditor,
EventTimeExtraButton,
EventReminders
}
export * from './utils'
+3 -1
View File
@@ -78,6 +78,8 @@ export default mergeIds(calendarId, calendar, {
AddParticipants: '' as IntlString,
Sync: '' as IntlString,
Busy: '' as IntlString,
AddReminder: '' as IntlString
AddReminder: '' as IntlString,
SeeAllNumberParticipants: '' as IntlString,
SeeAllNumberReminders: '' as IntlString
}
})
@@ -121,6 +121,7 @@
<div {id} bind:this={container} class="min-w-0" class:w-full={width === '100%'} class:h-full={$$slots.content}>
{#if $$slots.content}
<!-- svelte-ignore a11y-click-events-have-key-events -->
<div class="w-full h-full flex-streatch" on:click={_click}>
<slot name="content" />
</div>
@@ -143,7 +144,7 @@
{:else}
<div class="flex-row-center">
{#if icon}
<Icon {icon} size={kind === 'link' ? 'small' : size} />
<Icon {icon} size={kind === 'link' || kind === 'stepper' ? 'small' : size} />
{/if}
<div class="ml-2">
<Label {label} />
+3 -3
View File
@@ -93,15 +93,15 @@ test.describe('contact tests', () => {
await page.locator('.states >> svg >> nth=1').click()
await page.locator('text=Rename').click()
await page.locator('.box > .editbox-container input').fill('State1')
await page.locator('.box > .antiEditBox input').fill('State1')
await page.locator('button:has-text("Save")').click()
await page.waitForSelector('form.antiCard', { state: 'detached' })
await page.click('text=Active statuses >> div')
await page.locator('.box > .editbox-container input').fill('State2')
await page.locator('.box > .antiEditBox input').fill('State2')
await page.locator('button:has-text("Save")').click()
await page.waitForSelector('form.antiCard', { state: 'detached' })
await page.click('text=Active statuses >> div')
await page.locator('.box > .editbox-container input').fill('State3')
await page.locator('.box > .antiEditBox input').fill('State3')
await page.locator('button:has-text("Save")').click()
await page.waitForSelector('form.antiCard', { state: 'detached' })
})