mirror of
https://github.com/hcengineering/platform.git
synced 2025-01-22 19:38:17 +00:00
Merge remote-tracking branch 'origin/develop' into staging
Signed-off-by: Andrey Sobolev <haiodo@gmail.com>
This commit is contained in:
commit
cc2c0c31b2
@ -207,4 +207,11 @@
|
||||
<path d="M0.5 7.99988L3 10.4999L3.705 9.79488L2.415 8.49988H6.5C6.77614 8.49988 7 8.27602 7 7.99988C7 7.72374 6.77614 7.49988 6.5 7.49988H2.415L3.705 6.20488L3 5.49988L0.5 7.99988Z"/>
|
||||
<path d="M12.295 6.20488L13.585 7.49988H9.5C9.22386 7.49988 9 7.72374 9 7.99988C9 8.27602 9.22386 8.49988 9.5 8.49988H13.585L12.295 9.79488L13 10.4999L15.5 7.99988L13 5.49988L12.295 6.20488Z"/>
|
||||
</symbol>
|
||||
<symbol id="union" viewBox="0 0 32 32" fill="none">
|
||||
<path d="M17 3H6C4.34315 3 3 4.34315 3 6V17C3 18.6569 4.34315 20 6 20H12V26C12 27.6569 13.3431 29 15 29H26C27.6569 29 29 27.6569 29 26V15C29 13.3431 27.6569 12 26 12H20V6C20 4.34315 18.6569 3 17 3Z" stroke="currentColor" stroke-width="2" stroke-linejoin="round"/>
|
||||
</symbol>
|
||||
<symbol id="divide" viewBox="0 0 32 32" fill="none">
|
||||
<path d="M3 6C3 4.34315 4.34315 3 6 3H17C18.6569 3 20 4.34315 20 6V10.5556V17C20 18.6569 18.6569 20 17 20H10.5556H6C4.34314 20 3 18.6569 3 17V6Z" stroke="currentColor" stroke-width="2"/>
|
||||
<path d="M12 15C12 13.3431 13.3431 12 15 12H26C27.6569 12 29 13.3431 29 15V26C29 27.6569 27.6569 29 26 29H15C13.3431 29 12 27.6569 12 26V15Z" stroke="currentColor" stroke-width="2"/>
|
||||
</symbol>
|
||||
</svg>
|
Before Width: | Height: | Size: 23 KiB After Width: | Height: | Size: 23 KiB |
@ -46,9 +46,12 @@
|
||||
"AddRowAfter": "Add after",
|
||||
"DeleteRow": "Delete",
|
||||
"DeleteTable": "Delete",
|
||||
"MergeCells": "Merge cells",
|
||||
"SplitCells": "Split cells",
|
||||
"Duplicate": "Duplicate",
|
||||
"CategoryRow": "Rows",
|
||||
"CategoryColumn": "Columns",
|
||||
"CategoryCell": "Cells",
|
||||
"Table": "Table",
|
||||
"InsertTable": "Insert table",
|
||||
"TableOptions": "Customize table",
|
||||
|
@ -46,9 +46,12 @@
|
||||
"AddRowAfter": "Добавить после",
|
||||
"DeleteRow": "Удалить",
|
||||
"DeleteTable": "Удалить",
|
||||
"MergeCells": "Объединить ячейки",
|
||||
"SplitCells": "Разделить ячейки",
|
||||
"Duplicate": "Дублировать",
|
||||
"CategoryRow": "Строки",
|
||||
"CategoryColumn": "Колонки",
|
||||
"CategoryCell": "Ячейки",
|
||||
"Table": "Таблица",
|
||||
"InsertTable": "Добавить таблицу",
|
||||
"TableOptions": "Настроить таблицу",
|
||||
|
@ -41,5 +41,7 @@ loadMetadata(textEditor.icon, {
|
||||
Download: `${icons}#download`,
|
||||
Note: `${icons}#note`,
|
||||
Comment: `${icons}#comment`,
|
||||
SelectTable: `${icons}#move`
|
||||
SelectTable: `${icons}#move`,
|
||||
MergeCells: `${icons}#union`,
|
||||
SplitCells: `${icons}#divide`
|
||||
})
|
||||
|
@ -175,7 +175,7 @@
|
||||
}
|
||||
|
||||
&__col {
|
||||
right: -1.5rem;
|
||||
right: calc(var(--table-offscreen-spacing) - 1.5rem);
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
margin: 1.25rem 0;
|
||||
@ -188,7 +188,7 @@
|
||||
&__row {
|
||||
bottom: -0.25rem;
|
||||
left: var(--table-offscreen-spacing);
|
||||
right: 0;
|
||||
right: var(--table-offscreen-spacing);
|
||||
|
||||
.table-button {
|
||||
height: 1.25rem;
|
||||
|
@ -13,25 +13,76 @@
|
||||
// limitations under the License.
|
||||
//
|
||||
|
||||
import type { Node as ProseMirrorNode } from '@tiptap/pm/model'
|
||||
import { Fragment, type Node, type Node as ProseMirrorNode } from '@tiptap/pm/model'
|
||||
import type { Transaction } from '@tiptap/pm/state'
|
||||
import { TableMap } from '@tiptap/pm/tables'
|
||||
import { type CellSelection, TableMap } from '@tiptap/pm/tables'
|
||||
import type { TableNodeLocation } from '../types'
|
||||
import { type Editor } from '@tiptap/core'
|
||||
|
||||
type TableRow = Array<ProseMirrorNode | null>
|
||||
type TableRows = TableRow[]
|
||||
|
||||
export function moveColumn (table: TableNodeLocation, from: number, to: number, tr: Transaction): Transaction {
|
||||
const cols = transpose(tableToCells(table))
|
||||
moveRowInplace(cols, from, to)
|
||||
tableFromCells(table, transpose(cols), tr)
|
||||
export function moveSelectedColumns (
|
||||
editor: Editor,
|
||||
table: TableNodeLocation,
|
||||
selection: CellSelection,
|
||||
to: number,
|
||||
tr: Transaction
|
||||
): Transaction {
|
||||
const tableMap = TableMap.get(table.node)
|
||||
|
||||
let columnStart = -1
|
||||
let columnEnd = -1
|
||||
|
||||
selection.forEachCell((node, pos) => {
|
||||
const cell = tableMap.findCell(pos - table.pos - 1)
|
||||
for (let i = cell.left; i < cell.right; i++) {
|
||||
columnStart = columnStart >= 0 ? Math.min(cell.left, columnStart) : cell.left
|
||||
columnEnd = columnEnd >= 0 ? Math.max(cell.right, columnEnd) : cell.right
|
||||
}
|
||||
})
|
||||
|
||||
if (to < 0 || to > tableMap.width || (to >= columnStart && to < columnEnd)) return tr
|
||||
|
||||
const rows = tableToCells(table)
|
||||
for (const row of rows) {
|
||||
const range = row.splice(columnStart, columnEnd - columnStart)
|
||||
const offset = to > columnStart ? to - (columnEnd - columnStart - 1) : to
|
||||
row.splice(offset, 0, ...range)
|
||||
}
|
||||
|
||||
tableFromCells(editor, table, rows, tr)
|
||||
return tr
|
||||
}
|
||||
|
||||
export function moveRow (table: TableNodeLocation, from: number, to: number, tr: Transaction): Transaction {
|
||||
export function moveSelectedRows (
|
||||
editor: Editor,
|
||||
table: TableNodeLocation,
|
||||
selection: CellSelection,
|
||||
to: number,
|
||||
tr: Transaction
|
||||
): Transaction {
|
||||
const tableMap = TableMap.get(table.node)
|
||||
|
||||
let rowStart = -1
|
||||
let rowEnd = -1
|
||||
|
||||
selection.forEachCell((node, pos) => {
|
||||
const cell = tableMap.findCell(pos - table.pos - 1)
|
||||
for (let i = cell.top; i < cell.bottom; i++) {
|
||||
rowStart = rowStart >= 0 ? Math.min(cell.top, rowStart) : cell.top
|
||||
rowEnd = rowEnd >= 0 ? Math.max(cell.bottom, rowEnd) : cell.bottom
|
||||
}
|
||||
})
|
||||
|
||||
if (to < 0 || to > tableMap.height || (to >= rowStart && to < rowEnd)) return tr
|
||||
|
||||
const rows = tableToCells(table)
|
||||
moveRowInplace(rows, from, to)
|
||||
tableFromCells(table, rows, tr)
|
||||
const range = rows.splice(rowStart, rowEnd - rowStart)
|
||||
const offset = to > rowStart ? to - (rowEnd - rowStart - 1) : to
|
||||
rows.splice(offset, 0, ...range)
|
||||
|
||||
tableFromCells(editor, table, rows, tr)
|
||||
return tr
|
||||
}
|
||||
|
||||
@ -78,23 +129,17 @@ export function duplicateColumns (table: TableNodeLocation, columnIndices: numbe
|
||||
return tr
|
||||
}
|
||||
|
||||
function moveRowInplace (rows: TableRows, from: number, to: number): void {
|
||||
rows.splice(to, 0, rows.splice(from, 1)[0])
|
||||
}
|
||||
|
||||
function transpose (rows: TableRows): TableRows {
|
||||
return rows[0].map((_, colIdx) => rows.map((row) => row[colIdx]))
|
||||
}
|
||||
|
||||
function tableToCells (table: TableNodeLocation): TableRows {
|
||||
const { map, width, height } = TableMap.get(table.node)
|
||||
|
||||
const visitedCells = new Set<number>()
|
||||
const rows = []
|
||||
for (let row = 0; row < height; row++) {
|
||||
const cells = []
|
||||
for (let col = 0; col < width; col++) {
|
||||
const pos = map[row * width + col]
|
||||
cells.push(table.node.nodeAt(pos))
|
||||
cells.push(!visitedCells.has(pos) ? table.node.nodeAt(pos) : null)
|
||||
visitedCells.add(pos)
|
||||
}
|
||||
rows.push(cells)
|
||||
}
|
||||
@ -102,23 +147,11 @@ function tableToCells (table: TableNodeLocation): TableRows {
|
||||
return rows
|
||||
}
|
||||
|
||||
function tableFromCells (table: TableNodeLocation, rows: TableRows, tr: Transaction): void {
|
||||
const { map, width, height } = TableMap.get(table.node)
|
||||
const mapStart = tr.mapping.maps.length
|
||||
|
||||
for (let row = 0; row < height; row++) {
|
||||
for (let col = 0; col < width; col++) {
|
||||
const pos = map[row * width + col]
|
||||
|
||||
const oldCell = table.node.nodeAt(pos)
|
||||
const newCell = rows[row][col]
|
||||
|
||||
if (oldCell !== null && newCell !== null && oldCell !== newCell) {
|
||||
const start = tr.mapping.slice(mapStart).map(table.start + pos)
|
||||
const end = start + oldCell.nodeSize
|
||||
|
||||
tr.replaceWith(start, end, newCell)
|
||||
}
|
||||
}
|
||||
}
|
||||
function tableFromCells (editor: Editor, table: TableNodeLocation, rows: TableRows, tr: Transaction): void {
|
||||
const schema = editor.schema.nodes
|
||||
const newRowNodes = rows.map((row) =>
|
||||
schema.tableRow.create(null, row.filter((cell) => cell !== null) as readonly Node[])
|
||||
)
|
||||
const newTableNode = table.node.copy(Fragment.from(newRowNodes))
|
||||
tr.replaceWith(table.pos, table.pos + table.node.nodeSize, newTableNode)
|
||||
}
|
||||
|
@ -15,14 +15,14 @@
|
||||
|
||||
import { type Editor } from '@tiptap/core'
|
||||
import { type EditorState } from '@tiptap/pm/state'
|
||||
import { TableMap } from '@tiptap/pm/tables'
|
||||
import { CellSelection, TableMap } from '@tiptap/pm/tables'
|
||||
import { Decoration } from '@tiptap/pm/view'
|
||||
import textEditor from '@hcengineering/text-editor'
|
||||
|
||||
import { type TableNodeLocation } from '../types'
|
||||
import { findTable, getSelectedColumns, isColumnSelected, selectColumn } from '../utils'
|
||||
|
||||
import { duplicateColumns, moveColumn } from './actions'
|
||||
import { duplicateColumns, moveSelectedColumns } from './actions'
|
||||
import DeleteCol from '../../../icons/table/DeleteCol.svelte'
|
||||
import Duplicate from '../../../icons/table/Duplicate.svelte'
|
||||
import { createCellsHandle, type OptionItem } from './cellsHandle'
|
||||
@ -120,8 +120,10 @@ const handleMouseDown = (
|
||||
|
||||
if (col !== dropIndex) {
|
||||
let tr = editor.state.tr
|
||||
tr = selectColumn(table, dropIndex, tr)
|
||||
tr = moveColumn(table, col, dropIndex, tr)
|
||||
const selection = editor.state.selection
|
||||
if (selection instanceof CellSelection) {
|
||||
tr = moveSelectedColumns(editor, table, selection, dropIndex, tr)
|
||||
}
|
||||
editor.view.dispatch(tr)
|
||||
}
|
||||
window.removeEventListener('mouseup', handleFinish)
|
||||
|
@ -15,14 +15,14 @@
|
||||
|
||||
import { type Editor } from '@tiptap/core'
|
||||
import { type EditorState } from '@tiptap/pm/state'
|
||||
import { TableMap } from '@tiptap/pm/tables'
|
||||
import { CellSelection, TableMap } from '@tiptap/pm/tables'
|
||||
import { Decoration } from '@tiptap/pm/view'
|
||||
import textEditor from '@hcengineering/text-editor'
|
||||
|
||||
import { type TableNodeLocation } from '../types'
|
||||
import { findTable, getSelectedRows, isRowSelected, selectRow } from '../utils'
|
||||
|
||||
import { duplicateRows, moveRow } from './actions'
|
||||
import { duplicateRows, moveSelectedRows } from './actions'
|
||||
import DeleteRow from '../../../icons/table/DeleteRow.svelte'
|
||||
import Duplicate from '../../../icons/table/Duplicate.svelte'
|
||||
import { createCellsHandle, type OptionItem } from './cellsHandle'
|
||||
@ -120,8 +120,10 @@ const handleMouseDown = (
|
||||
|
||||
if (row !== dropIndex) {
|
||||
let tr = editor.state.tr
|
||||
tr = selectRow(table, dropIndex, tr)
|
||||
tr = moveRow(table, row, dropIndex, tr)
|
||||
const selection = editor.state.selection
|
||||
if (selection instanceof CellSelection) {
|
||||
tr = moveSelectedRows(editor, table, selection, dropIndex, tr)
|
||||
}
|
||||
editor.view.dispatch(tr)
|
||||
}
|
||||
window.removeEventListener('mouseup', handleFinish)
|
||||
|
@ -60,10 +60,17 @@ function getTableCellBorders (
|
||||
const { width, height } = tableMap
|
||||
const cellIndex = tableMap.map.indexOf(cell)
|
||||
|
||||
const rect = tableMap.findCell(cell)
|
||||
const cellW = rect.right - rect.left
|
||||
const cellH = rect.bottom - rect.top
|
||||
|
||||
const testRight = cellW
|
||||
const testBottom = width * cellH
|
||||
|
||||
const topCell = cellIndex >= width ? tableMap.map[cellIndex - width] : undefined
|
||||
const bottomCell = cellIndex < width * height - width ? tableMap.map[cellIndex + width] : undefined
|
||||
const leftCell = cellIndex % width !== 0 ? tableMap.map[cellIndex - 1] : undefined
|
||||
const rightCell = cellIndex % width !== width - 1 ? tableMap.map[cellIndex + 1] : undefined
|
||||
const bottomCell = cellIndex < width * height - testBottom ? tableMap.map[cellIndex + testBottom] : undefined
|
||||
const leftCell = cellIndex % width > 0 ? tableMap.map[cellIndex - 1] : undefined
|
||||
const rightCell = cellIndex % width < width - testRight ? tableMap.map[cellIndex + testRight] : undefined
|
||||
|
||||
return {
|
||||
top: topCell === undefined || !selection.includes(topCell),
|
||||
|
@ -116,6 +116,24 @@ export async function openTableOptions (editor: Editor, event: MouseEvent): Prom
|
||||
label: textEditor.string.CategoryRow
|
||||
}
|
||||
},
|
||||
{
|
||||
id: '#mergeCells',
|
||||
icon: textEditor.icon.MergeCells,
|
||||
label: textEditor.string.MergeCells,
|
||||
action: () => editor.commands.mergeCells(),
|
||||
category: {
|
||||
label: textEditor.string.CategoryCell
|
||||
}
|
||||
},
|
||||
{
|
||||
id: '#splitCell',
|
||||
icon: textEditor.icon.SplitCells,
|
||||
label: textEditor.string.SplitCells,
|
||||
action: () => editor.commands.splitCell(),
|
||||
category: {
|
||||
label: textEditor.string.CategoryCell
|
||||
}
|
||||
},
|
||||
{
|
||||
id: '#deleteTable',
|
||||
icon: DeleteTable,
|
||||
|
@ -18,17 +18,19 @@ import TiptapTableCell from '@tiptap/extension-table-cell'
|
||||
import { Plugin, PluginKey, type Selection } from '@tiptap/pm/state'
|
||||
import { DecorationSet } from '@tiptap/pm/view'
|
||||
|
||||
import { findTable } from './utils'
|
||||
import { CellSelection, type Rect, TableMap } from '@tiptap/pm/tables'
|
||||
import { columnHandlerDecoration } from './decorations/columnHandlerDecoration'
|
||||
import { columnInsertDecoration } from './decorations/columnInsertDecoration'
|
||||
import { rowHandlerDecoration } from './decorations/rowHandlerDecoration'
|
||||
import { rowInsertDecoration } from './decorations/rowInsertDecoration'
|
||||
import { tableDragMarkerDecoration } from './decorations/tableDragMarkerDecoration'
|
||||
import { tableSelectionDecoration } from './decorations/tableSelectionDecoration'
|
||||
import { rowHandlerDecoration } from './decorations/rowHandlerDecoration'
|
||||
import { findTable } from './utils'
|
||||
import { type Node } from '@tiptap/pm/model'
|
||||
|
||||
export const TableCell = TiptapTableCell.extend({
|
||||
addProseMirrorPlugins () {
|
||||
return [tableCellDecorationPlugin(this.editor)]
|
||||
return [tableCellDecorationPlugin(this.editor), tableSelectionNormalizer()]
|
||||
}
|
||||
})
|
||||
|
||||
@ -78,3 +80,80 @@ const tableCellDecorationPlugin = (editor: Editor): Plugin<TableCellDecorationPl
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
const tableSelectionNormalizer = (): Plugin<any> => {
|
||||
return new Plugin({
|
||||
appendTransaction: (transactions, oldState, newState) => {
|
||||
const selection = newState.selection
|
||||
if (selection.eq(oldState.selection) || !(selection instanceof CellSelection)) return
|
||||
|
||||
const table = findTable(newState.selection)
|
||||
if (table === undefined) return
|
||||
|
||||
const tableMap = TableMap.get(table.node)
|
||||
|
||||
let rect: Rect | undefined
|
||||
|
||||
const walkCell = (pos: number): void => {
|
||||
const cell = tableMap.findCell(pos)
|
||||
if (cell === undefined) return
|
||||
|
||||
if (rect === undefined) {
|
||||
rect = { ...cell }
|
||||
} else {
|
||||
rect.left = Math.min(rect.left, cell.left)
|
||||
rect.top = Math.min(rect.top, cell.top)
|
||||
|
||||
rect.right = Math.max(rect.right, cell.right)
|
||||
rect.bottom = Math.max(rect.bottom, cell.bottom)
|
||||
}
|
||||
}
|
||||
|
||||
selection.forEachCell((_node, pos) => {
|
||||
walkCell(pos - table.pos - 1)
|
||||
})
|
||||
if (rect === undefined) return
|
||||
|
||||
const rectSelection: number[] = []
|
||||
for (let row = rect.top; row < rect.bottom; row++) {
|
||||
for (let col = rect.left; col < rect.right; col++) {
|
||||
rectSelection.push(tableMap.map[row * tableMap.width + col])
|
||||
}
|
||||
}
|
||||
rectSelection.forEach((pos) => {
|
||||
walkCell(pos)
|
||||
})
|
||||
|
||||
if (rect === undefined) return
|
||||
|
||||
// Original promemirror implementation of TableMap.positionAt skips rowspawn cells, which leads to unpredictable selection behaviour
|
||||
const firstCellOffset = cellPositionAt(tableMap, rect.bottom - 1, rect.right - 1, table.node)
|
||||
const lastCellOffset = cellPositionAt(tableMap, rect.top, rect.left, table.node)
|
||||
|
||||
const firstCellPos = newState.doc.resolve(table.start + firstCellOffset)
|
||||
const lastCellPos = newState.doc.resolve(table.start + lastCellOffset)
|
||||
|
||||
const reverseOrder = selection.$anchorCell.pos > selection.$headCell.pos
|
||||
const $head = reverseOrder ? lastCellPos : firstCellPos
|
||||
const $anchor = reverseOrder ? firstCellPos : lastCellPos
|
||||
|
||||
const newSelection = new CellSelection($anchor, $head)
|
||||
|
||||
if (newSelection.eq(newState.selection)) return
|
||||
|
||||
return newState.tr.setSelection(new CellSelection($anchor, $head))
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
function cellPositionAt (tableMap: TableMap, row: number, col: number, table: Node): number {
|
||||
for (let i = 0, rowStart = 0; ; i++) {
|
||||
const rowEnd = rowStart + table.child(i).nodeSize
|
||||
if (i === row) {
|
||||
const index = col + row * tableMap.width
|
||||
const rowEndIndex = (row + 1) * tableMap.width
|
||||
return index === rowEndIndex ? rowEnd - 1 : tableMap.map[index]
|
||||
}
|
||||
rowStart = rowEnd
|
||||
}
|
||||
}
|
||||
|
@ -84,11 +84,14 @@ export default plugin(textEditorId, {
|
||||
DeleteColumn: '' as IntlString,
|
||||
AddRowBefore: '' as IntlString,
|
||||
AddRowAfter: '' as IntlString,
|
||||
MergeCells: '' as IntlString,
|
||||
SplitCells: '' as IntlString,
|
||||
DeleteRow: '' as IntlString,
|
||||
DeleteTable: '' as IntlString,
|
||||
Duplicate: '' as IntlString,
|
||||
CategoryRow: '' as IntlString,
|
||||
CategoryColumn: '' as IntlString,
|
||||
CategoryCell: '' as IntlString,
|
||||
Table: '' as IntlString,
|
||||
TableOptions: '' as IntlString,
|
||||
SelectTable: '' as IntlString,
|
||||
@ -125,6 +128,8 @@ export default plugin(textEditorId, {
|
||||
Download: '' as Asset,
|
||||
Note: '' as Asset,
|
||||
Comment: '' as Asset,
|
||||
SelectTable: '' as Asset
|
||||
SelectTable: '' as Asset,
|
||||
MergeCells: '' as Asset,
|
||||
SplitCells: '' as Asset
|
||||
}
|
||||
})
|
||||
|
@ -553,6 +553,13 @@ export interface Session {
|
||||
query: DocumentQuery<T>,
|
||||
options?: FindOptions<T>
|
||||
) => Promise<void>
|
||||
findAllRaw: <T extends Doc>(
|
||||
ctx: MeasureContext,
|
||||
pipeline: Pipeline,
|
||||
_class: Ref<Class<T>>,
|
||||
query: DocumentQuery<T>,
|
||||
options?: FindOptions<T>
|
||||
) => Promise<FindResult<T>>
|
||||
searchFulltext: (ctx: ClientSessionCtx, query: SearchQuery, options: SearchOptions) => Promise<void>
|
||||
tx: (ctx: ClientSessionCtx, tx: Tx) => Promise<void>
|
||||
loadChunk: (ctx: ClientSessionCtx, domain: Domain, idx?: number) => Promise<void>
|
||||
|
@ -716,21 +716,38 @@ class TSessionManager implements SessionManager {
|
||||
const user = pipeline.context.modelDb.getAccountByEmail(session.getUser())
|
||||
if (user === undefined) return
|
||||
|
||||
const status = (await pipeline.findAll(ctx, core.class.UserStatus, { user: user._id }, { limit: 1 }))[0]
|
||||
const clientCtx: ClientSessionCtx = {
|
||||
requestId: undefined,
|
||||
pipeline,
|
||||
sendResponse: async (msg) => {
|
||||
// No response
|
||||
},
|
||||
ctx,
|
||||
sendError: async (msg, error: Status) => {
|
||||
// Assume no error send
|
||||
},
|
||||
sendPong: () => {}
|
||||
}
|
||||
const status = (
|
||||
await session.findAllRaw(ctx, pipeline, core.class.UserStatus, { user: user._id }, { limit: 1 })
|
||||
)[0]
|
||||
const txFactory = new TxFactory(user._id, true)
|
||||
if (status === undefined) {
|
||||
const tx = txFactory.createTxCreateDoc(core.class.UserStatus, core.space.Space, {
|
||||
online,
|
||||
user: user._id
|
||||
})
|
||||
await pipeline.tx(ctx, [tx])
|
||||
await session.tx(clientCtx, tx)
|
||||
} else if (status.online !== online) {
|
||||
const tx = txFactory.createTxUpdateDoc(status._class, status.space, status._id, {
|
||||
online
|
||||
})
|
||||
await pipeline.tx(ctx, [tx])
|
||||
await session.tx(clientCtx, tx)
|
||||
}
|
||||
} catch {}
|
||||
} catch (err: any) {
|
||||
ctx.error('failed to set status', { err })
|
||||
Analytics.handleError(err)
|
||||
}
|
||||
}
|
||||
|
||||
async close (ctx: MeasureContext, ws: ConnectionSocket, wsid: string): Promise<void> {
|
||||
|
Loading…
Reference in New Issue
Block a user