diff --git a/common/scripts/each-diff.sh b/common/scripts/each-diff.sh
index 35b367f18b..8fc1d9dada 100755
--- a/common/scripts/each-diff.sh
+++ b/common/scripts/each-diff.sh
@@ -1,6 +1,6 @@
#!/usr/bin/env bash
-FILES=$(git diff origin/main --name-only --diff-filter=ACMR | sed 's| |\\ |g')
+FILES=$(git diff origin/develop --name-only --diff-filter=ACMR | sed 's| |\\ |g')
[ -z "$FILES" ] && exit 0
roots=$(rush list -p --json | grep "path" | cut -f 2 -d ':' | cut -f 2 -d '"')
diff --git a/models/love/src/index.ts b/models/love/src/index.ts
index 567edb65c4..0467e74658 100644
--- a/models/love/src/index.ts
+++ b/models/love/src/index.ts
@@ -16,14 +16,15 @@
import contact, { type Employee, type Person } from '@hcengineering/contact'
import {
AccountRole,
+ type CollaborativeDoc,
+ type CollectionSize,
+ DateRangeMode,
+ type Doc,
type Domain,
DOMAIN_TRANSIENT,
IndexKind,
type Ref,
- type CollaborativeDoc,
- type Doc,
- type Timestamp,
- type CollectionSize
+ type Timestamp
} from '@hcengineering/core'
import {
type DevicesPreference,
@@ -32,16 +33,16 @@ import {
type JoinRequest,
loveId,
type Meeting,
+ type MeetingMinutes,
+ type MeetingStatus,
type Office,
type ParticipantInfo,
type RequestStatus,
type Room,
type RoomAccess,
type RoomInfo,
- type RoomType,
type RoomLanguage,
- type MeetingMinutes,
- type MeetingStatus
+ type RoomType
} from '@hcengineering/love'
import {
type Builder,
@@ -53,18 +54,18 @@ import {
Model,
Prop,
ReadOnly,
+ TypeAny,
TypeCollaborativeDoc,
+ TypeDate,
TypeRef,
TypeString,
- TypeTimestamp,
- UX,
- TypeAny
+ UX
} from '@hcengineering/model'
import calendar, { TEvent } from '@hcengineering/model-calendar'
import core, { TAttachedDoc, TDoc } from '@hcengineering/model-core'
import preference, { TPreference } from '@hcengineering/model-preference'
import presentation from '@hcengineering/model-presentation'
-import view, { createAction } from '@hcengineering/model-view'
+import view, { createAction, createAttributePresenter } from '@hcengineering/model-view'
import notification from '@hcengineering/notification'
import { getEmbeddedLabel } from '@hcengineering/platform'
import setting from '@hcengineering/setting'
@@ -228,12 +229,12 @@ export class TMeetingMinutes extends TAttachedDoc implements MeetingMinutes, Tod
@Prop(PropCollection(chunter.class.ChatMessage), activity.string.Messages)
messages?: number
- @Prop(TypeTimestamp(), love.string.MeetingStart, { editor: view.component.TimestampPresenter })
+ @Prop(TypeDate(DateRangeMode.DATETIME), love.string.MeetingStart, { editor: view.component.DateTimePresenter })
@ReadOnly()
@Index(IndexKind.IndexedDsc)
declare createdOn: Timestamp
- @Prop(TypeTimestamp(), love.string.MeetingEnd)
+ @Prop(TypeDate(DateRangeMode.DATETIME), love.string.MeetingEnd, { editor: view.component.DateTimePresenter })
@ReadOnly()
meetingEnd?: Timestamp
@@ -506,10 +507,10 @@ export function createModel (builder: Builder): void {
config: [
'',
{ key: 'status', presenter: love.component.MeetingMinutesStatusPresenter, label: love.string.Status },
- 'createdOn',
- 'meetingEnd',
{ key: 'messages', displayProps: { key: 'messages', suffix: true } },
- { key: 'transcription', displayProps: { key: 'transcription', suffix: true } }
+ { key: 'transcription', displayProps: { key: 'transcription', suffix: true } },
+ 'createdOn',
+ 'meetingEnd'
],
configOptions: {
hiddenKeys: ['description'],
@@ -529,10 +530,13 @@ export function createModel (builder: Builder): void {
config: [
'',
{ key: 'status', presenter: love.component.MeetingMinutesStatusPresenter, label: love.string.Status },
+ { key: 'messages', displayProps: { key: 'messages', suffix: true } },
+ { key: 'transcription', displayProps: { key: 'transcription', suffix: true } },
'createdOn',
'meetingEnd'
],
configOptions: {
+ hiddenKeys: ['description'],
sortable: true
},
variant: 'embedded'
@@ -637,4 +641,19 @@ export function createModel (builder: Builder): void {
builder.mixin(love.class.MeetingMinutes, core.class.Class, view.mixin.ObjectPanelFooter, {
editor: love.component.PanelControlBar
})
+
+ createAttributePresenter(
+ builder,
+ view.component.DateTimePresenter,
+ love.class.MeetingMinutes,
+ 'createdOn',
+ 'attribute'
+ )
+ createAttributePresenter(
+ builder,
+ view.component.DateTimePresenter,
+ love.class.MeetingMinutes,
+ 'meetingEnd',
+ 'attribute'
+ )
}
diff --git a/models/view/src/plugin.ts b/models/view/src/plugin.ts
index c1f25d7a67..3c0b6a2bf7 100644
--- a/models/view/src/plugin.ts
+++ b/models/view/src/plugin.ts
@@ -64,6 +64,7 @@ export default mergeIds(viewId, view, {
TimestampPresenter: '' as AnyComponent,
DateEditor: '' as AnyComponent,
DatePresenter: '' as AnyComponent,
+ DateTimePresenter: '' as AnyComponent,
TableBrowser: '' as AnyComponent,
RolePresenter: '' as AnyComponent,
YoutubePresenter: '' as AnyComponent,
diff --git a/packages/ui/src/components/calendar/DateRangePresenter.svelte b/packages/ui/src/components/calendar/DateRangePresenter.svelte
index 1a5226be91..8f73ecc74f 100644
--- a/packages/ui/src/components/calendar/DateRangePresenter.svelte
+++ b/packages/ui/src/components/calendar/DateRangePresenter.svelte
@@ -478,9 +478,11 @@
{/if}
{:else}
-
-
-
+ {#if shouldShowAvatar}
+
+
+
+ {/if}
{#if value !== undefined && value !== null && value.toString() !== ''}
{#if withDate}
{new Date(value).getDate()}
@@ -524,7 +526,7 @@
border-radius: 0.375rem;
transition-property: border, background-color, color, box-shadow;
transition-duration: 0.15s;
- cursor: pointer;
+ cursor: default;
&.noPadding {
padding: 0;
diff --git a/plugins/love-resources/src/components/EditMeetingMinutes.svelte b/plugins/love-resources/src/components/EditMeetingMinutes.svelte
index 4b9569a024..e99d438368 100644
--- a/plugins/love-resources/src/components/EditMeetingMinutes.svelte
+++ b/plugins/love-resources/src/components/EditMeetingMinutes.svelte
@@ -26,8 +26,16 @@
const client = getClient()
const dispatch = createEventDispatcher()
+ let currentTitle = object.title
+ let newTitle = object.title
+
+ $: if (object.title !== currentTitle) {
+ newTitle = object.title
+ currentTitle = object.title
+ }
+
async function changeTitle (): Promise {
- await client.update(object, { title: object.title })
+ await client.diffUpdate(object, { title: newTitle })
}
onMount(() => {
@@ -41,7 +49,7 @@
diff --git a/plugins/love-resources/src/components/EditRoom.svelte b/plugins/love-resources/src/components/EditRoom.svelte
index 1483194cb5..8dbdc824b8 100644
--- a/plugins/love-resources/src/components/EditRoom.svelte
+++ b/plugins/love-resources/src/components/EditRoom.svelte
@@ -21,7 +21,7 @@
import { IntlString } from '@hcengineering/platform'
import love from '../plugin'
- import { getRoomName, tryConnect } from '../utils'
+ import { getRoomName, tryConnect, isConnected } from '../utils'
import { infos, invites, myInfo, myRequests, selectedRoomPlace, myOffice, currentRoom } from '../stores'
export let object: Room
@@ -61,7 +61,11 @@
selectedRoomPlace.set(undefined)
}
- let connectLabel: IntlString = love.string.StartMeeting
+ $: connecting = connecting || ($currentRoom?._id === object._id && !$isConnected)
+
+ let connectLabel: IntlString = $infos.some(({ room }) => room === object._id)
+ ? love.string.JoinMeeting
+ : love.string.StartMeeting
$: if ($infos.some(({ room }) => room === object._id) && !connecting) {
connectLabel = love.string.JoinMeeting
diff --git a/plugins/love-resources/src/components/MeetingMinutesDocEditor.svelte b/plugins/love-resources/src/components/MeetingMinutesDocEditor.svelte
index 0f33ec2e5d..d3ba1c66af 100644
--- a/plugins/love-resources/src/components/MeetingMinutesDocEditor.svelte
+++ b/plugins/love-resources/src/components/MeetingMinutesDocEditor.svelte
@@ -33,7 +33,7 @@
{#if doc}
-
+
{#if data}
-
+
{/if}
diff --git a/plugins/love-resources/src/components/RoomLanguageSelector.svelte b/plugins/love-resources/src/components/RoomLanguageSelector.svelte
index d21634b9c1..4e0e527c60 100644
--- a/plugins/love-resources/src/components/RoomLanguageSelector.svelte
+++ b/plugins/love-resources/src/components/RoomLanguageSelector.svelte
@@ -30,6 +30,7 @@
let container: HTMLElement
let selectedItem: RoomLanguage = room.language
+ $: selectedItem = room.language
let items: DropdownIntlItem[] = []
$: items = Object.entries(languagesDisplayData).map(([lang, data]) => ({
diff --git a/plugins/love-resources/src/utils.ts b/plugins/love-resources/src/utils.ts
index 49ffd92888..f906e1bd98 100644
--- a/plugins/love-resources/src/utils.ts
+++ b/plugins/love-resources/src/utils.ts
@@ -12,7 +12,9 @@ import core, {
makeCollaborativeDoc,
type Ref,
type Space,
- type TxOperations
+ type TxOperations,
+ type Hierarchy,
+ type Doc
} from '@hcengineering/core'
import login from '@hcengineering/login'
import {
@@ -79,7 +81,7 @@ import {
import { type Widget, type WidgetTab } from '@hcengineering/workbench'
import view from '@hcengineering/view'
import chunter from '@hcengineering/chunter'
-import { openDoc } from '@hcengineering/view-resources'
+import { getObjectLinkFragment } from '@hcengineering/view-resources'
import { sendMessage } from './broadcast'
import love from './plugin'
@@ -494,6 +496,20 @@ function closeMeetingMinutes (): void {
currentMeetingMinutes.set(undefined)
}
+function isRoomOpened (room: Room): boolean {
+ const loc = getCurrentLocation()
+
+ if (loc.path[2] === loveId) {
+ const panel = get(panelstore).panel
+ const { _id } = panel ?? {}
+
+ if (_id !== undefined && room._id !== undefined && _id === room._id) {
+ return true
+ }
+ }
+ return false
+}
+
export async function setCam (value: boolean): Promise {
if (value && get(currentRoom)?.type !== RoomType.Video) return
if ($isCurrentInstanceConnected) {
@@ -604,13 +620,9 @@ async function moveToRoom (
sessionId
})
}
- const loc = getCurrentLocation()
- if (room.type === RoomType.Video && loc.path[2] !== loveId) {
- loc.path[2] = loveId
- loc.path.length = 3
- loc.fragment = undefined
- loc.query = undefined
- navigate(loc)
+
+ if (!isRoomOpened(room)) {
+ await navigateToOfficeDoc(client.getHierarchy(), room)
}
}
@@ -622,63 +634,70 @@ async function connectLK (currentPerson: Person, room: Room): Promise {
])
}
+async function navigateToOfficeDoc (hierarchy: Hierarchy, object: Doc): Promise {
+ const panelComponent = hierarchy.classHierarchyMixin(object._class, view.mixin.ObjectPanel)
+ const comp = panelComponent?.component ?? view.component.EditDoc
+ const loc = await getObjectLinkFragment(hierarchy, object, {}, comp)
+ loc.path[2] = loveId
+ loc.path.length = 3
+ loc.query = undefined
+ navigate(loc)
+}
+
async function openMeetingMinutes (room: Room): Promise {
const client = getClient()
const sid = await lk.getSid()
+ const doc = await client.findOne(love.class.MeetingMinutes, { sid })
- if (sid !== undefined) {
- const doc = await client.findOne(love.class.MeetingMinutes, { sid })
-
- if (doc === undefined) {
- const date = new Date()
- .toLocaleDateString('en-GB', {
- day: 'numeric',
- month: 'long',
- year: 'numeric',
- hour: '2-digit',
- minute: '2-digit',
- hour12: false,
- timeZone: 'UTC'
- })
- .replace(',', ' at')
- const _id = generateId()
- const newDoc: MeetingMinutes = {
- _id,
- _class: love.class.MeetingMinutes,
- sid,
- attachedTo: room._id,
- attachedToClass: room._class,
- collection: 'meetings',
- space: core.space.Workspace,
- title: `${getRoomName(room, get(personByIdStore))} ${date}`,
- description: makeCollaborativeDoc(_id, 'description'),
- status: MeetingStatus.Active,
- modifiedBy: getCurrentAccount()._id,
- modifiedOn: Date.now()
- }
- await client.addCollection(
- love.class.MeetingMinutes,
- core.space.Workspace,
- room._id,
- room._class,
- 'meetings',
- { sid, title: newDoc.title, description: newDoc.description, status: newDoc.status },
- _id
- )
- currentMeetingMinutes.set(newDoc)
- const loc = getCurrentLocation()
- if (loc.path[2] === loveId) {
- await openDoc(client.getHierarchy(), newDoc)
- }
- } else {
- currentMeetingMinutes.set(doc)
- const loc = getCurrentLocation()
- if (loc.path[2] === loveId) {
- await openDoc(client.getHierarchy(), doc)
- }
- if (doc.status !== MeetingStatus.Active) {
- void client.update(doc, { status: MeetingStatus.Active, meetingEnd: undefined })
- }
+ if (doc === undefined) {
+ const date = new Date()
+ .toLocaleDateString('en-GB', {
+ day: 'numeric',
+ month: 'long',
+ year: 'numeric',
+ hour: '2-digit',
+ minute: '2-digit',
+ hour12: false,
+ timeZone: 'UTC'
+ })
+ .replace(',', ' at')
+ const _id = generateId()
+ const newDoc: MeetingMinutes = {
+ _id,
+ _class: love.class.MeetingMinutes,
+ sid,
+ attachedTo: room._id,
+ attachedToClass: room._class,
+ collection: 'meetings',
+ space: core.space.Workspace,
+ title: `${getRoomName(room, get(personByIdStore))} ${date}`,
+ description: makeCollaborativeDoc(_id, 'description'),
+ status: MeetingStatus.Active,
+ modifiedBy: getCurrentAccount()._id,
+ modifiedOn: Date.now()
+ }
+ await client.addCollection(
+ love.class.MeetingMinutes,
+ core.space.Workspace,
+ room._id,
+ room._class,
+ 'meetings',
+ { sid, title: newDoc.title, description: newDoc.description, status: newDoc.status },
+ _id
+ )
+ currentMeetingMinutes.set(newDoc)
+ const loc = getCurrentLocation()
+ if (loc.path[2] === loveId || room.type === RoomType.Video) {
+ await navigateToOfficeDoc(client.getHierarchy(), newDoc)
+ }
+ } else {
+ currentMeetingMinutes.set(doc)
+ const loc = getCurrentLocation()
+ if (loc.path[2] === loveId || room.type === RoomType.Video) {
+ await navigateToOfficeDoc(client.getHierarchy(), doc)
+ }
+ if (doc.status !== MeetingStatus.Active) {
+ void client.update(doc, { status: MeetingStatus.Active, meetingEnd: undefined })
}
}
}
diff --git a/plugins/view-resources/src/components/DatePresenter.svelte b/plugins/view-resources/src/components/DatePresenter.svelte
index 7890bc6d18..daa3d2854c 100644
--- a/plugins/view-resources/src/components/DatePresenter.svelte
+++ b/plugins/view-resources/src/components/DatePresenter.svelte
@@ -15,18 +15,23 @@
-->
-{#if onChange !== undefined}
+{#if onChange !== undefined && !readonly}
onChange?.(e.detail)}
{shouldShowAvatar}
@@ -34,5 +39,5 @@
{inline}
/>
{:else}
-
+
{/if}
diff --git a/plugins/view-resources/src/components/DateTimePresenter.svelte b/plugins/view-resources/src/components/DateTimePresenter.svelte
new file mode 100644
index 0000000000..da84c3e115
--- /dev/null
+++ b/plugins/view-resources/src/components/DateTimePresenter.svelte
@@ -0,0 +1,38 @@
+
+
+
+
diff --git a/plugins/view-resources/src/components/EditDoc.svelte b/plugins/view-resources/src/components/EditDoc.svelte
index ab3082b50f..2e7758a0a5 100644
--- a/plugins/view-resources/src/components/EditDoc.svelte
+++ b/plugins/view-resources/src/components/EditDoc.svelte
@@ -98,7 +98,9 @@
$: if (_class !== oldClass) {
oldClass = _class
+ realObjectClass = _class
mainEditor = undefined
+ fieldEditors = []
}
let keys: KeyedAttribute[] = []
@@ -289,7 +291,7 @@
- {#if headerEditor !== undefined}
+ {#if headerEditor !== undefined && object._id === _id}
{
- const readonlyParams = readonly
- ? {
- readonly: true,
- editable: false,
- disabled: true
- }
- : {}
+ const readonlyParams =
+ readonly || (attribute?.attribute?.readonly ?? false)
+ ? {
+ readonly: true,
+ editable: false,
+ disabled: true
+ }
+ : {}
if (attribute.collectionAttr) {
return { object, ...attribute.props, ...readonlyParams }
}
diff --git a/plugins/view-resources/src/index.ts b/plugins/view-resources/src/index.ts
index bdc437bc11..bb099c3cc9 100644
--- a/plugins/view-resources/src/index.ts
+++ b/plugins/view-resources/src/index.ts
@@ -31,6 +31,7 @@ import CollaborativeHTMLEditor from './components/CollaborativeHTMLEditor.svelte
import ColorsPopup from './components/ColorsPopup.svelte'
import DateEditor from './components/DateEditor.svelte'
import DatePresenter from './components/DatePresenter.svelte'
+import DateTimePresenter from './components/DateTimePresenter.svelte'
import DocAttributeBar from './components/DocAttributeBar.svelte'
import DocNavLink from './components/DocNavLink.svelte'
import DocReferencePresenter from './components/DocReferencePresenter.svelte'
@@ -257,6 +258,7 @@ export default async (): Promise => ({
TimestampPresenter,
DateEditor,
DatePresenter,
+ DateTimePresenter,
RolePresenter,
ObjectPresenter,
EditDoc,