1
0
mirror of https://github.com/gristlabs/grist-core.git synced 2024-10-27 20:44:07 +00:00
This commit is contained in:
Sven Hebrok 2024-10-24 08:35:04 +02:00 committed by GitHub
commit c747e8797c
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 98 additions and 2 deletions

12
.devcontainer/Dockerfile Normal file
View File

@ -0,0 +1,12 @@
FROM node:22-bookworm
RUN apt-get update && apt-get install -y python3.11 python3-pip pipx gdb
COPY sandbox/requirements3.txt package.json yarn.lock /grist/
RUN pip3 install --break-system-packages -r /grist/requirements3.txt
RUN yarn install --frozen-lockfile --verbose --network-timeout 600000
# absolutely bad idea normally, but I could not get python to attach to a running process otherwise
# it always failed with "ptrace: Operation not permitted."
RUN chmod u+s /usr/bin/gdb
ENV GRIST_HOST="0.0.0.0"

View File

@ -0,0 +1,44 @@
// For format details, see https://aka.ms/devcontainer.json. For config options, see the
// README at: https://github.com/devcontainers/templates/tree/main/src/docker-existing-dockerfile
{
"name": "Existing Dockerfile",
"build": {
// Sets the run context to one level up instead of the .devcontainer folder.
"context": "..",
// Update the 'dockerFile' property if you aren't using the standard 'Dockerfile' filename.
"dockerfile": "./Dockerfile"
},
"features": {
"ghcr.io/devcontainers/features/node:1": {
"nodeGypDependencies": true,
"installYarnUsingApt": true,
"version": "lts",
"pnpmVersion": "latest",
"nvmVersion": "latest"
},
"ghcr.io/devcontainers/features/python:1": {
"installTools": true,
"version": "os-provided"
}
},
// Features to add to the dev container. More info: https://containers.dev/features.
// "features": {},
// Use 'forwardPorts' to make a list of ports inside the container available locally.
"forwardPorts": [
8484
],
// Uncomment the next line to run commands after the container is created.
// "postCreateCommand": "cat /etc/os-release",
"postCreateCommand": "yarn install && yarn install:python",
// Configure tool-specific properties.
// "customizations": {},
// Uncomment to connect as an existing user other than the container default. More info: https://aka.ms/dev-containers-non-root.
"remoteUser": "node",
"capAdd": [
"SYS_PTRACE"
],
"securityOpt": [
"seccomp=unconfined",
"apparmor=unconfined",
],
}

View File

@ -2,6 +2,7 @@
* This module export a component for editing some document settings consisting of the timezone,
* (new settings to be added here ...).
*/
import * as AceEditor from 'app/client/components/AceEditor';
import {cssPrimarySmallLink, cssSmallButton, cssSmallLinkButton} from 'app/client/components/Forms/styles';
import {GristDoc} from 'app/client/components/GristDoc';
import {ACIndexImpl} from 'app/client/lib/ACIndex';
@ -41,6 +42,7 @@ export class DocSettingsPage extends Disposable {
private _timezone = this._docInfo.timezone;
private _locale: KoSaveableObservable<string> = this._docInfo.documentSettingsJson.prop('locale');
private _currency: KoSaveableObservable<string|undefined> = this._docInfo.documentSettingsJson.prop('currency');
private _customCode: KoSaveableObservable<string | undefined> = this._docInfo.documentSettingsJson.prop('customCode');
private _engine: Computed<EngineCode|undefined> = Computed.create(this, (
use => use(this._docInfo.documentSettingsJson.prop('engine'))
))
@ -85,6 +87,16 @@ export class DocSettingsPage extends Disposable {
{defaultCurrencyLabel: t("Local currency ({{currency}})", {currency: getCurrency(l)})})
)
}),
dom.create(AdminSectionItem, {
id: 'custom_code',
name: t('CustomCode'),
expandedContent: dom('div',
t('Custom python code to include when generating the model. Useful for defining custom functions.'),
AceEditor.create({ observable: this._customCode }).buildDom((aceObj: any) => {
aceObj.renderer.setShowGutter(true);
}),
),
}),
]),
dom.create(AdminSection, t('Data Engine'), [

View File

@ -2,6 +2,7 @@ export interface DocumentSettings {
locale: string;
currency?: string;
engine?: EngineCode;
customCode?: string;
}
/**

View File

@ -99,6 +99,13 @@ class DocActions(object):
("recalcWhen" in columns or "recalcDeps" in columns)):
self._engine.trigger_columns_changed()
# If we're updating documentSettings, rebuild usercode as the code might have changed.
if table_id == "_grist_DocInfo" and "documentSettings" in columns:
self._engine.rebuild_usercode()
for table in self._engine.tables.keys():
# I guess we invalidate everything, as we do not analyze in which regards the code may have changed :S
self._engine.invalidate_records(table)
def ReplaceTableData(self, table_id, row_ids, column_values):
old_data = self._engine.fetch_table(table_id, formulas=False)
self._engine.out_actions.undo.append(actions.ReplaceTableData(*old_data))

View File

@ -4,6 +4,7 @@ The data engine ties the code generated from the schema with the document data,
dependency tracking.
"""
import itertools
import json
import logging
import re
import rlcompleter
@ -346,6 +347,11 @@ class Engine(object):
# Add the records.
self.add_records(data.table_id, data.row_ids, columns)
if data.table_id == "_grist_DocInfo":
# when loading the DocInfo table, update the usercode module with the new doc settings.
# otherwise the custom code will not be loaded until the model is rebuilt due to other events.
self.rebuild_usercode()
def load_done(self):
"""
Finalizes the loading of data into this Engine.
@ -1137,7 +1143,14 @@ class Engine(object):
if not self._should_rebuild_usercode:
return
self.gencode.make_module(self.schema)
doc_info = None
try:
doc_info = self.docmodel.doc_info.lookupOne()
doc_settings = json.loads(doc_info.documentSettings)
except (AttributeError, ValueError) as e:
doc_settings = {"customCode": "## ERROR: " +
repr(e).replace("\n", "\n# ")}
self.gencode.make_module(self.schema, doc_settings)
# Re-populate self.tables, reusing existing tables whenever possible.
old_tables = self.tables

View File

@ -164,7 +164,7 @@ class GenCode(object):
return textbuilder.Combiner(parts)
def make_module(self, schema):
def make_module(self, schema, doc_settings):
"""Regenerates the code text and usercode module from updated document schema."""
# Collect summary tables to group them by source table.
summary_tables = {}
@ -176,6 +176,13 @@ class GenCode(object):
fullparts = ["import grist\n" +
"from functions import * # global uppercase functions\n" +
"import datetime, math, re # modules commonly needed in formulas\n"]
user_code = doc_settings.get('customCode', '')
if user_code:
fullparts.append("\n### BEGIN CUSTOM USER CODE ###\n")
fullparts.append(user_code)
fullparts.append("\n### END CUSTOM USER CODE ###\n")
userparts = fullparts[:]
for table_info in six.itervalues(schema):
fullparts.append("\n\n")