Signed-off-by: Denis Bykhov <bykhov.denis@gmail.com>
This commit is contained in:
Denis Bykhov 2023-08-01 13:58:03 +06:00 committed by GitHub
parent 6e44e556f6
commit 7cabfc746e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
28 changed files with 234 additions and 235 deletions

View File

@ -59,7 +59,6 @@ export default mergeIds(boardId, board, {
string: {
CommonBoardPreference: '' as IntlString,
ConvertToCard: '' as IntlString,
ConfigLabel: '' as IntlString,
ConfigDescription: '' as IntlString
},
action: {

View File

@ -27,7 +27,6 @@ export default mergeIds(calendarId, calendar, {
component: {
IntegrationConnect: '' as AnyComponent,
CreateCalendar: '' as AnyComponent,
CalendarView: '' as AnyComponent,
EventPresenter: '' as AnyComponent,
CalendarIntegrationIcon: '' as AnyComponent
},

View File

@ -33,7 +33,6 @@ export default mergeIds(leadId, lead, {
Title: '' as IntlString,
ManageFunnelStatuses: '' as IntlString,
GotoLeadApplication: '' as IntlString,
ConfigLabel: '' as IntlString,
ConfigDescription: '' as IntlString
},
component: {

View File

@ -64,7 +64,6 @@ export default mergeIds(recruitId, recruit, {
GotoApplicants: '' as IntlString,
GotoRecruitApplication: '' as IntlString,
VacancyList: '' as IntlString,
ConfigLabel: '' as IntlString,
ConfigDescription: '' as IntlString,
ShowApplications: '' as IntlString
},

View File

@ -46,8 +46,8 @@ import {
} from '@hcengineering/model'
import attachment from '@hcengineering/model-attachment'
import chunter from '@hcengineering/model-chunter'
import { TTask } from '@hcengineering/model-task'
import core, { DOMAIN_SPACE, TAttachedDoc, TDoc, TSpace, TStatus, TType } from '@hcengineering/model-core'
import core, { TAttachedDoc, TDoc, TStatus, TType } from '@hcengineering/model-core'
import { TSpaceWithStates, TTask } from '@hcengineering/model-task'
import view, { actionTemplates, classPresenter, createAction, showColorsViewOption } from '@hcengineering/model-view'
import workbench, { createNavigateAction } from '@hcengineering/model-workbench'
import notification from '@hcengineering/notification'
@ -121,9 +121,9 @@ export class TTypeMilestoneStatus extends TType {}
/**
* @public
*/
@Model(tracker.class.Project, core.class.Space, DOMAIN_SPACE)
@Model(tracker.class.Project, task.class.SpaceWithStates)
@UX(tracker.string.Project, tracker.icon.Issues, 'Project', 'name')
export class TProject extends TSpace implements Project {
export class TProject extends TSpaceWithStates implements Project {
@Prop(TypeString(), tracker.string.ProjectIdentifier)
@Index(IndexKind.FullText)
identifier!: IntlString

View File

@ -39,7 +39,6 @@ export default mergeIds(trackerId, tracker, {
Parent: '' as IntlString,
CreatedDate: '' as IntlString,
ChangeStatus: '' as IntlString,
ConfigLabel: '' as IntlString,
ConfigDescription: '' as IntlString,
Unarchive: '' as IntlString,
UnarchiveConfirm: '' as IntlString,

View File

@ -270,6 +270,7 @@ input.search {
.items-center { align-items: center; }
.self-end { align-self: end; }
.flex-gap-4 { gap: 1rem; }
.flex-gap-3 { gap: .75rem; }
.flex-gap-2 { gap: .5rem; }
.flex-gap-1-5 { gap: .375rem; }

View File

@ -16,7 +16,7 @@
import { DateRangeMode } from '@hcengineering/core'
import { createEventDispatcher } from 'svelte'
import ui from '../plugin'
import { DateOrShift } from '../types'
import { DAY, DateOrShift, HOUR, MINUTE } from '../types'
import DateRangePresenter from './calendar/DateRangePresenter.svelte'
import TimeShiftPresenter from './TimeShiftPresenter.svelte'
@ -30,9 +30,7 @@
const dispatch = createEventDispatcher()
$: base = direction === 'before' ? -1 : 1
const MINUTE = 60 * 1000
const HOUR = 60 * MINUTE
const DAY = 24 * HOUR
$: values = [...minutes.map((m) => m * MINUTE), ...hours.map((m) => m * HOUR), ...days.map((m) => m * DAY)]
</script>

View File

@ -16,14 +16,10 @@
import { translate } from '@hcengineering/platform'
import ui from '../plugin'
import { themeStore } from '@hcengineering/theme'
import { DAY, HOUR, MINUTE } from '../types'
export let value: number
const SECOND = 1000
const MINUTE = SECOND * 60
const HOUR = MINUTE * 60
const DAY = HOUR * 24
let time: string = ''
async function formatTime (value: number) {

View File

@ -13,21 +13,13 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-->
<script lang="ts" context="module">
const SECOND = 1000
const MINUTE = SECOND * 60
const HOUR = MINUTE * 60
const DAY = HOUR * 24
const MONTH = DAY * 30
const YEAR = MONTH * 12
</script>
<script lang="ts">
import { translate } from '@hcengineering/platform'
import { ticker } from '..'
import { DAY, HOUR, MINUTE, MONTH, YEAR } from '../types'
import ui from '../plugin'
import { tooltip } from '../tooltips'
import { themeStore } from '@hcengineering/theme'
import { ticker } from '..'
export let value: number | undefined
export let kind: 'no-border' | 'list' = 'no-border'

View File

@ -43,6 +43,7 @@
export let startHour = 0
export let startFromWeekStart = true
export let weekFormat: 'narrow' | 'short' | 'long' | undefined = displayedDaysCount > 4 ? 'short' : 'long'
export let showHeader = true
const dispatch = createEventDispatcher()
@ -120,7 +121,7 @@
.forEach((event, i, arr) => {
if (grid[event.day] === undefined) {
grid[event.day] = {
columns: [{ elements: [{ id: event.eventId, date: event.date, dueDate: event.dueDate, cols: 1 }] }]
columns: [{ elements: [{ id: event._id, date: event.date, dueDate: event.dueDate, cols: 1 }] }]
}
} else {
const index = grid[event.day].columns.findIndex(
@ -137,7 +138,7 @@
}
})
grid[event.day].columns.push({
elements: [{ id: event.eventId, date: event.date, dueDate: event.dueDate, cols: size }]
elements: [{ id: event._id, date: event.date, dueDate: event.dueDate, cols: size }]
})
} else {
const intersects = grid[event.day].columns.filter((col) =>
@ -156,7 +157,7 @@
}
})
grid[event.day].columns[index].elements.push({
id: event.eventId,
id: event._id,
date: event.date,
dueDate: event.dueDate,
cols: maxCols
@ -192,7 +193,7 @@
adMaxRow = 1
alldays.forEach((event) => {
const days = events
.filter((ev) => ev.allDay && ev.day !== -1 && event.eventId === ev.eventId)
.filter((ev) => ev.allDay && ev.day !== -1 && event._id === ev._id)
.map((ev) => {
return ev.day
})
@ -208,8 +209,8 @@
break
}
}
adRows.push({ id: event.eventId, row: emptyRow, startCol: days[0], endCol: days[days.length - 1] })
days.forEach((day) => (alldaysGrid[day].alldays[emptyRow] = event.eventId))
adRows.push({ id: event._id, row: emptyRow, startCol: days[0], endCol: days[days.length - 1] })
days.forEach((day) => (alldaysGrid[day].alldays[emptyRow] = event._id))
})
const shown = minimizedAD ? minAD : maxAD
let tempEventID: string = ''
@ -280,8 +281,7 @@
result.visibility = 0
}
result.top =
rem(3.5) +
styleAD +
(showHeader ? rem(3.5) + styleAD : 0) +
cellHeight * startTime.hours +
(startTime.mins / 60) * cellHeight +
getGridOffset(startTime.mins)
@ -293,7 +293,7 @@
let index: number = 0
grid[event.day].columns.forEach((col, i) =>
col.elements.forEach((el) => {
if (el.id === event.eventId) {
if (el.id === event._id) {
cols = el.cols
index = i
}
@ -399,7 +399,7 @@
<div
bind:this={container}
class="calendar-container"
style:grid={`[header] 3.5rem [all-day] ${styleAD}px repeat(${
style:grid={`${showHeader ? '[header] 3.5rem [all-day] ' + styleAD + 'px' : ''} repeat(${
(displayedHours - startHour) * 2
}, [row-start] 2rem) / [time-col] 3.5rem repeat(${displayedDaysCount}, [col-start] 1fr)`}
use:resizeObserver={(element) => checkSizes(element)}
@ -431,7 +431,7 @@
{#key styleAD}{#key calendarWidth}{#key displayedDaysCount}
<div style:min-height={`${shownHeightAD - cellBorder * 2}px`} />
{#each alldays as event, i}
{@const rect = getADRect(event.eventId)}
{@const rect = getADRect(event._id)}
<!-- svelte-ignore a11y-no-noninteractive-tabindex -->
<div
class="calendar-element"
@ -443,70 +443,70 @@
style:--mask-image={getMask(rect.visibility)}
tabindex={500 + i}
>
<slot name="event" id={event.eventId} size={{ width: rect.width, height: rect.height }} />
<slot name="event" id={event._id} size={{ width: rect.width, height: rect.height }} />
</div>
{/each}
{/key}{/key}{/key}
</Scroller>
{:else if shownAD}
{#key styleAD}{#key calendarWidth}{#key displayedDaysCount}
{#each alldays as event, i}
{@const rect = getADRect(event.eventId)}
<!-- svelte-ignore a11y-no-noninteractive-tabindex -->
<div
class="calendar-element"
style:top={`${rect.top}px`}
style:height={`${rect.height}px`}
style:left={`${rect.left}px`}
style:width={`${rect.width}px`}
style:opacity={rect.visibility === 0 ? 0.4 : 1}
style:--mask-image={getMask(rect.visibility)}
tabindex={500 + i}
>
<slot name="event" id={event.eventId} size={{ width: rect.width, height: rect.height }} />
</div>
{/each}
{/key}{/key}{/key}
{#key [styleAD, calendarWidth, displayedDaysCount]}
{#each alldays as event, i}
{@const rect = getADRect(event._id)}
<!-- svelte-ignore a11y-no-noninteractive-tabindex -->
<div
class="calendar-element"
style:top={`${rect.top}px`}
style:height={`${rect.height}px`}
style:left={`${rect.left}px`}
style:width={`${rect.width}px`}
style:opacity={rect.visibility === 0 ? 0.4 : 1}
style:--mask-image={getMask(rect.visibility)}
tabindex={500 + i}
>
<slot name="event" id={event._id} size={{ width: rect.width, height: rect.height }} />
</div>
{/each}
{/key}
{:else}
{#key styleAD}{#key calendarWidth}{#key displayedDaysCount}
{#each shortAlldays as event, i}
{@const rect = getADRect(event.id, event.day, event.fixRow)}
<!-- svelte-ignore a11y-no-noninteractive-tabindex -->
<div
class="calendar-element"
style:top={`${rect.top}px`}
style:height={`${rect.height}px`}
style:left={`${rect.left}px`}
style:width={`${rect.width}px`}
style:opacity={rect.visibility === 0 ? 0.4 : 1}
style:--mask-image={getMask(rect.visibility)}
tabindex={500 + i}
>
<slot name="event" id={event.id} size={{ width: rect.width, height: rect.height }} />
</div>
{/each}
{#each moreCounts as more, day}
{@const addon = shortAlldays.length}
{#if more !== 0}
{@const rect = getMore(day)}
<!-- svelte-ignore a11y-no-noninteractive-tabindex -->
<!-- svelte-ignore a11y-click-events-have-key-events -->
<div
class="calendar-element antiButton ghost medium accent cursor-pointer"
style:top={`${rect.top}px`}
style:height={`${heightAD}rem`}
style:left={`${rect.left}px`}
style:width={`${rect.width}px`}
style:padding-left={'1.25rem'}
style:--mask-image={'none'}
tabindex={500 + addon + day}
on:click={() => (shownAD = true)}
>
<Label label={ui.string.MoreCount} params={{ count: more }} />
</div>
{/if}
{/each}
{/key}{/key}{/key}
{#key [styleAD, calendarWidth, displayedDaysCount]}
{#each shortAlldays as event, i}
{@const rect = getADRect(event.id, event.day, event.fixRow)}
<!-- svelte-ignore a11y-no-noninteractive-tabindex -->
<div
class="calendar-element"
style:top={`${rect.top}px`}
style:height={`${rect.height}px`}
style:left={`${rect.left}px`}
style:width={`${rect.width}px`}
style:opacity={rect.visibility === 0 ? 0.4 : 1}
style:--mask-image={getMask(rect.visibility)}
tabindex={500 + i}
>
<slot name="event" id={event.id} size={{ width: rect.width, height: rect.height }} />
</div>
{/each}
{#each moreCounts as more, day}
{@const addon = shortAlldays.length}
{#if more !== 0}
{@const rect = getMore(day)}
<!-- svelte-ignore a11y-no-noninteractive-tabindex -->
<!-- svelte-ignore a11y-click-events-have-key-events -->
<div
class="calendar-element antiButton ghost medium accent cursor-pointer"
style:top={`${rect.top}px`}
style:height={`${heightAD}rem`}
style:left={`${rect.left}px`}
style:width={`${rect.width}px`}
style:padding-left={'1.25rem'}
style:--mask-image={'none'}
tabindex={500 + addon + day}
on:click={() => (shownAD = true)}
>
<Label label={ui.string.MoreCount} params={{ count: more }} />
</div>
{/if}
{/each}
{/key}
{/if}
</div>
@ -530,6 +530,14 @@
style:width={`${colWidth}px`}
style:grid-column={`col-start ${dayOfWeek + 1} / ${dayOfWeek + 2}`}
style:grid-row={`row-start ${hourOfDay * 2 + 1} / row-start ${hourOfDay * 2 + 3}`}
on:dragover|preventDefault
on:drop|preventDefault={(e) => {
dispatch('drop', {
day,
hour: hourOfDay + startHour,
date: new Date(day.setHours(hourOfDay + startHour, 0, 0, 0))
})
}}
on:click|stopPropagation={() => {
dispatch('create', {
date: new Date(day.setHours(hourOfDay + startHour, 0, 0, 0)),
@ -541,31 +549,31 @@
{#if hourOfDay === displayedHours - startHour - 1}<div class="clear-cell" />{/if}
{/each}
{#key styleAD}{#key calendarWidth}{#key displayedDaysCount}
{#each newEvents.filter((ev) => !ev.allDay) as event, i}
{@const rect = getRect(event)}
<!-- svelte-ignore a11y-no-noninteractive-tabindex -->
<div
class="calendar-element"
style:top={`${rect.top}px`}
style:bottom={`${rect.bottom}px`}
style:left={`${rect.left}px`}
style:right={`${rect.right}px`}
style:opacity={rect.visibility === 0 ? 0.4 : 1}
style:--mask-image={'none'}
tabindex={1000 + i}
>
<slot
name="event"
id={event.eventId}
size={{
width: rect.width,
height: (calendarRect?.height ?? rect.top + rect.bottom) - rect.top - rect.bottom
}}
/>
</div>
{/each}
{/key}{/key}{/key}
{#key [styleAD, calendarWidth, displayedDaysCount]}
{#each newEvents.filter((ev) => !ev.allDay) as event, i}
{@const rect = getRect(event)}
<!-- svelte-ignore a11y-no-noninteractive-tabindex -->
<div
class="calendar-element"
style:top={`${rect.top}px`}
style:bottom={`${rect.bottom}px`}
style:left={`${rect.left}px`}
style:right={`${rect.right}px`}
style:opacity={rect.visibility === 0 ? 0.4 : 1}
style:--mask-image={'none'}
tabindex={1000 + i}
>
<slot
name="event"
id={event._id}
size={{
width: rect.width,
height: (calendarRect?.height ?? rect.top + rect.bottom) - rect.top - rect.bottom
}}
/>
</div>
{/each}
{/key}
</div>
</Scroller>

View File

@ -17,6 +17,7 @@
import { createEventDispatcher } from 'svelte'
import Scroller from '../Scroller.svelte'
import TimeShiftPresenter from '../TimeShiftPresenter.svelte'
import { DAY, HOUR, MINUTE } from '../../types'
export let currentDate: Date | null
export let direction: 'before' | 'after' = 'after'
@ -32,9 +33,6 @@
const dispatch = createEventDispatcher()
$: base = direction === 'before' ? -1 : 1
const MINUTE = 60 * 1000
const HOUR = 60 * MINUTE
const DAY = 24 * HOUR
const shiftValues: (number | string)[] = []

View File

@ -394,10 +394,17 @@ export interface DialogStep {
* @public
*/
export interface CalendarItem {
eventId: string
_id: string
allDay: boolean
date: Timestamp
dueDate: Timestamp
day: number
access: 'freeBusyReader' | 'reader' | 'writer' | 'owner'
}
export const SECOND = 1000
export const MINUTE = SECOND * 60
export const HOUR = MINUTE * 60
export const DAY = HOUR * 24
export const MONTH = DAY * 30
export const YEAR = MONTH * 12

View File

@ -117,6 +117,9 @@ const boards = plugin(boardId, {
SendToBoard: '' as Ref<Action>,
Delete: '' as Ref<Action>
},
string: {
ConfigLabel: '' as IntlString
},
icon: {
Board: '' as Asset,
Card: '' as Asset

View File

@ -14,6 +14,7 @@
-->
<script lang="ts">
import { Calendar, Event, getAllEvents } from '@hcengineering/calendar'
import { EmployeeAccount } from '@hcengineering/contact'
import {
Class,
Doc,
@ -21,50 +22,52 @@
FindOptions,
Ref,
SortingOrder,
Space,
Timestamp,
getCurrentAccount
} from '@hcengineering/core'
import { IntlString } from '@hcengineering/platform'
import { createQuery } from '@hcengineering/presentation'
import {
AnyComponent,
Button,
IconBack,
IconForward,
MonthCalendar,
CalendarItem,
DayCalendar,
WeekCalendar,
DropdownLabelsIntl,
IconBack,
IconForward,
MILLISECONDS_IN_DAY,
MonthCalendar,
YearCalendar,
areDatesEqual,
getMonday,
DropdownLabelsIntl,
showPopup,
MILLISECONDS_IN_DAY
showPopup
} from '@hcengineering/ui'
import { BuildModelKey } from '@hcengineering/view'
import { CalendarMode } from '../index'
import calendar from '../plugin'
import Day from './Day.svelte'
import Hour from './Hour.svelte'
import EventElement from './EventElement.svelte'
import { IntlString } from '@hcengineering/platform'
export let _class: Ref<Class<Doc>>
export let space: Ref<Space> | undefined = undefined
export let query: DocumentQuery<Event> = {}
export let _class: Ref<Class<Doc>> = calendar.class.Event
export let query: DocumentQuery<Event> | undefined = undefined
export let options: FindOptions<Event> | undefined = undefined
export let baseMenuClass: Ref<Class<Event>> | undefined = undefined
export let config: (string | BuildModelKey)[]
export let createComponent: AnyComponent | undefined = undefined
export let createComponent: AnyComponent | undefined = calendar.component.CreateEvent
export let allowedModes: CalendarMode[] = [
CalendarMode.Days,
CalendarMode.Week,
CalendarMode.Month,
CalendarMode.Year
]
const me = getCurrentAccount() as EmployeeAccount
const mondayStart = true
let mode: CalendarMode = CalendarMode.Days
let mode: CalendarMode = allowedModes.includes(CalendarMode.Days) ? CalendarMode.Days : allowedModes[0]
// Current selected day
let currentDate: Date = new Date()
let selectedDate: Date = new Date()
let raw: Event[] = []
let objects: Event[] = []
function getFrom (date: Date, mode: CalendarMode): Timestamp {
@ -90,7 +93,7 @@
function getTo (date: Date, mode: CalendarMode): Timestamp {
switch (mode) {
case CalendarMode.Days: {
return new Date(date).setDate(date.getDate() + 1)
return new Date(date).setDate(date.getDate() + 4)
}
case CalendarMode.Day: {
return new Date(date).setDate(date.getDate() + 1)
@ -116,7 +119,7 @@
let calendars: Calendar[] = []
const offsetTZ = new Date().getTimezoneOffset() * 60 * 1000
calendarsQuery.query(calendar.class.Calendar, { createdBy: getCurrentAccount()._id }, (res) => {
calendarsQuery.query(calendar.class.Calendar, { createdBy: me._id }, (res) => {
calendars = res
})
@ -124,25 +127,21 @@
async function update (
_class: Ref<Class<Event>>,
query: DocumentQuery<Event>,
from: Timestamp,
to: Timestamp,
query: DocumentQuery<Event> | undefined,
calendars: Calendar[],
options?: FindOptions<Event>
) {
q.query<Event>(
_class,
{
space: { $in: calendars.map((p) => p._id) },
...query
},
query ?? { space: { $in: calendars.map((p) => p._id) } },
(result) => {
objects = getAllEvents(result, from, to)
raw = result
},
{ sort: { date: SortingOrder.Ascending }, ...options }
)
}
$: update(_class, query, from, to, calendars, options)
$: update(_class, query, calendars, options)
$: objects = getAllEvents(raw, from, to)
function inRange (start: Date, end: Date, startPeriod: Date, period: 'day' | 'hour'): boolean {
const endPeriod =
@ -211,9 +210,32 @@
showPopup(createComponent, { date, withTime }, 'top')
}
let indexes = new Map<Ref<Event>, number>()
function getDdItem (mode: CalendarMode) {
switch (mode) {
case CalendarMode.Day:
return { id: 'day', label: calendar.string.ModeDay, mode: CalendarMode.Day }
case CalendarMode.Days:
return { id: 'days', label: calendar.string.DueDays, mode: CalendarMode.Days, params: { days: 3 } }
case CalendarMode.Week:
return { id: 'week', label: calendar.string.ModeWeek, mode: CalendarMode.Week }
case CalendarMode.Month:
return { id: 'month', label: calendar.string.ModeMonth, mode: CalendarMode.Month }
case CalendarMode.Year:
return { id: 'year', label: calendar.string.ModeYear, mode: CalendarMode.Year }
}
}
const ddItems: {
function getDdItems (allowedModes: CalendarMode[]): void {
ddItems = []
for (const mode of allowedModes) {
ddItems.push(getDdItem(mode))
}
ddItems = ddItems
}
$: getDdItems(allowedModes)
let ddItems: {
id: string | number
label: IntlString
mode: CalendarMode
@ -243,7 +265,7 @@
const eventEnd = event.allDay ? event.dueDate + offsetTZ : event.dueDate
if ((eventStart < lastDate && eventEnd > startDate) || (eventStart === eventEnd && eventStart === startDay)) {
result.push({
eventId: event.eventId,
_id: event._id,
allDay: event.allDay,
date: eventStart,
dueDate: eventEnd,
@ -263,7 +285,7 @@
const eventEnd = event.dueDate + offsetTZ
if ((eventStart < ld && eventEnd > sd) || (eventStart === eventEnd && eventStart === sd)) {
result.push({
eventId: event.eventId,
_id: event._id,
allDay: event.allDay,
date: eventStart,
dueDate: eventEnd,
@ -282,14 +304,16 @@
<span>{currentDate.getFullYear()}</span>
</div>
<div class="flex-row-center gap-2">
<DropdownLabelsIntl
items={ddItems.map((it) => {
return { id: it.id, label: it.label, params: it.params }
})}
size={'medium'}
selected={ddItems.find((it) => it.mode === mode)?.id}
on:selected={(e) => (mode = ddItems.find((it) => it.id === e.detail)?.mode ?? ddItems[0].mode)}
/>
{#if ddItems.length > 1}
<DropdownLabelsIntl
items={ddItems.map((it) => {
return { id: it.id, label: it.label, params: it.params }
})}
size={'medium'}
selected={ddItems.find((it) => it.mode === mode)?.id}
on:selected={(e) => (mode = ddItems.find((it) => it.id === e.detail)?.mode ?? ddItems[0].mode)}
/>
{/if}
<Button
label={calendar.string.Today}
on:click={() => {
@ -328,18 +352,7 @@
}}
>
<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}
/>
<Day events={findEvents(objects, date)} {date} {_class} {options} {today} {selected} {wrongMonth} {query} />
</svelte:fragment>
</YearCalendar>
{:else if mode === CalendarMode.Month}
@ -350,9 +363,7 @@
{date}
size={'huge'}
{_class}
{baseMenuClass}
{options}
{config}
{today}
{selected}
{wrongMonth}
@ -379,9 +390,10 @@
bind:selectedDate
bind:currentDate
on:create={(e) => showCreateDialog(e.detail.date, e.detail.withTime)}
on:drop
>
<svelte:fragment slot="event" let:id let:size>
{@const event = objects.find((event) => event.eventId === id)}
{@const event = objects.find((event) => event._id === id)}
{#if event}
<EventElement {event} {size} />
{/if}
@ -397,36 +409,16 @@
bind:selectedDate
bind:currentDate
on:create={(e) => showCreateDialog(e.detail.date, e.detail.withTime)}
on:drop
>
<svelte:fragment slot="event" let:id let:size>
{@const event = objects.find((event) => event.eventId === id)}
{@const event = objects.find((event) => event._id === id)}
{#if event}
<EventElement {event} {size} />
{/if}
</svelte:fragment>
</DayCalendar>
{/key}
{:else if mode === CalendarMode.Day}
<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 class="min-h-4 max-h-4 h-4 flex-no-shrink" /> -->

View File

@ -16,7 +16,7 @@
import { Event } from '@hcengineering/calendar'
import { DateRangeMode } from '@hcengineering/core'
import { translate } from '@hcengineering/platform'
import { DateRangePresenter, themeStore } from '@hcengineering/ui'
import { DAY, DateRangePresenter, HOUR, MINUTE, themeStore } from '@hcengineering/ui'
import calendar from '../plugin'
export let value: Event
@ -36,11 +36,6 @@
}
}
const SECOND = 1000
const MINUTE = SECOND * 60
const HOUR = MINUTE * 60
const DAY = HOUR * 24
async function formatDueDate (interval: number): Promise<string> {
let passed = interval
if (interval < 0) passed = 0

View File

@ -16,7 +16,6 @@
import { Event } from '@hcengineering/calendar'
import { Class, Doc, DocumentQuery, FindOptions, Ref } from '@hcengineering/core'
import { Label, addZero, getPlatformColorForTextDef, showPopup, themeStore, tooltip } from '@hcengineering/ui'
import { BuildModelKey } from '@hcengineering/view'
import { createEventDispatcher } from 'svelte'
import calendar from '../plugin'
import EventsPopup from './EventsPopup.svelte'
@ -28,8 +27,6 @@
export let _class: Ref<Class<Doc>>
export let query: DocumentQuery<Event> = {}
export let options: FindOptions<Event> | undefined = undefined
export let baseMenuClass: Ref<Class<Event>> | undefined = undefined
export let config: (string | BuildModelKey)[]
export let today: boolean = false
export let selected: boolean = false

View File

@ -32,10 +32,13 @@ import SaveEventReminder from './components/SaveEventReminder.svelte'
import UpdateRecInstancePopup from './components/UpdateRecInstancePopup.svelte'
import ReminderViewlet from './components/activity/ReminderViewlet.svelte'
import CalendarIntegrationIcon from './components/icons/Calendar.svelte'
import EventElement from './components/EventElement.svelte'
import calendar from './plugin'
import contact from '@hcengineering/contact'
import { deleteObjects } from '@hcengineering/view-resources'
export { EventElement, CalendarView }
async function saveEventReminder (object: Doc): Promise<void> {
showPopup(SaveEventReminder, { objectId: object._id, objectClass: object._class })
}

View File

@ -35,7 +35,6 @@ export default mergeIds(calendarId, calendar, {
ModeWeek: '' as IntlString,
ModeMonth: '' as IntlString,
ModeYear: '' as IntlString,
Today: '' as IntlString,
TableView: '' as IntlString,
DueMinutes: '' as IntlString,
DueHours: '' as IntlString,

View File

@ -123,6 +123,7 @@ const calendarPlugin = plugin(calendarId, {
Calendar: '' as Ref<Doc>
},
component: {
CalendarView: '' as AnyComponent,
PersonsPresenter: '' as AnyComponent,
Events: '' as AnyComponent,
DateTimePresenter: '' as AnyComponent,
@ -141,7 +142,8 @@ const calendarPlugin = plugin(calendarId, {
NoParticipants: '' as IntlString,
PersonsLabel: '' as IntlString,
EventNumber: '' as IntlString,
Reminders: '' as IntlString
Reminders: '' as IntlString,
Today: '' as IntlString
},
handler: {
DisconnectHandler: '' as Handler

View File

@ -262,6 +262,8 @@ export function getAllEvents (events: Event[], from: Timestamp, to: Timestamp):
const instancesMap: Map<string, ReccuringInstance[]> = new Map()
for (const event of events) {
if (event._class === calendar.class.Event) {
if (from > event.dueDate) continue
if (event.date > to) continue
base.push(event)
} else if (event._class === calendar.class.ReccuringEvent) {
recur.push(event as ReccuringEvent)
@ -276,7 +278,13 @@ export function getAllEvents (events: Event[], from: Timestamp, to: Timestamp):
for (const rec of recur) {
recurData.push(...getReccuringEventInstances(rec, instancesMap.get(rec.eventId) ?? [], from, to))
}
const res = [...base, ...recurData, ...instances]
const res = [
...base,
...recurData,
...instances.filter((p) => {
return from <= p.dueDate && p.date <= to
})
]
res.sort((a, b) => a.date - b.date)
return res
}

View File

@ -334,7 +334,7 @@
span {
margin-left: 0.5rem;
font-weight: 400;
font-size: 0.875rem;
line-height: 1.125rem;
opacity: 0.4;
}

View File

@ -17,7 +17,7 @@
import type { Contact } from '@hcengineering/contact'
import type { Class, Doc, Ref, Timestamp } from '@hcengineering/core'
import { Mixin } from '@hcengineering/core'
import type { Asset, Plugin } from '@hcengineering/platform'
import type { Asset, IntlString, Plugin } from '@hcengineering/platform'
import { plugin } from '@hcengineering/platform'
import type { KanbanTemplateSpace, SpaceWithStates, State, Task } from '@hcengineering/task'
@ -68,6 +68,9 @@ const lead = plugin(leadId, {
mixin: {
Customer: '' as Ref<Mixin<Customer>>
},
string: {
ConfigLabel: '' as IntlString
},
icon: {
Funnel: '' as Asset,
Lead: '' as Asset,

View File

@ -16,7 +16,7 @@
import { Event } from '@hcengineering/calendar'
import type { Channel, Organization, Person } from '@hcengineering/contact'
import type { AttachedData, AttachedDoc, Class, Doc, Mixin, Ref, Space, Timestamp } from '@hcengineering/core'
import type { Asset, Plugin, Resource } from '@hcengineering/platform'
import type { Asset, IntlString, Plugin, Resource } from '@hcengineering/platform'
import { plugin } from '@hcengineering/platform'
import { TagReference } from '@hcengineering/tags'
import type { KanbanTemplateSpace, SpaceWithStates, State, Task } from '@hcengineering/task'
@ -158,6 +158,9 @@ const recruit = plugin(recruitId, {
component: {
EditVacancy: '' as AnyComponent
},
string: {
ConfigLabel: '' as IntlString
},
icon: {
RecruitApplication: '' as Asset,
Vacancy: '' as Asset,

View File

@ -12,19 +12,10 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-->
<script lang="ts" context="module">
const SECOND = 1000
const MINUTE = SECOND * 60
const HOUR = MINUTE * 60
const DAY = HOUR * 24
const MONTH = DAY * 30
const YEAR = MONTH * 12
</script>
<script lang="ts">
import { translate } from '@hcengineering/platform'
import tracker from '../../plugin'
import { themeStore } from '@hcengineering/ui'
import { DAY, HOUR, MINUTE, MONTH, YEAR, themeStore } from '@hcengineering/ui'
export let value: number

View File

@ -139,6 +139,7 @@ import ProjectSpacePresenter from './components/projects/ProjectSpacePresenter.s
import { get } from 'svelte/store'
export { default as SubIssueList } from './components/issues/edit/SubIssueList.svelte'
export { default as IssueStatusIcon } from './components/issues/IssueStatusIcon.svelte'
export { IssuePresenter, TitlePresenter }

View File

@ -24,7 +24,6 @@ import {
Markup,
Ref,
RelatedDocument,
Space,
Status,
StatusCategory,
Timestamp,
@ -33,7 +32,7 @@ import {
} from '@hcengineering/core'
import { Asset, IntlString, Plugin, Resource, plugin } from '@hcengineering/platform'
import { TagCategory, TagElement, TagReference } from '@hcengineering/tags'
import { Task } from '@hcengineering/task'
import { SpaceWithStates, Task } from '@hcengineering/task'
import { AnyComponent, Location, ResolvedLocation } from '@hcengineering/ui'
import { Action, ActionCategory, IconProps } from '@hcengineering/view'
@ -45,7 +44,7 @@ export interface IssueStatus extends Status {}
/**
* @public
*/
export interface Project extends Space, IconProps {
export interface Project extends SpaceWithStates, IconProps {
identifier: string // Project identifier
sequence: number
defaultIssueStatus: Ref<IssueStatus>
@ -451,6 +450,7 @@ export default plugin(trackerId, {
Location: '' as Resource<(loc: Location) => Promise<ResolvedLocation | undefined>>
},
string: {
ConfigLabel: '' as IntlString,
NewRelatedIssue: '' as IntlString
}
})

View File

@ -53,9 +53,16 @@
}
$: if (doc !== undefined) {
getObjectPresenter(client, doc._class, { key: '' }).then((p) => {
presenter = p
})
getObjectPresenter(client, doc._class, { key: '' })
.then((p) => {
presenter = p
})
.catch((p) => {
console.log(objectId)
console.log(_class)
console.log(value)
throw p
})
}
</script>