mirror of
https://github.com/hcengineering/platform.git
synced 2025-05-15 20:10:52 +00:00
Merge branch 'develop' into staging-new
Signed-off-by: Andrey Sobolev <haiodo@gmail.com>
This commit is contained in:
commit
a6cc9a0400
10
.vscode/launch.json
vendored
10
.vscode/launch.json
vendored
@ -55,7 +55,7 @@
|
||||
"MODEL_JSON": "${workspaceRoot}/models/all/bundle/model.json",
|
||||
// "SERVER_PROVIDER":"uweb"
|
||||
"SERVER_PROVIDER":"ws",
|
||||
"MODEL_VERSION": "0.6.427",
|
||||
"MODEL_VERSION": "0.6.431",
|
||||
// "VERSION": "0.6.289",
|
||||
"ELASTIC_INDEX_NAME": "local_storage_index",
|
||||
"UPLOAD_URL": "/files",
|
||||
@ -167,7 +167,7 @@
|
||||
"MINIO_ACCESS_KEY": "minioadmin",
|
||||
"MINIO_SECRET_KEY": "minioadmin",
|
||||
"MINIO_ENDPOINT": "localhost",
|
||||
"MODEL_VERSION": "v0.6.427",
|
||||
"MODEL_VERSION": "v0.6.431",
|
||||
"WS_OPERATION": "all+backup",
|
||||
"BACKUP_STORAGE": "minio|minio?accessKey=minioadmin&secretKey=minioadmin",
|
||||
"BACKUP_BUCKET": "dev-backups",
|
||||
@ -200,7 +200,7 @@
|
||||
"MINIO_ACCESS_KEY": "minioadmin",
|
||||
"MINIO_SECRET_KEY": "minioadmin",
|
||||
"MINIO_ENDPOINT": "localhost",
|
||||
"MODEL_VERSION": "0.6.427",
|
||||
"MODEL_VERSION": "0.6.431",
|
||||
"WS_OPERATION": "all+backup",
|
||||
"BACKUP_STORAGE": "minio|minio?accessKey=minioadmin&secretKey=minioadmin",
|
||||
"BACKUP_BUCKET": "dev-backups",
|
||||
@ -332,7 +332,7 @@
|
||||
"ACCOUNT_DB_URL": "mongodb://localhost:27017",
|
||||
"TELEGRAM_DATABASE": "telegram-service",
|
||||
"REKONI_URL": "http://localhost:4004",
|
||||
"MODEL_VERSION": "0.6.427"
|
||||
"MODEL_VERSION": "0.6.431"
|
||||
},
|
||||
"runtimeVersion": "20",
|
||||
"runtimeArgs": ["--nolazy", "-r", "ts-node/register"],
|
||||
@ -359,7 +359,7 @@
|
||||
"MONGO_URL": "mongodb://localhost:27017",
|
||||
"TELEGRAM_DATABASE": "telegram-service",
|
||||
"REKONI_URL": "http://localhost:4004",
|
||||
"MODEL_VERSION": "0.6.427"
|
||||
"MODEL_VERSION": "0.6.431"
|
||||
},
|
||||
"runtimeArgs": ["--nolazy", "-r", "ts-node/register"],
|
||||
"sourceMaps": true,
|
||||
|
@ -1 +1 @@
|
||||
"0.6.427"
|
||||
"0.6.431"
|
||||
|
@ -16,45 +16,18 @@
|
||||
/* eslint-disable @typescript-eslint/no-unused-vars */
|
||||
import accountPlugin, {
|
||||
assignWorkspace,
|
||||
confirmEmail,
|
||||
getAccount,
|
||||
getWorkspaceById,
|
||||
updateArchiveInfo,
|
||||
signUpByEmail,
|
||||
createWorkspaceRecord,
|
||||
updateWorkspaceInfo,
|
||||
flattenStatus,
|
||||
getAccountDB,
|
||||
getWorkspaceInfoWithStatusById,
|
||||
flattenStatus,
|
||||
type WorkspaceInfoWithStatus,
|
||||
type AccountDB,
|
||||
type Workspace,
|
||||
getEmailSocialId
|
||||
signUpByEmail,
|
||||
updateWorkspaceInfo,
|
||||
type AccountDB
|
||||
} from '@hcengineering/account'
|
||||
import { backupWorkspace } from '@hcengineering/backup-service'
|
||||
import { setMetadata } from '@hcengineering/platform'
|
||||
import { createFileBackupStorage, createStorageBackupStorage, restore } from '@hcengineering/server-backup'
|
||||
import serverClientPlugin, { getAccountClient } from '@hcengineering/server-client'
|
||||
import {
|
||||
backup,
|
||||
backupFind,
|
||||
backupList,
|
||||
backupRemoveLast,
|
||||
backupSize,
|
||||
checkBackupIntegrity,
|
||||
compactBackup,
|
||||
createFileBackupStorage,
|
||||
createStorageBackupStorage,
|
||||
restore
|
||||
} from '@hcengineering/server-backup'
|
||||
import serverClientPlugin, {
|
||||
BlobClient,
|
||||
createClient,
|
||||
getTransactorEndpoint,
|
||||
getAccountClient
|
||||
} from '@hcengineering/server-client'
|
||||
import {
|
||||
createBackupPipeline,
|
||||
getConfig,
|
||||
getWorkspaceDestroyAdapter,
|
||||
registerAdapterFactory,
|
||||
registerDestroyFactory,
|
||||
registerServerPlugins,
|
||||
@ -62,45 +35,31 @@ import {
|
||||
registerTxAdapterFactory,
|
||||
sharedPipelineContextVars
|
||||
} from '@hcengineering/server-pipeline'
|
||||
import serverToken, { decodeToken, generateToken } from '@hcengineering/server-token'
|
||||
import { buildModel, FileModelLogger } from '@hcengineering/server-tool'
|
||||
import serverToken from '@hcengineering/server-token'
|
||||
import { createWorkspace, upgradeWorkspace } from '@hcengineering/workspace-service'
|
||||
import path from 'path'
|
||||
|
||||
import { buildStorageFromConfig, createStorageFromConfig, storageConfigFromEnv } from '@hcengineering/server-storage'
|
||||
import { program, type Command } from 'commander'
|
||||
import { addControlledDocumentRank } from './qms'
|
||||
import { clearTelegramHistory } from './telegram'
|
||||
import { diffWorkspace, updateField } from './workspace'
|
||||
import { updateField } from './workspace'
|
||||
|
||||
import core, {
|
||||
import {
|
||||
AccountRole,
|
||||
generateId,
|
||||
isActiveMode,
|
||||
isArchivingMode,
|
||||
MeasureMetricsContext,
|
||||
metricsToString,
|
||||
RateLimiter,
|
||||
versionToString,
|
||||
type Data,
|
||||
type Doc,
|
||||
type Ref,
|
||||
type Tx,
|
||||
type Version
|
||||
type Version,
|
||||
type WorkspaceDataId
|
||||
} from '@hcengineering/core'
|
||||
import { consoleModelLogger, type MigrateOperation } from '@hcengineering/model'
|
||||
import contact from '@hcengineering/model-contact'
|
||||
import {
|
||||
createMongoAdapter,
|
||||
createMongoDestroyAdapter,
|
||||
createMongoTxAdapter,
|
||||
getMongoClient,
|
||||
getWorkspaceMongoDB,
|
||||
shutdownMongo
|
||||
} from '@hcengineering/mongo'
|
||||
import { backupDownload } from '@hcengineering/server-backup/src/backup'
|
||||
|
||||
import { createDatalakeClient, CONFIG_KIND as DATALAKE_CONFIG_KIND, type DatalakeConfig } from '@hcengineering/datalake'
|
||||
import { getModelVersion } from '@hcengineering/model-all'
|
||||
import {
|
||||
createPostgreeDestroyAdapter,
|
||||
@ -108,45 +67,12 @@ import {
|
||||
createPostgresTxAdapter,
|
||||
shutdownPostgres
|
||||
} from '@hcengineering/postgres'
|
||||
import { CONFIG_KIND as S3_CONFIG_KIND, S3Service, type S3Config } from '@hcengineering/s3'
|
||||
import type { PipelineFactory, StorageAdapter, StorageAdapterEx } from '@hcengineering/server-core'
|
||||
import { deepEqual } from 'fast-equals'
|
||||
import { createWriteStream, readFileSync } from 'fs'
|
||||
import { getAccountDBUrl, getMongoDBUrl } from './__start'
|
||||
import type { StorageAdapter } from '@hcengineering/server-core'
|
||||
import { getAccountDBUrl } from './__start'
|
||||
// import { fillGithubUsers, fixAccountEmails, renameAccount } from './account'
|
||||
import {
|
||||
benchmark,
|
||||
benchmarkWorker,
|
||||
generateWorkspaceData,
|
||||
stressBenchmark,
|
||||
testFindAll,
|
||||
type StressBenchmarkMode
|
||||
} from './benchmark'
|
||||
import {
|
||||
cleanArchivedSpaces,
|
||||
cleanRemovedTransactions,
|
||||
cleanWorkspace,
|
||||
fixCommentDoubleIdCreate,
|
||||
fixMinioBW,
|
||||
fixSkills,
|
||||
optimizeModel,
|
||||
removeDuplicateIds,
|
||||
restoreHrTaskTypesFromUpdates,
|
||||
restoreRecruitingTaskTypes
|
||||
} from './clean'
|
||||
import { changeConfiguration } from './configuration'
|
||||
import {
|
||||
generateUuidMissingWorkspaces,
|
||||
moveAccountDbFromMongoToPG,
|
||||
moveFromMongoToPG,
|
||||
moveWorkspaceFromMongoToPG,
|
||||
updateDataWorkspaceIdToUuid
|
||||
} from './db'
|
||||
import { reindexWorkspace } from './fulltext'
|
||||
import { restoreControlledDocContentMongo, restoreMarkupRefsMongo, restoreWikiContentMongo } from './markup'
|
||||
import { fixMixinForeignAttributes, showMixinForeignAttributes } from './mixin'
|
||||
|
||||
import { copyToDatalake, moveFiles, showLostFiles } from './storage'
|
||||
import { getToolToken, getWorkspace, getWorkspaceTransactorEndpoint } from './utils'
|
||||
|
||||
const colorConstants = {
|
||||
@ -1212,20 +1138,25 @@ export function devTool (
|
||||
// await storageAdapter.close()
|
||||
// })
|
||||
|
||||
// program
|
||||
// .command('backup-s3-download <bucketName> <dirName> <storeIn>')
|
||||
// .description('Download a full backup from s3 to local dir')
|
||||
// .action(async (bucketName: string, dirName: string, storeIn: string, cmd) => {
|
||||
// const backupStorageConfig = storageConfigFromEnv(process.env.STORAGE)
|
||||
// const storageAdapter = createStorageFromConfig(backupStorageConfig.storages[0])
|
||||
// try {
|
||||
// const storage = await createStorageBackupStorage(toolCtx, storageAdapter, getWorkspaceId(bucketName), dirName)
|
||||
// await backupDownload(storage, storeIn)
|
||||
// } catch (err: any) {
|
||||
// toolCtx.error('failed to size backup', { err })
|
||||
// }
|
||||
// await storageAdapter.close()
|
||||
// })
|
||||
program
|
||||
.command('backup-s3-download <bucketName> <dirName> <storeIn>')
|
||||
.description('Download a full backup from s3 to local dir')
|
||||
.action(async (bucketName: string, dirName: string, storeIn: string, cmd) => {
|
||||
const backupStorageConfig = storageConfigFromEnv(process.env.STORAGE)
|
||||
const storageAdapter = createStorageFromConfig(backupStorageConfig.storages[0])
|
||||
try {
|
||||
const storage = await createStorageBackupStorage(
|
||||
toolCtx,
|
||||
storageAdapter,
|
||||
bucketName as WorkspaceDataId,
|
||||
dirName
|
||||
)
|
||||
await backupDownload(storage, storeIn)
|
||||
} catch (err: any) {
|
||||
toolCtx.error('failed to size backup', { err })
|
||||
}
|
||||
await storageAdapter.close()
|
||||
})
|
||||
|
||||
// program
|
||||
// .command('copy-s3-datalake')
|
||||
|
@ -665,7 +665,7 @@ export const coreOperation: MigrateOperation = {
|
||||
func: migrateCollaborativeContentToStorage
|
||||
},
|
||||
{
|
||||
state: 'fix-backups-hash-timestamp',
|
||||
state: 'fix-backups-hash-timestamp-v2',
|
||||
func: async (client: MigrationClient): Promise<void> => {
|
||||
const now = Date.now().toString(16)
|
||||
for (const d of client.hierarchy.domains()) {
|
||||
|
@ -74,6 +74,14 @@ export function createModel (builder: Builder): void {
|
||||
}
|
||||
})
|
||||
|
||||
builder.createDoc(serverCore.class.Trigger, core.space.Model, {
|
||||
trigger: serverTracker.trigger.OnProjectRemove,
|
||||
txMatch: {
|
||||
_class: core.class.TxRemoveDoc,
|
||||
objectClass: tracker.class.Project
|
||||
}
|
||||
})
|
||||
|
||||
builder.mixin(
|
||||
tracker.ids.AssigneeNotification,
|
||||
notification.class.NotificationType,
|
||||
|
@ -7,7 +7,7 @@ import {
|
||||
navigate,
|
||||
languageStore
|
||||
} from '@hcengineering/ui'
|
||||
import { type Ref, type Doc, type Class, generateId } from '@hcengineering/core'
|
||||
import { type Ref, type Doc, type Class, generateId, concatLink } from '@hcengineering/core'
|
||||
import activity, { type ActivityMessage } from '@hcengineering/activity'
|
||||
import {
|
||||
type Channel,
|
||||
@ -19,10 +19,10 @@ import {
|
||||
import { type DocNotifyContext, notificationId } from '@hcengineering/notification'
|
||||
import workbench, { type Widget, workbenchId, type LocationData } from '@hcengineering/workbench'
|
||||
import { classIcon, getObjectLinkId, parseLinkId } from '@hcengineering/view-resources'
|
||||
import { getClient } from '@hcengineering/presentation'
|
||||
import presentation, { getClient } from '@hcengineering/presentation'
|
||||
import view, { encodeObjectURI, decodeObjectURI } from '@hcengineering/view'
|
||||
import { createWidgetTab, isElementFromSidebar, sidebarStore } from '@hcengineering/workbench-resources'
|
||||
import { type Asset, type IntlString, translate } from '@hcengineering/platform'
|
||||
import { type Asset, getMetadata, type IntlString, translate } from '@hcengineering/platform'
|
||||
import contact from '@hcengineering/contact'
|
||||
import { get } from 'svelte/store'
|
||||
|
||||
@ -113,8 +113,10 @@ export async function getMessageLink (message: ActivityMessage): Promise<string>
|
||||
}
|
||||
|
||||
const id = encodeURIComponent(encodeObjectURI(_id, _class))
|
||||
|
||||
return `${window.location.protocol}//${window.location.host}/${workbenchId}/${location.path[1]}/${chunterId}/${id}${threadParent}?message=${message._id}`
|
||||
const frontUrl = getMetadata(presentation.metadata.FrontUrl)
|
||||
const protocolAndHost = frontUrl ?? `${window.location.protocol}//${window.location.host}`
|
||||
const path = `${workbenchId}/${location.path[1]}/${chunterId}/${id}${threadParent}?message=${message._id}`
|
||||
return concatLink(protocolAndHost, path)
|
||||
}
|
||||
|
||||
export async function chunterSpaceLinkFragmentProvider (doc: ChunterSpace): Promise<Location> {
|
||||
|
@ -44,5 +44,9 @@
|
||||
"@hcengineering/notification": "^0.6.23",
|
||||
"@hcengineering/attachment": "^0.6.14",
|
||||
"@hcengineering/preference": "^0.6.13"
|
||||
},
|
||||
"repository": "https://github.com/hcengineering/platform",
|
||||
"publishConfig": {
|
||||
"registry": "https://npm.pkg.github.com"
|
||||
}
|
||||
}
|
||||
|
@ -13,7 +13,9 @@
|
||||
// limitations under the License.
|
||||
-->
|
||||
<script lang="ts">
|
||||
import { NavLink } from '@hcengineering/presentation'
|
||||
import { concatLink } from '@hcengineering/core'
|
||||
import { getMetadata } from '@hcengineering/platform'
|
||||
import presentation, { NavLink } from '@hcengineering/presentation'
|
||||
import { trackerId, type Issue, type IssueParentInfo } from '@hcengineering/tracker'
|
||||
import { getCurrentLocation, locationToUrl } from '@hcengineering/ui'
|
||||
|
||||
@ -26,7 +28,8 @@
|
||||
loc.path[2] = trackerId
|
||||
loc.path[3] = parentInfo.identifier
|
||||
loc.path.length = 4
|
||||
return `${window.location.origin}${locationToUrl(loc)}`
|
||||
const frontUrl = getMetadata(presentation.metadata.FrontUrl) ?? window.location.origin
|
||||
return concatLink(frontUrl, locationToUrl(loc))
|
||||
}
|
||||
</script>
|
||||
|
||||
|
@ -14,17 +14,13 @@
|
||||
//
|
||||
|
||||
import { Analytics } from '@hcengineering/analytics'
|
||||
import core, {
|
||||
type AttachedDoc,
|
||||
import {
|
||||
type Attribute,
|
||||
type Class,
|
||||
ClassifierKind,
|
||||
type Client,
|
||||
type Doc,
|
||||
type DocManager,
|
||||
type DocumentQuery,
|
||||
DOMAIN_CONFIGURATION,
|
||||
DOMAIN_MODEL,
|
||||
getCurrentAccount,
|
||||
type Ref,
|
||||
type RelatedDocument,
|
||||
@ -275,52 +271,7 @@ async function deleteProject (project: Project | undefined): Promise<void> {
|
||||
labelProps: { name: project.name },
|
||||
message: tracker.string.DeleteProjectConfirm,
|
||||
action: async () => {
|
||||
// void client.update(project, { archived: true })
|
||||
const client = getClient()
|
||||
const classes = await client.findAll(core.class.Class, {})
|
||||
const h = client.getHierarchy()
|
||||
for (const c of classes) {
|
||||
if (c.kind !== ClassifierKind.CLASS) {
|
||||
continue
|
||||
}
|
||||
const d = h.findDomain(c._id)
|
||||
if (d !== undefined && d !== DOMAIN_MODEL && d !== DOMAIN_CONFIGURATION) {
|
||||
try {
|
||||
while (true) {
|
||||
const docs = await client.findAll(c._id, { space: project._id }, { limit: 50 })
|
||||
if (docs.length === 0) {
|
||||
break
|
||||
}
|
||||
const ops = client.apply(undefined, 'delete-project')
|
||||
for (const object of docs) {
|
||||
if (client.getHierarchy().isDerived(object._class, core.class.AttachedDoc)) {
|
||||
const adoc = object as AttachedDoc
|
||||
await ops
|
||||
.removeCollection(
|
||||
object._class,
|
||||
object.space,
|
||||
adoc._id,
|
||||
adoc.attachedTo,
|
||||
adoc.attachedToClass,
|
||||
adoc.collection
|
||||
)
|
||||
.catch((err) => {
|
||||
console.error(err)
|
||||
})
|
||||
} else {
|
||||
await ops.removeDoc(object._class, object.space, object._id).catch((err) => {
|
||||
console.error(err)
|
||||
})
|
||||
}
|
||||
}
|
||||
await ops.commit()
|
||||
}
|
||||
} catch (err: any) {
|
||||
console.error(err)
|
||||
Analytics.handleError(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
await client.remove(project)
|
||||
}
|
||||
})
|
||||
|
@ -16,16 +16,20 @@
|
||||
-->
|
||||
|
||||
<script lang="ts">
|
||||
import { NavLink } from '@hcengineering/presentation'
|
||||
import presentation, { NavLink } from '@hcengineering/presentation'
|
||||
import { locationToUrl } from '@hcengineering/ui'
|
||||
import { Document } from '@hcengineering/controlled-documents'
|
||||
import { documentRoute } from '../routing/routes/documentRoute'
|
||||
import { getMetadata } from '@hcengineering/platform'
|
||||
import { concatLink } from '@hcengineering/core'
|
||||
|
||||
export let value: Document
|
||||
|
||||
const frontUrl = getMetadata(presentation.metadata.FrontUrl) ?? window.location.origin
|
||||
|
||||
let href: string | undefined
|
||||
$: {
|
||||
href = `${window.location.origin}${locationToUrl(documentRoute.build({ id: value._id }))}`
|
||||
href = concatLink(frontUrl, locationToUrl(documentRoute.build({ id: value._id })))
|
||||
}
|
||||
</script>
|
||||
|
||||
|
@ -13,11 +13,12 @@
|
||||
// limitations under the License.
|
||||
-->
|
||||
<script lang="ts">
|
||||
import { Doc, Hierarchy } from '@hcengineering/core'
|
||||
import { NavLink, getClient } from '@hcengineering/presentation'
|
||||
import { concatLink, Doc, Hierarchy } from '@hcengineering/core'
|
||||
import presentation, { NavLink, getClient } from '@hcengineering/presentation'
|
||||
import { AnyComponent, getPanelURI, locationToUrl } from '@hcengineering/ui'
|
||||
import view from '../plugin'
|
||||
import { getObjectLinkFragment, restrictionStore } from '../utils'
|
||||
import { getMetadata } from '@hcengineering/platform'
|
||||
|
||||
export let object: Doc | undefined
|
||||
export let disabled: boolean = false
|
||||
@ -50,7 +51,8 @@
|
||||
const panelComponent = hierarchy.classHierarchyMixin(object._class, view.mixin.ObjectPanel)
|
||||
const comp = panelComponent?.component ?? component
|
||||
const loc = await getObjectLinkFragment(hierarchy, object, props, comp)
|
||||
href = `${window.location.origin}${locationToUrl(loc)}`
|
||||
const frontUrl = getMetadata(presentation.metadata.FrontUrl) ?? window.location.origin
|
||||
href = concatLink(frontUrl, locationToUrl(loc))
|
||||
}
|
||||
|
||||
$: if (object !== undefined) getHref(object)
|
||||
|
@ -16,10 +16,11 @@
|
||||
import chunter, { ChatMessage } from '@hcengineering/chunter'
|
||||
import { Person } from '@hcengineering/contact'
|
||||
import core, {
|
||||
PersonId,
|
||||
AccountRole,
|
||||
concatLink,
|
||||
Doc,
|
||||
DocumentUpdate,
|
||||
PersonId,
|
||||
Ref,
|
||||
Space,
|
||||
Tx,
|
||||
@ -28,16 +29,15 @@ import core, {
|
||||
TxProcessor,
|
||||
TxRemoveDoc,
|
||||
TxUpdateDoc,
|
||||
WithLookup,
|
||||
AccountRole
|
||||
WithLookup
|
||||
} from '@hcengineering/core'
|
||||
import { NotificationContent } from '@hcengineering/notification'
|
||||
import { getMetadata, IntlString } from '@hcengineering/platform'
|
||||
import { getSocialStrings } from '@hcengineering/server-contact'
|
||||
import serverCore, { TriggerControl } from '@hcengineering/server-core'
|
||||
import { NOTIFICATION_BODY_SIZE } from '@hcengineering/server-notification'
|
||||
import { getSocialStrings } from '@hcengineering/server-contact'
|
||||
import { stripTags } from '@hcengineering/text'
|
||||
import tracker, { Component, Issue, IssueParentInfo, TimeSpendReport, trackerId } from '@hcengineering/tracker'
|
||||
import tracker, { Component, Issue, IssueParentInfo, TimeSpendReport, trackerId, type Project } from '@hcengineering/tracker'
|
||||
import { workbenchId } from '@hcengineering/workbench'
|
||||
|
||||
async function updateSubIssues (
|
||||
@ -176,6 +176,28 @@ export async function OnSocialIdentityCreate (_txes: Tx[], control: TriggerContr
|
||||
return []
|
||||
}
|
||||
|
||||
/**
|
||||
* @public
|
||||
*/
|
||||
export async function OnProjectRemove (txes: Tx[], control: TriggerControl): Promise<Tx[]> {
|
||||
const result: Tx[] = []
|
||||
for (const tx of txes) {
|
||||
const ctx = tx as TxRemoveDoc<Project>
|
||||
const classes = [tracker.class.Issue, tracker.class.Component, tracker.class.Milestone, tracker.class.IssueTemplate]
|
||||
for (const cls of classes) {
|
||||
const docs = await control.findAll(control.ctx, cls, { space: ctx.objectId })
|
||||
for (const doc of docs) {
|
||||
const tx = control.txFactory.createTxRemoveDoc(cls, doc.space, doc._id)
|
||||
result.push(tx)
|
||||
}
|
||||
}
|
||||
}
|
||||
control.ctx.contextData.broadcast.targets.projectRemove = (it) => {
|
||||
return []
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
/**
|
||||
* @public
|
||||
*/
|
||||
@ -516,6 +538,7 @@ export default async () => ({
|
||||
trigger: {
|
||||
OnSocialIdentityCreate,
|
||||
OnIssueUpdate,
|
||||
OnComponentRemove
|
||||
OnComponentRemove,
|
||||
OnProjectRemove
|
||||
}
|
||||
})
|
||||
|
@ -37,6 +37,7 @@ export default plugin(serverTrackerId, {
|
||||
trigger: {
|
||||
OnSocialIdentityCreate: '' as Resource<TriggerFunc>,
|
||||
OnIssueUpdate: '' as Resource<TriggerFunc>,
|
||||
OnComponentRemove: '' as Resource<TriggerFunc>
|
||||
OnComponentRemove: '' as Resource<TriggerFunc>,
|
||||
OnProjectRemove: '' as Resource<TriggerFunc>
|
||||
}
|
||||
})
|
||||
|
@ -326,7 +326,7 @@ export class SpaceSecurityMiddleware extends BaseMiddleware implements Middlewar
|
||||
private handleRemove (tx: TxCUD<Space>): void {
|
||||
const removeTx = tx as TxRemoveDoc<Space>
|
||||
if (!this.context.hierarchy.isDerived(removeTx.objectClass, core.class.Space)) return
|
||||
if (removeTx._class !== core.class.TxCreateDoc) return
|
||||
if (removeTx._class !== core.class.TxRemoveDoc) return
|
||||
this.removeSpace(tx.objectId)
|
||||
}
|
||||
|
||||
|
@ -1928,7 +1928,7 @@ class PostgresAdapter extends PostgresAdapterBase {
|
||||
for (const tx of txes) {
|
||||
const fields: string[] = ['modifiedBy', 'modifiedOn', '%hash%']
|
||||
const updates: string[] = ['"modifiedBy" = $2', '"modifiedOn" = $3', '"%hash%" = $4']
|
||||
const params: any[] = [tx.modifiedBy, tx.modifiedOn, null]
|
||||
const params: any[] = [tx.modifiedBy, tx.modifiedOn, this.curHash()]
|
||||
let paramsIndex = params.length
|
||||
const { extractedFields, remainingData } = parseUpdate(tx.operations, schemaFields)
|
||||
const { space, attachedTo, ...ops } = tx.operations as any
|
||||
|
@ -34,6 +34,7 @@
|
||||
"@hcengineering/server-github": "^0.6.0",
|
||||
"@hcengineering/server-core": "^0.6.1",
|
||||
"@hcengineering/github": "^0.6.0",
|
||||
"@hcengineering/tracker": "^0.6.24",
|
||||
"@hcengineering/notification": "^0.6.23",
|
||||
"@hcengineering/server-notification": "^0.6.1",
|
||||
"@hcengineering/time": "^0.6.0"
|
||||
|
@ -8,6 +8,7 @@ import core from '@hcengineering/core'
|
||||
import serverCore from '@hcengineering/server-core'
|
||||
import serverGithub from '@hcengineering/server-github'
|
||||
import time from '@hcengineering/time'
|
||||
import tracker from '@hcengineering/tracker'
|
||||
|
||||
export { serverGithubId } from '@hcengineering/server-github'
|
||||
|
||||
@ -16,6 +17,15 @@ export function createModel (builder: Builder): void {
|
||||
trigger: serverGithub.trigger.OnProjectChanges,
|
||||
isAsync: true
|
||||
})
|
||||
|
||||
builder.createDoc(serverCore.class.Trigger, core.space.Model, {
|
||||
trigger: serverGithub.trigger.OnProjectRemove,
|
||||
txMatch: {
|
||||
_class: core.class.TxRemoveDoc,
|
||||
objectClass: tracker.class.Project
|
||||
}
|
||||
})
|
||||
|
||||
builder.createDoc(serverCore.class.Trigger, core.space.Model, {
|
||||
trigger: serverGithub.trigger.OnGithubBroadcast,
|
||||
isAsync: false
|
||||
|
@ -97,10 +97,53 @@ export async function OnProjectChanges (txes: Tx[], control: TriggerControl): Pr
|
||||
return result
|
||||
}
|
||||
|
||||
/**
|
||||
* @public
|
||||
*/
|
||||
export async function OnProjectRemove (txes: Tx[], control: TriggerControl): Promise<Tx[]> {
|
||||
const result: Tx[] = []
|
||||
for (const ltx of txes) {
|
||||
if (ltx._class === core.class.TxRemoveDoc) {
|
||||
const cud = ltx as TxCUD<Doc>
|
||||
if (control.hierarchy.isDerived(cud.objectClass, tracker.class.Project)) {
|
||||
const project = control.removedMap.get(cud.objectId)
|
||||
if (project === undefined) {
|
||||
continue
|
||||
}
|
||||
if (control.hierarchy.hasMixin(project, github.mixin.GithubProject)) {
|
||||
const repos = await control.findAll(control.ctx, github.class.GithubIntegrationRepository, {
|
||||
githubProject: cud.objectId as Ref<GithubProject>
|
||||
})
|
||||
for (const repo of repos) {
|
||||
result.push(
|
||||
control.txFactory.createTxUpdateDoc(repo._class, repo.space, repo._id, {
|
||||
enabled: false,
|
||||
githubProject: null
|
||||
})
|
||||
)
|
||||
}
|
||||
|
||||
const syncDocs = control.modelDb.findAllSync(github.class.DocSyncInfo, {
|
||||
space: cud.objectId as Ref<Space>
|
||||
})
|
||||
for (const syncDoc of syncDocs) {
|
||||
result.push(control.txFactory.createTxRemoveDoc(syncDoc._class, syncDoc.space, syncDoc._id))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (result.length > 0) {
|
||||
await OnGithubBroadcast(txes, control)
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/explicit-function-return-type
|
||||
export default async () => ({
|
||||
trigger: {
|
||||
OnProjectChanges,
|
||||
OnProjectRemove,
|
||||
OnGithubBroadcast
|
||||
},
|
||||
functions: {
|
||||
|
@ -21,6 +21,7 @@ export const serverGithubId = 'server-github' as Plugin
|
||||
export default plugin(serverGithubId, {
|
||||
trigger: {
|
||||
OnProjectChanges: '' as Resource<TriggerFunc>,
|
||||
OnProjectRemove: '' as Resource<TriggerFunc>,
|
||||
OnGithubBroadcast: '' as Resource<TriggerFunc>
|
||||
},
|
||||
functions: {
|
||||
|
Loading…
Reference in New Issue
Block a user