Skip to content

Commit

Permalink
Improve calendar schema (#7156)
Browse files Browse the repository at this point in the history
Signed-off-by: Denis Bykhov <[email protected]>
  • Loading branch information
BykhovDenis authored Nov 12, 2024
1 parent e0ca033 commit 76bcd3c
Show file tree
Hide file tree
Showing 9 changed files with 151 additions and 27 deletions.
3 changes: 2 additions & 1 deletion models/calendar/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ export { calendarId } from '@hcengineering/calendar'
export { calendarOperation } from './migration'

export const DOMAIN_CALENDAR = 'calendar' as Domain
export const DOMAIN_EVENT = 'event' as Domain

@Model(calendar.class.Calendar, core.class.Doc, DOMAIN_CALENDAR)
@UX(calendar.string.Calendar, calendar.icon.Calendar)
Expand All @@ -85,7 +86,7 @@ export class TExternalCalendar extends TCalendar implements ExternalCalendar {
externalUser!: string
}

@Model(calendar.class.Event, core.class.AttachedDoc, DOMAIN_CALENDAR)
@Model(calendar.class.Event, core.class.AttachedDoc, DOMAIN_EVENT)
@UX(calendar.string.Event, calendar.icon.Calendar)
export class TEvent extends TAttachedDoc implements Event {
declare space: Ref<SystemSpace>
Expand Down
12 changes: 11 additions & 1 deletion models/calendar/src/migration.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ import {
type MigrationUpgradeClient
} from '@hcengineering/model'
import { DOMAIN_SPACE } from '@hcengineering/model-core'
import { DOMAIN_CALENDAR } from '.'
import { DOMAIN_CALENDAR, DOMAIN_EVENT } from '.'
import calendar from './plugin'

async function migrateCalendars (client: MigrationClient): Promise<void> {
Expand Down Expand Up @@ -136,6 +136,16 @@ export const calendarOperation: MigrateOperation = {
{
state: 'migrate_calendars',
func: migrateCalendars
},
{
state: 'move-events',
func: async (client) => {
await client.move(
DOMAIN_CALENDAR,
{ _class: { $in: client.hierarchy.getDescendants(calendar.class.Event) } },
DOMAIN_EVENT
)
}
}
])
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
// limitations under the License.
-->
<script lang="ts">
import calendar from '@hcengineering/calendar'
import calendar, { Calendar } from '@hcengineering/calendar'
import type { Contact, PersonAccount, Organization, Person } from '@hcengineering/contact'
import contact from '@hcengineering/contact'
import core, {
Expand Down Expand Up @@ -41,7 +41,6 @@
import recruit from '../../plugin'
import IconCompany from '../icons/Company.svelte'
import { Analytics } from '@hcengineering/analytics'
import { getCandidateIdentifier } from '../../utils'
// export let space: Ref<Project>
export let candidate: Ref<Person>
Expand Down Expand Up @@ -86,7 +85,8 @@
title,
participants: [currentUser.person],
eventId: '',
dueDate: 0
dueDate: 0,
calendar: '' as Ref<Calendar>
}
const dispatch = createEventDispatcher()
Expand Down Expand Up @@ -139,7 +139,7 @@
access: 'reader',
allDay: false,
eventId: '',
calendar: undefined
calendar: '' as Ref<Calendar>
}
)
Expand Down
5 changes: 5 additions & 0 deletions server/postgres/migrations/calendarSchema.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
ALTER TABLE calendar
ADD "hidden" bool;

UPDATE calendar
SET "hidden" = (data->>'hidden')::boolean;
19 changes: 19 additions & 0 deletions server/postgres/migrations/eventSchema.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
ALTER TABLE event
ADD "date" bigint,
ADD "dueDate" bigint,
add calendar text,
ADD "participants" text[];

UPDATE event
SET "date" = (data->>'date')::bigint;

UPDATE event
SET "dueDate" = (data->>'dueDate')::bigint;

UPDATE calendar
SET "calendar" = (data->>'calendar');

UPDATE event
SET "participants" = array(
SELECT jsonb_array_elements_text(data->'participants')
);
17 changes: 17 additions & 0 deletions server/postgres/migrations/timeSchema.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
ALTER TABLE time
ADD "workslots" bigint,
ADD "doneOn" bigint,
add rank text,
ADD "user" text;

UPDATE time
SET "workslots" = (data->>'workslots')::bigint;

UPDATE time
SET "doneOn" = (data->>'doneOn')::bigint;

UPDATE time
SET "rank" = (data->>'rank');

UPDATE time
SET "user" = (data->>'user');
60 changes: 60 additions & 0 deletions server/postgres/src/schemas.ts
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,63 @@ const docIndexStateSchema: Schema = {
}
}

const timeSchema: Schema = {
...baseSchema,
workslots: {
type: 'bigint',
notNull: false,
index: true
},
doneOn: {
type: 'bigint',
notNull: false,
index: true
},
user: {
type: 'text',
notNull: true,
index: true
},
rank: {
type: 'text',
notNull: true,
index: false
}
}

