Skip to content

Commit

Permalink
UBERF-8993: Part2 (#7532)
Browse files Browse the repository at this point in the history
Signed-off-by: Andrey Sobolev <[email protected]>
  • Loading branch information
haiodo authored Dec 24, 2024
1 parent 0db7adc commit 35981be
Show file tree
Hide file tree
Showing 28 changed files with 178 additions and 114 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -106,3 +106,4 @@ tests/profiles
dump
**/logs/**
dev/tool/history.json
.aider*
26 changes: 14 additions & 12 deletions packages/core/src/operator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,22 +28,23 @@ function $push (document: Doc, keyval: Record<string, PropertyType>): void {
if (doc[key] === undefined) {
doc[key] = []
}
const val = keyval[key]
if (typeof val === 'object') {
const kvk = keyval[key]
if (typeof kvk === 'object' && kvk != null) {
const arr = doc[key] as Array<any>
const desc = val as Position<PropertyType>
const desc = kvk as Position<PropertyType>
if ('$each' in desc) {
if (arr != null) {
if (arr != null && Array.isArray(arr)) {
arr.splice(desc.$position ?? 0, 0, ...desc.$each)
}
} else {
arr.push(val)
arr.push(kvk)
}
} else {
if (doc[key] == null) {
doc[key] = []
if (doc[key] === null || doc[key] === undefined) {
doc[key] = [kvk]
} else {
doc[key].push(kvk)
}
doc[key].push(val)
}
}
}
Expand All @@ -55,15 +56,16 @@ function $pull (document: Doc, keyval: Record<string, PropertyType>): void {
doc[key] = []
}
const arr = doc[key] as Array<any>
if (typeof keyval[key] === 'object' && keyval[key] !== null) {
const { $in } = keyval[key] as PullArray<PropertyType>
const kvk = keyval[key]
if (typeof kvk === 'object' && kvk !== null) {
const { $in } = kvk as PullArray<PropertyType>

doc[key] = (arr ?? []).filter((val) => {
if ($in !== undefined) {
return !$in.includes(val)
} else {
// We need to match all fields
for (const [kk, kv] of Object.entries(keyval[key])) {
for (const [kk, kv] of Object.entries(kvk)) {
if (val[kk] !== kv) {
return true
}
Expand All @@ -72,7 +74,7 @@ function $pull (document: Doc, keyval: Record<string, PropertyType>): void {
}
})
} else {
doc[key] = (arr ?? []).filter((val) => val !== keyval[key])
doc[key] = (arr ?? []).filter((val) => val !== kvk)
}
}
}
Expand Down
9 changes: 5 additions & 4 deletions packages/presentation/src/components/DocPopup.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -93,13 +93,14 @@
dispatch('update', selectedObjects)
}
const client = getClient()
let selection = 0
let list: ListView
async function handleSelection (evt: Event | undefined, objects: Doc[], selection: number): Promise<void> {
const item = objects[selection]
if (item === undefined) {
return
}
if (!multiSelect) {
if (allowDeselect) {
Expand Down Expand Up @@ -140,7 +141,7 @@
showPopup(c.component, c.props ?? {}, 'top', async (res) => {
if (res != null) {
// We expect reference to new object.
const newPerson = await client.findOne(_class, { _id: res })
const newPerson = await getClient().findOne(_class, { _id: res })
if (newPerson !== undefined) {
search = c.update?.(newPerson) ?? ''
dispatch('created', newPerson)
Expand All @@ -163,7 +164,7 @@
}
function findObjectPresenter (_class: Ref<Class<Doc>>): void {
const presenterMixin = client.getHierarchy().classHierarchyMixin(_class, view.mixin.ObjectPresenter)
const presenterMixin = getClient().getHierarchy().classHierarchyMixin(_class, view.mixin.ObjectPresenter)
if (presenterMixin?.presenter !== undefined) {
getResource(presenterMixin.presenter)
.then((result) => {
Expand Down
16 changes: 9 additions & 7 deletions packages/presentation/src/components/ObjectSearchPopup.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,6 @@
let categories: ObjectSearchCategory[] = []
let categoryStatus: Record<Ref<ObjectSearchCategory>, number> = {}
const client = getClient()
let category: ObjectSearchCategory | undefined
const categoryQuery: DocumentQuery<ObjectSearchCategory> = {
Expand All @@ -56,10 +55,12 @@
categoryQuery._id = { $in: allowCategory }
}
client.findAll(presentation.class.ObjectSearchCategory, categoryQuery).then((r) => {
categories = r.filter((it) => hasResource(it.query))
category = categories[0]
})
void getClient()
.findAll(presentation.class.ObjectSearchCategory, categoryQuery)
.then((r) => {
categories = r.filter((it) => hasResource(it.query))
category = categories[0]
})
const dispatch = createEventDispatcher()
Expand Down Expand Up @@ -96,7 +97,7 @@
key.preventDefault()
key.stopPropagation()
const item = items[selection]
if (item) {
if (item != null) {
dispatchItem(item)
return true
} else {
Expand All @@ -106,7 +107,7 @@
return false
}
export function done () {}
export function done (): void {}
const updateItems = reduceCalls(async function updateItems (
cat: ObjectSearchCategory | undefined,
Expand All @@ -120,6 +121,7 @@
const newCategoryStatus: Record<Ref<ObjectSearchCategory>, number> = {}
const f = await getResource(cat.query)
const client = getClient()
const result = await f(client, query, { in: relatedDocuments, nin: ignore })
// We need to sure, results we return is for proper category.
if (cat._id === category?._id) {
Expand Down
54 changes: 35 additions & 19 deletions packages/presentation/src/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ import { getRawCurrentLocation, workspaceId, type AnyComponent, type AnySvelteCo
import view, { type AttributeCategory, type AttributeEditor } from '@hcengineering/view'
import { deepEqual } from 'fast-equals'
import { onDestroy } from 'svelte'
import { get, writable, type Writable } from 'svelte/store'
import { get, writable } from 'svelte/store'

import { type KeyedAttribute } from '..'
import { OptimizeQueryMiddleware, PresentationPipelineImpl, type PresentationPipeline } from './pipeline'
Expand All @@ -63,7 +63,7 @@ export { reduceCalls } from '@hcengineering/core'

let liveQuery: LQ
let rawLiveQuery: LQ
let client: TxOperations & Client & OptimisticTxes
let client: TxOperations & Client
let pipeline: PresentationPipeline

const txListeners: Array<(...tx: Tx[]) => void> = []
Expand All @@ -89,13 +89,11 @@ export function removeTxListener (l: (tx: Tx) => void): void {
}
}

export interface OptimisticTxes {
pendingCreatedDocs: Writable<Record<Ref<Doc>, boolean>>
}

export const uiContext = new MeasureMetricsContext('client-ui', {})

class UIClient extends TxOperations implements Client, OptimisticTxes {
export const pendingCreatedDocs = writable<Record<Ref<Doc>, boolean>>({})

class UIClient extends TxOperations implements Client {
hook = getMetadata(plugin.metadata.ClientHook)
constructor (
client: Client,
Expand All @@ -105,14 +103,9 @@ class UIClient extends TxOperations implements Client, OptimisticTxes {
}

protected pendingTxes = new Set<Ref<Tx>>()
protected _pendingCreatedDocs = writable<Record<Ref<Doc>, boolean>>({})

get pendingCreatedDocs (): typeof this._pendingCreatedDocs {
return this._pendingCreatedDocs
}

async doNotify (...tx: Tx[]): Promise<void> {
const pending = get(this._pendingCreatedDocs)
const pending = get(pendingCreatedDocs)
let pendingUpdated = false
tx.forEach((t) => {
if (this.pendingTxes.has(t._id)) {
Expand All @@ -129,7 +122,7 @@ class UIClient extends TxOperations implements Client, OptimisticTxes {
}
})
if (pendingUpdated) {
this._pendingCreatedDocs.set(pending)
pendingCreatedDocs.set(pending)
}

// We still want to notify about all transactions because there might be queries created after
Expand Down Expand Up @@ -214,9 +207,9 @@ class UIClient extends TxOperations implements Client, OptimisticTxes {
}

if (innerTx._class === core.class.TxCreateDoc) {
const pending = get(this._pendingCreatedDocs)
const pending = get(pendingCreatedDocs)
pending[innerTx.objectId] = true
this._pendingCreatedDocs.set(pending)
pendingCreatedDocs.set(pending)
}

this.pendingTxes.add(tx._id)
Expand All @@ -231,11 +224,33 @@ class UIClient extends TxOperations implements Client, OptimisticTxes {
}
}

const hierarchyProxy = new Proxy(
{},
{
get (target, p, receiver) {
const h = client.getHierarchy()
return Reflect.get(h, p)
}
}
) as TxOperations & Client

// We need a proxy to handle all the calls to the proper client.
const clientProxy = new Proxy(
{},
{
get (target, p, receiver) {
if (p === 'getHierarchy') {
return () => hierarchyProxy
}
return Reflect.get(client, p)
}
}
) as TxOperations & Client
/**
* @public
*/
export function getClient (): TxOperations & Client & OptimisticTxes {
return client
export function getClient (): TxOperations & Client {
return clientProxy
}

let txQueue: Tx[] = []
Expand All @@ -252,6 +267,7 @@ export function addRefreshListener (r: RefreshListener): void {
* @public
*/
export async function setClient (_client: Client): Promise<void> {
pendingCreatedDocs.set({})
if (liveQuery !== undefined) {
await liveQuery.close()
}
Expand Down Expand Up @@ -700,7 +716,7 @@ export function isSpace (space: Doc): space is Space {
}

export function isSpaceClass (_class: Ref<Class<Doc>>): boolean {
return getClient().getHierarchy().isDerived(_class, core.class.Space)
return client.getHierarchy().isDerived(_class, core.class.Space)
}

export function setPresentationCookie (token: string, workspaceId: string): void {
Expand Down
3 changes: 3 additions & 0 deletions packages/ui/src/components/CodeForm.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,9 @@
}
function onKeydown (e: KeyboardEvent): void {
if (e.key === undefined) {
return
}
const key = e.key.toLowerCase()
const target = e.target as HTMLInputElement
if (key !== 'backspace' && key !== 'delete') return
Expand Down
4 changes: 2 additions & 2 deletions packages/ui/src/focus.ts
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ class FocusManagerImpl implements FocusManager {
return
}
this.current = this.elements.findIndex((it) => it.id === idx) ?? 0
this.elements[Math.abs(this.current) % this.elements.length].focus()
this.elements[Math.abs(this.current) % this.elements.length]?.focus()
}

setFocusPos (order: number): void {
Expand All @@ -73,7 +73,7 @@ class FocusManagerImpl implements FocusManager {
const idx = this.elements.findIndex((it) => it.order === order)
if (idx !== undefined) {
this.current = idx
this.elements[Math.abs(this.current) % this.elements.length].focus()
this.elements[Math.abs(this.current) % this.elements.length]?.focus()
}
}

Expand Down
11 changes: 6 additions & 5 deletions packages/ui/src/popups.ts
Original file line number Diff line number Diff line change
Expand Up @@ -149,16 +149,17 @@ export function closePopup (category?: string): void {
} else {
for (let i = popups.length - 1; i >= 0; i--) {
if (popups[i].type !== 'popup') continue
if ((popups[i] as CompAndProps).options.fixed !== true) {
const isClosing = (popups[i] as CompAndProps).closing ?? false
const popi = popups[i] as CompAndProps
if (popi.options.fixed !== true) {
const isClosing = popi.closing ?? false
if (popups[i].type === 'popup') {
;(popups[i] as CompAndProps).closing = true
popi.closing = true
}
if (!isClosing) {
// To prevent possible recursion, we need to check if we call some code from popup close, to do close.
;(popups[i] as CompAndProps).onClose?.(undefined)
popi.onClose?.(undefined)
}
;(popups[i] as CompAndProps).closing = false
popi.closing = false
popups.splice(i, 1)
break
}
Expand Down
8 changes: 6 additions & 2 deletions packages/ui/src/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -214,8 +214,12 @@ export function replaceURLs (text: string): string {
* @returns {string} string with parsed URL
*/
export function parseURL (text: string): string {
const matches = autolinker.parse(text, { urls: true })
return matches.length > 0 ? matches[0].getAnchorHref() : ''
try {
const matches = autolinker.parse(text ?? '', { urls: true })
return matches.length > 0 ? matches[0].getAnchorHref() : ''
} catch (err: any) {
return ''
}
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
import contact, { Person, PersonAccount } from '@hcengineering/contact'
import { personAccountByIdStore, personByIdStore } from '@hcengineering/contact-resources'
import { Class, Doc, getCurrentAccount, Markup, Ref, Space, WithLookup } from '@hcengineering/core'
import { getClient, MessageViewer } from '@hcengineering/presentation'
import { getClient, MessageViewer, pendingCreatedDocs } from '@hcengineering/presentation'
import { AttachmentDocList, AttachmentImageSize } from '@hcengineering/attachment-resources'
import { getDocLinkTitle } from '@hcengineering/view-resources'
import { Action, Button, IconEdit, ShowMore } from '@hcengineering/ui'
Expand Down Expand Up @@ -58,7 +58,6 @@
export let onReply: ((message: ActivityMessage) => void) | undefined = undefined
const client = getClient()
const { pendingCreatedDocs } = client
const hierarchy = client.getHierarchy()
const STALE_TIMEOUT_MS = 5000
const currentAccount = getCurrentAccount()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -82,9 +82,11 @@
included = []
}
$: employees = Array.from(
(value ?? []).map((it) => $personAccountByIdStore.get(it as Ref<PersonAccount>)?.person)
).filter((it) => it !== undefined) as Ref<Employee>[]
$: employees = Array.isArray(value)
? (Array.from((value ?? []).map((it) => $personAccountByIdStore.get(it as Ref<PersonAccount>)?.person)).filter(
(it) => it !== undefined
) as Ref<Employee>[])
: []
$: docQuery =
excluded.length === 0 && included.length === 0
Expand Down
Loading

0 comments on commit 35981be

Please sign in to comment.