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
fb276bade7
@ -9,8 +9,11 @@ import {icon} from 'app/client/ui2018/icons';
|
|||||||
import {cssModalTooltip, modalTooltip} from 'app/client/ui2018/modals';
|
import {cssModalTooltip, modalTooltip} from 'app/client/ui2018/modals';
|
||||||
import {dom, DomContents, keyframes, observable, styled, svg} from 'grainjs';
|
import {dom, DomContents, keyframes, observable, styled, svg} from 'grainjs';
|
||||||
import {IPopupOptions} from 'popweasel';
|
import {IPopupOptions} from 'popweasel';
|
||||||
|
import {makeT} from 'app/client/lib/localization';
|
||||||
import merge = require('lodash/merge');
|
import merge = require('lodash/merge');
|
||||||
|
|
||||||
|
const t = makeT('modals');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This is a file for all custom and pre-configured popups, modals, toasts and tooltips, used
|
* This is a file for all custom and pre-configured popups, modals, toasts and tooltips, used
|
||||||
* in more then one component.
|
* in more then one component.
|
||||||
@ -35,19 +38,21 @@ export function buildConfirmDelete(
|
|||||||
Escape: () => ctl.close(),
|
Escape: () => ctl.close(),
|
||||||
Enter: () => { onSave(remember.get()); ctl.close(); },
|
Enter: () => { onSave(remember.get()); ctl.close(); },
|
||||||
}),
|
}),
|
||||||
dom('div', `Are you sure you want to delete ${single ? 'this' : 'these'} record${single ? '' : 's'}?`,
|
dom('div', single ?
|
||||||
|
t(`Are you sure you want to delete this record?`)
|
||||||
|
: t(`Are you sure you want to delete these records?`),
|
||||||
dom.style('margin-bottom', '10px'),
|
dom.style('margin-bottom', '10px'),
|
||||||
),
|
),
|
||||||
dom('div',
|
dom('div',
|
||||||
labeledSquareCheckbox(remember, "Don't ask again.", testId('confirm-remember')),
|
labeledSquareCheckbox(remember, t("Don't ask again."), testId('confirm-remember')),
|
||||||
dom.style('margin-bottom', '10px'),
|
dom.style('margin-bottom', '10px'),
|
||||||
),
|
),
|
||||||
cssButtons(
|
cssButtons(
|
||||||
primaryButton('Delete', testId('confirm-save'), dom.on('click', () => {
|
primaryButton(t('Delete'), testId('confirm-save'), dom.on('click', () => {
|
||||||
onSave(remember.get());
|
onSave(remember.get());
|
||||||
ctl.close();
|
ctl.close();
|
||||||
})),
|
})),
|
||||||
basicButton('Cancel', testId('confirm-cancel'), dom.on('click', () => ctl.close()))
|
basicButton(t('Cancel'), testId('confirm-cancel'), dom.on('click', () => ctl.close()))
|
||||||
)
|
)
|
||||||
), {}
|
), {}
|
||||||
);
|
);
|
||||||
@ -81,9 +86,9 @@ export function showDeprecatedWarning(
|
|||||||
dom.style('justify-content', 'space-between'),
|
dom.style('justify-content', 'space-between'),
|
||||||
dom.style('align-items', 'center'),
|
dom.style('align-items', 'center'),
|
||||||
dom('div',
|
dom('div',
|
||||||
labeledSquareCheckbox(remember, "Don't show again.", testId('confirm-remember')),
|
labeledSquareCheckbox(remember, t("Don't show again."), testId('confirm-remember')),
|
||||||
),
|
),
|
||||||
basicButton('Dismiss', testId('confirm-save'),
|
basicButton(t('Dismiss'), testId('confirm-save'),
|
||||||
dom.on('click', () => { ctl.close(); onClose(remember.get()); })
|
dom.on('click', () => { ctl.close(); onClose(remember.get()); })
|
||||||
)
|
)
|
||||||
),
|
),
|
||||||
@ -105,7 +110,7 @@ export function showDeprecatedWarning(
|
|||||||
export function reportUndo(
|
export function reportUndo(
|
||||||
doc: GristDoc,
|
doc: GristDoc,
|
||||||
messageLabel: string,
|
messageLabel: string,
|
||||||
buttonLabel = 'Undo to restore'
|
buttonLabel = t('Undo to restore')
|
||||||
) {
|
) {
|
||||||
// First create a notification with a button to undo the delete.
|
// First create a notification with a button to undo the delete.
|
||||||
let notification = reportSuccess(messageLabel, {
|
let notification = reportSuccess(messageLabel, {
|
||||||
@ -179,12 +184,12 @@ export function showBehavioralPrompt(
|
|||||||
dom.style('align-items', 'center'),
|
dom.style('align-items', 'center'),
|
||||||
dom('div',
|
dom('div',
|
||||||
cssSkipTipsCheckbox(dontShowTips,
|
cssSkipTipsCheckbox(dontShowTips,
|
||||||
cssSkipTipsCheckboxLabel("Don't show tips"),
|
cssSkipTipsCheckboxLabel(t("Don't show tips")),
|
||||||
testId('behavioral-prompt-dont-show-tips')
|
testId('behavioral-prompt-dont-show-tips')
|
||||||
),
|
),
|
||||||
dom.style('visibility', hideDontShowTips ? 'hidden' : ''),
|
dom.style('visibility', hideDontShowTips ? 'hidden' : ''),
|
||||||
),
|
),
|
||||||
cssDismissPromptButton('Got it', testId('behavioral-prompt-dismiss'),
|
cssDismissPromptButton(t('Got it'), testId('behavioral-prompt-dismiss'),
|
||||||
dom.on('click', () => { onClose(dontShowTips.get()); ctl.close(); })
|
dom.on('click', () => { onClose(dontShowTips.get()); ctl.close(); })
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
@ -526,11 +526,19 @@ export class Client {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private async _onMessage(message: string): Promise<void> {
|
||||||
|
try {
|
||||||
|
await this._onMessageImpl(message);
|
||||||
|
} catch (err) {
|
||||||
|
this._log.warn(null, 'onMessage error received for message "%s": %s', shortDesc(message), err.stack);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Processes a request from a client. All requests from a client get a response, at least to
|
* Processes a request from a client. All requests from a client get a response, at least to
|
||||||
* indicate success or failure.
|
* indicate success or failure.
|
||||||
*/
|
*/
|
||||||
private async _onMessage(message: string): Promise<void> {
|
private async _onMessageImpl(message: string): Promise<void> {
|
||||||
const request = JSON.parse(message);
|
const request = JSON.parse(message);
|
||||||
if (request.beat) {
|
if (request.beat) {
|
||||||
// this is a heart beat, to keep the websocket alive. No need to reply.
|
// this is a heart beat, to keep the websocket alive. No need to reply.
|
||||||
|
@ -433,7 +433,19 @@
|
|||||||
"Created by": "Created by",
|
"Created by": "Created by",
|
||||||
"Detect duplicates in...": "Detect duplicates in...",
|
"Detect duplicates in...": "Detect duplicates in...",
|
||||||
"Last updated at": "Last updated at",
|
"Last updated at": "Last updated at",
|
||||||
"Last updated by": "Last updated by"
|
"Last updated by": "Last updated by",
|
||||||
|
"Any": "Any",
|
||||||
|
"Numeric": "Numeric",
|
||||||
|
"Text": "Text",
|
||||||
|
"Integer": "Integer",
|
||||||
|
"Toggle": "Toggle",
|
||||||
|
"Date": "Date",
|
||||||
|
"DateTime": "DateTime",
|
||||||
|
"Choice": "Choice",
|
||||||
|
"Choice List": "Choice List",
|
||||||
|
"Reference": "Reference",
|
||||||
|
"Reference List": "Reference List",
|
||||||
|
"Attachment": "Attachment"
|
||||||
},
|
},
|
||||||
"GristDoc": {
|
"GristDoc": {
|
||||||
"Added new linked section to view {{viewName}}": "Added new linked section to view {{viewName}}",
|
"Added new linked section to view {{viewName}}": "Added new linked section to view {{viewName}}",
|
||||||
@ -622,7 +634,23 @@
|
|||||||
"Widget": "Widget",
|
"Widget": "Widget",
|
||||||
"You do not have edit access to this document": "You do not have edit access to this document",
|
"You do not have edit access to this document": "You do not have edit access to this document",
|
||||||
"Add referenced columns": "Add referenced columns",
|
"Add referenced columns": "Add referenced columns",
|
||||||
"Reset form": "Reset form"
|
"Reset form": "Reset form",
|
||||||
|
"Configuration": "Configuration",
|
||||||
|
"Default field value": "Default field value",
|
||||||
|
"Display button": "Display button",
|
||||||
|
"Enter text": "Enter text",
|
||||||
|
"Field rules": "Field rules",
|
||||||
|
"Field title": "Field title",
|
||||||
|
"Hidden field": "Hidden field",
|
||||||
|
"Layout": "Layout",
|
||||||
|
"Redirect automatically after submission": "Redirect automatically after submission",
|
||||||
|
"Redirection": "Redirection",
|
||||||
|
"Required field": "Required field",
|
||||||
|
"Submission": "Submission",
|
||||||
|
"Submit another response": "Submit another response",
|
||||||
|
"Submit button label": "Submit button label",
|
||||||
|
"Success text": "Success text",
|
||||||
|
"Table column name": "Table column name"
|
||||||
},
|
},
|
||||||
"RowContextMenu": {
|
"RowContextMenu": {
|
||||||
"Copy anchor link": "Copy anchor link",
|
"Copy anchor link": "Copy anchor link",
|
||||||
@ -761,7 +789,8 @@
|
|||||||
"Show raw data": "Show raw data",
|
"Show raw data": "Show raw data",
|
||||||
"Widget options": "Widget options",
|
"Widget options": "Widget options",
|
||||||
"Add to page": "Add to page",
|
"Add to page": "Add to page",
|
||||||
"Collapse widget": "Collapse widget"
|
"Collapse widget": "Collapse widget",
|
||||||
|
"Create a form": "Create a form"
|
||||||
},
|
},
|
||||||
"ViewSectionMenu": {
|
"ViewSectionMenu": {
|
||||||
"(customized)": "(customized)",
|
"(customized)": "(customized)",
|
||||||
@ -863,7 +892,16 @@
|
|||||||
"modals": {
|
"modals": {
|
||||||
"Cancel": "Cancel",
|
"Cancel": "Cancel",
|
||||||
"Ok": "OK",
|
"Ok": "OK",
|
||||||
"Save": "Save"
|
"Save": "Save",
|
||||||
|
"Are you sure you want to delete these records?": "Are you sure you want to delete these records?",
|
||||||
|
"Are you sure you want to delete this record?": "Are you sure you want to delete this record?",
|
||||||
|
"Delete": "Delete",
|
||||||
|
"Dismiss": "Dismiss",
|
||||||
|
"Don't ask again.": "Don't ask again.",
|
||||||
|
"Don't show again.": "Don't show again.",
|
||||||
|
"Don't show tips": "Don't show tips",
|
||||||
|
"Undo to restore": "Undo to restore",
|
||||||
|
"Got it": "Got it"
|
||||||
},
|
},
|
||||||
"pages": {
|
"pages": {
|
||||||
"Duplicate Page": "Duplicate Page",
|
"Duplicate Page": "Duplicate Page",
|
||||||
@ -1266,5 +1304,28 @@
|
|||||||
"Publish your form?": "Publish your form?",
|
"Publish your form?": "Publish your form?",
|
||||||
"Unpublish": "Unpublish",
|
"Unpublish": "Unpublish",
|
||||||
"Unpublish your form?": "Unpublish your form?"
|
"Unpublish your form?": "Unpublish your form?"
|
||||||
|
},
|
||||||
|
"Editor": {
|
||||||
|
"Delete": "Delete"
|
||||||
|
},
|
||||||
|
"Menu": {
|
||||||
|
"Building blocks": "Building blocks",
|
||||||
|
"Columns": "Columns",
|
||||||
|
"Copy": "Copy",
|
||||||
|
"Cut": "Cut",
|
||||||
|
"Insert question above": "Insert question above",
|
||||||
|
"Insert question below": "Insert question below",
|
||||||
|
"Paragraph": "Paragraph",
|
||||||
|
"Paste": "Paste",
|
||||||
|
"Separator": "Separator",
|
||||||
|
"Unmapped fields": "Unmapped fields"
|
||||||
|
},
|
||||||
|
"UnmappedFieldsConfig": {
|
||||||
|
"Clear": "Clear",
|
||||||
|
"Map fields": "Map fields",
|
||||||
|
"Mapped": "Mapped",
|
||||||
|
"Select All": "Select All",
|
||||||
|
"Unmap fields": "Unmap fields",
|
||||||
|
"Unmapped": "Unmapped"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -188,6 +188,24 @@ describe('Comm', function() {
|
|||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should only log warning for malformed JSON data', async function () {
|
||||||
|
const logMessages = await testUtils.captureLog('warn', async () => {
|
||||||
|
ws.send('foobar');
|
||||||
|
}, {waitForFirstLog: true});
|
||||||
|
testUtils.assertMatchArray(logMessages, [
|
||||||
|
/^warn: Client.* Unexpected token.*/
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should log warning when null value is passed', async function () {
|
||||||
|
const logMessages = await testUtils.captureLog('warn', async () => {
|
||||||
|
ws.send('null');
|
||||||
|
}, {waitForFirstLog: true});
|
||||||
|
testUtils.assertMatchArray(logMessages, [
|
||||||
|
/^warn: Client.*Cannot read properties of null*/
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
|
||||||
it("should support app-level events correctly", async function() {
|
it("should support app-level events correctly", async function() {
|
||||||
comm!.broadcastMessage('fooType' as any, 'hello');
|
comm!.broadcastMessage('fooType' as any, 'hello');
|
||||||
comm!.broadcastMessage('barType' as any, 'world');
|
comm!.broadcastMessage('barType' as any, 'world');
|
||||||
|
@ -126,16 +126,18 @@ export function setTmpLogLevel(level: string, optCaptureFunc?: (level: string, m
|
|||||||
*/
|
*/
|
||||||
export async function captureLog(
|
export async function captureLog(
|
||||||
minLevel: string, callback: (messages: string[]) => void|Promise<void>,
|
minLevel: string, callback: (messages: string[]) => void|Promise<void>,
|
||||||
options: {timestamp: boolean} = {timestamp: false}
|
options: {timestamp?: boolean, waitForFirstLog?: boolean} = {timestamp: false, waitForFirstLog: false}
|
||||||
): Promise<string[]> {
|
): Promise<string[]> {
|
||||||
const messages: string[] = [];
|
const messages: string[] = [];
|
||||||
const prevLogLevel = log.transports.file.level;
|
const prevLogLevel = log.transports.file.level;
|
||||||
const name = _.uniqueId('CaptureLog');
|
const name = _.uniqueId('CaptureLog');
|
||||||
|
|
||||||
|
const captureFirstLogPromise = new Promise((resolve) => {
|
||||||
function capture(level: string, msg: string, meta: any) {
|
function capture(level: string, msg: string, meta: any) {
|
||||||
if ((log as any).levels[level] <= (log as any).levels[minLevel]) { // winston types are off?
|
if ((log as any).levels[level] <= (log as any).levels[minLevel]) { // winston types are off?
|
||||||
const timePrefix = options.timestamp ? new Date().toISOString() + ' ' : '';
|
const timePrefix = options.timestamp ? new Date().toISOString() + ' ' : '';
|
||||||
messages.push(`${timePrefix}${level}: ${msg}${meta ? ' ' + serialize(meta) : ''}`);
|
messages.push(`${timePrefix}${level}: ${msg}${meta ? ' ' + serialize(meta) : ''}`);
|
||||||
|
resolve(null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -143,8 +145,13 @@ export async function captureLog(
|
|||||||
log.transports.file.level = -1 as any; // Suppress all log output.
|
log.transports.file.level = -1 as any; // Suppress all log output.
|
||||||
}
|
}
|
||||||
log.add(CaptureTransport as any, { captureFunc: capture, name, level: minLevel}); // types are off.
|
log.add(CaptureTransport as any, { captureFunc: capture, name, level: minLevel}); // types are off.
|
||||||
|
});
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await callback(messages);
|
await callback(messages);
|
||||||
|
if (options.waitForFirstLog) {
|
||||||
|
await captureFirstLogPromise;
|
||||||
|
}
|
||||||
} finally {
|
} finally {
|
||||||
log.remove(name);
|
log.remove(name);
|
||||||
log.transports.file.level = prevLogLevel;
|
log.transports.file.level = prevLogLevel;
|
||||||
|
Loading…
Reference in New Issue
Block a user