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
fc16b4c8f6
8
.github/CONTRIBUTING.md
vendored
Normal file
8
.github/CONTRIBUTING.md
vendored
Normal file
@ -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)
|
||||||
|
|
@ -7,9 +7,10 @@ const {ACIndexImpl, buildHighlightedDom} = require('app/client/lib/ACIndex');
|
|||||||
const {ChoiceItem, cssChoiceList, cssMatchText, cssPlusButton,
|
const {ChoiceItem, cssChoiceList, cssMatchText, cssPlusButton,
|
||||||
cssPlusIcon} = require('app/client/widgets/ChoiceListEditor');
|
cssPlusIcon} = require('app/client/widgets/ChoiceListEditor');
|
||||||
const {menuCssClass} = require('app/client/ui2018/menus');
|
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 {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.
|
* ChoiceEditor - TextEditor with a dropdown for possible choices.
|
||||||
@ -19,7 +20,10 @@ function ChoiceEditor(options) {
|
|||||||
|
|
||||||
this.choices = options.field.widgetOptionsJson.peek().choices || [];
|
this.choices = options.field.widgetOptionsJson.peek().choices || [];
|
||||||
this.choiceOptions = options.field.widgetOptionsJson.peek().choiceOptions || {};
|
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.
|
// Whether to include a button to show a new choice.
|
||||||
// TODO: Disable when the user cannot change column configuration.
|
// TODO: Disable when the user cannot change column configuration.
|
||||||
this.enableAddNew = true;
|
this.enableAddNew = true;
|
||||||
@ -107,4 +111,18 @@ ChoiceEditor.prototype.maybeShowAddNew = function(result, text) {
|
|||||||
return result;
|
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;
|
module.exports = ChoiceEditor;
|
||||||
|
@ -4,7 +4,8 @@ import {ViewFieldRec} from 'app/client/models/entities/ViewFieldRec';
|
|||||||
import {KoSaveableObservable} from 'app/client/models/modelUtil';
|
import {KoSaveableObservable} from 'app/client/models/modelUtil';
|
||||||
import {Style} from 'app/client/models/Styles';
|
import {Style} from 'app/client/models/Styles';
|
||||||
import {cssLabel, cssRow} from 'app/client/ui/RightPanelStyles';
|
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 {ChoiceListEntry} from 'app/client/widgets/ChoiceListEntry';
|
||||||
import {choiceToken, DEFAULT_FILL_COLOR, DEFAULT_TEXT_COLOR} from 'app/client/widgets/ChoiceToken';
|
import {choiceToken, DEFAULT_FILL_COLOR, DEFAULT_TEXT_COLOR} from 'app/client/widgets/ChoiceToken';
|
||||||
import {NTextBox} from 'app/client/widgets/NTextBox';
|
import {NTextBox} from 'app/client/widgets/NTextBox';
|
||||||
@ -45,9 +46,13 @@ export class ChoiceTextBox extends NTextBox {
|
|||||||
|
|
||||||
public buildDom(row: DataRowModel) {
|
public buildDom(row: DataRowModel) {
|
||||||
const value = row.cells[this.field.colId()];
|
const value = row.cells[this.field.colId()];
|
||||||
|
const isSingle = this.field.viewSection().parentKey() === "single";
|
||||||
|
const maybeDropDownCssChoiceEditIcon = isSingle ? cssChoiceEditIcon('Dropdown') : null;
|
||||||
|
|
||||||
return cssChoiceField(
|
return cssChoiceField(
|
||||||
cssChoiceTextWrapper(
|
cssChoiceTextWrapper(
|
||||||
dom.style('justify-content', (use) => use(this.alignment) === 'right' ? 'flex-end' : use(this.alignment)),
|
dom.style('justify-content', (use) => use(this.alignment) === 'right' ? 'flex-end' : use(this.alignment)),
|
||||||
|
maybeDropDownCssChoiceEditIcon,
|
||||||
dom.domComputed((use) => {
|
dom.domComputed((use) => {
|
||||||
if (this.isDisposed() || use(row._isAddRow)) { return null; }
|
if (this.isDisposed() || use(row._isAddRow)) { return null; }
|
||||||
|
|
||||||
@ -150,3 +155,9 @@ const cssChoiceText = styled('div', `
|
|||||||
height: min-content;
|
height: min-content;
|
||||||
line-height: 16px;
|
line-height: 16px;
|
||||||
`);
|
`);
|
||||||
|
|
||||||
|
const cssChoiceEditIcon = styled(icon, `
|
||||||
|
background-color: ${colors.slate};
|
||||||
|
display: block;
|
||||||
|
height: inherit;
|
||||||
|
`);
|
||||||
|
@ -39,7 +39,7 @@ function TextEditor(options) {
|
|||||||
|
|
||||||
this.dom = dom('div.default_editor',
|
this.dom = dom('div.default_editor',
|
||||||
kd.toggleClass("readonly_editor", options.readonly),
|
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.
|
testId('widget-text-editor'), // new-style testId matches NTextEditor, for more uniform tests.
|
||||||
this.contentSizer = dom('div.celleditor_content_measure'),
|
this.contentSizer = dom('div.celleditor_content_measure'),
|
||||||
this.textInput = dom('textarea.celleditor_text_editor',
|
this.textInput = dom('textarea.celleditor_text_editor',
|
||||||
|
@ -3,7 +3,6 @@
|
|||||||
set -e
|
set -e
|
||||||
|
|
||||||
PROJECT=""
|
PROJECT=""
|
||||||
export GRIST_EXT=stubs
|
|
||||||
if [[ -e ext/app ]]; then
|
if [[ -e ext/app ]]; then
|
||||||
PROJECT="tsconfig-ext.json"
|
PROJECT="tsconfig-ext.json"
|
||||||
fi
|
fi
|
||||||
|
134
documentation/develop.md
Normal file
134
documentation/develop.md
Normal file
@ -0,0 +1,134 @@
|
|||||||
|
# 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
|
||||||
|
|
||||||
|
## 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:
|
||||||
|
- `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/)
|
@ -7,6 +7,7 @@
|
|||||||
"repository": "git://github.com/gristlabs/grist-core.git",
|
"repository": "git://github.com/gristlabs/grist-core.git",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"start": "sandbox/watch.sh",
|
"start": "sandbox/watch.sh",
|
||||||
|
"start:debug": "NODE_INSPECT=1 sandbox/watch.sh",
|
||||||
"install:python": "buildtools/prepare_python.sh",
|
"install:python": "buildtools/prepare_python.sh",
|
||||||
"install:python2": "buildtools/prepare_python2.sh",
|
"install:python2": "buildtools/prepare_python2.sh",
|
||||||
"install:python3": "buildtools/prepare_python3.sh",
|
"install:python3": "buildtools/prepare_python3.sh",
|
||||||
|
@ -3,7 +3,6 @@
|
|||||||
set -x
|
set -x
|
||||||
|
|
||||||
PROJECT=""
|
PROJECT=""
|
||||||
export GRIST_EXT=stubs
|
|
||||||
if [[ -e ext/app ]]; then
|
if [[ -e ext/app ]]; then
|
||||||
PROJECT="tsconfig-ext.json"
|
PROJECT="tsconfig-ext.json"
|
||||||
fi
|
fi
|
||||||
@ -18,6 +17,6 @@ fi
|
|||||||
|
|
||||||
tsc --build -w --preserveWatchOutput $PROJECT &
|
tsc --build -w --preserveWatchOutput $PROJECT &
|
||||||
catw app/client/*.css app/client/*/*.css -o static/bundle.css -v & webpack --config $WEBPACK_CONFIG --mode development --watch &
|
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
|
wait
|
||||||
|
@ -190,7 +190,7 @@
|
|||||||
"Raw Data Tables": "Données sources",
|
"Raw Data Tables": "Données sources",
|
||||||
"Click to copy": "Cliquez ici pour copier",
|
"Click to copy": "Cliquez ici pour copier",
|
||||||
"Table ID copied to clipboard": "Identifiant de table copié",
|
"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",
|
"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 ?"
|
"Delete {{formattedTableName}} data, and remove it from all pages?": "Supprimer les données de {{formattedTableName}} et les supprimer de toutes les pages ?"
|
||||||
},
|
},
|
||||||
|
@ -64,4 +64,4 @@ TEST_ADD_SAMPLES=1 TEST_ACCOUNT_PASSWORD=not-needed \
|
|||||||
GRIST_SESSION_COOKIE=grist_test_cookie \
|
GRIST_SESSION_COOKIE=grist_test_cookie \
|
||||||
GRIST_TEST_LOGIN=1 \
|
GRIST_TEST_LOGIN=1 \
|
||||||
NODE_PATH=_build:_build/stubs \
|
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}" "$@"
|
||||||
|
Loading…
Reference in New Issue
Block a user