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
a3442aee77
132
README.md
132
README.md
@ -233,72 +233,72 @@ For more on Grist Labs' history and principles, see our [About Us](https://www.g
|
||||
|
||||
Grist can be configured in many ways. Here are the main environment variables it is sensitive to:
|
||||
|
||||
Variable | Purpose
|
||||
-------- | -------
|
||||
ALLOWED_WEBHOOK_DOMAINS | comma-separated list of permitted domains to use in webhooks (e.g. webhook.site,zapier.com). You can set this to `*` to allow all domains, but if doing so, we recommend using a carefully locked-down proxy (see `GRIST_HTTPS_PROXY`) if you do not entirely trust users. Otherwise services on your internal network may become vulnerable to manipulation.
|
||||
APP_DOC_URL | doc worker url, set when starting an individual doc worker (other servers will find doc worker urls via redis)
|
||||
APP_DOC_INTERNAL_URL | like `APP_DOC_URL` but used by the home server to reach the server using an internal domain name resolution (like in a docker environment). Defaults to `APP_DOC_URL`
|
||||
APP_HOME_URL | url prefix for home api (home and doc servers need this)
|
||||
APP_STATIC_URL | url prefix for static resources
|
||||
APP_STATIC_INCLUDE_CUSTOM_CSS | set to "true" to include custom.css (from APP_STATIC_URL) in static pages
|
||||
APP_UNTRUSTED_URL | URL at which to serve/expect plugin content.
|
||||
GRIST_ADAPT_DOMAIN | set to "true" to support multiple base domains (careful, host header should be trustworthy)
|
||||
GRIST_APP_ROOT | directory containing Grist sandbox and assets (specifically the sandbox and static subdirectories).
|
||||
GRIST_BACKUP_DELAY_SECS | wait this long after a doc change before making a backup
|
||||
GRIST_BOOT_KEY | if set, offer diagnostics at /boot/GRIST_BOOT_KEY
|
||||
GRIST_DATA_DIR | directory in which to store document caches.
|
||||
GRIST_DEFAULT_EMAIL | if set, login as this user if no other credentials presented
|
||||
GRIST_DEFAULT_PRODUCT | if set, this controls enabled features and limits of new sites. See names of PRODUCTS in Product.ts.
|
||||
GRIST_DEFAULT_LOCALE | Locale to use as fallback when Grist cannot honour the browser locale.
|
||||
GRIST_DOMAIN | in hosted Grist, Grist is served from subdomains of this domain. Defaults to "getgrist.com".
|
||||
GRIST_EXPERIMENTAL_PLUGINS | enables experimental plugins
|
||||
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_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.
|
||||
GRIST_INST_DIR | path to Grist instance configuration files, for Grist server.
|
||||
GRIST_LIST_PUBLIC_SITES | if set to true, sites shared with the public will be listed for anonymous users. Defaults to false.
|
||||
GRIST_MANAGED_WORKERS | if set, Grist can assume that if a url targeted at a doc worker returns a 404, that worker is gone
|
||||
GRIST_MAX_UPLOAD_ATTACHMENT_MB | max allowed size for attachments (0 or empty for unlimited).
|
||||
GRIST_MAX_UPLOAD_IMPORT_MB | max allowed size for imports (except .grist files) (0 or empty for unlimited).
|
||||
GRIST_OFFER_ALL_LANGUAGES | if set, all translated langauages are offered to the user (by default, only languages with a special 'good enough' key set are offered to user).
|
||||
GRIST_ORG_IN_PATH | if true, encode org in path rather than domain
|
||||
GRIST_PAGE_TITLE_SUFFIX | a string to append to the end of the `<title>` in HTML documents. Defaults to `" - Grist"`. Set to `_blank` for no suffix at all.
|
||||
~GRIST_PROXY_AUTH_HEADER~ | Deprecated, and interpreted as a synonym for GRIST_FORWARD_AUTH_HEADER.
|
||||
GRIST_ROUTER_URL | optional url for an api that allows servers to be (un)registered with a load balancer
|
||||
GRIST_SERVE_SAME_ORIGIN | set to "true" to access home server and doc workers on the same protocol-host-port as the top-level page, same as for custom domains (careful, host header should be trustworthy)
|
||||
GRIST_SERVERS | the types of server to setup. Comma separated values which may contain "home", "docs", static" and/or "app". Defaults to "home,docs,static".
|
||||
GRIST_SESSION_COOKIE | if set, overrides the name of Grist's cookie
|
||||
GRIST_SESSION_DOMAIN | if set, associates the cookie with the given domain - otherwise defaults to GRIST_DOMAIN
|
||||
GRIST_SESSION_SECRET | a key used to encode sessions
|
||||
GRIST_SKIP_BUNDLED_WIDGETS | if set, Grist will ignore any bundled widgets included via NPM packages.
|
||||
GRIST_ANON_PLAYGROUND | When set to 'false' deny anonymous users access to the home page
|
||||
GRIST_FORCE_LOGIN | Much like GRIST_ANON_PLAYGROUND but don't support anonymous access at all (features like sharing docs publicly requires authentication)
|
||||
GRIST_SINGLE_ORG | set to an org "domain" to pin client to that org
|
||||
GRIST_TEMPLATE_ORG | set to an org "domain" to show public docs from that org
|
||||
GRIST_HELP_CENTER | set the help center link ref
|
||||
FREE_COACHING_CALL_URL | set the link to the human help (example: email adress or meeting scheduling tool)
|
||||
GRIST_CONTACT_SUPPORT_URL | set the link to contact support on error pages (example: email adress or online form)
|
||||
GRIST_SUPPORT_ANON | if set to 'true', show UI for anonymous access (not shown by default)
|
||||
GRIST_SUPPORT_EMAIL | if set, give a user with the specified email support powers. The main extra power is the ability to share sites, workspaces, and docs with all users in a listed way.
|
||||
GRIST_TELEMETRY_LEVEL | the telemetry level. Can be set to: `off` (default), `limited`, or `full`.
|
||||
GRIST_THROTTLE_CPU | if set, CPU throttling is enabled
|
||||
GRIST_TRUST_PLUGINS | if set, plugins are expect to be served from the same host as the rest of the Grist app, rather than from a distinct host. Ordinarily, plugins are served from a distinct host so that the cookies used by the Grist app are not automatically available to them. Enable this only if you understand the security implications.
|
||||
GRIST_USER_ROOT | an extra path to look for plugins in - Grist will scan for plugins in `$GRIST_USER_ROOT/plugins`.
|
||||
GRIST_UI_FEATURES | comma-separated list of UI features to enable. Allowed names of parts: `helpCenter,billing,templates,createSite,multiSite,multiAccounts,sendToDrive,tutorials,supportGrist`. If a part also exists in GRIST_HIDE_UI_ELEMENTS, it won't be enabled.
|
||||
GRIST_UNTRUSTED_PORT | if set, plugins will be served from the given port. This is an alternative to setting APP_UNTRUSTED_URL.
|
||||
GRIST_WIDGET_LIST_URL | a url pointing to a widget manifest, by default `https://github.com/gristlabs/grist-widget/releases/download/latest/manifest.json` is used
|
||||
COOKIE_MAX_AGE | session cookie max age, defaults to 90 days; can be set to "none" to make it a session cookie
|
||||
HOME_PORT | port number to listen on for REST API server; if set to "share", add API endpoints to regular grist port.
|
||||
PORT | port number to listen on for Grist server
|
||||
REDIS_URL | optional redis server for browser sessions and db query caching
|
||||
GRIST_SKIP_REDIS_CHECKSUM_MISMATCH | Experimental. If set, only warn if the checksum in Redis differs with the one in your S3 backend storage. You may turn it on if your backend storage implements the [read-after-write consistency](https://aws.amazon.com/fr/blogs/aws/amazon-s3-update-strong-read-after-write-consistency/). Defaults to false.
|
||||
GRIST_SNAPSHOT_TIME_CAP | optional. Define the caps for tracking buckets. Usage: {"hour": 25, "day": 32, "isoWeek": 12, "month": 96, "year": 1000}
|
||||
GRIST_SNAPSHOT_KEEP | optional. Number of recent snapshots to retain unconditionally for a document, regardless of when they were made
|
||||
GRIST_PROMCLIENT_PORT | optional. If set, serve the Prometheus metrics on the specified port number. ⚠️ Be sure to use a port which is not publicly exposed ⚠️.
|
||||
| Variable | Purpose |
|
||||
|------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
||||
| ALLOWED_WEBHOOK_DOMAINS | comma-separated list of permitted domains to use in webhooks (e.g. webhook.site,zapier.com). You can set this to `*` to allow all domains, but if doing so, we recommend using a carefully locked-down proxy (see `GRIST_HTTPS_PROXY`) if you do not entirely trust users. Otherwise services on your internal network may become vulnerable to manipulation. |
|
||||
| APP_DOC_URL | doc worker url, set when starting an individual doc worker (other servers will find doc worker urls via redis) |
|
||||
| APP_DOC_INTERNAL_URL | like `APP_DOC_URL` but used by the home server to reach the server using an internal domain name resolution (like in a docker environment). Defaults to `APP_DOC_URL` |
|
||||
| APP_HOME_URL | url prefix for home api (home and doc servers need this) |
|
||||
| APP_STATIC_URL | url prefix for static resources |
|
||||
| APP_STATIC_INCLUDE_CUSTOM_CSS | set to "true" to include custom.css (from APP_STATIC_URL) in static pages |
|
||||
| APP_UNTRUSTED_URL | URL at which to serve/expect plugin content. |
|
||||
| GRIST_ADAPT_DOMAIN | set to "true" to support multiple base domains (careful, host header should be trustworthy) |
|
||||
| GRIST_APP_ROOT | directory containing Grist sandbox and assets (specifically the sandbox and static subdirectories). |
|
||||
| GRIST_BACKUP_DELAY_SECS | wait this long after a doc change before making a backup |
|
||||
| GRIST_BOOT_KEY | if set, offer diagnostics at /boot/GRIST_BOOT_KEY |
|
||||
| GRIST_DATA_DIR | Directory in which to store documents. Defaults to `docs/` relative to the Grist application directory. In Grist's default Docker image, its default value is /persist/docs so that it will be used as a mounted volume. |
|
||||
| GRIST_DEFAULT_EMAIL | if set, login as this user if no other credentials presented |
|
||||
| GRIST_DEFAULT_PRODUCT | if set, this controls enabled features and limits of new sites. See names of PRODUCTS in Product.ts. |
|
||||
| GRIST_DEFAULT_LOCALE | Locale to use as fallback when Grist cannot honour the browser locale. |
|
||||
| GRIST_DOMAIN | in hosted Grist, Grist is served from subdomains of this domain. Defaults to "getgrist.com". |
|
||||
| GRIST_EXPERIMENTAL_PLUGINS | enables experimental plugins |
|
||||
| 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_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. |
|
||||
| GRIST_INST_DIR | path to Grist instance configuration files, for Grist server. |
|
||||
| GRIST_LIST_PUBLIC_SITES | if set to true, sites shared with the public will be listed for anonymous users. Defaults to false. |
|
||||
| GRIST_MANAGED_WORKERS | if set, Grist can assume that if a url targeted at a doc worker returns a 404, that worker is gone |
|
||||
| GRIST_MAX_UPLOAD_ATTACHMENT_MB | max allowed size for attachments (0 or empty for unlimited). |
|
||||
| GRIST_MAX_UPLOAD_IMPORT_MB | max allowed size for imports (except .grist files) (0 or empty for unlimited). |
|
||||
| GRIST_OFFER_ALL_LANGUAGES | if set, all translated langauages are offered to the user (by default, only languages with a special 'good enough' key set are offered to user). |
|
||||
| GRIST_ORG_IN_PATH | if true, encode org in path rather than domain |
|
||||
| GRIST_PAGE_TITLE_SUFFIX | a string to append to the end of the `<title>` in HTML documents. Defaults to `" - Grist"`. Set to `_blank` for no suffix at all. |
|
||||
| ~GRIST_PROXY_AUTH_HEADER~ | Deprecated, and interpreted as a synonym for GRIST_FORWARD_AUTH_HEADER. |
|
||||
| GRIST_ROUTER_URL | optional url for an api that allows servers to be (un)registered with a load balancer |
|
||||
| GRIST_SERVE_SAME_ORIGIN | set to "true" to access home server and doc workers on the same protocol-host-port as the top-level page, same as for custom domains (careful, host header should be trustworthy) |
|
||||
| GRIST_SERVERS | the types of server to setup. Comma separated values which may contain "home", "docs", static" and/or "app". Defaults to "home,docs,static". |
|
||||
| GRIST_SESSION_COOKIE | if set, overrides the name of Grist's cookie |
|
||||
| GRIST_SESSION_DOMAIN | if set, associates the cookie with the given domain - otherwise defaults to GRIST_DOMAIN |
|
||||
| GRIST_SESSION_SECRET | a key used to encode sessions |
|
||||
| GRIST_SKIP_BUNDLED_WIDGETS | if set, Grist will ignore any bundled widgets included via NPM packages. |
|
||||
| GRIST_ANON_PLAYGROUND | When set to 'false' deny anonymous users access to the home page |
|
||||
| GRIST_FORCE_LOGIN | Much like GRIST_ANON_PLAYGROUND but don't support anonymous access at all (features like sharing docs publicly requires authentication) |
|
||||
| GRIST_SINGLE_ORG | set to an org "domain" to pin client to that org |
|
||||
| GRIST_TEMPLATE_ORG | set to an org "domain" to show public docs from that org |
|
||||
| GRIST_HELP_CENTER | set the help center link ref |
|
||||
| FREE_COACHING_CALL_URL | set the link to the human help (example: email adress or meeting scheduling tool) |
|
||||
| GRIST_CONTACT_SUPPORT_URL | set the link to contact support on error pages (example: email adress or online form) |
|
||||
| GRIST_SUPPORT_ANON | if set to 'true', show UI for anonymous access (not shown by default) |
|
||||
| GRIST_SUPPORT_EMAIL | if set, give a user with the specified email support powers. The main extra power is the ability to share sites, workspaces, and docs with all users in a listed way. |
|
||||
| GRIST_TELEMETRY_LEVEL | the telemetry level. Can be set to: `off` (default), `limited`, or `full`. |
|
||||
| GRIST_THROTTLE_CPU | if set, CPU throttling is enabled |
|
||||
| GRIST_TRUST_PLUGINS | if set, plugins are expect to be served from the same host as the rest of the Grist app, rather than from a distinct host. Ordinarily, plugins are served from a distinct host so that the cookies used by the Grist app are not automatically available to them. Enable this only if you understand the security implications. |
|
||||
| GRIST_USER_ROOT | an extra path to look for plugins in - Grist will scan for plugins in `$GRIST_USER_ROOT/plugins`. |
|
||||
| GRIST_UI_FEATURES | comma-separated list of UI features to enable. Allowed names of parts: `helpCenter,billing,templates,createSite,multiSite,multiAccounts,sendToDrive,tutorials,supportGrist`. If a part also exists in GRIST_HIDE_UI_ELEMENTS, it won't be enabled. |
|
||||
| GRIST_UNTRUSTED_PORT | if set, plugins will be served from the given port. This is an alternative to setting APP_UNTRUSTED_URL. |
|
||||
| GRIST_WIDGET_LIST_URL | a url pointing to a widget manifest, by default `https://github.com/gristlabs/grist-widget/releases/download/latest/manifest.json` is used |
|
||||
| COOKIE_MAX_AGE | session cookie max age, defaults to 90 days; can be set to "none" to make it a session cookie |
|
||||
| HOME_PORT | port number to listen on for REST API server; if set to "share", add API endpoints to regular grist port. |
|
||||
| PORT | port number to listen on for Grist server |
|
||||
| REDIS_URL | optional redis server for browser sessions and db query caching |
|
||||
| GRIST_SKIP_REDIS_CHECKSUM_MISMATCH | Experimental. If set, only warn if the checksum in Redis differs with the one in your S3 backend storage. You may turn it on if your backend storage implements the [read-after-write consistency](https://aws.amazon.com/fr/blogs/aws/amazon-s3-update-strong-read-after-write-consistency/). Defaults to false. |
|
||||
| GRIST_SNAPSHOT_TIME_CAP | optional. Define the caps for tracking buckets. Usage: {"hour": 25, "day": 32, "isoWeek": 12, "month": 96, "year": 1000} |
|
||||
| GRIST_SNAPSHOT_KEEP | optional. Number of recent snapshots to retain unconditionally for a document, regardless of when they were made |
|
||||
| GRIST_PROMCLIENT_PORT | optional. If set, serve the Prometheus metrics on the specified port number. ⚠️ Be sure to use a port which is not publicly exposed ⚠️. |
|
||||
|
||||
#### AI Formula Assistant related variables (all optional):
|
||||
|
||||
|
@ -6,6 +6,7 @@ import {AppModel, reportError} from 'app/client/models/AppModel';
|
||||
import {IProgress} from 'app/client/models/NotifyModel';
|
||||
import {openFilePicker} from 'app/client/ui/FileDialog';
|
||||
import {byteString} from 'app/common/gutil';
|
||||
import { AxiosProgressEvent } from 'axios';
|
||||
import {Disposable} from 'grainjs';
|
||||
|
||||
/**
|
||||
@ -39,9 +40,9 @@ export async function fileImport(
|
||||
const timezone = await guessTimezone();
|
||||
|
||||
if (workspaceId === "unsaved") {
|
||||
function onUploadProgress(ev: ProgressEvent) {
|
||||
if (ev.lengthComputable) {
|
||||
progress.setUploadProgress(ev.loaded / ev.total * 100); // percentage complete
|
||||
function onUploadProgress(ev: AxiosProgressEvent) {
|
||||
if (ev.event.lengthComputable) {
|
||||
progress.setUploadProgress(ev.event.loaded / ev.event.total * 100); // percentage complete
|
||||
}
|
||||
}
|
||||
return await app.api.importUnsavedDoc(files[0], {timezone, onUploadProgress});
|
||||
|
@ -22,6 +22,7 @@ import {
|
||||
WebhookUpdate
|
||||
} from 'app/common/Triggers';
|
||||
import {addCurrentOrgToPath, getGristConfig} from 'app/common/urlUtils';
|
||||
import { AxiosProgressEvent } from 'axios';
|
||||
import omitBy from 'lodash/omitBy';
|
||||
|
||||
|
||||
@ -405,7 +406,7 @@ export interface UserAPI {
|
||||
importUnsavedDoc(material: UploadType, options?: {
|
||||
filename?: string,
|
||||
timezone?: string,
|
||||
onUploadProgress?: (ev: ProgressEvent) => void,
|
||||
onUploadProgress?: (ev: AxiosProgressEvent) => void,
|
||||
}): Promise<string>;
|
||||
deleteUser(userId: number, name: string): Promise<void>;
|
||||
getBaseUrl(): string; // Get the prefix for all the endpoints this object wraps.
|
||||
@ -826,7 +827,7 @@ export class UserAPIImpl extends BaseAPI implements UserAPI {
|
||||
public async importUnsavedDoc(material: UploadType, options?: {
|
||||
filename?: string,
|
||||
timezone?: string,
|
||||
onUploadProgress?: (ev: ProgressEvent) => void,
|
||||
onUploadProgress?: (ev: AxiosProgressEvent) => void,
|
||||
}): Promise<string> {
|
||||
options = options || {};
|
||||
const formData = this.newFormData();
|
||||
|
@ -132,7 +132,7 @@ export class MinIOExternalStorage implements ExternalStorage {
|
||||
v.lastModified && (v as any).versionId &&
|
||||
(options?.includeDeleteMarkers || !(v as any).isDeleteMarker))
|
||||
.map(v => ({
|
||||
lastModified: v.lastModified.toISOString(),
|
||||
lastModified: v.lastModified!.toISOString(),
|
||||
// Circumvent inconsistency of MinIO API with versionId by casting it to string
|
||||
// PR to MinIO so we don't have to do that anymore:
|
||||
// https://github.com/minio/minio-js/pull/1193
|
||||
|
@ -74,6 +74,10 @@ module.exports = {
|
||||
{ test: /\.js$/,
|
||||
use: ["source-map-loader"],
|
||||
enforce: "pre"
|
||||
},
|
||||
{
|
||||
test: /\.css$/,
|
||||
type: 'asset/resource'
|
||||
}
|
||||
]
|
||||
},
|
||||
|
22
package.json
22
package.json
@ -87,14 +87,14 @@
|
||||
"@typescript-eslint/eslint-plugin": "5.29.0",
|
||||
"@typescript-eslint/parser": "5.29.0",
|
||||
"app-module-path": "2.2.0",
|
||||
"catw": "1.0.1",
|
||||
"chai": "4.2.0",
|
||||
"chai-as-promised": "7.1.1",
|
||||
"chance": "1.0.16",
|
||||
"chokidar-cli": "3.0.0",
|
||||
"esbuild-loader": "2.19.0",
|
||||
"eslint": "8.18.0",
|
||||
"http-proxy": "1.18.1",
|
||||
"i18next-scanner": "4.1.0",
|
||||
"i18next-scanner": "4.4.0",
|
||||
"mocha": "10.2.0",
|
||||
"mocha-webdriver": "0.3.2",
|
||||
"moment-locales-webpack-plugin": "^1.2.0",
|
||||
@ -106,7 +106,7 @@
|
||||
"tmp-promise": "1.0.5",
|
||||
"ts-interface-builder": "0.3.2",
|
||||
"typescript": "4.7.4",
|
||||
"webpack": "5.73.0",
|
||||
"webpack": "5.91.0",
|
||||
"webpack-cli": "4.10.0",
|
||||
"why-is-node-running": "2.0.3"
|
||||
},
|
||||
@ -123,9 +123,9 @@
|
||||
"accept-language-parser": "1.5.0",
|
||||
"ace-builds": "1.23.3",
|
||||
"async-mutex": "0.2.4",
|
||||
"axios": "0.21.2",
|
||||
"axios": "1.6.8",
|
||||
"backbone": "1.3.3",
|
||||
"bootstrap": "3.3.5",
|
||||
"bootstrap": "3.4.1",
|
||||
"bootstrap-datepicker": "1.9.0",
|
||||
"bowser": "2.7.0",
|
||||
"collect-js-deps": "^0.1.1",
|
||||
@ -135,7 +135,7 @@
|
||||
"connect-redis": "3.4.0",
|
||||
"cookie": "0.5.0",
|
||||
"cookie-parser": "1.4.3",
|
||||
"csv": "4.0.0",
|
||||
"csv": "6.3.8",
|
||||
"currency-symbol-map": "5.1.0",
|
||||
"diff-match-patch": "1.0.5",
|
||||
"dompurify": "3.0.6",
|
||||
@ -143,7 +143,7 @@
|
||||
"engine.io": "^6.5.4",
|
||||
"engine.io-client": "^6.5.3",
|
||||
"exceljs": "4.2.1",
|
||||
"express": "4.18.2",
|
||||
"express": "4.19.2",
|
||||
"file-type": "16.5.4",
|
||||
"fs-extra": "7.0.0",
|
||||
"grain-rpc": "0.1.7",
|
||||
@ -160,12 +160,12 @@
|
||||
"js-yaml": "3.14.1",
|
||||
"jsdom": "^23.0.0",
|
||||
"jsesc": "3.0.2",
|
||||
"jsonwebtoken": "8.3.0",
|
||||
"jsonwebtoken": "9.0.2",
|
||||
"knockout": "3.5.0",
|
||||
"locale-currency": "0.0.2",
|
||||
"lodash": "4.17.21",
|
||||
"marked": "4.2.12",
|
||||
"minio": "7.0.32",
|
||||
"minio": "7.1.3",
|
||||
"moment": "2.29.4",
|
||||
"moment-timezone": "0.5.35",
|
||||
"morgan": "1.9.1",
|
||||
@ -184,13 +184,13 @@
|
||||
"randomcolor": "0.5.3",
|
||||
"redis": "3.1.1",
|
||||
"redlock": "3.1.2",
|
||||
"saml2-js": "2.0.5",
|
||||
"saml2-js": "4.0.2",
|
||||
"short-uuid": "3.1.1",
|
||||
"slugify": "1.6.6",
|
||||
"swagger-ui-dist": "5.11.0",
|
||||
"tmp": "0.0.33",
|
||||
"ts-interface-checker": "1.0.2",
|
||||
"typeorm": "0.3.9",
|
||||
"typeorm": "0.3.20",
|
||||
"underscore": "1.12.1",
|
||||
"uuid": "3.3.2",
|
||||
"winston": "2.4.5",
|
||||
|
@ -16,7 +16,9 @@ if [ ! -e _build ]; then
|
||||
fi
|
||||
|
||||
tsc --build -w --preserveWatchOutput $PROJECT &
|
||||
catw app/client/*.css app/client/*/*.css -o static/bundle.css -v & webpack --config $WEBPACK_CONFIG --mode development --watch &
|
||||
css_files="app/client/**/*.css"
|
||||
chokidar "${css_files}" -c "bash -O globstar -c 'cat ${css_files} > static/bundle.css'" &
|
||||
webpack --config $WEBPACK_CONFIG --mode development --watch &
|
||||
NODE_PATH=_build:_build/stubs:_build/ext nodemon ${NODE_INSPECT:+--inspect} --delay 1 -w _build/app/server -w _build/app/common _build/stubs/app/server/server.js &
|
||||
|
||||
wait
|
||||
|
@ -207,12 +207,12 @@
|
||||
"Duplicate Table": "Dupliquer la table",
|
||||
"You do not have edit access to this document": "Vous n’avez pas accès en écriture à ce document",
|
||||
"Delete {{formattedTableName}} data, and remove it from all pages?": "Supprimer les données de {{formattedTableName}} et les supprimer de toutes les pages ?",
|
||||
"Edit Record Card": "Modifier la vue carte",
|
||||
"Edit Record Card": "Modifier la vue fiche",
|
||||
"Rename Table": "Renommer la table",
|
||||
"{{action}} Record Card": "{{action}} la vue carte",
|
||||
"Record Card": "Vue carte",
|
||||
"{{action}} Record Card": "{{action}} la vue fiche",
|
||||
"Record Card": "Vue fiche",
|
||||
"Remove Table": "Supprimer la table",
|
||||
"Record Card Disabled": "Vue carte désactivée"
|
||||
"Record Card Disabled": "Vue fiche désactivée"
|
||||
},
|
||||
"DocHistory": {
|
||||
"Activity": "Activité",
|
||||
@ -478,7 +478,8 @@
|
||||
"Welcome to {{- orgName}}": "Bienvenue sur {{- orgName}}",
|
||||
"Visit our {{link}} to learn more about Grist.": "Visitez notre {{link}} pour en savoir plus sur Grist.",
|
||||
"Sign in": "Connexion",
|
||||
"To use Grist, please either sign up or sign in.": "Pour utiliser Grist, connectez-vous ou créez-vous un compte."
|
||||
"To use Grist, please either sign up or sign in.": "Pour utiliser Grist, connectez-vous ou créez-vous un compte.",
|
||||
"Learn more in our {{helpCenterLink}}, or find an expert via our {{sproutsProgram}}.": "Pour en savoir plus, consultez notre {{helpCenterLink}}, ou trouvez un expert via notre {{sproutsProgram}}."
|
||||
},
|
||||
"HomeLeftPane": {
|
||||
"All Documents": "Tous les documents",
|
||||
@ -665,7 +666,7 @@
|
||||
"Duplicate rows_other": "Dupliquer les lignes",
|
||||
"Delete": "Supprimer",
|
||||
"Copy anchor link": "Copier l'ancre",
|
||||
"View as card": "Voir en carte",
|
||||
"View as card": "Voir en fiche",
|
||||
"Use as table headers": "Utiliser en tant qu'en-têtes de table"
|
||||
},
|
||||
"SelectionSummary": {
|
||||
@ -694,7 +695,10 @@
|
||||
"Share": "Partager",
|
||||
"Download...": "Télécharger...",
|
||||
"Microsoft Excel (.xlsx)": "Microsoft Excel (.xlsx)",
|
||||
"Export as...": "Exporter en tant que..."
|
||||
"Export as...": "Exporter en tant que...",
|
||||
"Comma Separated Values (.csv)": "Comma Separated Values (.csv)",
|
||||
"DOO Separated Values (.dsv)": "DOO Separated Values (.dsv)",
|
||||
"Tab Separated Values (.tsv)": "Tab Separated Values (.tsv)"
|
||||
},
|
||||
"SiteSwitcher": {
|
||||
"Switch Sites": "Changer d’espace",
|
||||
@ -776,7 +780,7 @@
|
||||
"Form": "Formulaire",
|
||||
"Compact": "Compact",
|
||||
"Blocks": "Blocs",
|
||||
"Edit Card Layout": "Disposition de la carte",
|
||||
"Edit Card Layout": "Disposition de la fiche",
|
||||
"Plugin: ": "Plugin : ",
|
||||
"Section: ": "Section : "
|
||||
},
|
||||
@ -787,7 +791,7 @@
|
||||
"Print widget": "Imprimer la vue",
|
||||
"Download as CSV": "Télécharger en CSV",
|
||||
"Download as XLSX": "Télécharger en XLSX",
|
||||
"Edit Card Layout": "Disposition de la carte",
|
||||
"Edit Card Layout": "Disposition de la fiche",
|
||||
"Widget options": "Options de la vue",
|
||||
"Advanced Sort & Filter": "Tri et filtre avancés",
|
||||
"Data selection": "Sélection des données",
|
||||
@ -931,7 +935,11 @@
|
||||
},
|
||||
"NTextBox": {
|
||||
"false": "faux",
|
||||
"true": "vrai"
|
||||
"true": "vrai",
|
||||
"Single line": "Ligne unique",
|
||||
"Multi line": "Multi-lignes",
|
||||
"Lines": "Lignes",
|
||||
"Field Format": "Format du champ"
|
||||
},
|
||||
"ViewAsDropdown": {
|
||||
"View As": "Voir en tant que",
|
||||
@ -1002,7 +1010,7 @@
|
||||
"Make it relational! Use the {{ref}} type to link tables. ": "Rendez-le relationnel ! Utilisez le type {{ref}} pour lier les tableaux. ",
|
||||
"Toggle the {{creatorPanel}} to format columns, ": "Ouvrez le {{creatorPanel}} pour formater les colonnes ",
|
||||
"Use {{addNew}} to add widgets, pages, or import more data. ": "Cliquez sur {{addNew}} pour ajouter des vues, des pages ou importer plus de données. ",
|
||||
"convert to card view, select data, and more.": "convertir en vue carte, sélectionner des données et plus.",
|
||||
"convert to card view, select data, and more.": "convertir en vue fiche, sélectionner des données et plus.",
|
||||
"Set formatting options, formulas, or column types, such as dates, choices, or attachments. ": "Définissez des options de formatage de la colonne, des formules ou bien les types de la colonne (dates, liste à choix unique, pièce jointe etc.) ",
|
||||
"Use {{helpCenter}} for documentation or questions.": "Cliquez sur {{helpCenter}} pour voir la documentation et poser vos questions.",
|
||||
"creator panel": "menu latéral"
|
||||
@ -1065,7 +1073,11 @@
|
||||
"Decimals": "Décimales",
|
||||
"Currency": "Devise",
|
||||
"Default currency ({{defaultCurrency}})": "Devise par défaut ({{defaultCurrency}})",
|
||||
"Number Format": "Format de nombre"
|
||||
"Number Format": "Format de nombre",
|
||||
"min": "min",
|
||||
"Text": "Texte",
|
||||
"max": "max",
|
||||
"Field Format": "Format du champ"
|
||||
},
|
||||
"LanguageMenu": {
|
||||
"Language": "Langue"
|
||||
@ -1092,12 +1104,12 @@
|
||||
"Only those rows will appear which match all of the filters.": "Seules les lignes qui correspondent à tous les filtres apparaîtront.",
|
||||
"Select the table to link to.": "Sélectionnez la table vers laquelle vous souhaitez établir un lien.",
|
||||
"Selecting Data": "Sélection de données",
|
||||
"Rearrange the fields in your card by dragging and resizing cells.": "Réorganisez les champs de votre vue carte en faisant glisser et en redimensionnant les cellules.",
|
||||
"Rearrange the fields in your card by dragging and resizing cells.": "Réorganisez les champs de votre vue fiche en faisant glisser et en redimensionnant les cellules.",
|
||||
"The Raw Data page lists all data tables in your document, including summary tables and tables not included in page layouts.": "La page des données sources liste toutes les tables de votre document, y compris les tables récapitulatives et les tables non-inclues dans les mises en page.",
|
||||
"The total size of all data in this document, excluding attachments.": "La taille totale de toutes les données de ce document, à l'exclusion des pièces jointes.",
|
||||
"Click the Add New button to create new documents or workspaces, or import data.": "Cliquez sur le bouton Nouveau pour créer de nouveaux documents dans votre espace de travail ou importer des données.",
|
||||
"Clicking {{EyeHideIcon}} in each cell hides the field from this view without deleting it.": "En cliquant sur {{EyeHideIcon}} dans chaque cellule, vous masquez le champ de cette vue sans le supprimer.",
|
||||
"Editing Card Layout": "Modification de la mise en page de la carte",
|
||||
"Editing Card Layout": "Modification de la mise en page de la fiche",
|
||||
"Linking Widgets": "Lier les vues",
|
||||
"Nested Filtering": "Filtrage imbriqué",
|
||||
"Pinned filters are displayed as buttons above the widget.": "Les filtres épinglés sont affichés sous forme de boutons au-dessus de la vue.",
|
||||
@ -1230,7 +1242,8 @@
|
||||
"Opt in to Telemetry": "S'inscrire à l'envoi de données de télémétrie",
|
||||
"Opted In": "Accepté",
|
||||
"Support Grist page": "Soutenir Grist",
|
||||
"Admin Panel": "Panneau d'administration"
|
||||
"Admin Panel": "Panneau d'administration",
|
||||
"Thank you! Your trust and support is greatly appreciated. Opt out any time from the {{link}} in the user menu.": "Nous vous remercions ! Votre confiance et votre soutien sont très appréciés. Vous pouvez vous désinscrire à tout moment en cliquant sur le {{link}} dans le menu utilisateur."
|
||||
},
|
||||
"GridView": {
|
||||
"Click to insert": "Cliquer pour insérer"
|
||||
@ -1327,12 +1340,12 @@
|
||||
"You have access to the following Grist sites.": "Vous avez accès aux espaces Grist suivants."
|
||||
},
|
||||
"CardContextMenu": {
|
||||
"Insert card above": "Insérer une carte au dessus",
|
||||
"Duplicate card": "Dupliquer la carte",
|
||||
"Insert card below": "Insérer une carte en dessous",
|
||||
"Delete card": "Supprimer la carte",
|
||||
"Insert card above": "Insérer une fiche au dessus",
|
||||
"Duplicate card": "Dupliquer la fiche",
|
||||
"Insert card below": "Insérer une fiche en dessous",
|
||||
"Delete card": "Supprimer la fiche",
|
||||
"Copy anchor link": "Copier le lien d'ancrage",
|
||||
"Insert card": "Insérer une carte"
|
||||
"Insert card": "Insérer une fiche"
|
||||
},
|
||||
"WelcomeCoachingCall": {
|
||||
"Maybe Later": "Peut-être plus tard",
|
||||
@ -1387,7 +1400,17 @@
|
||||
},
|
||||
"FormConfig": {
|
||||
"Field rules": "Règles du champ",
|
||||
"Required field": "Champ obligatoire"
|
||||
"Required field": "Champ obligatoire",
|
||||
"Ascending": "Croissant",
|
||||
"Default": "Par défaut",
|
||||
"Descending": "Décroissant",
|
||||
"Field Format": "Format du champ",
|
||||
"Field Rules": "Règles du champ",
|
||||
"Horizontal": "Horizontale",
|
||||
"Options Alignment": "Option d'alignement",
|
||||
"Options Sort Order": "Option d'ordonnancement",
|
||||
"Vertical": "Verticale",
|
||||
"Radio": "Radio"
|
||||
},
|
||||
"Editor": {
|
||||
"Delete": "Supprimer"
|
||||
@ -1414,7 +1437,8 @@
|
||||
},
|
||||
"FormSuccessPage": {
|
||||
"Form Submitted": "Formulaire envoyé",
|
||||
"Thank you! Your response has been recorded.": "Nous vous remercions. Votre réponse a été enregistrée."
|
||||
"Thank you! Your response has been recorded.": "Nous vous remercions. Votre réponse a été enregistrée.",
|
||||
"Submit new response": "Soumettre une nouvelle réponse"
|
||||
},
|
||||
"DateRangeOptions": {
|
||||
"Last 30 days": "30 derniers jours",
|
||||
@ -1449,5 +1473,29 @@
|
||||
"Sponsor": "Parrainage",
|
||||
"Support Grist": "Soutenir Grist",
|
||||
"Version": "Version"
|
||||
},
|
||||
"Field": {
|
||||
"No choices configured": "Aucun choix configuré",
|
||||
"No values in show column of referenced table": "Pas de valeurs dans la colonne montrée de la table de référence"
|
||||
},
|
||||
"CreateTeamModal": {
|
||||
"Cancel": "Annuler",
|
||||
"Choose a name and url for your team site": "Choisissez un nom et une adresse URL pour votre espace d'équipe",
|
||||
"Create site": "Créer",
|
||||
"Domain name is invalid": "Le nom de domaine n'est pas valide",
|
||||
"Domain name is required": "Le nom de domaine est requis",
|
||||
"Go to your site": "Aller vers votre espace d'équipe",
|
||||
"Team name": "Nom de l'espace d'équipe",
|
||||
"Team site created": "L'espace d'équipe a été créé",
|
||||
"Team url": "Url de l'espace d'équipe",
|
||||
"Work as a Team": "Travailler en équipe",
|
||||
"Billing is not supported in grist-core": "La facturation n'est pas prise en charge dans un Grist auto hébergé",
|
||||
"Team name is required": "Le nom de l'espace d'équipe est requis"
|
||||
},
|
||||
"Toggle": {
|
||||
"Field Format": "Format du champ"
|
||||
},
|
||||
"Columns": {
|
||||
"Remove Column": "Supprimer la colonne"
|
||||
}
|
||||
}
|
||||
|
@ -1274,7 +1274,7 @@
|
||||
"User inherits permissions from {{parent}}. To remove, set 'Inherit access' option to 'None'.": "Пользователь наследует разрешения от {{parent}}. Чтобы удалить, установите для параметра 'Наследовать доступ' значение 'None'.",
|
||||
"Allow anyone with the link to open.": "Разрешить открывать всем, у кого есть ссылка.",
|
||||
"Grist support": "Grist поддержка",
|
||||
"Invite people to {{resourceType}}": "Пригласите людей в {{resourceType}}",
|
||||
"Invite people to {{resourceType}}": "Пригласите людей к {{resourceType}}",
|
||||
"Create a team to share with more people": "Создайте команду, чтобы поделиться с большим количеством людей",
|
||||
"Link copied to clipboard": "Ссылка скопирована в буфер обмена",
|
||||
"No default access allows access to be granted to individual documents or workspaces, rather than the full team site.": "Отсутствие доступа по умолчанию позволяет предоставлять доступ к отдельным документам или рабочим областям, а не ко всему групповому сайту.",
|
||||
|
@ -31,7 +31,7 @@ import { ActiveDoc, Deps as ActiveDocDeps } from "app/server/lib/ActiveDoc";
|
||||
import { DEPS, sendForCompletion } from "app/server/lib/Assistance";
|
||||
import log from 'app/server/lib/log';
|
||||
import crypto from 'crypto';
|
||||
import parse from 'csv-parse/lib/sync';
|
||||
import { parse } from 'csv-parse/sync';
|
||||
import fetch, {RequestInfo, RequestInit, Response} from 'node-fetch';
|
||||
import * as fs from "fs";
|
||||
import JSZip from "jszip";
|
||||
|
@ -254,7 +254,7 @@ export class TestSession {
|
||||
) {
|
||||
const resp = await axios.get(`${this.home.getOwnUrl()}/test/session`,
|
||||
{validateStatus: (s => s < 400), headers: this.headers});
|
||||
const cookie = this.headers.Cookie || resp.headers['set-cookie'][0];
|
||||
const cookie = this.headers.Cookie || resp.headers['set-cookie']![0];
|
||||
const cid = decodeURIComponent(cookie.split('=')[1].split(';')[0]);
|
||||
const sessionId = this.home.getSessions().getSessionIdFromCookie(cid);
|
||||
const scopedSession = this.home.getSessions().getOrCreateSession(sessionId as string, org, '');
|
||||
|
@ -21,7 +21,7 @@ export function configForUser(username: string): AxiosRequestConfig {
|
||||
}
|
||||
};
|
||||
if (username !== 'Anonymous') {
|
||||
config.headers.Authorization = 'Bearer api_key_for_' + username.toLowerCase();
|
||||
config.headers!.Authorization = 'Bearer api_key_for_' + username.toLowerCase();
|
||||
}
|
||||
return config;
|
||||
}
|
||||
|
@ -166,7 +166,7 @@ export async function openClient(server: FlexServer, email: string, org: string,
|
||||
const headers: Record<string, string> = {};
|
||||
if (!emailHeader) {
|
||||
const resp = await axios.get(`${server.getOwnUrl()}/test/session`);
|
||||
const cookie = resp.headers['set-cookie'][0];
|
||||
const cookie = resp.headers['set-cookie']![0];
|
||||
if (email !== 'anon@getgrist.com') {
|
||||
const cid = decodeURIComponent(cookie.split('=')[1].split(';')[0]);
|
||||
const comm = server.getComm();
|
||||
|
@ -1351,10 +1351,10 @@ function testDocApi() {
|
||||
}
|
||||
} else {
|
||||
if (sort) {
|
||||
config.headers['x-sort'] = sort.join(',');
|
||||
config.headers!['x-sort'] = sort.join(',');
|
||||
}
|
||||
if (limit) {
|
||||
config.headers['x-limit'] = String(limit);
|
||||
config.headers!['x-limit'] = String(limit);
|
||||
}
|
||||
}
|
||||
return axios.get(url.href, config);
|
||||
@ -4976,11 +4976,11 @@ function testDocApi() {
|
||||
|
||||
const chimpyConfig = configForUser("Chimpy");
|
||||
const anonConfig = configForUser("Anonymous");
|
||||
delete chimpyConfig.headers["X-Requested-With"];
|
||||
delete anonConfig.headers["X-Requested-With"];
|
||||
delete chimpyConfig.headers!["X-Requested-With"];
|
||||
delete anonConfig.headers!["X-Requested-With"];
|
||||
|
||||
// Target a more realistic Host than "localhost:port"
|
||||
anonConfig.headers.Host = chimpyConfig.headers.Host = 'api.example.com';
|
||||
anonConfig.headers!.Host = chimpyConfig.headers!.Host = 'api.example.com';
|
||||
|
||||
const url = `${serverUrl}/api/docs/${docId}/tables/Table1/records`;
|
||||
const data = { records: [{ fields: {} }] };
|
||||
@ -4989,7 +4989,7 @@ function testDocApi() {
|
||||
const forbiddenOrigin = 'http://evil.com';
|
||||
|
||||
// Normal same origin requests
|
||||
anonConfig.headers.Origin = allowedOrigin;
|
||||
anonConfig.headers!.Origin = allowedOrigin;
|
||||
let response: AxiosResponse;
|
||||
for (response of [
|
||||
await axios.post(url, data, anonConfig),
|
||||
@ -5005,7 +5005,7 @@ function testDocApi() {
|
||||
|
||||
// Cross origin requests from untrusted origin.
|
||||
for (const config of [anonConfig, chimpyConfig]) {
|
||||
config.headers.Origin = forbiddenOrigin;
|
||||
config.headers!.Origin = forbiddenOrigin;
|
||||
for (response of [
|
||||
await axios.post(url, data, config),
|
||||
await axios.get(url, config),
|
||||
|
@ -28,6 +28,12 @@ describe('ManyFetches', function() {
|
||||
let docs: TestServer;
|
||||
let userApi: UserAPIImpl;
|
||||
|
||||
before(function () {
|
||||
if (!process.env.TEST_REDIS_URL) {
|
||||
return this.skip();
|
||||
}
|
||||
});
|
||||
|
||||
beforeEach(async function() {
|
||||
oldEnv = new EnvironmentSnapshot(); // Needed for prepareDatabase, which changes process.env
|
||||
log.info("Starting servers");
|
||||
|
Loading…
Reference in New Issue
Block a user