From 1e7cf9001e7df919699ad1643789a5d3858c17c9 Mon Sep 17 00:00:00 2001 From: Florent Date: Tue, 13 Jun 2023 17:13:07 +0200 Subject: [PATCH 1/6] Remove unused GRIST_EXT env variable #531 (#532) Co-authored-by: Florent FAYOLLE --- buildtools/build.sh | 1 - sandbox/watch.sh | 1 - 2 files changed, 2 deletions(-) diff --git a/buildtools/build.sh b/buildtools/build.sh index 0571eaa5..c87643a6 100755 --- a/buildtools/build.sh +++ b/buildtools/build.sh @@ -3,7 +3,6 @@ set -e PROJECT="" -export GRIST_EXT=stubs if [[ -e ext/app ]]; then PROJECT="tsconfig-ext.json" fi diff --git a/sandbox/watch.sh b/sandbox/watch.sh index d8b8d642..ae77fcd3 100755 --- a/sandbox/watch.sh +++ b/sandbox/watch.sh @@ -3,7 +3,6 @@ set -x PROJECT="" -export GRIST_EXT=stubs if [[ -e ext/app ]]; then PROJECT="tsconfig-ext.json" fi From 3d808f67f1b03dfbbd17f87bce538a6ec4815cab Mon Sep 17 00:00:00 2001 From: Florent Date: Tue, 13 Jun 2023 19:14:01 +0200 Subject: [PATCH 2/6] Visually identify that a field is a drop-down list (single choice) #491 (#525) * Visually identify that a field is a drop-down list (single choice) #491 --------- Co-authored-by: Florent --- app/client/widgets/ChoiceEditor.js | 24 +++++++++++++++++++++--- app/client/widgets/ChoiceTextBox.ts | 13 ++++++++++++- app/client/widgets/TextEditor.js | 2 +- 3 files changed, 34 insertions(+), 5 deletions(-) diff --git a/app/client/widgets/ChoiceEditor.js b/app/client/widgets/ChoiceEditor.js index 85f4facb..1e7aef72 100644 --- a/app/client/widgets/ChoiceEditor.js +++ b/app/client/widgets/ChoiceEditor.js @@ -7,9 +7,10 @@ const {ACIndexImpl, buildHighlightedDom} = require('app/client/lib/ACIndex'); const {ChoiceItem, cssChoiceList, cssMatchText, cssPlusButton, cssPlusIcon} = require('app/client/widgets/ChoiceListEditor'); const {menuCssClass} = require('app/client/ui2018/menus'); -const {testId} = require('app/client/ui2018/cssVars'); +const {testId, colors} = require('app/client/ui2018/cssVars'); const {choiceToken, cssChoiceACItem} = require('app/client/widgets/ChoiceToken'); -const {dom} = require('grainjs'); +const {dom, styled} = require('grainjs'); +const {icon} = require('../ui2018/icons'); /** * ChoiceEditor - TextEditor with a dropdown for possible choices. @@ -19,7 +20,10 @@ function ChoiceEditor(options) { this.choices = options.field.widgetOptionsJson.peek().choices || []; this.choiceOptions = options.field.widgetOptionsJson.peek().choiceOptions || {}; - + if (!options.readonly && options.field.viewSection().parentKey() === "single") { + this.cellEditorDiv.classList.add(cssChoiceEditor.className); + this.cellEditorDiv.appendChild(cssChoiceEditIcon('Dropdown')); + } // Whether to include a button to show a new choice. // TODO: Disable when the user cannot change column configuration. this.enableAddNew = true; @@ -107,4 +111,18 @@ ChoiceEditor.prototype.maybeShowAddNew = function(result, text) { return result; } +const cssChoiceEditIcon = styled(icon, ` + background-color: ${colors.slate}; + position: absolute; + top: 0; + left: 0; + margin: 3px 3px 0 3px; +`); + +const cssChoiceEditor = styled('div', ` + & > .celleditor_text_editor, & > .celleditor_content_measure { + padding-left: 18px; + } +`); + module.exports = ChoiceEditor; diff --git a/app/client/widgets/ChoiceTextBox.ts b/app/client/widgets/ChoiceTextBox.ts index e8635d70..558328fc 100644 --- a/app/client/widgets/ChoiceTextBox.ts +++ b/app/client/widgets/ChoiceTextBox.ts @@ -4,7 +4,8 @@ import {ViewFieldRec} from 'app/client/models/entities/ViewFieldRec'; import {KoSaveableObservable} from 'app/client/models/modelUtil'; import {Style} from 'app/client/models/Styles'; import {cssLabel, cssRow} from 'app/client/ui/RightPanelStyles'; -import {testId} from 'app/client/ui2018/cssVars'; +import {colors, testId} from 'app/client/ui2018/cssVars'; +import {icon} from 'app/client/ui2018/icons'; import {ChoiceListEntry} from 'app/client/widgets/ChoiceListEntry'; import {choiceToken, DEFAULT_FILL_COLOR, DEFAULT_TEXT_COLOR} from 'app/client/widgets/ChoiceToken'; import {NTextBox} from 'app/client/widgets/NTextBox'; @@ -45,9 +46,13 @@ export class ChoiceTextBox extends NTextBox { public buildDom(row: DataRowModel) { const value = row.cells[this.field.colId()]; + const isSingle = this.field.viewSection().parentKey() === "single"; + const maybeDropDownCssChoiceEditIcon = isSingle ? cssChoiceEditIcon('Dropdown') : null; + return cssChoiceField( cssChoiceTextWrapper( dom.style('justify-content', (use) => use(this.alignment) === 'right' ? 'flex-end' : use(this.alignment)), + maybeDropDownCssChoiceEditIcon, dom.domComputed((use) => { if (this.isDisposed() || use(row._isAddRow)) { return null; } @@ -150,3 +155,9 @@ const cssChoiceText = styled('div', ` height: min-content; line-height: 16px; `); + +const cssChoiceEditIcon = styled(icon, ` + background-color: ${colors.slate}; + display: block; + height: inherit; +`); diff --git a/app/client/widgets/TextEditor.js b/app/client/widgets/TextEditor.js index 0dee97d4..593317c4 100644 --- a/app/client/widgets/TextEditor.js +++ b/app/client/widgets/TextEditor.js @@ -39,7 +39,7 @@ function TextEditor(options) { this.dom = dom('div.default_editor', kd.toggleClass("readonly_editor", options.readonly), - dom('div.celleditor_cursor_editor', dom.testId('TextEditor_editor'), + this.cellEditorDiv = dom('div.celleditor_cursor_editor', dom.testId('TextEditor_editor'), testId('widget-text-editor'), // new-style testId matches NTextEditor, for more uniform tests. this.contentSizer = dom('div.celleditor_content_measure'), this.textInput = dom('textarea.celleditor_text_editor', From 6a2010f9f03f8dc094a3d2c26b8346d91998b0f7 Mon Sep 17 00:00:00 2001 From: Florent Date: Wed, 14 Jun 2023 16:43:11 +0200 Subject: [PATCH 3/6] Add contribution guide #527 (#528) Co-authored-by: Florent --- .github/CONTRIBUTING.md | 8 +++ documentation/develop.md | 124 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 132 insertions(+) create mode 100644 .github/CONTRIBUTING.md create mode 100644 documentation/develop.md diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md new file mode 100644 index 00000000..471554fd --- /dev/null +++ b/.github/CONTRIBUTING.md @@ -0,0 +1,8 @@ +# Welcome to the contribution guide for Grist! + +You are eager to contribute to Grist? That's awesome! See below some contributions you can make: +- [translate](/documentation/translate.md) +- [write tutorials and user documentation](https://github.com/gristlabs/grist-help) +- [develop](/documentation/develop.md) +- [report issues or suggest enhancement](https://github.com/gristlabs/grist-core/issues/new) + diff --git a/documentation/develop.md b/documentation/develop.md new file mode 100644 index 00000000..a5b6f63b --- /dev/null +++ b/documentation/develop.md @@ -0,0 +1,124 @@ +# Development + +Please as a first start, tell the community about your intent to develop a feature or fix a bug. Search for the associated issue if it exists or open one with steps to reproduce (for bugs) or a [user story](https://en.wikipedia.org/wiki/User_story#Principle) (for features). + +## Setup + +### Prerequisites + +To setup your environment, you would need to install the following dependencies: + - git + - [nvm](https://github.com/nvm-sh/nvm/blob/master/README.md) (recommended) or nodejs installed on your system + - Chromium to run the end-to-end tests + - Python (preferably Python 3.9) and virtualenv + - :warning: As of 2023-06-06, Python 3.11 is not supported due to the version of the [wrapt dependency](https://github.com/GrahamDumpleton/wrapt/issues/196) + +### Clone the repository + +```bash +$ git clone https://github.com/gristlabs/grist-core +``` + +And then, enter the grist-core root directory: + +```bash +$ cd grist-core/ +``` + +### Setup nodejs + +#### Using nvm (recommanded) + +You need to install the supported nodejs version as well as yarn. To do so, in the grist-core root directory, run the following command to install nodejs via nvm: + +```bash +$ nvm install +``` + +Now check that node is installed in the version specified in the `.nvmrc` file: + +```bash +$ node --version +``` + +Then install yarn (the `-g` flag here means that yarn will be available globally): +```bash +$ npm install -g yarn +``` + +Now each time you want to load nodejs and yarn in your environment, just run the following command at grist-core root directory: + +```bash +$ nvm use +``` + +#### Using nodejs + +You can also use nodejs installed in your system. To prevent incompatibilities, ensure that the `node --version` command reports a version equal or greater to the one in `.nvmrc`. + +### Install the python packages + +Be sure to have Python and virtualenv installed. On debian-based Linux distributions, you can simply run the following command as root: + +```bash +# apt install python3.9 python3.9-venv +``` + +### Install the project dependencies and build + +First install the nodejs dependencies: + +```bash +$ yarn install +``` + +Then prepare the virtual environment with all the python dependencies: + +```bash +$ yarn install:python +``` + +Finally run this to do an initial build: + +```bash +$ yarn run build:prod +``` + +## Start the server in development mode + +Just run the following command: +```bash +$ yarn start +``` + +Each time you change something, just reload the webpage in your browser. + +Happy coding! + +### Pick an issue + +Lost on what you can do to help? If you are new to Grist, you may just pick one of the issues labelled `good first issue`: + +https://github.com/gristlabs/grist-core/labels/good%20first%20issue + +## Run tests + +You may run the tests using one of these commands: + - `yarn test` to run all the tests + - `yarn test:smoke` to run the minimal test checking Grist can open, create and edit a document + - `yarn test:nbrowser` to run the end-to-end tests + - `yarn test:client` to run the tests for the client libraries + - `yarn test:common` to run the tests for the common libraries shared between the client and the server + - `yarn test:server` to run the backend tests + - `yarn test:docker` to run some end-to-end tests under docker + - `yarn test:python` to run the data engine tests + +## Develop widgets + +Check out this repository: https://github.com/gristlabs/grist-widget#readme + +## Documentation + +Some documentation to help you starting developing: + - [Grainjs](https://github.com/gristlabs/grainjs/) (The library used to build the DOM) + - [The user support documentation](https://support.getgrist.com/) From fa306eba15b07e13d81d38690cb76c32874f942d Mon Sep 17 00:00:00 2001 From: Florent Date: Thu, 15 Jun 2023 21:45:32 +0200 Subject: [PATCH 4/6] Support spaces in GREP_TESTS values (#535) Not only GREP_TESTS can be assigned a single word like: GREP_TESTS=DocApi yarn test But also can be assigned a whole sentence part: GREP_TESTS="supports ascending sort" yarn test That's especially useful to run a single test (and not a whole test suit) Co-authored-by: Florent FAYOLLE --- package.json | 4 ++-- test/test_under_docker.sh | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/package.json b/package.json index 8e920b57..9a34bea1 100644 --- a/package.json +++ b/package.json @@ -12,8 +12,8 @@ "install:python3": "buildtools/prepare_python3.sh", "build:prod": "buildtools/build.sh", "start:prod": "sandbox/run.sh", - "test": "GRIST_SESSION_COOKIE=grist_test_cookie GRIST_TEST_LOGIN=1 TEST_SUPPORT_API_KEY=api_key_for_support TEST_CLEAN_DATABASE=true NODE_PATH=_build:_build/stubs:_build/ext mocha ${DEBUG:+-b --no-exit} --slow 8000 ${DEBUG:---forbid-only} -g ${GREP_TESTS:-''} '_build/test/common/*.js' '_build/test/client/*.js' '_build/test/nbrowser/*.js' '_build/test/server/**/*.js' '_build/test/gen-server/**/*.js'", - "test:nbrowser": "TEST_SUITE=nbrowser TEST_SUITE_FOR_TIMINGS=nbrowser TIMINGS_FILE=test/timings/nbrowser.txt GRIST_SESSION_COOKIE=grist_test_cookie GRIST_TEST_LOGIN=1 TEST_SUPPORT_API_KEY=api_key_for_support TEST_CLEAN_DATABASE=true NODE_PATH=_build:_build/stubs:_build/ext mocha ${DEBUG:+-b --no-exit} ${DEBUG:---forbid-only} -g ${GREP_TESTS:-''} --slow 8000 -R test/xunit-file '_build/test/nbrowser/**/*.js'", + "test": "GRIST_SESSION_COOKIE=grist_test_cookie GRIST_TEST_LOGIN=1 TEST_SUPPORT_API_KEY=api_key_for_support TEST_CLEAN_DATABASE=true NODE_PATH=_build:_build/stubs:_build/ext mocha ${DEBUG:+-b --no-exit} --slow 8000 ${DEBUG:---forbid-only} -g \"${GREP_TESTS}\" '_build/test/common/*.js' '_build/test/client/*.js' '_build/test/nbrowser/*.js' '_build/test/server/**/*.js' '_build/test/gen-server/**/*.js'", + "test:nbrowser": "TEST_SUITE=nbrowser TEST_SUITE_FOR_TIMINGS=nbrowser TIMINGS_FILE=test/timings/nbrowser.txt GRIST_SESSION_COOKIE=grist_test_cookie GRIST_TEST_LOGIN=1 TEST_SUPPORT_API_KEY=api_key_for_support TEST_CLEAN_DATABASE=true NODE_PATH=_build:_build/stubs:_build/ext mocha ${DEBUG:+-b --no-exit} ${DEBUG:---forbid-only} -g \"${GREP_TESTS}\" --slow 8000 -R test/xunit-file '_build/test/nbrowser/**/*.js'", "test:client": "GRIST_SESSION_COOKIE=grist_test_cookie NODE_PATH=_build:_build/stubs:_build/ext mocha ${DEBUG:+'-b'} '_build/test/client/**/*.js'", "test:common": "GRIST_SESSION_COOKIE=grist_test_cookie NODE_PATH=_build:_build/stubs:_build/ext mocha ${DEBUG:+'-b'} '_build/test/common/**/*.js'", "test:server": "TEST_SUITE=server TEST_SUITE_FOR_TIMINGS=server TIMINGS_FILE=test/timings/server.txt GRIST_SESSION_COOKIE=grist_test_cookie NODE_PATH=_build:_build/stubs:_build/ext mocha ${DEBUG:+'-b'} -R test/xunit-file '_build/test/server/**/*.js' '_build/test/gen-server/**/*.js'", diff --git a/test/test_under_docker.sh b/test/test_under_docker.sh index 73682fc7..3e54603c 100755 --- a/test/test_under_docker.sh +++ b/test/test_under_docker.sh @@ -64,4 +64,4 @@ TEST_ADD_SAMPLES=1 TEST_ACCOUNT_PASSWORD=not-needed \ GRIST_SESSION_COOKIE=grist_test_cookie \ GRIST_TEST_LOGIN=1 \ NODE_PATH=_build:_build/stubs \ - $MOCHA _build/test/deployment/*.js --slow 6000 -g ${GREP_TESTS:-''} "$@" + $MOCHA _build/test/deployment/*.js --slow 6000 -g "${GREP_TESTS}" "$@" From d280e796a0621eca29fae7581357bf76abeff400 Mon Sep 17 00:00:00 2001 From: Thomas Guillet Date: Mon, 19 Jun 2023 23:22:53 +0200 Subject: [PATCH 5/6] Fix typo in a French translation (#538) --- static/locales/fr.client.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/static/locales/fr.client.json b/static/locales/fr.client.json index ba8fb79d..91382661 100644 --- a/static/locales/fr.client.json +++ b/static/locales/fr.client.json @@ -190,7 +190,7 @@ "Raw Data Tables": "Données sources", "Click to copy": "Cliquez ici pour copier", "Table ID copied to clipboard": "Identifiant de table copié", - "Duplicate Table": "Dupliquer la page", + "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 ?" }, From bf15a14dd412d2e818048ffaba4a532ca6b3ac88 Mon Sep 17 00:00:00 2001 From: Florent Date: Tue, 20 Jun 2023 18:49:57 +0200 Subject: [PATCH 6/6] Add command to debug the server (#533) Co-authored-by: Florent FAYOLLE --- documentation/develop.md | 10 ++++++++++ package.json | 1 + sandbox/watch.sh | 2 +- 3 files changed, 12 insertions(+), 1 deletion(-) diff --git a/documentation/develop.md b/documentation/develop.md index a5b6f63b..56f12c1b 100644 --- a/documentation/develop.md +++ b/documentation/develop.md @@ -101,6 +101,16 @@ Lost on what you can do to help? If you are new to Grist, you may just pick one https://github.com/gristlabs/grist-core/labels/good%20first%20issue +## Debug the server + +You can debug the NodeJS application using this command: + +```bash +$ yarn start:debug +``` + +And start using your nodejs debugger client (like the Chrome Devtools). See https://nodejs.org/en/docs/guides/debugging-getting-started#inspector-clients + ## Run tests You may run the tests using one of these commands: diff --git a/package.json b/package.json index 9a34bea1..6d8d9f3f 100644 --- a/package.json +++ b/package.json @@ -7,6 +7,7 @@ "repository": "git://github.com/gristlabs/grist-core.git", "scripts": { "start": "sandbox/watch.sh", + "start:debug": "NODE_INSPECT=1 sandbox/watch.sh", "install:python": "buildtools/prepare_python.sh", "install:python2": "buildtools/prepare_python2.sh", "install:python3": "buildtools/prepare_python3.sh", diff --git a/sandbox/watch.sh b/sandbox/watch.sh index ae77fcd3..cac00b81 100755 --- a/sandbox/watch.sh +++ b/sandbox/watch.sh @@ -17,6 +17,6 @@ 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 & -NODE_PATH=_build:_build/stubs:_build/ext nodemon --delay 1 -w _build/app/server -w _build/app/common _build/stubs/app/server/server.js & +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