Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

UBERF-7011: Switch to Ref<Blob> #5661

Merged
merged 1 commit into from
May 27, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
61 changes: 58 additions & 3 deletions common/config/rush/pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

30 changes: 15 additions & 15 deletions dev/tool/src/clean.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,42 +17,42 @@ import attachment from '@hcengineering/attachment'
import chunter, { type ChatMessage } from '@hcengineering/chunter'
import contact from '@hcengineering/contact'
import core, {
ClassifierKind,
DOMAIN_STATUS,
DOMAIN_TX,
type MeasureContext,
SortingOrder,
TxOperations,
TxProcessor,
generateId,
getObjectValue,
toIdMap,
type BackupClient,
type Class,
type Client as CoreClient,
type Doc,
type Domain,
type MeasureContext,
type Ref,
type TxCreateDoc,
type WorkspaceId,
type Status,
type StatusCategory,
type TxMixin,
type TxCUD,
type TxCreateDoc,
type TxMixin,
type TxUpdateDoc,
DOMAIN_STATUS,
type Status,
toIdMap,
type Class,
ClassifierKind
type WorkspaceId
} from '@hcengineering/core'
import { DOMAIN_ACTIVITY } from '@hcengineering/model-activity'
import { DOMAIN_SPACE } from '@hcengineering/model-core'
import recruitModel, { defaultApplicantStatuses } from '@hcengineering/model-recruit'
import { getWorkspaceDB } from '@hcengineering/mongo'
import recruit, { type Applicant, type Vacancy } from '@hcengineering/recruit'
import recruitModel, { defaultApplicantStatuses } from '@hcengineering/model-recruit'
import { type StorageAdapter } from '@hcengineering/server-core'
import { connect } from '@hcengineering/server-tool'
import tags, { type TagCategory, type TagElement, type TagReference } from '@hcengineering/tags'
import task, { type Task, type ProjectType, type TaskType } from '@hcengineering/task'
import task, { type ProjectType, type Task, type TaskType } from '@hcengineering/task'
import tracker from '@hcengineering/tracker'
import { deepEqual } from 'fast-equals'
import { MongoClient } from 'mongodb'
import { DOMAIN_ACTIVITY } from '@hcengineering/model-activity'
import { DOMAIN_SPACE } from '@hcengineering/model-core'

