mirror of
https://github.com/gristlabs/grist-core.git
synced 2024-10-27 20:44:07 +00:00
(core) Removing the new menu flag
Summary: Enabling the `GRIST_NEW_COLUMN_MENU` flag by default and removing it. Test Plan: Existing Reviewers: georgegevoian Reviewed By: georgegevoian Differential Revision: https://phab.getgrist.com/D4098
This commit is contained in:
parent
9262e1f1ef
commit
3c219e05f6
@ -44,7 +44,6 @@ const {
|
|||||||
buildAddColumnMenu,
|
buildAddColumnMenu,
|
||||||
buildColumnContextMenu,
|
buildColumnContextMenu,
|
||||||
buildMultiColumnMenu,
|
buildMultiColumnMenu,
|
||||||
buildOldAddColumnMenu,
|
|
||||||
calcFieldsCondition,
|
calcFieldsCondition,
|
||||||
freezeAction,
|
freezeAction,
|
||||||
} = require('app/client/ui/GridViewMenus');
|
} = require('app/client/ui/GridViewMenus');
|
||||||
@ -56,7 +55,6 @@ const {NEW_FILTER_JSON} = require('app/client/models/ColumnFilter');
|
|||||||
const {CombinedStyle} = require("app/client/models/Styles");
|
const {CombinedStyle} = require("app/client/models/Styles");
|
||||||
const {buildRenameColumn} = require('app/client/ui/ColumnTitle');
|
const {buildRenameColumn} = require('app/client/ui/ColumnTitle');
|
||||||
const {makeT} = require('app/client/lib/localization');
|
const {makeT} = require('app/client/lib/localization');
|
||||||
const {GRIST_NEW_COLUMN_MENU} = require("../models/features");
|
|
||||||
|
|
||||||
const t = makeT('GridView');
|
const t = makeT('GridView');
|
||||||
|
|
||||||
@ -311,14 +309,14 @@ GridView.gridCommands = {
|
|||||||
editField: function() { closeRegisteredMenu(); this.scrollToCursor(true); this.activateEditorAtCursor(); },
|
editField: function() { closeRegisteredMenu(); this.scrollToCursor(true); this.activateEditorAtCursor(); },
|
||||||
|
|
||||||
insertFieldBefore: function(maybeKeyboardEvent) {
|
insertFieldBefore: function(maybeKeyboardEvent) {
|
||||||
if (GRIST_NEW_COLUMN_MENU() && !maybeKeyboardEvent) {
|
if (!maybeKeyboardEvent) {
|
||||||
this._openInsertColumnMenu(this.cursor.fieldIndex());
|
this._openInsertColumnMenu(this.cursor.fieldIndex());
|
||||||
} else {
|
} else {
|
||||||
this.insertColumn(null, {index: this.cursor.fieldIndex()});
|
this.insertColumn(null, {index: this.cursor.fieldIndex()});
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
insertFieldAfter: function(maybeKeyboardEvent) {
|
insertFieldAfter: function(maybeKeyboardEvent) {
|
||||||
if (GRIST_NEW_COLUMN_MENU() && !maybeKeyboardEvent) {
|
if (!maybeKeyboardEvent) {
|
||||||
this._openInsertColumnMenu(this.cursor.fieldIndex() + 1);
|
this._openInsertColumnMenu(this.cursor.fieldIndex() + 1);
|
||||||
} else {
|
} else {
|
||||||
this.insertColumn(null, {index: this.cursor.fieldIndex() + 1});
|
this.insertColumn(null, {index: this.cursor.fieldIndex() + 1});
|
||||||
@ -1302,8 +1300,7 @@ GridView.prototype.buildDom = function() {
|
|||||||
testId('column-menu-trigger'),
|
testId('column-menu-trigger'),
|
||||||
),
|
),
|
||||||
dom('div.selection'),
|
dom('div.selection'),
|
||||||
// FIXME: remove once New Column menu is enabled by default.
|
this._buildInsertColumnMenu({field}),
|
||||||
GRIST_NEW_COLUMN_MENU() ? this._buildInsertColumnMenu({field}) : null,
|
|
||||||
);
|
);
|
||||||
}),
|
}),
|
||||||
this.isPreview ? null : kd.maybe(() => !this.gristDoc.isReadonlyKo(), () => (
|
this.isPreview ? null : kd.maybe(() => !this.gristDoc.isReadonlyKo(), () => (
|
||||||
@ -2004,7 +2001,6 @@ GridView.prototype._scrollColumnIntoView = function(colIndex) {
|
|||||||
* the GridView.
|
* the GridView.
|
||||||
*/
|
*/
|
||||||
GridView.prototype._buildInsertColumnMenu = function(options = {}) {
|
GridView.prototype._buildInsertColumnMenu = function(options = {}) {
|
||||||
if (GRIST_NEW_COLUMN_MENU()) {
|
|
||||||
const {field} = options;
|
const {field} = options;
|
||||||
const triggers = [];
|
const triggers = [];
|
||||||
if (!field) { triggers.push('click'); }
|
if (!field) { triggers.push('click'); }
|
||||||
@ -2049,21 +2045,6 @@ GridView.prototype._buildInsertColumnMenu = function(options = {}) {
|
|||||||
}
|
}
|
||||||
),
|
),
|
||||||
];
|
];
|
||||||
} else {
|
|
||||||
// FIXME: remove once New Column menu is enabled by default.
|
|
||||||
return [
|
|
||||||
dom.on('click', async ev => {
|
|
||||||
// If there are no hidden columns, clicking the plus just adds a new column.
|
|
||||||
// If there are hidden columns, display a dropdown menu.
|
|
||||||
if (this.viewSection.hiddenColumns().length === 0) {
|
|
||||||
// Don't open the menu defined below.
|
|
||||||
ev.stopImmediatePropagation();
|
|
||||||
await this.insertColumn();
|
|
||||||
}
|
|
||||||
}),
|
|
||||||
menu((() => buildOldAddColumnMenu(this, this.viewSection))),
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
GridView.prototype._openInsertColumnMenu = function(columnIndex) {
|
GridView.prototype._openInsertColumnMenu = function(columnIndex) {
|
||||||
|
@ -25,10 +25,6 @@ export function WHICH_FORMULA_ASSISTANT() {
|
|||||||
return getGristConfig().assistantService;
|
return getGristConfig().assistantService;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function GRIST_NEW_COLUMN_MENU(){
|
|
||||||
return Boolean(getGristConfig().gristNewColumnMenu);
|
|
||||||
}
|
|
||||||
|
|
||||||
export function PERMITTED_CUSTOM_WIDGETS(): Observable<string[]> {
|
export function PERMITTED_CUSTOM_WIDGETS(): Observable<string[]> {
|
||||||
const G = getBrowserGlobals('document', 'window');
|
const G = getBrowserGlobals('document', 'window');
|
||||||
if (!G.window.PERMITTED_CUSTOM_WIDGETS) {
|
if (!G.window.PERMITTED_CUSTOM_WIDGETS) {
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
import {allCommands} from 'app/client/components/commands';
|
import {allCommands} from 'app/client/components/commands';
|
||||||
import GridView from 'app/client/components/GridView';
|
import GridView from 'app/client/components/GridView';
|
||||||
import {makeT} from 'app/client/lib/localization';
|
import {makeT} from 'app/client/lib/localization';
|
||||||
import {ViewSectionRec} from 'app/client/models/DocModel';
|
|
||||||
import {ViewFieldRec} from 'app/client/models/entities/ViewFieldRec';
|
import {ViewFieldRec} from 'app/client/models/entities/ViewFieldRec';
|
||||||
import {GristTooltips} from 'app/client/ui/GristTooltips';
|
import {GristTooltips} from 'app/client/ui/GristTooltips';
|
||||||
import {withInfoTooltip} from 'app/client/ui/tooltips';
|
import {withInfoTooltip} from 'app/client/ui/tooltips';
|
||||||
@ -29,18 +28,6 @@ import isEqual = require('lodash/isEqual');
|
|||||||
|
|
||||||
const t = makeT('GridViewMenus');
|
const t = makeT('GridViewMenus');
|
||||||
|
|
||||||
// FIXME: remove once New Column menu is enabled by default.
|
|
||||||
export function buildOldAddColumnMenu(gridView: GridView, viewSection: ViewSectionRec) {
|
|
||||||
return [
|
|
||||||
menuItem(async () => { await gridView.insertColumn(); }, t("Add Column")),
|
|
||||||
menuDivider(),
|
|
||||||
...viewSection.hiddenColumns().map((col: any) => menuItem(
|
|
||||||
async () => {
|
|
||||||
await gridView.showColumn(col.id());
|
|
||||||
}, t("Show column {{- label}}", {label: col.label()})))
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
export function buildAddColumnMenu(gridView: GridView, index?: number) {
|
export function buildAddColumnMenu(gridView: GridView, index?: number) {
|
||||||
const isSummaryTable = Boolean(gridView.viewSection.table().summarySourceTable());
|
const isSummaryTable = Boolean(gridView.viewSection.table().summarySourceTable());
|
||||||
return [
|
return [
|
||||||
@ -66,13 +53,14 @@ function buildHiddenColumnsMenuItems(gridView: GridView, index?: number) {
|
|||||||
if (hiddenColumns.length <= 5) {
|
if (hiddenColumns.length <= 5) {
|
||||||
return [
|
return [
|
||||||
menuDivider(),
|
menuDivider(),
|
||||||
menuSubHeader(t('Hidden Columns'), testId('new-columns-menu-hidden-columns')),
|
menuSubHeader(t('Hidden Columns'), testId('new-columns-menu-hidden-columns-header')),
|
||||||
hiddenColumns.map((col: ColumnRec) =>
|
hiddenColumns.map((col: ColumnRec) =>
|
||||||
menuItem(
|
menuItem(
|
||||||
async () => {
|
async () => {
|
||||||
await gridView.showColumn(col.id(), index);
|
await gridView.showColumn(col.id(), index);
|
||||||
},
|
},
|
||||||
col.label(),
|
col.label(),
|
||||||
|
testId('new-columns-menu-hidden-column-inlined'),
|
||||||
)
|
)
|
||||||
),
|
),
|
||||||
];
|
];
|
||||||
@ -84,13 +72,18 @@ function buildHiddenColumnsMenuItems(gridView: GridView, index?: number) {
|
|||||||
return searchableMenu(
|
return searchableMenu(
|
||||||
hiddenColumns.map((col) => ({
|
hiddenColumns.map((col) => ({
|
||||||
cleanText: col.label().trim().toLowerCase(),
|
cleanText: col.label().trim().toLowerCase(),
|
||||||
builder: () => menuItemTrimmed(() => gridView.showColumn(col.id(), index), col.label())
|
builder: () => menuItemTrimmed(
|
||||||
|
() => gridView.showColumn(col.id(), index),
|
||||||
|
col.label(),
|
||||||
|
testId('new-columns-menu-hidden-column-collapsed'),
|
||||||
|
)
|
||||||
})),
|
})),
|
||||||
{searchInputPlaceholder: t('Search columns')}
|
{searchInputPlaceholder: t('Search columns')}
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
{allowNothingSelected: true},
|
{allowNothingSelected: true},
|
||||||
t('Hidden Columns'),
|
t('Hidden Columns'),
|
||||||
|
testId('new-columns-menu-hidden-columns-menu')
|
||||||
),
|
),
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
@ -145,7 +138,10 @@ function buildTimestampMenuItems(gridView: GridView, index?: number) {
|
|||||||
t("Apply on record changes"),
|
t("Apply on record changes"),
|
||||||
testId('new-columns-menu-shortcuts-timestamp-change'),
|
testId('new-columns-menu-shortcuts-timestamp-change'),
|
||||||
),
|
),
|
||||||
], {}, t("Timestamp"), testId('new-columns-menu-shortcuts-timestamp'));
|
], {},
|
||||||
|
t("Timestamp"),
|
||||||
|
testId('new-columns-menu-shortcuts-timestamp')
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function buildAuthorshipMenuItems(gridView: GridView, index?: number) {
|
function buildAuthorshipMenuItems(gridView: GridView, index?: number) {
|
||||||
@ -291,7 +287,7 @@ function buildUUIDMenuItem(gridView: GridView, index?: number) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function menuLabelWithToast(label: string, toast: string) {
|
function menuLabelWithBadge(label: string, toast: string) {
|
||||||
return cssListLabel(
|
return cssListLabel(
|
||||||
cssListCol(label),
|
cssListCol(label),
|
||||||
cssListFun(toast));
|
cssListFun(toast));
|
||||||
@ -332,7 +328,7 @@ function buildLookupSection(gridView: GridView, index?: number){
|
|||||||
case 'count':
|
case 'count':
|
||||||
case 'sum': return `SUM(${referenceToSource}.${col.colId()})`;
|
case 'sum': return `SUM(${referenceToSource}.${col.colId()})`;
|
||||||
case 'percent':
|
case 'percent':
|
||||||
return `AVERAGE(map(int, ${referenceToSource}.${col.colId()})) if ${referenceToSource} else 0`;
|
return `AVERAGE(map(int, ${referenceToSource}.${col.colId()})) if ${referenceToSource} else None`;
|
||||||
default: return `${referenceToSource}`;
|
default: return `${referenceToSource}`;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -365,8 +361,6 @@ function buildLookupSection(gridView: GridView, index?: number){
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
function buildLookupsMenuItems() {
|
function buildLookupsMenuItems() {
|
||||||
// Function that builds a menu for one of our Ref columns, we will show all columns
|
// Function that builds a menu for one of our Ref columns, we will show all columns
|
||||||
// from the referenced table and offer to create a formula column with aggregation in case
|
// from the referenced table and offer to create a formula column with aggregation in case
|
||||||
@ -383,7 +377,7 @@ function buildLookupSection(gridView: GridView, index?: number){
|
|||||||
} else {
|
} else {
|
||||||
// For RefList column we will show the column name and the aggregation function which is the first
|
// For RefList column we will show the column name and the aggregation function which is the first
|
||||||
// on of suggested action (and a default action).
|
// on of suggested action (and a default action).
|
||||||
label = menuLabelWithToast(col.label(), suggestAggregation(col)[0]);
|
label = menuLabelWithBadge(col.label(), suggestAggregation(col)[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
@ -394,14 +388,36 @@ function buildLookupSection(gridView: GridView, index?: number){
|
|||||||
function buildItem() {
|
function buildItem() {
|
||||||
if (ref.pureType() === 'Ref') {
|
if (ref.pureType() === 'Ref') {
|
||||||
// Just insert a plain menu item that will insert a formula column with lookup.
|
// Just insert a plain menu item that will insert a formula column with lookup.
|
||||||
return menuItemTrimmed(() => insertPlainLookup(), col.label());
|
return menuItemTrimmed(
|
||||||
} else {
|
() => insertPlainLookup(), col.label(),
|
||||||
// Built nested menu.
|
testId(`new-columns-menu-lookup-column`),
|
||||||
return menuItemSubmenu(
|
testId(`new-columns-menu-lookup-column-${col.colId()}`),
|
||||||
() => suggestAggregation(col).map((fun) => menuItem(() => insertAggLookup(fun), fun)),
|
|
||||||
{},
|
|
||||||
label
|
|
||||||
);
|
);
|
||||||
|
} else {
|
||||||
|
// Depending on the number of aggregation functions we will either create a plain menu item
|
||||||
|
// or submenu with all the functions.
|
||||||
|
const functions = suggestAggregation(col);
|
||||||
|
if (functions.length === 1) {
|
||||||
|
const action = () => insertAggLookup(functions[0]);
|
||||||
|
return menuItem(action, label,
|
||||||
|
testId(`new-columns-menu-lookup-column`),
|
||||||
|
testId(`new-columns-menu-lookup-column-${col.colId()}`)
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
return menuItemSubmenu(
|
||||||
|
() => functions.map((fun) => menuItem(
|
||||||
|
() => insertAggLookup(fun), fun,
|
||||||
|
testId(`new-columns-menu-lookup-submenu-function`),
|
||||||
|
testId(`new-columns-menu-lookup-submenu-function-${fun}`),
|
||||||
|
)),
|
||||||
|
{
|
||||||
|
action: () => insertAggLookup(suggestAggregation(col)[0]),
|
||||||
|
},
|
||||||
|
label,
|
||||||
|
testId(`new-columns-menu-lookup-submenu`),
|
||||||
|
testId(`new-columns-menu-lookup-submenu-${col.colId()}`),
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -451,7 +467,8 @@ function buildLookupSection(gridView: GridView, index?: number){
|
|||||||
),
|
),
|
||||||
{allowNothingSelected: true},
|
{allowNothingSelected: true},
|
||||||
`${ref.refTable()?.tableNameDef()} [${ref.label()}]`,
|
`${ref.refTable()?.tableNameDef()} [${ref.label()}]`,
|
||||||
testId(`new-columns-menu-lookups-${ref.colId()}`),
|
testId(`new-columns-menu-lookup-${ref.colId()}`),
|
||||||
|
testId(`new-columns-menu-lookup`),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -463,6 +480,7 @@ function buildLookupSection(gridView: GridView, index?: number){
|
|||||||
}
|
}
|
||||||
|
|
||||||
function buildReverseLookupsMenuItems() {
|
function buildReverseLookupsMenuItems() {
|
||||||
|
|
||||||
const getReferencesToThisTable = (): RefTable[] => {
|
const getReferencesToThisTable = (): RefTable[] => {
|
||||||
const {viewSection} = gridView;
|
const {viewSection} = gridView;
|
||||||
const otherTables = gridView.gristDoc.docModel.allTables.all().filter((tab) =>
|
const otherTables = gridView.gristDoc.docModel.allTables.all().filter((tab) =>
|
||||||
@ -473,16 +491,16 @@ function buildLookupSection(gridView: GridView, index?: number){
|
|||||||
tableName: tab.tableNameDef(),
|
tableName: tab.tableNameDef(),
|
||||||
columns: tab.visibleColumns(),
|
columns: tab.visibleColumns(),
|
||||||
referenceFields:
|
referenceFields:
|
||||||
tab.columns().peek().filter((c) => (c.pureType() === 'Ref' || c.pureType() == 'RefList') &&
|
tab.visibleColumns.peek().filter((c) => (c.pureType() === 'Ref' || c.pureType() == 'RefList') &&
|
||||||
c.refTable()?.tableId() === viewSection.tableId())
|
c.refTable()?.tableId() === viewSection.tableId())
|
||||||
};
|
};
|
||||||
})
|
})
|
||||||
.filter((tab) => tab.referenceFields.length > 0);
|
.filter((tab) => tab.referenceFields.length > 0);
|
||||||
};
|
};
|
||||||
|
|
||||||
const buildColumn = async (tab: RefTable, col: ColumnRec, refCol: ColumnRec, aggregate: string) => {
|
const insertColumn = async (tab: RefTable, col: ColumnRec, refCol: ColumnRec, aggregate: string) => {
|
||||||
const formula = `${tab.tableId}.lookupRecords(${refCol.colId()}=
|
const formula =
|
||||||
${refCol.pureType() == 'RefList' ? 'CONTAINS($id)' : '$id'})`;
|
`${tab.tableId}.lookupRecords(${refCol.colId()}=${refCol.pureType() == 'RefList' ? 'CONTAINS($id)' : '$id'})`;
|
||||||
await gridView.insertColumn(`${tab.tableId}_${col.label()}`, {
|
await gridView.insertColumn(`${tab.tableId}_${col.label()}`, {
|
||||||
colInfo: {
|
colInfo: {
|
||||||
label: `${tab.tableId}_${col.label()}`,
|
label: `${tab.tableId}_${col.label()}`,
|
||||||
@ -495,41 +513,51 @@ function buildLookupSection(gridView: GridView, index?: number){
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
const buildSubmenuForRevLookup = (tab: RefTable, refCol: any) => {
|
const tablesWithAnyRefColumn = getReferencesToThisTable();
|
||||||
|
return tablesWithAnyRefColumn.map((tab: RefTable) => tab.referenceFields.map((refCol) => {
|
||||||
const buildSubmenuForRevLookupMenuItem = (col: ColumnRec): SearchableMenuItem => {
|
const buildSubmenuForRevLookupMenuItem = (col: ColumnRec): SearchableMenuItem => {
|
||||||
const suggestedColumns = suggestAggregation(col);
|
const aggregationList = suggestAggregation(col);
|
||||||
const primarySuggestedColumn = suggestedColumns[0];
|
const firstAggregation = aggregationList[0];
|
||||||
|
if (!firstAggregation) {
|
||||||
|
throw new Error(`No aggregation suggested for column ${col.label()}`);
|
||||||
|
}
|
||||||
return {
|
return {
|
||||||
cleanText: col.label().trim().toLowerCase(),
|
cleanText: col.label().trim().toLowerCase(),
|
||||||
builder: () => {
|
builder: () => {
|
||||||
if (suggestedColumns.length === 1) {
|
const content = menuLabelWithBadge(col.label(), firstAggregation);
|
||||||
return menuItem(() => buildColumn(tab, col, refCol, primarySuggestedColumn),
|
// In case we have only one suggested column we will just insert it, and there is no,
|
||||||
menuLabelWithToast(col.label(), primarySuggestedColumn));
|
// need for submenu.
|
||||||
|
if (aggregationList.length === 1) {
|
||||||
|
const action = () => insertColumn(tab, col, refCol, firstAggregation);
|
||||||
|
return menuItem(action, content, testId('new-columns-menu-revlookup-column'));
|
||||||
} else {
|
} else {
|
||||||
return menuItemSubmenu((ctl) =>
|
// We have some other suggested columns, we will build submenu for them.
|
||||||
suggestedColumns.map(fun =>
|
const submenu = () => {
|
||||||
menuItem(async () =>
|
const items = aggregationList.map((fun) => {
|
||||||
buildColumn(tab, col, refCol, fun), t(fun)))
|
const action = () => insertColumn(tab, col, refCol, fun);
|
||||||
, {}, menuLabelWithToast(col.label(), primarySuggestedColumn));
|
return menuItem(action, fun, testId('new-columns-menu-revlookup-column-function'));
|
||||||
}
|
});
|
||||||
}
|
return items;
|
||||||
};
|
};
|
||||||
};
|
const options = {};
|
||||||
|
|
||||||
return menuItemSubmenu(
|
return menuItemSubmenu(
|
||||||
() =>
|
submenu,
|
||||||
searchableMenu(
|
options,
|
||||||
tab.columns.map(col => buildSubmenuForRevLookupMenuItem(col)),
|
content,
|
||||||
{searchInputPlaceholder: t('Search columns')}
|
testId('new-columns-menu-revlookup-submenu'),
|
||||||
),
|
);
|
||||||
{allowNothingSelected: true}, `${tab.tableName} [← ${refCol.label()}]`);
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
};
|
||||||
const tablesWithAnyRefColumn = getReferencesToThisTable();
|
const label = `${tab.tableName} [← ${refCol.label()}]`;
|
||||||
return tablesWithAnyRefColumn.map((tab: RefTable) => tab.referenceFields.map((refCol) =>
|
const options = {allowNothingSelected: true};
|
||||||
buildSubmenuForRevLookup(tab, refCol)
|
const submenu = () => {
|
||||||
));
|
const subItems = tab.columns.map(buildSubmenuForRevLookupMenuItem);
|
||||||
|
return searchableMenu(subItems, {searchInputPlaceholder: t('Search columns')});
|
||||||
|
};
|
||||||
|
return menuItemSubmenu(submenu, options, label, testId('new-columns-menu-revlookup'));
|
||||||
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
const lookupMenu = buildLookupsMenuItems();
|
const lookupMenu = buildLookupsMenuItems();
|
||||||
|
@ -701,9 +701,6 @@ export interface GristLoadConfig {
|
|||||||
|
|
||||||
permittedCustomWidgets?: IAttachedCustomWidget[];
|
permittedCustomWidgets?: IAttachedCustomWidget[];
|
||||||
|
|
||||||
// Feature flag for the new column menu.
|
|
||||||
gristNewColumnMenu?: boolean;
|
|
||||||
|
|
||||||
// Used to determine which disclosure links should be provided to user of
|
// Used to determine which disclosure links should be provided to user of
|
||||||
// formula assistance.
|
// formula assistance.
|
||||||
assistantService?: 'OpenAI' | undefined;
|
assistantService?: 'OpenAI' | undefined;
|
||||||
|
@ -80,7 +80,6 @@ export function makeGristConfig(options: MakeGristConfigOptions): GristLoadConfi
|
|||||||
featureFormulaAssistant: Boolean(process.env.OPENAI_API_KEY || process.env.ASSISTANT_CHAT_COMPLETION_ENDPOINT),
|
featureFormulaAssistant: Boolean(process.env.OPENAI_API_KEY || process.env.ASSISTANT_CHAT_COMPLETION_ENDPOINT),
|
||||||
assistantService: process.env.OPENAI_API_KEY ? 'OpenAI' : undefined,
|
assistantService: process.env.OPENAI_API_KEY ? 'OpenAI' : undefined,
|
||||||
permittedCustomWidgets: getPermittedCustomWidgets(server),
|
permittedCustomWidgets: getPermittedCustomWidgets(server),
|
||||||
gristNewColumnMenu: isAffirmative(process.env.GRIST_NEW_COLUMN_MENU),
|
|
||||||
supportEmail: SUPPORT_EMAIL,
|
supportEmail: SUPPORT_EMAIL,
|
||||||
userLocale: (req as RequestWithLogin | undefined)?.user?.options?.locale,
|
userLocale: (req as RequestWithLogin | undefined)?.user?.options?.locale,
|
||||||
telemetry: server?.getTelemetry().getTelemetryConfig(req as RequestWithLogin | undefined),
|
telemetry: server?.getTelemetry().getTelemetryConfig(req as RequestWithLogin | undefined),
|
||||||
|
@ -10,7 +10,6 @@ processes = []
|
|||||||
APP_STATIC_URL="https://{APP_NAME}.fly.dev"
|
APP_STATIC_URL="https://{APP_NAME}.fly.dev"
|
||||||
ALLOWED_WEBHOOK_DOMAINS="webhook.site"
|
ALLOWED_WEBHOOK_DOMAINS="webhook.site"
|
||||||
PERMITTED_CUSTOM_WIDGETS="calendar"
|
PERMITTED_CUSTOM_WIDGETS="calendar"
|
||||||
GRIST_NEW_COLUMN_MENU="true"
|
|
||||||
GRIST_SINGLE_ORG="docs"
|
GRIST_SINGLE_ORG="docs"
|
||||||
PORT = "8080"
|
PORT = "8080"
|
||||||
FLY_DEPLOY_EXPIRATION = "{FLY_DEPLOY_EXPIRATION}"
|
FLY_DEPLOY_EXPIRATION = "{FLY_DEPLOY_EXPIRATION}"
|
||||||
|
@ -461,6 +461,7 @@ describe('CellColor', function() {
|
|||||||
it('should handle correctly default text color', async function() {
|
it('should handle correctly default text color', async function() {
|
||||||
// Create new checkbox column
|
// Create new checkbox column
|
||||||
await driver.find('.mod-add-column').click();
|
await driver.find('.mod-add-column').click();
|
||||||
|
await driver.find('.test-new-columns-menu-add-new').click();
|
||||||
await gu.waitForServer();
|
await gu.waitForServer();
|
||||||
await gu.setType(/Toggle/);
|
await gu.setType(/Toggle/);
|
||||||
|
|
||||||
@ -497,6 +498,8 @@ describe('CellColor', function() {
|
|||||||
|
|
||||||
// create a new checkbox column
|
// create a new checkbox column
|
||||||
await driver.find('.mod-add-column').click();
|
await driver.find('.mod-add-column').click();
|
||||||
|
await driver.find('.test-new-columns-menu-add-new').click();
|
||||||
|
|
||||||
await gu.waitForServer();
|
await gu.waitForServer();
|
||||||
await gu.setType(/Toggle/);
|
await gu.setType(/Toggle/);
|
||||||
|
|
||||||
|
@ -18,6 +18,7 @@ describe('ColumnOps.ntest', function() {
|
|||||||
|
|
||||||
it("should allow adding and deleting columns", async function() {
|
it("should allow adding and deleting columns", async function() {
|
||||||
await gu.clickColumnMenuItem('Name', 'Insert column to the right');
|
await gu.clickColumnMenuItem('Name', 'Insert column to the right');
|
||||||
|
await $('.test-new-columns-menu-add-new').click();
|
||||||
await gu.waitForServer();
|
await gu.waitForServer();
|
||||||
// Newly created columns labels become editable automatically. The next line checks that the
|
// Newly created columns labels become editable automatically. The next line checks that the
|
||||||
// label is editable and then closes the editor.
|
// label is editable and then closes the editor.
|
||||||
@ -78,7 +79,7 @@ describe('ColumnOps.ntest', function() {
|
|||||||
// Then show it using the add column menu
|
// Then show it using the add column menu
|
||||||
await $('.mod-add-column').scrollIntoView(true);
|
await $('.mod-add-column').scrollIntoView(true);
|
||||||
await $(".mod-add-column").click();
|
await $(".mod-add-column").click();
|
||||||
await gu.actions.selectFloatingOption('Show column Name');
|
await showColumn('Name');
|
||||||
await gu.waitForServer();
|
await gu.waitForServer();
|
||||||
await assert.isPresent(gu.getColumnHeader('Name'), true);
|
await assert.isPresent(gu.getColumnHeader('Name'), true);
|
||||||
});
|
});
|
||||||
@ -86,13 +87,14 @@ describe('ColumnOps.ntest', function() {
|
|||||||
it("[+] button show add column directly if no hidden columns", async function() {
|
it("[+] button show add column directly if no hidden columns", async function() {
|
||||||
await $('.mod-add-column').scrollIntoView(true);
|
await $('.mod-add-column').scrollIntoView(true);
|
||||||
await $(".mod-add-column").click();
|
await $(".mod-add-column").click();
|
||||||
await gu.actions.selectFloatingOption('Show column Pop');
|
await showColumn("Pop");
|
||||||
await gu.waitForServer();
|
await gu.waitForServer();
|
||||||
await assert.isPresent(gu.getColumnHeader("Pop. '000"), true);
|
await assert.isPresent(gu.getColumnHeader("Pop. '000"), true);
|
||||||
|
|
||||||
await assert.isPresent(gu.getColumnHeader('B'), false);
|
await assert.isPresent(gu.getColumnHeader('B'), false);
|
||||||
await $('.mod-add-column').scrollIntoView(true);
|
await $('.mod-add-column').scrollIntoView(true);
|
||||||
await $(".mod-add-column").click();
|
await $(".mod-add-column").click();
|
||||||
|
await $('.test-new-columns-menu-add-new').click();
|
||||||
await gu.waitToPass(() => gu.getColumnHeader('B'));
|
await gu.waitToPass(() => gu.getColumnHeader('B'));
|
||||||
await gu.getOpenEditingLabel(await gu.getColumnHeader('B')).wait().sendKeys($.ENTER);
|
await gu.getOpenEditingLabel(await gu.getColumnHeader('B')).wait().sendKeys($.ENTER);
|
||||||
await gu.waitForServer();
|
await gu.waitForServer();
|
||||||
@ -273,3 +275,7 @@ describe('ColumnOps.ntest', function() {
|
|||||||
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
function showColumn(name) {
|
||||||
|
return $(`.test-new-columns-menu-hidden-column-inlined:contains(${name})`).click();
|
||||||
|
}
|
||||||
|
@ -577,6 +577,7 @@ async function clickAddDescription() {
|
|||||||
|
|
||||||
async function addColumn() {
|
async function addColumn() {
|
||||||
await driver.find(".mod-add-column").click();
|
await driver.find(".mod-add-column").click();
|
||||||
|
await driver.find('.test-new-columns-menu-add-new').click();
|
||||||
await gu.waitForServer();
|
await gu.waitForServer();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -129,23 +129,23 @@ describe('MultiColumn', function() {
|
|||||||
|
|
||||||
it('should show proper behavior label', async () => {
|
it('should show proper behavior label', async () => {
|
||||||
await selectColumns('Test1');
|
await selectColumns('Test1');
|
||||||
assert.equal(await columnBehavior(), 'Empty Column');
|
assert.equal(await gu.columnBehavior(), 'Empty Column');
|
||||||
await selectColumns('Test1', 'Test3');
|
await selectColumns('Test1', 'Test3');
|
||||||
assert.equal(await columnBehavior(), 'Empty Columns');
|
assert.equal(await gu.columnBehavior(), 'Empty Columns');
|
||||||
|
|
||||||
// Change first to be data column.
|
// Change first to be data column.
|
||||||
await selectColumns('Test1');
|
await selectColumns('Test1');
|
||||||
await driver.find(".test-field-set-data").click();
|
await driver.find(".test-field-set-data").click();
|
||||||
await gu.waitForServer();
|
await gu.waitForServer();
|
||||||
await selectColumns('Test1', 'Test3');
|
await selectColumns('Test1', 'Test3');
|
||||||
assert.equal(await columnBehavior(), 'Mixed Behavior');
|
assert.equal(await gu.columnBehavior(), 'Mixed Behavior');
|
||||||
|
|
||||||
// Change second to be a data column
|
// Change second to be a data column
|
||||||
await selectColumns('Test2');
|
await selectColumns('Test2');
|
||||||
await driver.find(".test-field-set-data").click();
|
await driver.find(".test-field-set-data").click();
|
||||||
await gu.waitForServer();
|
await gu.waitForServer();
|
||||||
await selectColumns('Test1', 'Test2');
|
await selectColumns('Test1', 'Test2');
|
||||||
assert.equal(await columnBehavior(), 'Data Columns');
|
assert.equal(await gu.columnBehavior(), 'Data Columns');
|
||||||
// Now make them all formulas
|
// Now make them all formulas
|
||||||
await gu.sendActions([
|
await gu.sendActions([
|
||||||
['ModifyColumn', 'Table1', 'Test1', {formula: '1', isFormula: true}],
|
['ModifyColumn', 'Table1', 'Test1', {formula: '1', isFormula: true}],
|
||||||
@ -153,13 +153,13 @@ describe('MultiColumn', function() {
|
|||||||
['ModifyColumn', 'Table1', 'Test3', {formula: '1', isFormula: true}],
|
['ModifyColumn', 'Table1', 'Test3', {formula: '1', isFormula: true}],
|
||||||
]);
|
]);
|
||||||
await selectColumns('Test1', 'Test3');
|
await selectColumns('Test1', 'Test3');
|
||||||
assert.equal(await columnBehavior(), 'Formula Columns');
|
assert.equal(await gu.columnBehavior(), 'Formula Columns');
|
||||||
|
|
||||||
// Make one of them data column and test that the mix is recognized.
|
// Make one of them data column and test that the mix is recognized.
|
||||||
await selectColumns('Test1');
|
await selectColumns('Test1');
|
||||||
await gu.changeBehavior('Convert column to data');
|
await gu.changeBehavior('Convert column to data');
|
||||||
await selectColumns('Test1', 'Test3');
|
await selectColumns('Test1', 'Test3');
|
||||||
assert.equal(await columnBehavior(), 'Mixed Behavior');
|
assert.equal(await gu.columnBehavior(), 'Mixed Behavior');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should reset multiple columns', async () => {
|
it('should reset multiple columns', async () => {
|
||||||
@ -170,14 +170,14 @@ describe('MultiColumn', function() {
|
|||||||
['ModifyColumn', 'Table1', 'Test3', {formula: '1', isFormula: true}],
|
['ModifyColumn', 'Table1', 'Test3', {formula: '1', isFormula: true}],
|
||||||
]);
|
]);
|
||||||
await selectColumns('Test1', 'Test3');
|
await selectColumns('Test1', 'Test3');
|
||||||
assert.equal(await columnBehavior(), 'Formula Columns');
|
assert.equal(await gu.columnBehavior(), 'Formula Columns');
|
||||||
await alignment('center');
|
await alignment('center');
|
||||||
assert.equal(await alignment(), 'center');
|
assert.equal(await alignment(), 'center');
|
||||||
|
|
||||||
// Reset all of them
|
// Reset all of them
|
||||||
assert.deepEqual(await gu.availableBehaviorOptions(), ['Convert columns to data', 'Clear and reset']);
|
assert.deepEqual(await gu.availableBehaviorOptions(), ['Convert columns to data', 'Clear and reset']);
|
||||||
await gu.changeBehavior('Clear and reset');
|
await gu.changeBehavior('Clear and reset');
|
||||||
assert.equal(await columnBehavior(), 'Empty Columns');
|
assert.equal(await gu.columnBehavior(), 'Empty Columns');
|
||||||
assert.equal(await alignment(), 'left');
|
assert.equal(await alignment(), 'left');
|
||||||
|
|
||||||
// Make them all data columns
|
// Make them all data columns
|
||||||
@ -185,17 +185,17 @@ describe('MultiColumn', function() {
|
|||||||
await gu.getCell('Test2', 1).click(); await gu.enterCell('a');
|
await gu.getCell('Test2', 1).click(); await gu.enterCell('a');
|
||||||
await gu.getCell('Test3', 1).click(); await gu.enterCell('a');
|
await gu.getCell('Test3', 1).click(); await gu.enterCell('a');
|
||||||
await selectColumns('Test1', 'Test3');
|
await selectColumns('Test1', 'Test3');
|
||||||
assert.equal(await columnBehavior(), 'Data Columns');
|
assert.equal(await gu.columnBehavior(), 'Data Columns');
|
||||||
await selectColumns('Test1');
|
await selectColumns('Test1');
|
||||||
assert.equal(await columnBehavior(), 'Data Column');
|
assert.equal(await gu.columnBehavior(), 'Data Column');
|
||||||
|
|
||||||
// Reset all of them
|
// Reset all of them
|
||||||
await selectColumns('Test1', 'Test3');
|
await selectColumns('Test1', 'Test3');
|
||||||
assert.deepEqual(await gu.availableBehaviorOptions(), ['Clear and reset']);
|
assert.deepEqual(await gu.availableBehaviorOptions(), ['Clear and reset']);
|
||||||
await gu.changeBehavior('Clear and reset');
|
await gu.changeBehavior('Clear and reset');
|
||||||
assert.equal(await columnBehavior(), 'Empty Columns');
|
assert.equal(await gu.columnBehavior(), 'Empty Columns');
|
||||||
await selectColumns('Test1');
|
await selectColumns('Test1');
|
||||||
assert.equal(await columnBehavior(), 'Empty Column');
|
assert.equal(await gu.columnBehavior(), 'Empty Column');
|
||||||
assert.equal(await gu.getCell('Test1', 1).getText(), '');
|
assert.equal(await gu.getCell('Test1', 1).getText(), '');
|
||||||
assert.equal(await gu.getCell('Test2', 1).getText(), '');
|
assert.equal(await gu.getCell('Test2', 1).getText(), '');
|
||||||
assert.equal(await gu.getCell('Test3', 1).getText(), '');
|
assert.equal(await gu.getCell('Test3', 1).getText(), '');
|
||||||
@ -203,12 +203,12 @@ describe('MultiColumn', function() {
|
|||||||
|
|
||||||
it('should convert to data multiple columns', async () => {
|
it('should convert to data multiple columns', async () => {
|
||||||
await selectColumns('Test1', 'Test3');
|
await selectColumns('Test1', 'Test3');
|
||||||
assert.equal(await columnBehavior(), 'Empty Columns');
|
assert.equal(await gu.columnBehavior(), 'Empty Columns');
|
||||||
assert.deepEqual(await gu.availableBehaviorOptions(), ['Convert columns to data', 'Clear and reset']);
|
assert.deepEqual(await gu.availableBehaviorOptions(), ['Convert columns to data', 'Clear and reset']);
|
||||||
await gu.changeBehavior('Convert columns to data');
|
await gu.changeBehavior('Convert columns to data');
|
||||||
assert.equal(await columnBehavior(), 'Data Columns');
|
assert.equal(await gu.columnBehavior(), 'Data Columns');
|
||||||
await selectColumns('Test1');
|
await selectColumns('Test1');
|
||||||
assert.equal(await columnBehavior(), 'Data Column');
|
assert.equal(await gu.columnBehavior(), 'Data Column');
|
||||||
|
|
||||||
// Now make them all formula columns
|
// Now make them all formula columns
|
||||||
await gu.sendActions([
|
await gu.sendActions([
|
||||||
@ -217,14 +217,14 @@ describe('MultiColumn', function() {
|
|||||||
['ModifyColumn', 'Table1', 'Test3', {formula: '3', isFormula: true}],
|
['ModifyColumn', 'Table1', 'Test3', {formula: '3', isFormula: true}],
|
||||||
]);
|
]);
|
||||||
await selectColumns('Test1', 'Test3');
|
await selectColumns('Test1', 'Test3');
|
||||||
assert.equal(await columnBehavior(), 'Formula Columns');
|
assert.equal(await gu.columnBehavior(), 'Formula Columns');
|
||||||
|
|
||||||
// Convert them to data
|
// Convert them to data
|
||||||
assert.deepEqual(await gu.availableBehaviorOptions(), ['Convert columns to data', 'Clear and reset']);
|
assert.deepEqual(await gu.availableBehaviorOptions(), ['Convert columns to data', 'Clear and reset']);
|
||||||
await gu.changeBehavior('Convert columns to data');
|
await gu.changeBehavior('Convert columns to data');
|
||||||
assert.equal(await columnBehavior(), 'Data Columns');
|
assert.equal(await gu.columnBehavior(), 'Data Columns');
|
||||||
await selectColumns('Test1');
|
await selectColumns('Test1');
|
||||||
assert.equal(await columnBehavior(), 'Data Column');
|
assert.equal(await gu.columnBehavior(), 'Data Column');
|
||||||
// Test that data stays.
|
// Test that data stays.
|
||||||
assert.equal(await gu.getCell('Test1', 1).getText(), '1');
|
assert.equal(await gu.getCell('Test1', 1).getText(), '1');
|
||||||
assert.equal(await gu.getCell('Test2', 1).getText(), '2');
|
assert.equal(await gu.getCell('Test2', 1).getText(), '2');
|
||||||
@ -1250,9 +1250,7 @@ async function toggleDerived() {
|
|||||||
await gu.waitForServer();
|
await gu.waitForServer();
|
||||||
}
|
}
|
||||||
|
|
||||||
async function columnBehavior() {
|
|
||||||
return (await driver.find(".test-field-behaviour").getText());
|
|
||||||
}
|
|
||||||
|
|
||||||
async function wrapDisabled() {
|
async function wrapDisabled() {
|
||||||
return (await driver.find(".test-tb-wrap-text > div").matches('[class*=disabled]'));
|
return (await driver.find(".test-tb-wrap-text > div").matches('[class*=disabled]'));
|
||||||
|
@ -20,6 +20,7 @@ describe('ReferenceColumns', function() {
|
|||||||
it('should render Row ID values as TableId[RowId]', async function() {
|
it('should render Row ID values as TableId[RowId]', async function() {
|
||||||
await driver.find('.test-right-tab-field').click();
|
await driver.find('.test-right-tab-field').click();
|
||||||
await driver.find('.mod-add-column').click();
|
await driver.find('.mod-add-column').click();
|
||||||
|
await driver.findWait('.test-new-columns-menu-add-new', 100).click();
|
||||||
await gu.waitForServer();
|
await gu.waitForServer();
|
||||||
await gu.setType(/Reference/);
|
await gu.setType(/Reference/);
|
||||||
await gu.waitForServer();
|
await gu.waitForServer();
|
||||||
|
@ -253,6 +253,8 @@ describe('ReferenceList', function() {
|
|||||||
// Create a new Reference List column.
|
// Create a new Reference List column.
|
||||||
await driver.find('.test-right-tab-field').click();
|
await driver.find('.test-right-tab-field').click();
|
||||||
await driver.find('.mod-add-column').click();
|
await driver.find('.mod-add-column').click();
|
||||||
|
await driver.findWait('.test-new-columns-menu-add-new', 100).click();
|
||||||
|
|
||||||
await gu.waitForServer();
|
await gu.waitForServer();
|
||||||
await gu.setType(/Reference List/);
|
await gu.setType(/Reference List/);
|
||||||
await gu.waitForServer();
|
await gu.waitForServer();
|
||||||
|
@ -133,6 +133,7 @@ describe('TextEditor.ntest', function() {
|
|||||||
async function addColumnRightOf(index) {
|
async function addColumnRightOf(index) {
|
||||||
// Add a column. We have to hover over the column header first.
|
// Add a column. We have to hover over the column header first.
|
||||||
await gu.openColumnMenu({col: index}, 'Insert column to the right');
|
await gu.openColumnMenu({col: index}, 'Insert column to the right');
|
||||||
|
await driver.find('.test-new-columns-menu-add-new').click();
|
||||||
await gu.waitForServer();
|
await gu.waitForServer();
|
||||||
await gu.sendKeys($.ESCAPE);
|
await gu.sendKeys($.ESCAPE);
|
||||||
}
|
}
|
||||||
|
@ -16,7 +16,6 @@ import {CommandName} from 'app/client/components/commandList';
|
|||||||
import {csvDecodeRow} from 'app/common/csvFormat';
|
import {csvDecodeRow} from 'app/common/csvFormat';
|
||||||
import { AccessLevel } from 'app/common/CustomWidget';
|
import { AccessLevel } from 'app/common/CustomWidget';
|
||||||
import { decodeUrl } from 'app/common/gristUrls';
|
import { decodeUrl } from 'app/common/gristUrls';
|
||||||
import { isAffirmative } from "app/common/gutil";
|
|
||||||
import { FullUser, UserProfile } from 'app/common/LoginSessionAPI';
|
import { FullUser, UserProfile } from 'app/common/LoginSessionAPI';
|
||||||
import { resetOrg } from 'app/common/resetOrg';
|
import { resetOrg } from 'app/common/resetOrg';
|
||||||
import { UserAction } from 'app/common/DocActions';
|
import { UserAction } from 'app/common/DocActions';
|
||||||
@ -689,20 +688,26 @@ export async function enterFormula(formula: string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check that formula editor is shown and its value matches the given regexp.
|
* Check that formula editor is shown and returns its value.
|
||||||
|
* By default returns only text that is visible to the user, pass false to get all text.
|
||||||
*/
|
*/
|
||||||
export async function getFormulaText() {
|
export async function getFormulaText(onlyVisible = true): Promise<string> {
|
||||||
assert.equal(await driver.findWait('.test-formula-editor', 500).isDisplayed(), true);
|
assert.equal(await driver.findWait('.test-formula-editor', 500).isDisplayed(), true);
|
||||||
|
if (onlyVisible) {
|
||||||
return await driver.find('.code_editor_container').getText();
|
return await driver.find('.code_editor_container').getText();
|
||||||
|
} else {
|
||||||
|
return await driver.executeScript(
|
||||||
|
() => (document as any).querySelector(".code_editor_container").innerText
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check that formula editor is shown and its value matches the given regexp.
|
* Check that formula editor is shown and its value matches the given regexp.
|
||||||
*/
|
*/
|
||||||
export async function checkFormulaEditor(value: RegExp|string) {
|
export async function checkFormulaEditor(value: RegExp|string) {
|
||||||
assert.equal(await driver.findWait('.test-formula-editor', 500).isDisplayed(), true);
|
|
||||||
const valueRe = typeof value === 'string' ? exactMatch(value) : value;
|
const valueRe = typeof value === 'string' ? exactMatch(value) : value;
|
||||||
assert.match(await driver.find('.code_editor_container').getText(), valueRe);
|
assert.match(await getFormulaText(), valueRe);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -1291,6 +1296,40 @@ export async function begin(invariant: () => any = () => true) {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A hook that can be used to clear a state after suite is finished and current test passed.
|
||||||
|
* If under debugging session and NO_CLEANUP env variable is set it will skip this cleanup and allow you
|
||||||
|
* to examine the state of the database or browser.
|
||||||
|
*/
|
||||||
|
export function afterCleanup(test: () => void | Promise<void>) {
|
||||||
|
after(function() {
|
||||||
|
if (process.env.NO_CLEANUP) {
|
||||||
|
function anyTestFailed(suite: Mocha.Suite): boolean {
|
||||||
|
return suite.tests.some(t => t.state === 'failed') || suite.suites.some(anyTestFailed);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.currentTest?.parent && anyTestFailed(this.currentTest?.parent)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return test();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A hook that can be used to clear state after each test that has passed.
|
||||||
|
* If under debugging session and NO_CLEANUP env variable is set it will skip this cleanup and allow you
|
||||||
|
* to examine the state of the database or browser.
|
||||||
|
*/
|
||||||
|
export function afterEachCleanup(test: () => void | Promise<void>) {
|
||||||
|
afterEach(function() {
|
||||||
|
if (this.currentTest?.state !== 'passed' && !this.currentTest?.pending && process.env.NO_CLEANUP) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
return test();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Simulates a transaction on the GristDoc. Use with cautions, as there is no guarantee it will undo correctly
|
* Simulates a transaction on the GristDoc. Use with cautions, as there is no guarantee it will undo correctly
|
||||||
* in a case of failure.
|
* in a case of failure.
|
||||||
@ -1546,6 +1585,7 @@ export function openColumnMenu(col: IColHeader|string, option?: string): WebElem
|
|||||||
export async function deleteColumn(col: IColHeader|string) {
|
export async function deleteColumn(col: IColHeader|string) {
|
||||||
await openColumnMenu(col, 'Delete column');
|
await openColumnMenu(col, 'Delete column');
|
||||||
await waitForServer();
|
await waitForServer();
|
||||||
|
await wipeToasts();
|
||||||
}
|
}
|
||||||
|
|
||||||
export type ColumnType =
|
export type ColumnType =
|
||||||
@ -2339,9 +2379,7 @@ export function hexToRgb(hex: string) {
|
|||||||
export async function addColumn(name: string, type?: string) {
|
export async function addColumn(name: string, type?: string) {
|
||||||
await scrollIntoView(await driver.find('.active_section .mod-add-column'));
|
await scrollIntoView(await driver.find('.active_section .mod-add-column'));
|
||||||
await driver.find('.active_section .mod-add-column').click();
|
await driver.find('.active_section .mod-add-column').click();
|
||||||
if (isAffirmative(process.env.GRIST_NEW_COLUMN_MENU)) {
|
|
||||||
await driver.findWait('.test-new-columns-menu-add-new', 100).click();
|
await driver.findWait('.test-new-columns-menu-add-new', 100).click();
|
||||||
}
|
|
||||||
// If we are on a summary table, we could be see a menu helper
|
// If we are on a summary table, we could be see a menu helper
|
||||||
const menu = (await driver.findAll('.grist-floating-menu'))[0];
|
const menu = (await driver.findAll('.grist-floating-menu'))[0];
|
||||||
if (menu) {
|
if (menu) {
|
||||||
@ -2360,7 +2398,11 @@ export async function addColumn(name: string, type?: string) {
|
|||||||
export async function showColumn(name: string) {
|
export async function showColumn(name: string) {
|
||||||
await scrollIntoView(await driver.find('.active_section .mod-add-column'));
|
await scrollIntoView(await driver.find('.active_section .mod-add-column'));
|
||||||
await driver.find('.active_section .mod-add-column').click();
|
await driver.find('.active_section .mod-add-column').click();
|
||||||
await driver.findContent('.grist-floating-menu li', `Show column ${name}`).click();
|
if (await driver.findContent('.test-new-columns-menu-hidden-column-inlined', `${name}`).isPresent()) {
|
||||||
|
await driver.findContent('.test-new-columns-menu-hidden-column-inlined', `${name}`).click();
|
||||||
|
} else {
|
||||||
|
await driver.findContent('.test-new-columns-menu-hidden-column-collapsed', `${name}`).click();
|
||||||
|
}
|
||||||
await waitForServer();
|
await waitForServer();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2739,6 +2781,40 @@ export async function onNewTab(action: () => Promise<void>) {
|
|||||||
await driver.switchTo().window(tabs[tabs.length - 2]);
|
await driver.switchTo().window(tabs[tabs.length - 2]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a controller for the current tab.
|
||||||
|
*/
|
||||||
|
export async function myTab() {
|
||||||
|
const tabs = await driver.getAllWindowHandles();
|
||||||
|
const myTab = tabs[tabs.length - 1];
|
||||||
|
return {
|
||||||
|
open() {
|
||||||
|
return driver.switchTo().window(myTab);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Duplicate current tab and return a controller for it. Assumes the current tab shows document.
|
||||||
|
*/
|
||||||
|
export async function duplicateTab() {
|
||||||
|
const url = await driver.getCurrentUrl();
|
||||||
|
await driver.executeScript("window.open('about:blank', '_blank')");
|
||||||
|
const tabs = await driver.getAllWindowHandles();
|
||||||
|
const myTab = tabs[tabs.length - 1];
|
||||||
|
await driver.switchTo().window(myTab);
|
||||||
|
await driver.get(url);
|
||||||
|
await waitForDocToLoad();
|
||||||
|
return {
|
||||||
|
close() {
|
||||||
|
return driver.close();
|
||||||
|
},
|
||||||
|
open() {
|
||||||
|
return driver.switchTo().window(myTab);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Scrolls active Grid or Card list view.
|
* Scrolls active Grid or Card list view.
|
||||||
*/
|
*/
|
||||||
@ -3042,6 +3118,10 @@ export async function changeBehavior(option: BehaviorActions|RegExp) {
|
|||||||
await waitForServer();
|
await waitForServer();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export async function columnBehavior() {
|
||||||
|
return (await driver.find(".test-field-behaviour").getText());
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets all available options in the behavior menu.
|
* Gets all available options in the behavior menu.
|
||||||
*/
|
*/
|
||||||
@ -3426,15 +3506,15 @@ class Clipboard implements IClipboard {
|
|||||||
/**
|
/**
|
||||||
* Runs a Grist command in the browser window.
|
* Runs a Grist command in the browser window.
|
||||||
*/
|
*/
|
||||||
export async function sendCommand(name: CommandName) {
|
export async function sendCommand(name: CommandName, argument: any = null) {
|
||||||
await driver.executeAsyncScript((name: any, done: any) => {
|
await driver.executeAsyncScript((name: any, argument: any, done: any) => {
|
||||||
const result = (window as any).gristApp.allCommands[name].run();
|
const result = (window as any).gristApp.allCommands[name].run(argument);
|
||||||
if (result?.finally) {
|
if (result?.finally) {
|
||||||
result.finally(done);
|
result.finally(done);
|
||||||
} else {
|
} else {
|
||||||
done();
|
done();
|
||||||
}
|
}
|
||||||
}, name);
|
}, name, argument);
|
||||||
await waitForServer();
|
await waitForServer();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user