Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.
Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.
Path: blob/master/src/packages/database/postgres/syncdoc-history.ts
Views: 687
/*1* This file is part of CoCalc: Copyright © 2020 Sagemath, Inc.2* License: MS-RSL – see LICENSE.md for details3*/45import { callback2 } from "@cocalc/util/async-utils";6import { trunc } from "@cocalc/util/misc";7import { PostgreSQL } from "./types";89export interface Patch {10time_utc: Date;11patch_length?: number;12patch?: string;13user?: string;14account_id?: string;15format?: number;16snapshot?: string;17}1819type User = { account_id: string; user: string };2021async function get_users(db: PostgreSQL, where): Promise<User[]> {22const query = "SELECT project_id, users FROM syncstrings";23// get the user_id --> account_id map24const results = await callback2(db._query, { query, where });25if (results.rows.length != 1) {26throw Error("no such syncstring");27}28const account_ids: string[] = results.rows[0].users29? results.rows[0].users30: []; // syncdoc exists, but not used yet.31const project_id: string = results.rows[0].project_id;32const project_title: string = trunc(33(34await callback2(db.get_project, {35columns: ["title"],36project_id,37})38).title,3980,40);4142// get the names of the users43// TODO: this whole file should be in @cocalc/server, be an api endpoint for api/v2,44// and this code below should instead use @cocalc/server/accounts/get-name:getNames.45const names = await callback2(db.account_ids_to_usernames, { account_ids });46const users: User[] = [];47for (const account_id of account_ids) {48if (account_id == project_id) {49users.push({ account_id, user: `Project: ${project_title}` });50continue;51}52const name = names[account_id];53if (name == null) continue;54const user = trunc(`${name.first_name} ${name.last_name}`, 80);55users.push({ account_id, user });56}57return users;58}5960export async function syncdoc_history(61db: PostgreSQL,62string_id: string,63include_patches: boolean = false,64): Promise<Patch[]> {65const where = { "string_id = $::CHAR(40)": string_id };66const users: User[] = await get_users(db, where);6768const order_by = "time";69let query: string;70if (include_patches) {71query = "SELECT time, user_id, format, patch, snapshot FROM patches";72} else {73query =74"SELECT time, user_id, format, length(patch) as patch_length FROM patches";75}76const results = await callback2(db._query, {77query,78where,79order_by,80timeout_s: 300,81});82const patches: Patch[] = [];83function format_patch(row): Patch {84const patch: Patch = { time_utc: row.time, format: row.format };85const u = users[row.user_id];86if (u != null) {87for (const k in u) {88patch[k] = u[k];89}90}91if (include_patches) {92patch.patch = row.patch;93if (row.snapshot != null) {94patch.snapshot = row.snapshot;95}96} else {97patch.patch_length = row.patch_length;98}99return patch;100}101for (const row of results.rows) {102patches.push(format_patch(row));103}104return patches;105}106107108