mirror of
https://github.com/gristlabs/grist-core.git
synced 2024-10-27 20:44:07 +00:00
(core) updates from grist-core
This commit is contained in:
commit
e8f9da9b5c
@ -275,7 +275,7 @@ Grist can be configured in many ways. Here are the main environment variables it
|
||||
| GRIST_ENABLE_REQUEST_FUNCTION | enables the REQUEST function. This function performs HTTP requests in a similar way to `requests.request`. This function presents a significant security risk, since it can let users call internal endpoints when Grist is available publicly. This function can also cause performance issues. Unset by default. |
|
||||
| GRIST_HIDE_UI_ELEMENTS | comma-separated list of UI features to disable. Allowed names of parts: `helpCenter,billing,templates,createSite,multiSite,multiAccounts,sendToDrive,tutorials,supportGrist`. If a part also exists in GRIST_UI_FEATURES, it will still be disabled. |
|
||||
| GRIST_HOST | hostname to use when listening on a port. |
|
||||
| GRIST_HTTPS_PROXY | if set, use this proxy for webhook payload delivery. |
|
||||
| GRIST_HTTPS_PROXY | if set, use this proxy for webhook payload delivery or fetching custom widgets repository from url. |
|
||||
| GRIST_ID_PREFIX | for subdomains of form o-*, expect or produce o-${GRIST_ID_PREFIX}*. |
|
||||
| GRIST_IGNORE_SESSION | if set, Grist will not use a session for authentication. |
|
||||
| GRIST_INCLUDE_CUSTOM_SCRIPT_URL | if set, will load the referenced URL in a `<script>` tag on all app pages. |
|
||||
|
@ -580,8 +580,10 @@ let dummyDocWorkerMap: DummyDocWorkerMap|null = null;
|
||||
|
||||
export function getDocWorkerMap(): IDocWorkerMap {
|
||||
if (process.env.REDIS_URL) {
|
||||
log.info("Creating Redis-based DocWorker");
|
||||
return new DocWorkerMap();
|
||||
} else {
|
||||
log.info("Creating local/dummy DocWorker");
|
||||
dummyDocWorkerMap = dummyDocWorkerMap || new DummyDocWorkerMap();
|
||||
return dummyDocWorkerMap;
|
||||
}
|
||||
|
@ -158,8 +158,7 @@ export class OpenAIAssistant implements Assistant {
|
||||
private _maxTokens = process.env.ASSISTANT_MAX_TOKENS ?
|
||||
parseInt(process.env.ASSISTANT_MAX_TOKENS, 10) : undefined;
|
||||
|
||||
public constructor() {
|
||||
const apiKey = process.env.ASSISTANT_API_KEY || process.env.OPENAI_API_KEY;
|
||||
public constructor(apiKey: string | undefined) {
|
||||
const endpoint = process.env.ASSISTANT_CHAT_COMPLETION_ENDPOINT;
|
||||
if (!apiKey && !endpoint) {
|
||||
throw new Error('Please set either OPENAI_API_KEY or ASSISTANT_CHAT_COMPLETION_ENDPOINT');
|
||||
@ -485,11 +484,13 @@ class EchoAssistant implements Assistant {
|
||||
* Instantiate an assistant, based on environment variables.
|
||||
*/
|
||||
export function getAssistant() {
|
||||
if (process.env.OPENAI_API_KEY === 'test') {
|
||||
const apiKey = process.env.ASSISTANT_API_KEY || process.env.OPENAI_API_KEY;
|
||||
|
||||
if (apiKey === 'test') {
|
||||
return new EchoAssistant();
|
||||
}
|
||||
if (process.env.OPENAI_API_KEY || process.env.ASSISTANT_CHAT_COMPLETION_ENDPOINT) {
|
||||
return new OpenAIAssistant();
|
||||
if (apiKey || process.env.ASSISTANT_CHAT_COMPLETION_ENDPOINT) {
|
||||
return new OpenAIAssistant(apiKey);
|
||||
}
|
||||
throw new Error('Please set OPENAI_API_KEY or ASSISTANT_CHAT_COMPLETION_ENDPOINT');
|
||||
}
|
||||
|
@ -638,6 +638,7 @@ export class DocManager extends EventEmitter {
|
||||
throw new Error('Grist docs must be uploaded individually');
|
||||
}
|
||||
const first = uploadInfo.files[0].origName;
|
||||
log.debug(`DocManager._doImportDoc: Received doc with name ${first}`);
|
||||
const ext = extname(first);
|
||||
const basename = path.basename(first, ext).trim() || "Untitled upload";
|
||||
let id: string;
|
||||
@ -662,6 +663,7 @@ export class DocManager extends EventEmitter {
|
||||
}
|
||||
await options.register?.(id, basename);
|
||||
if (ext === '.grist') {
|
||||
log.debug(`DocManager._doImportDoc: Importing .grist doc`);
|
||||
// If the import is a grist file, copy it to the docs directory.
|
||||
// TODO: We should be skeptical of the upload file to close a possible
|
||||
// security vulnerability. See https://phab.getgrist.com/T457.
|
||||
|
@ -1,6 +1,9 @@
|
||||
import {DocumentMetadata, HomeDBManager} from 'app/gen-server/lib/homedb/HomeDBManager';
|
||||
import {DocumentMetadata} from 'app/gen-server/lib/homedb/HomeDBManager';
|
||||
import log from 'app/server/lib/log';
|
||||
|
||||
// Callback that persists the updated metadata to storage for each document.
|
||||
export type SaveDocsMetadataFunc = (metadata: { [docId: string]: DocumentMetadata }) => Promise<any>;
|
||||
|
||||
/**
|
||||
* HostedMetadataManager handles pushing document metadata changes to the Home database when
|
||||
* a doc is updated. Currently updates doc updatedAt time and usage.
|
||||
@ -29,7 +32,7 @@ export class HostedMetadataManager {
|
||||
* Create an instance of HostedMetadataManager.
|
||||
* The minPushDelay is the default delay in seconds between metadata pushes to the database.
|
||||
*/
|
||||
constructor(private _dbManager: HomeDBManager, minPushDelay: number = 60) {
|
||||
constructor(private _saveDocsMetadata: SaveDocsMetadataFunc, minPushDelay: number = 60) {
|
||||
this._minPushDelayMs = minPushDelay * 1000;
|
||||
}
|
||||
|
||||
@ -68,7 +71,7 @@ export class HostedMetadataManager {
|
||||
}
|
||||
|
||||
public setDocsMetadata(docUpdateMap: {[docId: string]: DocumentMetadata}): Promise<any> {
|
||||
return this._dbManager.setDocsMetadata(docUpdateMap);
|
||||
return this._saveDocsMetadata(docUpdateMap);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -8,7 +8,6 @@ import {DocumentUsage} from 'app/common/DocUsage';
|
||||
import {buildUrlId, parseUrlId} from 'app/common/gristUrls';
|
||||
import {KeyedOps} from 'app/common/KeyedOps';
|
||||
import {DocReplacementOptions, NEW_DOCUMENT_CODE} from 'app/common/UserAPI';
|
||||
import {HomeDBManager} from 'app/gen-server/lib/homedb/HomeDBManager';
|
||||
import {checksumFile} from 'app/server/lib/checksumFile';
|
||||
import {DocSnapshotInventory, DocSnapshotPruner} from 'app/server/lib/DocSnapshots';
|
||||
import {IDocWorkerMap} from 'app/server/lib/DocWorkerMap';
|
||||
@ -19,7 +18,7 @@ import {
|
||||
ExternalStorageCreator, ExternalStorageSettings,
|
||||
Unchanged
|
||||
} from 'app/server/lib/ExternalStorage';
|
||||
import {HostedMetadataManager} from 'app/server/lib/HostedMetadataManager';
|
||||
import {HostedMetadataManager, SaveDocsMetadataFunc} from 'app/server/lib/HostedMetadataManager';
|
||||
import {EmptySnapshotProgress, IDocStorageManager, SnapshotProgress} from 'app/server/lib/IDocStorageManager';
|
||||
import {LogMethods} from "app/server/lib/LogMethods";
|
||||
import {fromCallback} from 'app/server/lib/serverUtils';
|
||||
@ -27,6 +26,7 @@ import * as fse from 'fs-extra';
|
||||
import * as path from 'path';
|
||||
import uuidv4 from "uuid/v4";
|
||||
import {OpenMode, SQLiteDB} from './SQLiteDB';
|
||||
import {Features} from "app/common/Features";
|
||||
|
||||
// Check for a valid document id.
|
||||
const docIdRegex = /^[-=_\w~%]+$/;
|
||||
@ -52,6 +52,13 @@ function checkValidDocId(docId: string): void {
|
||||
}
|
||||
}
|
||||
|
||||
export interface HostedStorageCallbacks {
|
||||
// Saves the given metadata for the specified documents.
|
||||
setDocsMetadata: SaveDocsMetadataFunc,
|
||||
// Retrieves account features enabled for the given document.
|
||||
getDocFeatures: (docId: string) => Promise<Features | undefined>
|
||||
}
|
||||
|
||||
export interface HostedStorageOptions {
|
||||
secondsBeforePush: number;
|
||||
secondsBeforeFirstRetry: number;
|
||||
@ -133,7 +140,7 @@ export class HostedStorageManager implements IDocStorageManager {
|
||||
private _docWorkerId: string,
|
||||
private _disableS3: boolean,
|
||||
private _docWorkerMap: IDocWorkerMap,
|
||||
dbManager: HomeDBManager,
|
||||
callbacks: HostedStorageCallbacks,
|
||||
createExternalStorage: ExternalStorageCreator,
|
||||
options: HostedStorageOptions = defaultOptions
|
||||
) {
|
||||
@ -144,7 +151,7 @@ export class HostedStorageManager implements IDocStorageManager {
|
||||
if (!externalStoreDoc) { this._disableS3 = true; }
|
||||
const secondsBeforePush = options.secondsBeforePush;
|
||||
if (options.pushDocUpdateTimes) {
|
||||
this._metadataManager = new HostedMetadataManager(dbManager);
|
||||
this._metadataManager = new HostedMetadataManager(callbacks.setDocsMetadata);
|
||||
}
|
||||
this._uploads = new KeyedOps(key => this._pushToS3(key), {
|
||||
delayBeforeOperationMs: secondsBeforePush * 1000,
|
||||
@ -178,7 +185,7 @@ export class HostedStorageManager implements IDocStorageManager {
|
||||
return path.join(dir, 'meta.json');
|
||||
},
|
||||
async docId => {
|
||||
const features = await dbManager.getDocFeatures(docId);
|
||||
const features = await callbacks.getDocFeatures(docId);
|
||||
return features?.snapshotWindow;
|
||||
},
|
||||
);
|
||||
@ -639,7 +646,7 @@ export class HostedStorageManager implements IDocStorageManager {
|
||||
|
||||
const existsLocally = await fse.pathExists(this.getPath(docName));
|
||||
if (existsLocally) {
|
||||
if (!docStatus.docMD5 || docStatus.docMD5 === DELETED_TOKEN) {
|
||||
if (!docStatus.docMD5 || docStatus.docMD5 === DELETED_TOKEN || docStatus.docMD5 === 'unknown') {
|
||||
// New doc appears to already exist, but may not exist in S3.
|
||||
// Let's check.
|
||||
const head = await this._ext.head(docName);
|
||||
|
@ -9,6 +9,7 @@ import {GristServer} from 'app/server/lib/GristServer';
|
||||
import LRUCache from 'lru-cache';
|
||||
import * as url from 'url';
|
||||
import { AsyncCreate } from 'app/common/AsyncCreate';
|
||||
import { proxyAgent } from 'app/server/lib/ProxyAgent';
|
||||
|
||||
// Static url for UrlWidgetRepository
|
||||
const STATIC_URL = process.env.GRIST_WIDGET_LIST_URL;
|
||||
@ -109,7 +110,7 @@ export class UrlWidgetRepository implements IWidgetRepository {
|
||||
return [];
|
||||
}
|
||||
try {
|
||||
const response = await fetch(this._staticUrl);
|
||||
const response = await fetch(this._staticUrl, { agent: proxyAgent(new URL(this._staticUrl)) });
|
||||
if (!response.ok) {
|
||||
if (response.status === 404) {
|
||||
throw new ApiError('WidgetRepository: Remote widget list not found', 404);
|
||||
|
@ -89,7 +89,9 @@ export function makeGristConfig(options: MakeGristConfigOptions): GristLoadConfi
|
||||
supportedLngs: readLoadedLngs(req?.i18n),
|
||||
namespaces: readLoadedNamespaces(req?.i18n),
|
||||
featureComments: isAffirmative(process.env.COMMENTS),
|
||||
featureFormulaAssistant: Boolean(process.env.OPENAI_API_KEY || process.env.ASSISTANT_CHAT_COMPLETION_ENDPOINT),
|
||||
featureFormulaAssistant: Boolean(process.env.OPENAI_API_KEY ||
|
||||
process.env.ASSISTANT_API_KEY ||
|
||||
process.env.ASSISTANT_CHAT_COMPLETION_ENDPOINT),
|
||||
assistantService: process.env.OPENAI_API_KEY ? 'OpenAI' : undefined,
|
||||
permittedCustomWidgets: getPermittedCustomWidgets(server),
|
||||
supportEmail: SUPPORT_EMAIL,
|
||||
|
@ -71,7 +71,7 @@
|
||||
"Sign Out": "Amaitu saioa",
|
||||
"Sign in": "Hasi saioa",
|
||||
"Switch Accounts": "Aldatu kontua",
|
||||
"Support Grist": "Babestu Grist",
|
||||
"Support Grist": "Eman babesa Grist-i",
|
||||
"Sign In": "Hasi saioa",
|
||||
"Sign Up": "Eman izena",
|
||||
"Use This Template": "Txantiloi hau erabili",
|
||||
@ -148,7 +148,8 @@
|
||||
"Cut": "Ebaki",
|
||||
"Paste": "Itsatsi",
|
||||
"Clear cell": "Garbitu gelaxka",
|
||||
"Filter by this value": "Iragazi balio honen arabera"
|
||||
"Filter by this value": "Iragazi balio honen arabera",
|
||||
"Copy with headers": "Kopiatu goiburuekin"
|
||||
},
|
||||
"ColorSelect": {
|
||||
"Apply": "Aplikatu",
|
||||
@ -192,7 +193,15 @@
|
||||
"No {{columnType}} columns in table.": "Ez dago {{columnType}} zutaberik taulan.",
|
||||
" (optional)": " (aukerakoa)",
|
||||
"{{wrongTypeCount}} non-{{columnType}} columns are not shown_other": "{{wrongTypeCount}} ez dira {{columnType}} zutabeak erakusten",
|
||||
"Full document access": "Sarbide osoa dokumentura"
|
||||
"Full document access": "Sarbide osoa dokumentura",
|
||||
"Accept": "Onartu",
|
||||
"Developer:": "Garatzailea:",
|
||||
"Last updated:": "Azkenekoz eguneratua:",
|
||||
"Missing description and author information.": "Ez dago deskribapen ezta egilearen informaziorik ere.",
|
||||
"Reject": "Baztertu",
|
||||
"ACCESS LEVEL": "SARBIDE-MAILA",
|
||||
"Custom URL": "URL pertsonalizatua",
|
||||
"Widget": "Widgeta"
|
||||
},
|
||||
"DataTables": {
|
||||
"Click to copy": "Egin klik kopiatzeko",
|
||||
@ -257,7 +266,11 @@
|
||||
"Workspace not found": "Ez da lan-eremua aurkitu",
|
||||
"You are on the {{siteName}} site. You also have access to the following sites:": "{{siteName}} gunean zaude. Honako gune hauetara ere sar zaitezke:",
|
||||
"You are on your personal site. You also have access to the following sites:": "Zure leku pertsonalean zaude. Honako gune hauetara ere sar zaitezke:",
|
||||
"You may delete a workspace forever once it has no documents in it.": "Lan-eremu bat betiko ezabatzeko ezin du barruan dokumenturik izan."
|
||||
"You may delete a workspace forever once it has no documents in it.": "Lan-eremu bat betiko ezabatzeko ezin du barruan dokumenturik izan.",
|
||||
"Create my first document": "Sortu nire lehen dokumentua",
|
||||
"Any documents created in this site will appear here.": "Gune honetan sortutako dokumentuak hemen agertuko dira.",
|
||||
"personal site": "gune pertsonala",
|
||||
"You have read-only access to this site. Currently there are no documents.": "Soilik irakurtzeko sarbidea duzu gune honetan. Unean ez dago dokumenturik."
|
||||
},
|
||||
"DocPageModel": {
|
||||
"Add Empty Table": "Gehitu taula hutsa",
|
||||
@ -493,7 +506,8 @@
|
||||
"Get started by exploring templates, or creating your first Grist document.": "Has zaitez txantiloiak arakatuz edo zure lehen Grist dokumentua sortuz.",
|
||||
"Get started by inviting your team and creating your first Grist document.": "Has zaitez zure taldea gonbidatuz eta zure lehen Grist dokumentua sortuz.",
|
||||
"Interested in using Grist outside of your team? Visit your free ": "Grist zure taldetik kanpo erabili nahi duzu? Bisitatu zure doako ",
|
||||
"Sprouts Program": "Kimuen programa"
|
||||
"Sprouts Program": "Kimuen programa",
|
||||
"Only show documents": "Erakutsi dokumentuak bakarrik"
|
||||
},
|
||||
"HomeLeftPane": {
|
||||
"All Documents": "Dokumentu guztiak",
|
||||
@ -720,7 +734,8 @@
|
||||
"API Console": "API kontsola"
|
||||
},
|
||||
"TopBar": {
|
||||
"Manage Team": "Kudeatu taldea"
|
||||
"Manage Team": "Kudeatu taldea",
|
||||
"Manage team": "Kudeatu taldea"
|
||||
},
|
||||
"TriggerFormulas": {
|
||||
"Cancel": "Utzi",
|
||||
@ -844,7 +859,9 @@
|
||||
"You are signed in as {{email}}. You can sign in with a different account, or ask an administrator for access.": "{{email}} gisa hasi duzu saioa. Beste kontu batekin hasi dezakezu saioa, edo administratzaile bati sarbidea eskatu.",
|
||||
"Build your own form": "Sortu zure formularioa",
|
||||
"Powered by": "Honi esker:",
|
||||
"Account deleted{{suffix}}": "Kontua ezabatu da{{suffix}}"
|
||||
"Account deleted{{suffix}}": "Kontua ezabatu da{{suffix}}",
|
||||
"Failed to log in.{{separator}}Please try again or contact support.": "Saioaren hasierak huts egin du.{{separator}}Saiatu berriro edo jarri harremanetan laguntza eskatzeko.",
|
||||
"Sign-in failed{{suffix}}": "Saioaren hasierak huts egin du{{suffix}}"
|
||||
},
|
||||
"menus": {
|
||||
"Select fields": "Hautatu eremuak",
|
||||
@ -1083,7 +1100,14 @@
|
||||
"Select the table to link to.": "Hautatu lotu beharreko taula.",
|
||||
"Use the 𝚺 icon to create summary (or pivot) tables, for totals or subtotals.": "Erabili 𝚺 ikonoa laburpen-taulak edo taula dinamikoak sortzeko, guztizkoetarako edo guztizko partzialetarako.",
|
||||
"Can't find the right columns? Click 'Change Widget' to select the table with events data.": "Ez dituzu zutabe egokiak aurkitzen? Egin klik \"Aldatu widgeta\"-n gertaeren datuak dituen taula hautatzeko.",
|
||||
"Clicking {{EyeHideIcon}} in each cell hides the field from this view without deleting it.": "Gelaxka bakoitzeko {{EyeHideIcon}}-en klik eginez gero, eremua ikuspegi honetatik ezkutatuko da ezabatu gabe."
|
||||
"Clicking {{EyeHideIcon}} in each cell hides the field from this view without deleting it.": "Gelaxka bakoitzeko {{EyeHideIcon}}-en klik eginez gero, eremua ikuspegi honetatik ezkutatuko da ezabatu gabe.",
|
||||
"Creates a reverse column in target table that can be edited from either end.": "Helburuko taulan bi muturretatik editatu daitekeen alderantzizko zutabe bat sortzen du.",
|
||||
"To allow multiple assignments, change the type of the Reference column to Reference List.": "Esleipen bat baino gehiago baimentzeko, aldatu erreferentzia-zutabearen mota Erreferentzia zerrendara.",
|
||||
"This limitation occurs when one end of a two-way reference is configured as a single Reference.": "Muga hau bi noranzkoko erreferentzia bateko muturretako bat erreferentzia bakar gisa konfiguratuta dagoenean ematen da.",
|
||||
"Community widgets are created and maintained by Grist community members.": "Komunitatearen widgetak Gristen komunitateko kideek sortzen eta mantentzen dituztenak dira.",
|
||||
"To allow multiple assignments, change the referenced column's type to Reference List.": "Esleipen bat baino gehiago baimentzeko, aldatu erreferentzia-zutabearen mota Erreferentzia zerrendara.",
|
||||
"This limitation occurs when one column in a two-way reference has the Reference type.": "Muga hau bi noranzkoko erreferentzia bateko zutabetako bat erreferentzia mota gisa konfiguratuta dagoenean ematen da.",
|
||||
"Two-way references are not currently supported for Formula or Trigger Formula columns": "Bi noranzkoko erreferentziak ez dira unean bateragarriak Formula edo formula-abiarazle zutabeekin."
|
||||
},
|
||||
"ColumnTitle": {
|
||||
"Column ID copied to clipboard": "Zutabearen IDa arbelera kopiatu da",
|
||||
@ -1283,7 +1307,7 @@
|
||||
},
|
||||
"UserManager": {
|
||||
"Add {{member}} to your team": "Gehitu {{member}} zure taldean",
|
||||
"Allow anyone with the link to open.": "Utzi esteka duen edonori irekitzen.",
|
||||
"Allow anyone with the link to open.": "Baimendu esteka duen edonori irekitzea.",
|
||||
"Confirm": "Baieztatu",
|
||||
"Copy Link": "Kopiatu esteka",
|
||||
"Guest": "Gonbidatua",
|
||||
@ -1330,11 +1354,11 @@
|
||||
"Help Center": "Laguntza Gunea",
|
||||
"Opt in to Telemetry": "Bidali telemetria",
|
||||
"Support Grist": "Eman babesa Grist-i",
|
||||
"Support Grist page": "Eman babesa Grist-en orriari",
|
||||
"Support Grist page": "Grist-en laguntza orria",
|
||||
"Opted In": "Izena emanda",
|
||||
"Close": "Itxi",
|
||||
"Contribute": "Hartu parte",
|
||||
"Thank you! Your trust and support is greatly appreciated. Opt out any time from the {{link}} in the user menu.": "Mila esker! Zure konfiantza eta babesa oso estimatua da. Edozein unetan bidaltzeari utzi diezaiokezu erabiltzailearen menuko {{link}}tik.",
|
||||
"Thank you! Your trust and support is greatly appreciated. Opt out any time from the {{link}} in the user menu.": "Mila esker! Zure konfiantza eta babesa oso estimatuak dira. Edozein unetan bidaltzeari utzi diezaiokezu erabiltzailearen menuko {{link}}tik.",
|
||||
"Admin Panel": "Administratzailearen mahaigaina"
|
||||
},
|
||||
"SupportGristPage": {
|
||||
@ -1537,7 +1561,8 @@
|
||||
"Grist allows for very powerful formulas, using Python. We recommend setting the environment variable GRIST_SANDBOX_FLAVOR to gvisor if your hardware supports it (most will), to run formulas in each document within a sandbox isolated from other documents and isolated from the network.": "Gristek formula oso boteretsuak onartzen ditu, Python erabiliz. Dokumentu bakoitzean beste dokumentu batzuetatik eta saretik isolatutako sandbox baten barruan formulak exekutatzeko, GRIST_SANDBOX_FLAVOR aldagaia gvisor-era aldatzea gomendatzen dugu, zure hardwarea bateragarria bada (gehienak badira).",
|
||||
"Session Secret": "Saioaren gakoa",
|
||||
"Enable Grist Enterprise": "Gaitu Grist Enterprise",
|
||||
"Enterprise": "Enterprise"
|
||||
"Enterprise": "Enterprise",
|
||||
"checking": "egiaztatzen"
|
||||
},
|
||||
"Columns": {
|
||||
"Remove Column": "Kendu zutabea"
|
||||
@ -1649,7 +1674,8 @@
|
||||
"3 minute video tour": "3 minutuko bideo-bisitaldia",
|
||||
"Complete our basics tutorial": "Burutu oinarrizko tutoriala",
|
||||
"Complete the tutorial": "Burutu tutoriala",
|
||||
"Learn the basic of reference columns, linked widgets, column types, & cards.": "Ikasi erreferentzia-zutabeen, lotutako widgeten, zutabe-moten eta txartelen oinarriak."
|
||||
"Learn the basic of reference columns, linked widgets, column types, & cards.": "Ikasi erreferentzia-zutabeen, lotutako widgeten, zutabe-moten eta txartelen oinarriak.",
|
||||
"Learn the basics of reference columns, linked widgets, column types, & cards.": "Ikasi erreferentzia-zutabeen, lotutako widgeten, zutabe moten, eta txartelen oinarriak."
|
||||
},
|
||||
"OnboardingPage": {
|
||||
"Go hands-on with the Grist Basics tutorial": "Murgildu Gristen oinarrizko tutorialean",
|
||||
@ -1680,5 +1706,87 @@
|
||||
"Table {{tableName}} will no longer be visible": "{{tableName}} taula ez da ikusgai egongo aurrerantzean",
|
||||
"raw data page": "datu gordinen orria",
|
||||
"Delete": "Ezabatu"
|
||||
},
|
||||
"CustomWidgetGallery": {
|
||||
"Add Your Own Widget": "Gehitu zure widgeta",
|
||||
"Cancel": "Utzi",
|
||||
"Change Widget": "Aldatu widgeta",
|
||||
"Developer:": "Garatzailea:",
|
||||
"Last updated:": "Azkenekoz eguneratua:",
|
||||
"Search": "Bilatu",
|
||||
"Widget URL": "Widgetaren URLa",
|
||||
"Add Widget": "Gehitu widgeta",
|
||||
"(Missing info)": "(Informaziorik gabe)",
|
||||
"Grist Widget": "Grist widgeta",
|
||||
"No matching widgets": "Ez dago bat datorren widgetik",
|
||||
"Add a widget from outside this gallery.": "Gehitu galeria honetatik kanpoko widgetak.",
|
||||
"Choose Custom Widget": "Aukeratu widget pertsonalizatua",
|
||||
"Community Widget": "Komunitatearen widgetak",
|
||||
"Custom URL": "URL pertsonalizatua",
|
||||
"Learn more about Custom Widgets": "Ikasi gehiago widget pertsonalizatuei buruz"
|
||||
},
|
||||
"HomeIntroCards": {
|
||||
"Help center": "Laguntza gunea",
|
||||
"Learn more {{webinarsLinks}}": "Ikasi gehiago {{webinarsLinks}}",
|
||||
"Start a new document": "Hasi dokuemntu berria",
|
||||
"Templates": "Txantiloiak",
|
||||
"Blank document": "Dokumentu zuria",
|
||||
"Import file": "Inportatu fitxategia",
|
||||
"3 minute video tour": "3 minutuko bideo-bisitaldia",
|
||||
"Finish our basics tutorial": "Amaitu oinarrizko tutoriala",
|
||||
"Tutorial": "Tutoriala",
|
||||
"Webinars": "Web-mintegiak",
|
||||
"Find solutions and explore more resources {{helpCenterLink}}": "Ikusi adibideak eta arakatu baliabide gehiago {{helpCenterLink}}"
|
||||
},
|
||||
"ReverseReferenceConfig": {
|
||||
"Delete": "Ezabatu",
|
||||
"Table": "Taula",
|
||||
"Target table": "Helmugako taula",
|
||||
"Delete column {{column}} in table {{table}}?": "{{table}} taulako {{column}} zutabea ezabatu nahi duzu?",
|
||||
"Column": "Zutabea",
|
||||
"Add two-way reference": "Gehitu bi noranzkoko erreferentzia",
|
||||
"Two-way Reference": "Bi noranzkoko erreferentzia",
|
||||
"Delete two-way reference?": "Bi noranzkoko erreferentzia ezabatu?",
|
||||
"It is the reverse of the reference column {{column}} in table {{table}}.": "{{table}} taulako {{column}} zutabearen alderantzizko erreferentzia da."
|
||||
},
|
||||
"SupportGristButton": {
|
||||
"Close": "Itxi",
|
||||
"Help Center": "Laguntza gunea",
|
||||
"Admin Panel": "Administratzailearen mahaigaina",
|
||||
"Support Grist": "Eman babesa Grist-i",
|
||||
"Opted In": "Telemetria bidaltzen da",
|
||||
"Thank you! Your trust and support is greatly appreciated. Opt out any time from the {{link}} in the user menu.": "Mila esker! Zure konfiantza eta babesa oso estimatuak dira. Edozein unetan bidaltzeari utzi diezaiokezu erabiltzailearen menuko {{link}}tik.",
|
||||
"Opt in to Telemetry": "Bidali telemetria"
|
||||
},
|
||||
"buildReassignModal": {
|
||||
"Cancel": "Utzi",
|
||||
"Each {{targetTable}} record may only be assigned to a single {{sourceTable}} record.": "{{targetTable}} erregistro bakoitzari {{sourceTable}} erregistro bakarra esleitu dakioke.",
|
||||
"Reassign to {{sourceTable}} record {{sourceName}}.": "Berresleitu {{sourceTable}}(e)ko {{sourceName}} erregistroari.",
|
||||
"Record already assigned_one": "Erregistroa esleituta dago lehendik ere",
|
||||
"Record already assigned_other": "Erregistroa esleituta dago lehendik ere",
|
||||
"Reassign": "Berresleitu",
|
||||
"Reassign to new {{sourceTable}} records.": "Berresleitu {{sourceTable}}(e)ko erregistro berri bati.",
|
||||
"{{targetTable}} record {{targetName}} is already assigned to {{sourceTable}} record {{oldSourceName}}.": "{{targetTable}}(e)ko {{targetName}} erregistroa lehendik dago {{sourceTable}}(e)ko {{oldSourceName}} erregistroari esleituta."
|
||||
},
|
||||
"AdminPanelName": {
|
||||
"Admin Panel": "Administratzailearen mahaigaina"
|
||||
},
|
||||
"markdown": {
|
||||
"# New Markdown Function\n *\n * We can _write_ [the usual Markdown](https:": {
|
||||
"": {
|
||||
"markdownguide.org) *inside*\n * a Grainjs element.": "# Markdown funtzio berria\n *\n * Grainjs elementu baten *barruan*\n * [ohiko Markdown sintaxia](https://markdownguide.org) _idatz_ dezakegu."
|
||||
}
|
||||
},
|
||||
"The toggle is **off**": "Ezaugarria **desaktibatuta** dago",
|
||||
"The toggle is **on**": "Ezaugarria **aktibatuta** dago"
|
||||
},
|
||||
"markdown.d": {
|
||||
"# New Markdown Function\n *\n * We can _write_ [the usual Markdown](https:": {
|
||||
"": {
|
||||
"markdownguide.org) *inside*\n * a Grainjs element.": "# Markdown funtzio berria\n *\n * Grainjs elementu baten *barruan*\n * [ohiko Markdown sintaxia](https://markdownguide.org) _idatz_ dezakegu."
|
||||
}
|
||||
},
|
||||
"The toggle is **off**": "Ezaugarria **desaktibatuta** dago",
|
||||
"The toggle is **on**": "Ezaugarria **aktibatuta** dago"
|
||||
}
|
||||
}
|
||||
|
@ -133,7 +133,8 @@
|
||||
"Cut": "Izreži",
|
||||
"Paste": "Prilepi",
|
||||
"Clear values": "Izbriši vrednosti",
|
||||
"Clear cell": "Čista celica"
|
||||
"Clear cell": "Čista celica",
|
||||
"Copy with headers": "Kopiraj z glavami"
|
||||
},
|
||||
"DocMenu": {
|
||||
"Document will be moved to Trash.": "Dokument se bo premaknil v koš.",
|
||||
@ -174,7 +175,11 @@
|
||||
"Restore": "Obnovi",
|
||||
"Move {{name}} to workspace": "Premakni {{name}} v delovni prostor",
|
||||
"You are on the {{siteName}} site. You also have access to the following sites:": "Nahajate se na spletnem mestu {{siteName}}. Prav tako imate dostop do naslednjih spletnih mest:",
|
||||
"Examples & Templates": "Primeri & predloge"
|
||||
"Examples & Templates": "Primeri & predloge",
|
||||
"Any documents created in this site will appear here.": "Vsi dokumenti, ustvarjeni na tem mestu, bodo prikazani tukaj.",
|
||||
"Create my first document": "Ustvari moj prvi dokument",
|
||||
"personal site": "osebno spletno mesto",
|
||||
"You have read-only access to this site. Currently there are no documents.": "Do tega mesta imate dostop samo za branje. Trenutno ni dokumentov."
|
||||
},
|
||||
"GridViewMenus": {
|
||||
"Rename column": "Preimenuj stolpec",
|
||||
@ -407,7 +412,15 @@
|
||||
"{{wrongTypeCount}} non-{{columnType}} columns are not shown_other": "{{wrongTypeCount}} stolpci, ki niso{{columnType}}, niso prikazani",
|
||||
"Widget needs to {{read}} the current table.": "Widget mora {{read}} trenutno tabelo.",
|
||||
"No {{columnType}} columns in table.": "V tabeli ni stolpcev tipa {{columnType}}.",
|
||||
"Clear selection": "Briši izbor"
|
||||
"Clear selection": "Briši izbor",
|
||||
"Custom URL": "URL po meri",
|
||||
"Developer:": "Razvijalec:",
|
||||
"ACCESS LEVEL": "STOPNJA DOSTOPOV",
|
||||
"Reject": "Zavrni",
|
||||
"Accept": "Sprejmi",
|
||||
"Last updated:": "Zadnja posodobitev:",
|
||||
"Missing description and author information.": "Manjka opis in podatki o avtorju.",
|
||||
"Widget": "Widget"
|
||||
},
|
||||
"DocHistory": {
|
||||
"Activity": "Dejavnost",
|
||||
@ -784,7 +797,14 @@
|
||||
"Build simple forms right in Grist and share in a click with our new widget. {{learnMoreButton}}": "Ustvari preproste obrazce neposredno v Gristu in jih deli z enim klikom z našim novim pripomočkom. {{learnMoreButton}}",
|
||||
"These rules are applied after all column rules have been processed, if applicable.": "Ta pravila se uporabijo, ko so obdelana vsa pravila stolpcev, če so na voljo.",
|
||||
"Filter displayed dropdown values with a condition.": "Filtriraj prikazane vrednosti .",
|
||||
"Example: {{example}}": "Primer: {{example}}"
|
||||
"Example: {{example}}": "Primer: {{example}}",
|
||||
"Creates a reverse column in target table that can be edited from either end.": "Ustvari vzvratni stolpec v ciljni tabeli, ki ga je mogoče urejati z obeh koncev.",
|
||||
"To allow multiple assignments, change the type of the Reference column to Reference List.": "Če želiš dovoliti več dodelitev, spremeni vrsto stolpca Reference v Seznam referenc.",
|
||||
"To allow multiple assignments, change the referenced column's type to Reference List.": "Če želiš omogočiti več dodelitev, spremeni vrsto referenčnega stolpca v Referenčni seznam.",
|
||||
"Two-way references are not currently supported for Formula or Trigger Formula columns": "Dvosmerne reference trenutno niso podprte za stolpce formule ali formule sprožilca",
|
||||
"Community widgets are created and maintained by Grist community members.": "Pripomočke skupnosti ustvarjajo in vzdržujejo člani skupnosti Grist.",
|
||||
"This limitation occurs when one end of a two-way reference is configured as a single Reference.": "Do te omejitve pride, ko je en konec dvosmerne reference konfiguriran kot ena sama referenca.",
|
||||
"This limitation occurs when one column in a two-way reference has the Reference type.": "Do te omejitve pride, ko ima en stolpec v dvosmernem sklicu vrsto Reference."
|
||||
},
|
||||
"UserManager": {
|
||||
"Anyone with link ": "Vsakdo s povezavo ",
|
||||
@ -922,7 +942,8 @@
|
||||
"Visit our {{link}} to learn more about Grist.": "Obiščite našo spletno stran {{link}} da izveste več o Grisstu.",
|
||||
"Sign in": "Prijavi se",
|
||||
"To use Grist, please either sign up or sign in.": "Če želiš uporabljati Grist, se prijavi ali prvič prijavi.",
|
||||
"Learn more in our {{helpCenterLink}}.": "Izvedi več v našem {{helpCenterLink}}."
|
||||
"Learn more in our {{helpCenterLink}}.": "Izvedi več v našem {{helpCenterLink}}.",
|
||||
"Only show documents": "Pokaži samo dokumente"
|
||||
},
|
||||
"WelcomeSitePicker": {
|
||||
"You have access to the following Grist sites.": "Imate dostop do naslednjih Grist spletnih mest .",
|
||||
@ -1101,7 +1122,8 @@
|
||||
"Rule {{length}}": "Pravilo {{length}}"
|
||||
},
|
||||
"TopBar": {
|
||||
"Manage Team": "Upravljanje ekipe"
|
||||
"Manage Team": "Upravljanje ekipe",
|
||||
"Manage team": "Uredi ekipo"
|
||||
},
|
||||
"UserManagerModel": {
|
||||
"View & Edit": "Ogled in urejanje",
|
||||
@ -1175,7 +1197,9 @@
|
||||
"Build your own form": "Ustvari svoj obrazec",
|
||||
"Powered by": "Poganja ga",
|
||||
"An unknown error occurred.": "Prišlo je do neznane napake.",
|
||||
"Form not found": "Ne najdem obrazca"
|
||||
"Form not found": "Ne najdem obrazca",
|
||||
"Sign-in failed{{suffix}}": "Prijava ni uspela{{suffix}}",
|
||||
"Failed to log in.{{separator}}Please try again or contact support.": "Prijava ni uspela.{{separator}}Poskusi znova ali se obrni na podporo."
|
||||
},
|
||||
"WidgetTitle": {
|
||||
"DATA TABLE NAME": "IME PODATKOVNE TABELE",
|
||||
@ -1560,7 +1584,8 @@
|
||||
"Grist signs user session cookies with a secret key. Please set this key via the environment variable GRIST_SESSION_SECRET. Grist falls back to a hard-coded default when it is not set. We may remove this notice in the future since session IDs have been updated to be inherently cryptographically secure.": "Grist podpisuje piškotke uporabniške seje s skrivnim ključem. Ta ključ nastavite prek spremenljivke okolja GRIST_SESSION_SECRET. Grist se vrne na trdo kodirano privzeto vrednost, če ni nastavljena. To obvestilo bomo morda odstranili v prihodnosti, saj so ID-ji sej, ustvarjeni od različice 1.1.16, sami po sebi kriptografsko varni.",
|
||||
"Grist signs user session cookies with a secret key. Please set this key via the environment variable GRIST_SESSION_SECRET. Grist falls back to a hard-coded default when it is not set. We may remove this notice in the future as session IDs generated since v1.1.16 are inherently cryptographically secure.": "Grist podpisuje piškotke uporabniške seje s skrivnim ključem. Ta ključ nastavite prek spremenljivke okolja GRIST_SESSION_SECRET. Grist se vrne na trdo kodirano privzeto vrednost, če ni nastavljena. To obvestilo bomo morda odstranili v prihodnosti, saj so ID-ji sej, ustvarjeni od različice 1.1.16, sami po sebi kriptografsko varni.",
|
||||
"Enable Grist Enterprise": "Omogoči Grist Enterprise",
|
||||
"Enterprise": "Podjetje"
|
||||
"Enterprise": "Podjetje",
|
||||
"checking": "preverjanje"
|
||||
},
|
||||
"ChoiceEditor": {
|
||||
"Error in dropdown condition": "Napaka v spustnem meniju",
|
||||
@ -1649,7 +1674,8 @@
|
||||
"3 minute video tour": "3 minutni video ogled",
|
||||
"Complete our basics tutorial": "Dokončaj našo vadnico o osnovah",
|
||||
"Complete the tutorial": "Dokončaj vadnico",
|
||||
"Learn the basic of reference columns, linked widgets, column types, & cards.": "Nauči se osnov referenčnih stolpcev, povezanih pripomočkov, vrst stolpcev in kartic."
|
||||
"Learn the basic of reference columns, linked widgets, column types, & cards.": "Nauči se osnov referenčnih stolpcev, povezanih pripomočkov, vrst stolpcev in kartic.",
|
||||
"Learn the basics of reference columns, linked widgets, column types, & cards.": "Naučite se osnov referenčnih stolpcev, povezanih pripomočkov, vrst stolpcev in kartic."
|
||||
},
|
||||
"OnboardingPage": {
|
||||
"Back": "Nazaj",
|
||||
@ -1680,5 +1706,87 @@
|
||||
"Keep data and delete widget. Table will remain available in {{rawDataLink}}": "Ohranite podatke in izbrišite pripomoček. Tabela bo ostala na voljo v {{rawDataLink}}",
|
||||
"Table {{tableName}} will no longer be visible": "Tabela {{tableName}} ne bo več vidna",
|
||||
"raw data page": "stran z neobdelanimi podatki"
|
||||
},
|
||||
"AdminPanelName": {
|
||||
"Admin Panel": "Skrbniška plošča"
|
||||
},
|
||||
"CustomWidgetGallery": {
|
||||
"(Missing info)": "(Manjkajo informacije)",
|
||||
"Add Widget": "Dodaj pripomoček",
|
||||
"Add Your Own Widget": "Dodajte svoj pripomoček",
|
||||
"Add a widget from outside this gallery.": "Dodaj pripomoček zunaj te galerije.",
|
||||
"Cancel": "Prekliči",
|
||||
"Change Widget": "Spremeni pripomoček",
|
||||
"Developer:": "razvijalec:",
|
||||
"Grist Widget": "Grist Pripomoček",
|
||||
"Learn more about Custom Widgets": "Izvedite več o pripomočkih po meri",
|
||||
"No matching widgets": "Ni ujemajočih se pripomočkov",
|
||||
"Search": "Iskanje",
|
||||
"Widget URL": "URL pripomočka",
|
||||
"Choose Custom Widget": "Izberite Pripomoček po meri",
|
||||
"Community Widget": "Pripomoček skupnosti",
|
||||
"Custom URL": "URL po meri",
|
||||
"Last updated:": "Zadnja posodobitev:"
|
||||
},
|
||||
"markdown": {
|
||||
"The toggle is **off**": "Preklop je **izklopljen**",
|
||||
"The toggle is **on**": "Preklop je **vklopljen**",
|
||||
"# New Markdown Function\n *\n * We can _write_ [the usual Markdown](https:": {
|
||||
"": {
|
||||
"markdownguide.org) *inside*\n * a Grainjs element.": "# Nova funkcija Markdown\n *\n * Lahko _napišemo_ [običajni Markdown](https://markdownguide.org) *znotraj*\n * element Grainjs."
|
||||
}
|
||||
}
|
||||
},
|
||||
"markdown.d": {
|
||||
"The toggle is **on**": "Preklop je **vklopljen**",
|
||||
"The toggle is **off**": "Preklop je **izklopljen**",
|
||||
"# New Markdown Function\n *\n * We can _write_ [the usual Markdown](https:": {
|
||||
"": {
|
||||
"markdownguide.org) *inside*\n * a Grainjs element.": "# Nova funkcija Markdown\n *\n * Lahko _napišemo_ [običajni Markdown](https://markdownguide.org) *znotraj*\n * element Grainjs."
|
||||
}
|
||||
}
|
||||
},
|
||||
"HomeIntroCards": {
|
||||
"3 minute video tour": "3 minutni video ogled",
|
||||
"Blank document": "Prazen dokument",
|
||||
"Finish our basics tutorial": "Dokončaj našo vadnico o osnovah",
|
||||
"Learn more {{webinarsLinks}}": "Več o tem {{webinarsLinks}}",
|
||||
"Start a new document": "Začni nov dokument",
|
||||
"Templates": "Predloge",
|
||||
"Tutorial": "Vadnica",
|
||||
"Find solutions and explore more resources {{helpCenterLink}}": "Poiščite rešitve in raziščite več virov {{helpCenterLink}}",
|
||||
"Help center": "Center za pomoč",
|
||||
"Import file": "Uvozi datoteko",
|
||||
"Webinars": "Spletni seminarji"
|
||||
},
|
||||
"ReverseReferenceConfig": {
|
||||
"Add two-way reference": "Dodaj dvosmerno referenco",
|
||||
"Delete column {{column}} in table {{table}}?": "Želiš izbrisati stolpec {{column}} v tabeli {{table}}?",
|
||||
"It is the reverse of the reference column {{column}} in table {{table}}.": "Je obratna stran referenčnega stolpca {{column}} v tabeli {{table}}.",
|
||||
"Two-way Reference": "Dvosmerna referenca",
|
||||
"Delete two-way reference?": "Želiš izbrisati dvosmerno referenco?",
|
||||
"Target table": "Ciljna tabela",
|
||||
"Column": "Stolpec",
|
||||
"Delete": "Izbriši",
|
||||
"Table": "Tabela"
|
||||
},
|
||||
"SupportGristButton": {
|
||||
"Admin Panel": "Skrbniška plošča",
|
||||
"Close": "Zapri",
|
||||
"Help Center": "Center za pomoč",
|
||||
"Opted In": "Omogočeno",
|
||||
"Opt in to Telemetry": "Omogoči uporabo telemetrije",
|
||||
"Support Grist": "Podpora Gristu",
|
||||
"Thank you! Your trust and support is greatly appreciated. Opt out any time from the {{link}} in the user menu.": "Hvala! Vaše zaupanje in podporo zelo cenimo. Kadar koli se odjavite na {{link}} v uporabniškem meniju."
|
||||
},
|
||||
"buildReassignModal": {
|
||||
"Cancel": "Prekliči",
|
||||
"Each {{targetTable}} record may only be assigned to a single {{sourceTable}} record.": "Vsak zapis {{targetTable}} je lahko dodeljen samo enemu zapisu {{sourceTable}}.",
|
||||
"Reassign": "Prerazporedi",
|
||||
"Reassign to new {{sourceTable}} records.": "Ponovno dodelite novim zapisom {{sourceTable}}.",
|
||||
"Reassign to {{sourceTable}} record {{sourceName}}.": "Znova dodeli zapisu {{sourceTable}} {{sourceName}}.",
|
||||
"Record already assigned_one": "Zapis je že dodeljen",
|
||||
"Record already assigned_other": "Zapis je že dodeljen",
|
||||
"{{targetTable}} record {{targetName}} is already assigned to {{sourceTable}} record {{oldSourceName}}.": "Zapis {{targetTable}} {{targetName}} je že dodeljen zapisu {{sourceTable}} {{oldSourceName}}."
|
||||
}
|
||||
}
|
||||
|
@ -1,12 +1,13 @@
|
||||
import {ErrorOrValue, freezeError, mapGetOrSet, MapWithTTL} from 'app/common/AsyncCreate';
|
||||
import {ObjMetadata, ObjSnapshot, ObjSnapshotWithMetadata} from 'app/common/DocSnapshot';
|
||||
import {SCHEMA_VERSION} from 'app/common/schema';
|
||||
import {DocWorkerMap} from 'app/gen-server/lib/DocWorkerMap';
|
||||
import {DocWorkerMap, getDocWorkerMap} from 'app/gen-server/lib/DocWorkerMap';
|
||||
import {HomeDBManager} from 'app/gen-server/lib/homedb/HomeDBManager';
|
||||
import {ActiveDoc} from 'app/server/lib/ActiveDoc';
|
||||
import {create} from 'app/server/lib/create';
|
||||
import {DocManager} from 'app/server/lib/DocManager';
|
||||
import {makeExceptionalDocSession} from 'app/server/lib/DocSession';
|
||||
import {IDocWorkerMap} from 'app/server/lib/DocWorkerMap';
|
||||
import {
|
||||
DELETED_TOKEN,
|
||||
ExternalStorage, ExternalStorageCreator,
|
||||
@ -274,7 +275,7 @@ class TestStore {
|
||||
public constructor(
|
||||
private _localDirectory: string,
|
||||
private _workerId: string,
|
||||
private _workers: DocWorkerMap,
|
||||
private _workers: IDocWorkerMap,
|
||||
private _externalStorageCreate: ExternalStorageCreator) {
|
||||
}
|
||||
|
||||
@ -962,6 +963,98 @@ describe('HostedStorageManager', function() {
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
describe('minio-without-redis', async () => {
|
||||
const workerId = 'dw17';
|
||||
let tmpDir: string;
|
||||
let oldEnv: EnvironmentSnapshot;
|
||||
let docWorkerMap: IDocWorkerMap;
|
||||
let externalStorageCreate: ExternalStorageCreator;
|
||||
let defaultParams: ConstructorParameters<typeof HostedStorageManager>;
|
||||
|
||||
before(async function() {
|
||||
tmpDir = await createTmpDir();
|
||||
oldEnv = new EnvironmentSnapshot();
|
||||
// Disable Redis
|
||||
delete process.env.REDIS_URL;
|
||||
|
||||
const storage = create?.getStorageOptions?.('minio');
|
||||
const creator = storage?.create;
|
||||
if (!creator || !storage?.check()) {
|
||||
return this.skip();
|
||||
}
|
||||
externalStorageCreate = creator;
|
||||
});
|
||||
|
||||
after(async () => {
|
||||
oldEnv.restore();
|
||||
});
|
||||
|
||||
beforeEach(async function() {
|
||||
// With Redis disabled, this should be the non-redis version of IDocWorkerMap (DummyDocWorkerMap)
|
||||
docWorkerMap = getDocWorkerMap();
|
||||
await docWorkerMap.addWorker({
|
||||
id: workerId,
|
||||
publicUrl: "none",
|
||||
internalUrl: "none",
|
||||
});
|
||||
await docWorkerMap.setWorkerAvailability(workerId, true);
|
||||
|
||||
defaultParams = [
|
||||
tmpDir,
|
||||
workerId,
|
||||
false,
|
||||
docWorkerMap,
|
||||
{
|
||||
setDocsMetadata: async (metadata) => {},
|
||||
getDocFeatures: async (docId) => undefined,
|
||||
},
|
||||
externalStorageCreate,
|
||||
];
|
||||
});
|
||||
|
||||
it("doesn't wipe local docs when they exist on disk but not remote storage", async function() {
|
||||
const storageManager = new HostedStorageManager(...defaultParams);
|
||||
|
||||
const docId = "NewDoc";
|
||||
|
||||
const path = storageManager.getPath(docId);
|
||||
// Simulate an uploaded .grist file.
|
||||
await fse.writeFile(path, "");
|
||||
|
||||
await storageManager.prepareLocalDoc(docId);
|
||||
|
||||
assert.isTrue(await fse.pathExists(path));
|
||||
});
|
||||
|
||||
it("fetches remote docs if they don't exist locally", async function() {
|
||||
const testStore = new TestStore(
|
||||
tmpDir,
|
||||
workerId,
|
||||
docWorkerMap,
|
||||
externalStorageCreate
|
||||
);
|
||||
|
||||
let docName: string = "";
|
||||
let docPath: string = "";
|
||||
|
||||
await testStore.run(async () => {
|
||||
const newDoc = await testStore.docManager.createNewEmptyDoc(docSession, "NewRemoteDoc");
|
||||
docName = newDoc.docName;
|
||||
docPath = testStore.storageManager.getPath(docName);
|
||||
});
|
||||
|
||||
// This should be safe since testStore.run closes everything down.
|
||||
await fse.remove(docPath);
|
||||
assert.isFalse(await fse.pathExists(docPath));
|
||||
|
||||
await testStore.run(async () => {
|
||||
await testStore.docManager.fetchDoc(docSession, docName);
|
||||
});
|
||||
|
||||
assert.isTrue(await fse.pathExists(docPath));
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
// This is a performance test, to check if the backup settings are plausible.
|
||||
|
Loading…
Reference in New Issue
Block a user