const calendarSchema: Schema = {
...baseSchema,
hidden: {
type: 'bool',
notNull: true,
index: true
}
}

const eventSchema: Schema = {
...defaultSchema,
calendar: {
type: 'text',
notNull: true,
index: true
},
date: {
type: 'bigint',
notNull: true,
index: true
},
dueDate: {
type: 'bigint',
notNull: true,
index: true
},
participants: {
type: 'text[]',
notNull: true,
index: true
}
}

export function addSchema (domain: string, schema: Schema): void {
domainSchemas[translateDomain(domain)] = schema
}
Expand All @@ -166,6 +223,9 @@ export function translateDomain (domain: string): string {
export const domainSchemas: Record<string, Schema> = {
[DOMAIN_SPACE]: spaceSchema,
[DOMAIN_TX]: txSchema,
[translateDomain('time')]: timeSchema,
[translateDomain('calendar')]: calendarSchema,
[translateDomain('event')]: eventSchema,
[translateDomain(DOMAIN_DOC_INDEX_STATE)]: docIndexStateSchema,
notification: notificationSchema,
[translateDomain('notification-dnc')]: dncSchema,
Expand Down
32 changes: 19 additions & 13 deletions server/postgres/src/storage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -210,7 +210,7 @@ abstract class PostgresAdapterBase implements DbAdapter {
await close(cursorName)
return null
}
return result.map((p) => parseDoc(p as any))
return result.map((p) => parseDoc(p as any, _domain))
}

await init()
Expand Down Expand Up @@ -254,7 +254,7 @@ abstract class PostgresAdapterBase implements DbAdapter {
}
const finalSql: string = [select, ...sqlChunks].join(' ')
const result = await this.client.unsafe(finalSql)
return result.map((p) => parseDocWithProjection(p as any, options?.projection))
return result.map((p) => parseDocWithProjection(p as any, domain, options?.projection))
}

