fix: better handle markup in api client (#7180)
Some checks are pending
CI / build (push) Waiting to run
CI / svelte-check (push) Blocked by required conditions
CI / formatting (push) Blocked by required conditions
CI / test (push) Blocked by required conditions
CI / uitest (push) Waiting to run
CI / uitest-pg (push) Waiting to run
CI / uitest-qms (push) Waiting to run
CI / docker-build (push) Blocked by required conditions
CI / dist-build (push) Blocked by required conditions

Signed-off-by: Alexander Onnikov <Alexander.Onnikov@xored.com>
This commit is contained in:
Alexander Onnikov 2024-11-22 09:29:59 +07:00 committed by GitHub
parent 9bea2f6be6
commit 1e2b3645b0
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 86 additions and 23 deletions

View File

@ -34,15 +34,22 @@ import {
AttachedData,
Mixin,
MixinUpdate,
MixinData
MixinData,
generateId
} from '@hcengineering/core'
import client, { clientId } from '@hcengineering/client'
import { addLocation, getResource } from '@hcengineering/platform'
import { login, selectWorkspace } from './account'
import { type ServerConfig, loadServerConfig } from './config'
import { type MarkupOperations, type MarkupFormat, type MarkupRef, createMarkupOperations } from './markup'
import { type PlatformClient, type ConnectOptions } from './types'
import {
type MarkupFormat,
type MarkupOperations,
type MarkupRef,
MarkupContent,
createMarkupOperations
} from './markup'
import { type PlatformClient, type ConnectOptions, WithMarkup } from './types'
/**
* Create platform client
@ -121,41 +128,62 @@ class PlatformClientImpl implements PlatformClient {
await this.connection.close()
}
// TxOperations
private async processMarkup<T>(id: Ref<Doc>, data: WithMarkup<T>): Promise<T> {
const result: any = {}
for (const [key, value] of Object.entries(data)) {
if (value instanceof MarkupContent) {
result[key] = this.markup.uploadMarkup(id, key, value.content, value.kind)
} else {
result[key] = value
}
}
return result as T
}
// DocOperations
async createDoc<T extends Doc>(
_class: Ref<Class<T>>,
space: Ref<Space>,
attributes: Data<T>,
attributes: WithMarkup<Data<T>>,
id?: Ref<T>
): Promise<Ref<T>> {
return await this.client.createDoc(_class, space, attributes, id)
id ??= generateId()
const data = await this.processMarkup<Data<T>>(id, attributes)
return await this.client.createDoc(_class, space, data, id)
}
async updateDoc<T extends Doc>(
_class: Ref<Class<T>>,
space: Ref<Space>,
objectId: Ref<T>,
operations: DocumentUpdate<T>,
operations: WithMarkup<DocumentUpdate<T>>,
retrieve?: boolean
): Promise<TxResult> {
return await this.client.updateDoc(_class, space, objectId, operations, retrieve)
const update = await this.processMarkup<DocumentUpdate<T>>(objectId, operations)
return await this.client.updateDoc(_class, space, objectId, update, retrieve)
}
async removeDoc<T extends Doc>(_class: Ref<Class<T>>, space: Ref<Space>, objectId: Ref<T>): Promise<TxResult> {
return await this.client.removeDoc(_class, space, objectId)
}
// CollectionOperations
async addCollection<T extends Doc, P extends AttachedDoc>(
_class: Ref<Class<P>>,
space: Ref<Space>,
attachedTo: Ref<T>,
attachedToClass: Ref<Class<T>>,
collection: Extract<keyof T, string> | string,
attributes: AttachedData<P>,
attributes: WithMarkup<AttachedData<P>>,
id?: Ref<P>
): Promise<Ref<P>> {
return await this.client.addCollection(_class, space, attachedTo, attachedToClass, collection, attributes, id)
id ??= generateId()
const data = await this.processMarkup<AttachedData<P>>(id, attributes)
return await this.client.addCollection(_class, space, attachedTo, attachedToClass, collection, data, id)
}
async updateCollection<T extends Doc, P extends AttachedDoc>(
@ -165,9 +193,10 @@ class PlatformClientImpl implements PlatformClient {
attachedTo: Ref<T>,
attachedToClass: Ref<Class<T>>,
collection: Extract<keyof T, string> | string,
operations: DocumentUpdate<P>,
operations: WithMarkup<DocumentUpdate<P>>,
retrieve?: boolean
): Promise<Ref<T>> {
const update = await this.processMarkup<DocumentUpdate<P>>(objectId, operations)
return await this.client.updateCollection(
_class,
space,
@ -175,7 +204,7 @@ class PlatformClientImpl implements PlatformClient {
attachedTo,
attachedToClass,
collection,
operations,
update,
retrieve
)
}
@ -191,14 +220,17 @@ class PlatformClientImpl implements PlatformClient {
return await this.client.removeCollection(_class, space, objectId, attachedTo, attachedToClass, collection)
}
// MixinOperations
async createMixin<D extends Doc, M extends D>(
objectId: Ref<D>,
objectClass: Ref<Class<D>>,
objectSpace: Ref<Space>,
mixin: Ref<Mixin<M>>,
attributes: MixinData<D, M>
attributes: WithMarkup<MixinData<D, M>>
): Promise<TxResult> {
return await this.client.createMixin(objectId, objectClass, objectSpace, mixin, attributes)
const data = await this.processMarkup<MixinData<D, M>>(objectId, attributes)
return await this.client.createMixin(objectId, objectClass, objectSpace, mixin, data)
}
async updateMixin<D extends Doc, M extends D>(
@ -206,9 +238,10 @@ class PlatformClientImpl implements PlatformClient {
objectClass: Ref<Class<D>>,
objectSpace: Ref<Space>,
mixin: Ref<Mixin<M>>,
attributes: MixinUpdate<D, M>
attributes: WithMarkup<MixinUpdate<D, M>>
): Promise<TxResult> {
return await this.client.updateMixin(objectId, objectClass, objectSpace, mixin, attributes)
const update = await this.processMarkup<MixinUpdate<D, M>>(objectId, attributes)
return await this.client.updateMixin(objectId, objectClass, objectSpace, mixin, update)
}
// Markup

View File

@ -21,6 +21,24 @@ export type MarkupRef = CollaborativeDoc
/** @public */
export type MarkupFormat = 'markup' | 'html' | 'markdown'
/** @public */
export class MarkupContent {
constructor (
readonly content: string,
readonly kind: MarkupFormat
) {}
}
/** @public */
export function html (content: string): MarkupContent {
return new MarkupContent(content, 'html')
}
/** @public */
export function markdown (content: string): MarkupContent {
return new MarkupContent(content, 'markdown')
}
/**
* Provides operations for managing markup (rich-text) content.
* @public */

View File

@ -15,6 +15,7 @@
import { type ClientSocketFactory } from '@hcengineering/client'
import {
CollaborativeDoc,
type AttachedData,
type AttachedDoc,
type Class,
@ -34,7 +35,18 @@ import {
type TxResult,
type WithLookup
} from '@hcengineering/core'
import { type MarkupOperations } from './markup'
import { type MarkupContent, type MarkupOperations } from './markup'
type WithPropertyType<T, X, Y> = {
[P in keyof T]: T[P] extends X ? Y : T[P]
}
/** @public */
export type WithMarkup<T> = WithPropertyType<
WithPropertyType<T, CollaborativeDoc | undefined, MarkupContent | undefined>,
CollaborativeDoc,
MarkupContent
>
/**
* Platform API client
@ -77,7 +89,7 @@ export interface DocOperations {
createDoc: <T extends Doc>(
_class: Ref<Class<T>>,
space: Ref<Space>,
attributes: Data<T>,
attributes: WithMarkup<Data<T>>,
id?: Ref<T>
) => Promise<Ref<T>>
@ -85,7 +97,7 @@ export interface DocOperations {
_class: Ref<Class<T>>,
space: Ref<Space>,
objectId: Ref<T>,
operations: DocumentUpdate<T>,
operations: WithMarkup<DocumentUpdate<T>>,
retrieve?: boolean
) => Promise<TxResult>
@ -102,7 +114,7 @@ export interface CollectionOperations {
attachedTo: Ref<T>,
attachedToClass: Ref<Class<T>>,
collection: Extract<keyof T, string> | string,
attributes: AttachedData<P>,
attributes: WithMarkup<AttachedData<P>>,
id?: Ref<P>
) => Promise<Ref<P>>
@ -113,7 +125,7 @@ export interface CollectionOperations {
attachedTo: Ref<T>,
attachedToClass: Ref<Class<T>>,
collection: Extract<keyof T, string> | string,
operations: DocumentUpdate<P>,
operations: WithMarkup<DocumentUpdate<P>>,
retrieve?: boolean
) => Promise<Ref<T>>
@ -136,7 +148,7 @@ export interface MixinOperations {
objectClass: Ref<Class<D>>,
objectSpace: Ref<Space>,
mixin: Ref<Mixin<M>>,
attributes: MixinData<D, M>
attributes: WithMarkup<MixinData<D, M>>
) => Promise<TxResult>
updateMixin: <D extends Doc, M extends D>(
@ -144,7 +156,7 @@ export interface MixinOperations {
objectClass: Ref<Class<D>>,
objectSpace: Ref<Space>,
mixin: Ref<Mixin<M>>,
attributes: MixinUpdate<D, M>
attributes: WithMarkup<MixinUpdate<D, M>>
) => Promise<TxResult>
}