mirror of
https://github.com/hcengineering/platform.git
synced 2025-04-29 03:34:31 +00:00
Fixed work slots layout in Planner (#5262)
Signed-off-by: Alexander Platov <alexander.platov@hardcoreeng.com>
This commit is contained in:
parent
babbc490f2
commit
50d5c3bad9
@ -678,6 +678,7 @@ input.search {
|
||||
.h-50 { height: 12.5rem; }
|
||||
.h-60 { height: 15.0rem; }
|
||||
.w-min { width: min-content; }
|
||||
.w-max { width: max-content; }
|
||||
.w-full { width: 100%; }
|
||||
.w-2 { width: .5rem; }
|
||||
.w-4 { width: 1rem; }
|
||||
@ -708,6 +709,7 @@ input.search {
|
||||
.min-w-144 { min-width: 25rem; }
|
||||
.min-w-168 { min-width: 42rem; }
|
||||
.min-w-min { min-width: min-content; }
|
||||
.min-w-full { min-width: 100%; }
|
||||
.min-h-0 { min-height: 0; }
|
||||
.min-h-2 { min-height: .5rem; }
|
||||
.min-h-4 { min-height: 1rem; }
|
||||
@ -1001,6 +1003,7 @@ a.no-line {
|
||||
.content-primary-color { color: var(--primary-button-color); }
|
||||
.red-color { color: var(--highlight-red); }
|
||||
.error-color { color: var(--theme-error-color); }
|
||||
.sunshine-text-color { color: var(--tag-accent-SunshineText) !important; }
|
||||
|
||||
.border-radius-4 { border-radius: 1rem; }
|
||||
.border-radius-3 { border-radius: 0.75rem; }
|
||||
|
@ -37,6 +37,7 @@
|
||||
export let selected: DropdownIntlItem['id'] | undefined = undefined
|
||||
export let element: HTMLButtonElement | undefined = undefined
|
||||
export let focusIndex = -1
|
||||
export let id: string | undefined = undefined
|
||||
|
||||
let opened: boolean = false
|
||||
|
||||
@ -83,5 +84,6 @@
|
||||
{inheritColor}
|
||||
pressed={opened}
|
||||
{focusIndex}
|
||||
{id}
|
||||
on:click={openPopup}
|
||||
/>
|
||||
|
@ -25,6 +25,7 @@
|
||||
getUserTimezone,
|
||||
showPopup
|
||||
} from '@hcengineering/ui'
|
||||
import { FixedColumn } from '@hcengineering/view-resources'
|
||||
import { createEventDispatcher } from 'svelte'
|
||||
import DateLocalePresenter from './DateLocalePresenter.svelte'
|
||||
|
||||
@ -38,6 +39,7 @@
|
||||
export let disabled: boolean = false
|
||||
export let focusIndex = -1
|
||||
export let timeZone: string = getUserTimezone()
|
||||
export let fixed: string | undefined = undefined
|
||||
|
||||
const dispatch = createEventDispatcher()
|
||||
|
||||
@ -80,11 +82,19 @@
|
||||
class:flex-gap-2={direction === 'horizontal'}
|
||||
>
|
||||
{#if showDate || withoutTime}
|
||||
{#if fixed === undefined}
|
||||
<div class="min-w-28">
|
||||
<ButtonBase type="type-button" {kind} {size} {disabled} {focusIndex} on:click={dateClick}>
|
||||
<DateLocalePresenter date={currentDate.getTime()} {timeZone} />
|
||||
<span class="overflow-label"><DateLocalePresenter date={currentDate.getTime()} {timeZone} /></span>
|
||||
</ButtonBase>
|
||||
</div>
|
||||
{:else}
|
||||
<FixedColumn key={fixed + '-date'} addClass={'min-w-28'}>
|
||||
<ButtonBase type="type-button" {kind} {size} {disabled} {focusIndex} on:click={dateClick}>
|
||||
<span class="overflow-label"><DateLocalePresenter date={currentDate.getTime()} {timeZone} /></span>
|
||||
</ButtonBase>
|
||||
</FixedColumn>
|
||||
{/if}
|
||||
{/if}
|
||||
|
||||
{#if showDate && !withoutTime && direction === 'horizontal'}
|
||||
@ -92,6 +102,7 @@
|
||||
{/if}
|
||||
|
||||
{#if !withoutTime}
|
||||
{#if fixed === undefined}
|
||||
<ButtonBase
|
||||
type="type-button"
|
||||
{kind}
|
||||
@ -110,14 +121,42 @@
|
||||
}}
|
||||
/>
|
||||
</ButtonBase>
|
||||
{:else}
|
||||
<FixedColumn key={fixed + '-time'} addClass={'min-w-28'}>
|
||||
<ButtonBase
|
||||
type="type-button"
|
||||
{kind}
|
||||
{size}
|
||||
{disabled}
|
||||
focusIndex={focusIndex !== -1 ? focusIndex + 1 : focusIndex}
|
||||
on:click={timeClick}
|
||||
>
|
||||
<TimeInputBox
|
||||
bind:currentDate
|
||||
{timeZone}
|
||||
noBorder
|
||||
size={'small'}
|
||||
on:update={(date) => {
|
||||
updateTime(date.detail)
|
||||
}}
|
||||
/>
|
||||
</ButtonBase>
|
||||
</FixedColumn>
|
||||
{/if}
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
{#if !withoutTime && difference > 0}
|
||||
<div class="divider" />
|
||||
<div class="duration font-regular-14">
|
||||
{#if fixed === undefined}
|
||||
<div class="p-2 font-regular-14 sunshine-text-color">
|
||||
<TimeShiftPresenter value={date - difference} exact />
|
||||
</div>
|
||||
{:else}
|
||||
<FixedColumn key={fixed + '-duration'} addClass={'p-2 font-regular-14 sunshine-text-color'}>
|
||||
<TimeShiftPresenter value={date - difference} exact />
|
||||
</FixedColumn>
|
||||
{/if}
|
||||
{/if}
|
||||
|
||||
<style lang="scss">
|
||||
@ -140,11 +179,6 @@
|
||||
}
|
||||
}
|
||||
|
||||
.duration {
|
||||
padding: var(--spacing-1);
|
||||
color: var(--tag-accent-SunshineText);
|
||||
}
|
||||
|
||||
.divider {
|
||||
width: 0;
|
||||
height: 1.25rem;
|
||||
|
@ -25,14 +25,11 @@
|
||||
weekday: 'short',
|
||||
month: 'short'
|
||||
}
|
||||
if (current.getFullYear() !== new Date(date).getFullYear()) {
|
||||
options = {
|
||||
$: options = {
|
||||
...options,
|
||||
year: '2-digit'
|
||||
timeZone,
|
||||
year: current.getFullYear() !== new Date(date).getFullYear() ? '2-digit' : undefined
|
||||
}
|
||||
}
|
||||
|
||||
$: options.timeZone = timeZone
|
||||
</script>
|
||||
|
||||
{new Date(date).toLocaleDateString('default', options)}
|
||||
|
@ -24,6 +24,8 @@
|
||||
export let disabled: boolean = false
|
||||
export let timeZone: string = getUserTimezone()
|
||||
export let focusIndex = -1
|
||||
export let grow: boolean = false
|
||||
export let fixed: string | undefined = undefined
|
||||
|
||||
$: sameDate = areDatesEqual(utcToZonedTime(startDate, timeZone), utcToZonedTime(dueDate, timeZone))
|
||||
|
||||
@ -49,7 +51,7 @@
|
||||
}
|
||||
</script>
|
||||
|
||||
<div class="flex-row-center flex-gap-2">
|
||||
<div class="flex-row-center flex-gap-2 flex-no-shrink" class:flex-grow={grow}>
|
||||
<DateEditor
|
||||
bind:date={startDate}
|
||||
direction={sameDate ? 'horizontal' : 'vertical'}
|
||||
@ -58,6 +60,7 @@
|
||||
on:update={dateChange}
|
||||
{disabled}
|
||||
{focusIndex}
|
||||
fixed={fixed === undefined ? undefined : fixed + '-startDate'}
|
||||
/>
|
||||
<div class="flex-no-shrink content-darker-color">—</div>
|
||||
<DateEditor
|
||||
@ -69,6 +72,7 @@
|
||||
{disabled}
|
||||
{timeZone}
|
||||
focusIndex={focusIndex !== -1 ? focusIndex + 1 : focusIndex}
|
||||
fixed={fixed === undefined ? undefined : fixed + '-dueDate'}
|
||||
on:update={dueChange}
|
||||
/>
|
||||
</div>
|
||||
|
@ -64,6 +64,7 @@
|
||||
{size}
|
||||
{disabled}
|
||||
{focusIndex}
|
||||
id={'visibleButton'}
|
||||
on:selected={(event) => {
|
||||
if (event.detail) change(event.detail)
|
||||
}}
|
||||
|
@ -249,6 +249,7 @@
|
||||
<Workslots
|
||||
bind:slots
|
||||
shortcuts={false}
|
||||
fixed={'createToDo'}
|
||||
on:remove={removeSlot}
|
||||
on:create={createSlot}
|
||||
on:change={changeSlot}
|
||||
|
@ -236,6 +236,7 @@
|
||||
.slots-content {
|
||||
gap: var(--spacing-2);
|
||||
padding: var(--spacing-2) var(--spacing-4);
|
||||
min-width: 0;
|
||||
border-top: 1px solid var(--theme-divider-color);
|
||||
}
|
||||
.eventPopup-container {
|
||||
|
@ -92,4 +92,4 @@
|
||||
}
|
||||
</script>
|
||||
|
||||
<Workslots {slots} on:change={change} on:dueChange={dueChange} on:create={create} on:remove={remove} />
|
||||
<Workslots {slots} fixed={'toDo'} on:change={change} on:dueChange={dueChange} on:create={create} on:remove={remove} />
|
||||
|
@ -13,7 +13,7 @@
|
||||
// limitations under the License.
|
||||
-->
|
||||
<script lang="ts">
|
||||
import { ButtonBase, ButtonIcon, IconDelete, themeStore, Hotkey, HotkeyGroup } from '@hcengineering/ui'
|
||||
import { ButtonBase, ButtonIcon, IconDelete, themeStore, Hotkey, HotkeyGroup, Scroller } from '@hcengineering/ui'
|
||||
import { EventTimeEditor } from '@hcengineering/calendar-resources'
|
||||
import { WorkSlot } from '@hcengineering/time'
|
||||
import { createEventDispatcher } from 'svelte'
|
||||
@ -23,6 +23,7 @@
|
||||
|
||||
export let slots: WorkSlot[] = []
|
||||
export let shortcuts: boolean = true
|
||||
export let fixed: string | undefined = undefined
|
||||
|
||||
const dispatch = createEventDispatcher()
|
||||
|
||||
@ -51,18 +52,20 @@
|
||||
|
||||
<svelte:window on:keydown={handleKeyDown} />
|
||||
|
||||
<div class="flex-col w-full flex-gap-1">
|
||||
<Scroller gap={'flex-gap-1'} horizontal>
|
||||
{#each slots as slot, i}
|
||||
<div class="flex justify-start items-center flex-gap-2 w-full pr-4 slot">
|
||||
<div class="flex-between flex-no-shrink flex-gap-2 min-w-full w-max slot">
|
||||
<Hotkey key={(i + 1).toString()} />
|
||||
<EventTimeEditor
|
||||
allDay={false}
|
||||
startDate={slot.date}
|
||||
dueDate={slot.dueDate}
|
||||
grow
|
||||
{fixed}
|
||||
on:change={(e) => change(e, slot)}
|
||||
on:dueChange={(e) => dueChange(e, slot)}
|
||||
/>
|
||||
<div class="tool">
|
||||
<div class="tool flex-no-shrink">
|
||||
<ButtonIcon
|
||||
kind="tertiary"
|
||||
size="small"
|
||||
@ -74,7 +77,7 @@
|
||||
</div>
|
||||
</div>
|
||||
{/each}
|
||||
</div>
|
||||
</Scroller>
|
||||
<div class="flex-row-center flex-gap-4">
|
||||
<ButtonBase
|
||||
kind="secondary"
|
||||
@ -98,25 +101,11 @@
|
||||
|
||||
<style lang="scss">
|
||||
.slot {
|
||||
position: relative;
|
||||
padding: var(--spacing-1) var(--spacing-1) var(--spacing-1) var(--spacing-2_5);
|
||||
border-radius: var(--small-BorderRadius);
|
||||
padding: var(--spacing-1) var(--spacing-1) var(--spacing-1) var(--spacing-2);
|
||||
background-color: var(--tag-nuance-SunshineBackground);
|
||||
|
||||
&:before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 0.25rem;
|
||||
height: 100%;
|
||||
background-color: var(--tag-accent-SunshineBackground);
|
||||
border-radius: var(--small-BorderRadius) 0 0 var(--small-BorderRadius);
|
||||
}
|
||||
|
||||
.tool {
|
||||
margin-left: auto;
|
||||
}
|
||||
border-left: var(--extra-small-BorderRadius) solid var(--tag-accent-SunshineBackground);
|
||||
border-radius: var(--extra-small-BorderRadius) var(--small-BorderRadius) var(--small-BorderRadius)
|
||||
var(--extra-small-BorderRadius);
|
||||
}
|
||||
|
||||
.duration {
|
||||
|
@ -48,10 +48,8 @@ export class PlanningPage extends CalendarPage {
|
||||
)
|
||||
this.buttonPopupCreatePriority = page.locator('div.popup button#priorityButton')
|
||||
this.buttonPanelCreatePriority = page.locator('div.hulyModal-container button#priorityButton')
|
||||
this.buttonPopupCreateVisible = page.locator('div.popup button.type-button.menu', { hasText: 'visible' })
|
||||
this.buttonPanelCreateVisible = page.locator('div.hulyModal-container button.type-button.menu', {
|
||||
hasText: 'visible'
|
||||
})
|
||||
this.buttonPopupCreateVisible = page.locator('div.popup button#visibleButton')
|
||||
this.buttonPanelCreateVisible = page.locator('div.hulyModal-container button#visibleButton')
|
||||
this.buttonPopupCreateAddLabel = page.locator('div.popup button.antiButton', { hasText: 'Add label' })
|
||||
this.buttonPanelCreateAddLabel = page.locator('.hulyHeader-titleGroup > button:nth-child(2)')
|
||||
this.buttonPopupCreateAddSlot = page.locator('div.popup button', { hasText: 'Add Slot' })
|
||||
@ -137,12 +135,12 @@ export class PlanningPage extends CalendarPage {
|
||||
|
||||
public async setTimeSlot (rowNumber: number, slot: Slot, popup: boolean = false): Promise<void> {
|
||||
const p = popup
|
||||
? 'div.popup div.horizontalBox div.end div.flex-col div.flex'
|
||||
: 'div.hulyModal-container div.slots-content div.flex-col div.flex'
|
||||
? 'div.popup div.horizontalBox div.end div.scroller-container div.box div.flex-between.min-w-full'
|
||||
: 'div.hulyModal-container div.slots-content div.scroller-container div.box div.flex-between.min-w-full'
|
||||
const row = this.page.locator(p).nth(rowNumber)
|
||||
|
||||
// dateStart
|
||||
await row.locator('div.dateEditor-container:nth-child(1) button:first-child').click()
|
||||
await row.locator('div.dateEditor-container:first-child > div.min-w-28:first-child button').click()
|
||||
if (slot.dateStart === 'today') {
|
||||
await this.buttonCalendarToday.click()
|
||||
} else {
|
||||
@ -177,8 +175,8 @@ export class PlanningPage extends CalendarPage {
|
||||
|
||||
private async checkTimeSlot (rowNumber: number, slot: Slot, popup: boolean = false): Promise<void> {
|
||||
const p = popup
|
||||
? 'div.popup div.horizontalBox div.end div.flex-col div.flex'
|
||||
: 'div.hulyModal-container div.slots-content div.flex-col div.flex'
|
||||
? 'div.popup div.horizontalBox div.end div.scroller-container div.box div.flex-between.min-w-full'
|
||||
: 'div.hulyModal-container div.slots-content div.scroller-container div.box div.flex-between.min-w-full'
|
||||
const row = this.page.locator(p).nth(rowNumber)
|
||||
// timeStart
|
||||
await expect(row.locator('div.dateEditor-container:nth-child(1) button:last-child div.datetime-input')).toHaveText(
|
||||
@ -260,7 +258,9 @@ export class PlanningPage extends CalendarPage {
|
||||
|
||||
public async deleteTimeSlot (rowNumber: number): Promise<void> {
|
||||
const row = this.page
|
||||
.locator('div.hulyModal-container div.slots-content div.flex-col div.flex div.tool')
|
||||
.locator(
|
||||
'div.hulyModal-container div.slots-content div.scroller-container div.box div.flex-between.min-w-full div.tool'
|
||||
)
|
||||
.nth(rowNumber)
|
||||
await row.locator('xpath=..').hover()
|
||||
await row.locator('button').click()
|
||||
@ -268,8 +268,12 @@ export class PlanningPage extends CalendarPage {
|
||||
}
|
||||
|
||||
public async checkTimeSlotEndDate (rowNumber: number, dateEnd: string): Promise<void> {
|
||||
const row = this.page.locator('div.hulyModal-container div.slots-content div.flex-col div.flex').nth(rowNumber)
|
||||
const row = this.page
|
||||
.locator('div.hulyModal-container div.slots-content div.scroller-container div.box div.flex-between.min-w-full')
|
||||
.nth(rowNumber)
|
||||
// dateEnd
|
||||
await expect(row.locator('div.dateEditor-container:nth-child(1) button:first-child')).toContainText(dateEnd)
|
||||
await expect(row.locator('div.dateEditor-container:first-child > div.min-w-28:first-child button')).toContainText(
|
||||
dateEnd
|
||||
)
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user