export async function cleanWorkspace (
ctx: MeasureContext,
Expand All @@ -77,7 +77,7 @@ export async function cleanWorkspace (
const contacts = await ops.findAll(contact.class.Contact, {})

const files = new Set(
attachments.map((it) => it.file).concat(contacts.map((it) => it.avatar).filter((it) => it) as string[])
attachments.map((it) => it.file as string).concat(contacts.map((it) => it.avatar).filter((it) => it) as string[])
)

const minioList = await storageAdapter.listStream(ctx, workspaceId)
Expand Down Expand Up @@ -177,7 +177,7 @@ export async function fixMinioBW (
break
}
if (obj.modifiedOn < from) continue
if ((obj._id as string).includes('%size%')) {
if ((obj._id as string).includes('%preview%')) {
await storageService.remove(ctx, workspaceId, [obj._id])
removed++
if (removed % 100 === 0) {
Expand Down
12 changes: 6 additions & 6 deletions models/attachment/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,18 +15,18 @@

import activity from '@hcengineering/activity'
import type { Attachment, AttachmentMetadata, Photo, SavedAttachments } from '@hcengineering/attachment'
import { type Domain, IndexKind, type Ref } from '@hcengineering/core'
import { IndexKind, type Blob, type Domain, type Ref } from '@hcengineering/core'
import {
type Builder,
Index,
Model,
Prop,
TypeAttachment,
TypeBlob,
TypeBoolean,
TypeRef,
TypeString,
TypeTimestamp,
UX
UX,
type Builder
} from '@hcengineering/model'
import core, { TAttachedDoc } from '@hcengineering/model-core'
import preference, { TPreference } from '@hcengineering/model-preference'
Expand All @@ -46,8 +46,8 @@ export class TAttachment extends TAttachedDoc implements Attachment {
@Index(IndexKind.FullText)
name!: string

@Prop(TypeAttachment(), attachment.string.File)
file!: string
@Prop(TypeBlob(), attachment.string.File)
file!: Ref<Blob>

@Prop(TypeString(), attachment.string.Size)
size!: number
Expand Down
31 changes: 28 additions & 3 deletions models/contact/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ import {
DOMAIN_MODEL,
DateRangeMode,
IndexKind,
type Blob,
type Class,
type Domain,
type Markup,
Expand All @@ -50,10 +51,11 @@ import {
Model,
Prop,
ReadOnly,
TypeAttachment,
TypeBlob,
TypeBoolean,
TypeCollaborativeMarkup,
TypeDate,
TypeRecord,
TypeRef,
TypeString,
TypeTimestamp,
Expand Down Expand Up @@ -104,10 +106,23 @@ export class TContact extends TDoc implements Contact {
@Index(IndexKind.FullText)
name!: string

@Prop(TypeAttachment(), contact.string.Avatar)
@Prop(TypeString(), contact.string.Avatar)
@Index(IndexKind.FullText)
@Hidden()
avatar?: string | null
avatarType!: AvatarType

@Prop(TypeBlob(), contact.string.Avatar)
@Index(IndexKind.FullText)
@Hidden()
avatar!: Ref<Blob> | null | undefined

@Prop(TypeRecord(), contact.string.Avatar)
@Index(IndexKind.FullText)
@Hidden()
avatarProps?: {
color?: string
url?: string
}

@Prop(Collection(contact.class.Channel), contact.string.ContactInfo)
channels?: number
Expand Down Expand Up @@ -709,6 +724,16 @@ export function createModel (builder: Builder): void {
contact.avatarProvider.Gravatar
)

builder.createDoc(
contact.class.AvatarProvider,
core.space.Model,
{
type: AvatarType.EXTERNAL,
getUrl: contact.function.GetExternalUrl
},
contact.avatarProvider.Color
)

builder.mixin(contact.class.Person, core.class.Class, view.mixin.ObjectPresenter, {
presenter: contact.component.PersonPresenter
})
Expand Down
60 changes: 59 additions & 1 deletion models/contact/src/migration.ts
Original file line number Diff line number Diff line change
@@ -1,19 +1,22 @@
//

import { DOMAIN_TX, type Space, TxOperations, type Class, type Doc, type Domain, type Ref } from '@hcengineering/core'
import { DOMAIN_TX, TxOperations, type Class, type Doc, type Domain, type Ref, type Space } from '@hcengineering/core'
import {
createDefaultSpace,
tryMigrate,
tryUpgrade,
type MigrateOperation,
type MigrateUpdate,
type MigrationClient,
type MigrationDocumentQuery,
type MigrationUpgradeClient,
type ModelLogger
} from '@hcengineering/model'
import activity, { DOMAIN_ACTIVITY } from '@hcengineering/model-activity'
import core from '@hcengineering/model-core'
import { DOMAIN_VIEW } from '@hcengineering/model-view'

import { AvatarType, type Contact } from '@hcengineering/contact'
import contact, { DOMAIN_CONTACT, contactId } from './index'

async function createEmployeeEmail (client: TxOperations): Promise<void> {
Expand Down Expand Up @@ -48,6 +51,55 @@ async function createEmployeeEmail (client: TxOperations): Promise<void> {
}
}

const colorPrefix = 'color://'
const gravatarPrefix = 'gravatar://'

async function migrateAvatars (client: MigrationClient): Promise<void> {
const classes = client.hierarchy.getDescendants(contact.class.Contact)
const i = await client.traverse<Contact>(DOMAIN_CONTACT, {
_class: { $in: classes },
avatar: { $regex: 'color|gravatar://.*' }
})
while (true) {
const docs = await i.next(50)
if (docs === null || docs?.length === 0) {
break
}
const updates: { filter: MigrationDocumentQuery<Contact>, update: MigrateUpdate<Contact> }[] = []
for (const d of docs) {
if (d.avatar?.startsWith(colorPrefix) ?? false) {
d.avatarProps = { color: d.avatar?.slice(colorPrefix.length) ?? '' }
updates.push({
filter: { _id: d._id },
update: {
avatarType: AvatarType.COLOR,
avatar: null,
avatarProps: { color: d.avatar?.slice(colorPrefix.length) ?? '' }
}
})
} else if (d.avatar?.startsWith(gravatarPrefix) ?? false) {
updates.push({
filter: { _id: d._id },
update: {
avatarType: AvatarType.GRAVATAR,
avatar: null,
avatarProps: { url: d.avatar?.slice(gravatarPrefix.length) ?? '' }
}
})
}
}
if (updates.length > 0) {
await client.bulk(DOMAIN_CONTACT, updates)
}
}

await client.update(
DOMAIN_CONTACT,
{ _class: { $in: classes }, avatarKind: { $exists: false } },
{ avatarKind: AvatarType.IMAGE }
)
}

export const contactOperation: MigrateOperation = {
async migrate (client: MigrationClient, logger: ModelLogger): Promise<void> {
await tryMigrate(client, contactId, [
Expand Down Expand Up @@ -183,6 +235,12 @@ export const contactOperation: MigrateOperation = {
}
)
}
},
{
state: 'avatars',
func: async (client) => {
await migrateAvatars(client)
}
}
])
},
Expand Down
4 changes: 2 additions & 2 deletions models/core/src/core.ts
Original file line number Diff line number Diff line change
Expand Up @@ -213,8 +213,8 @@ export class TTypeString extends TType {}
export class TTypeRecord extends TType {}

@UX(core.string.String)
@Model(core.class.TypeAttachment, core.class.Type)
export class TTypeAttachment extends TType {}
@Model(core.class.TypeBlob, core.class.Type)
export class TTypeBlob extends TType {}

@UX(core.string.Hyperlink)
@Model(core.class.TypeHyperlink, core.class.Type)
Expand Down
Loading