buildRawOrder<T extends Doc>(domain: string, sort: SortingQuery<T>): string {
Expand Down Expand Up @@ -307,7 +307,7 @@ abstract class PostgresAdapterBase implements DbAdapter {
const res = await client.unsafe(
`SELECT * FROM ${translateDomain(domain)} WHERE ${translatedQuery} FOR UPDATE`
)
const docs = res.map((p) => parseDoc(p as any))
const docs = res.map((p) => parseDoc(p as any, domain))
for (const doc of docs) {
if (doc === undefined) continue
const prevAttachedTo = (doc as any).attachedTo
Expand Down Expand Up @@ -460,11 +460,11 @@ abstract class PostgresAdapterBase implements DbAdapter {
const result = await connection.unsafe(finalSql)
if (options?.lookup === undefined && options?.domainLookup === undefined) {
return toFindResult(
result.map((p) => parseDocWithProjection(p as any, options?.projection)),
result.map((p) => parseDocWithProjection(p as any, domain, options?.projection)),
total
)
} else {
const res = this.parseLookup<T>(result, joins, options?.projection)
const res = this.parseLookup<T>(result, joins, options?.projection, domain)
return toFindResult(res, total)
}
} catch (err) {
Expand Down Expand Up @@ -493,7 +493,8 @@ abstract class PostgresAdapterBase implements DbAdapter {
private parseLookup<T extends Doc>(
rows: any[],
joins: JoinProps[],
projection: Projection<T> | undefined
projection: Projection<T> | undefined,
domain: string
): WithLookup<T>[] {
const map = new Map<Ref<T>, WithLookup<T>>()
const modelJoins: JoinProps[] = []
Expand Down Expand Up @@ -526,7 +527,7 @@ abstract class PostgresAdapterBase implements DbAdapter {
if (res === undefined) continue
const { obj, key } = res

const parsed = row[column].map(parseDoc)
const parsed = row[column].map((p: any) => parseDoc(p, domain))
obj[key] = parsed
}
} else if (column.startsWith('lookup_')) {
Expand Down Expand Up @@ -982,7 +983,11 @@ abstract class PostgresAdapterBase implements DbAdapter {
const val = value[operator]
switch (operator) {
case '$ne':
res.push(`${tkey} != '${val}'`)
if (val === null) {
res.push(`${tkey} IS NOT NULL`)
} else {
res.push(`${tkey} != '${val}'`)
}
break
case '$gt':
res.push(`${tkey} > '${val}'`)
Expand Down Expand Up @@ -1131,7 +1136,7 @@ abstract class PostgresAdapterBase implements DbAdapter {
if (result.length === 0) {
return []
}
return result.filter((it) => it != null).map((it) => parseDoc(it as any))
return result.filter((it) => it != null).map((it) => parseDoc(it as any, domain))
}

const flush = async (flush = false): Promise<void> => {
Expand Down Expand Up @@ -1221,7 +1226,7 @@ abstract class PostgresAdapterBase implements DbAdapter {
const connection = (await this.getConnection(ctx)) ?? this.client
const res =
await connection`SELECT * FROM ${connection(translateDomain(domain))} WHERE _id = ANY(${docs}) AND "workspaceId" = ${this.workspaceId.name}`
return res.map((p) => parseDocWithProjection(p as any))
return res.map((p) => parseDocWithProjection(p as any, domain))
})
}

Expand Down Expand Up @@ -1306,7 +1311,7 @@ abstract class PostgresAdapterBase implements DbAdapter {
try {
const res =
await client`SELECT * FROM ${client(translateDomain(domain))} WHERE _id = ANY(${ids}) AND "workspaceId" = ${this.workspaceId.name} FOR UPDATE`
const docs = res.map((p) => parseDoc(p as any))
const docs = res.map((p) => parseDoc(p as any, domain))
const map = new Map(docs.map((d) => [d._id, d]))
for (const [_id, ops] of operations) {
const doc = map.get(_id)
Expand Down Expand Up @@ -1581,7 +1586,8 @@ class PostgresAdapter extends PostgresAdapterBase {
forUpdate ? client` FOR UPDATE` : client``
}`
const dbDoc = res[0]
return dbDoc !== undefined ? parseDoc(dbDoc as any) : undefined
const domain = this.hierarchy.getDomain(_class)
return dbDoc !== undefined ? parseDoc(dbDoc as any, domain) : undefined
})
}

Expand Down Expand Up @@ -1621,7 +1627,7 @@ class PostgresTxAdapter extends PostgresAdapterBase implements TxAdapter {
const res = await this
.client`SELECT * FROM ${this.client(translateDomain(DOMAIN_TX))} WHERE "workspaceId" = ${this.workspaceId.name} AND "objectSpace" = ${core.space.Model} ORDER BY _id ASC, "modifiedOn" ASC`

const model = res.map((p) => parseDoc<Tx>(p as any))
const model = res.map((p) => parseDoc<Tx>(p as any, DOMAIN_TX))
// We need to put all core.account.System transactions first
const systemTx: Tx[] = []
const userTx: Tx[] = []
Expand Down
22 changes: 14 additions & 8 deletions server/postgres/src/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -326,8 +326,8 @@ export function parseUpdate<T extends Doc> (
const remainingData: Partial<T> = {}

for (const key in ops) {
if (key === '$push' || key === '$pull') {
const val = (ops as any)[key]
const val = (ops as any)[key]
if (key.startsWith('$')) {
for (const k in val) {
if (getDocFieldsByDomains(domain).includes(k)) {
;(extractedFields as any)[k] = val[key]
Expand All @@ -337,9 +337,9 @@ export function parseUpdate<T extends Doc> (
}
} else {
if (getDocFieldsByDomains(domain).includes(key)) {
;(extractedFields as any)[key] = (ops as any)[key]
;(extractedFields as any)[key] = val
} else {
;(remainingData as any)[key] = (ops as any)[key]
;(remainingData as any)[key] = val
}
}
}
Expand Down Expand Up @@ -396,8 +396,13 @@ export class DBCollectionHelper implements DomainHelperOperations {
}
}

export function parseDocWithProjection<T extends Doc> (doc: DBDoc, projection?: Projection<T> | undefined): T {
export function parseDocWithProjection<T extends Doc> (
doc: DBDoc,
domain: string,
projection?: Projection<T> | undefined
): T {
const { workspaceId, data, ...rest } = doc
const schema = getSchema(domain)
for (const key in rest) {
if ((rest as any)[key] === 'NULL' || (rest as any)[key] === null) {
if (key === 'attachedTo') {
Expand All @@ -407,7 +412,7 @@ export function parseDocWithProjection<T extends Doc> (doc: DBDoc, projection?:
;(rest as any)[key] = null
}
}
if (key === 'modifiedOn' || key === 'createdOn') {
if (schema[key] !== undefined && schema[key].type === 'bigint') {
;(rest as any)[key] = Number.parseInt((rest as any)[key])
}
}
Expand All @@ -427,7 +432,8 @@ export function parseDocWithProjection<T extends Doc> (doc: DBDoc, projection?:
return res
}

export function parseDoc<T extends Doc> (doc: DBDoc): T {
export function parseDoc<T extends Doc> (doc: DBDoc, domain: string): T {
const schema = getSchema(domain)
const { workspaceId, data, ...rest } = doc
for (const key in rest) {
if ((rest as any)[key] === 'NULL' || (rest as any)[key] === null) {
Expand All @@ -438,7 +444,7 @@ export function parseDoc<T extends Doc> (doc: DBDoc): T {
;(rest as any)[key] = null
}
}
if (key === 'modifiedOn' || key === 'createdOn') {
if (schema[key] !== undefined && schema[key].type === 'bigint') {
;(rest as any)[key] = Number.parseInt((rest as any)[key])
}
}
Expand Down

0 comments on commit 76bcd3c

Please sign in to comment.