mirror of
https://github.com/gristlabs/grist-core.git
synced 2024-10-27 20:44:07 +00:00
Feat: rename all column label from a given row with right click (#848)
This commit is contained in:
parent
8b267c1e00
commit
f3f320a193
@ -55,6 +55,7 @@ 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 { isList } = require('app/common/gristTypes');
|
||||||
|
|
||||||
const t = makeT('GridView');
|
const t = makeT('GridView');
|
||||||
|
|
||||||
@ -345,6 +346,7 @@ GridView.gridCommands = {
|
|||||||
this.insertColumn(null, {index: this.cursor.fieldIndex() + 1});
|
this.insertColumn(null, {index: this.cursor.fieldIndex() + 1});
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
makeHeadersFromRow: function() { this.makeHeadersFromRow(this.getSelection()); },
|
||||||
renameField: function() { this.renameColumn(this.cursor.fieldIndex()); },
|
renameField: function() { this.renameColumn(this.cursor.fieldIndex()); },
|
||||||
hideFields: function() { this.hideFields(this.getSelection()); },
|
hideFields: function() { this.hideFields(this.getSelection()); },
|
||||||
deleteFields: function() {
|
deleteFields: function() {
|
||||||
@ -902,6 +904,38 @@ GridView.prototype.insertColumn = async function(colId = null, options = {}) {
|
|||||||
return newColInfo;
|
return newColInfo;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
GridView.prototype.makeHeadersFromRow = async function(selection) {
|
||||||
|
if (this._getCellContextMenuOptions().disableMakeHeadersFromRow){
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const record = this.tableModel.tableData.getRecord(selection.rowIds[0]);
|
||||||
|
const actions = this.viewSection.viewFields().peek().reduce((acc, field) => {
|
||||||
|
const col = field.column();
|
||||||
|
const colId = col.colId.peek();
|
||||||
|
let formatter = field.formatter();
|
||||||
|
let newColLabel = record[colId];
|
||||||
|
// Manage column that are references
|
||||||
|
if (col.refTable()) {
|
||||||
|
const refTableDisplayCol = this.gristDoc.docModel.columns.getRowModel(col.displayCol());
|
||||||
|
newColLabel = record[refTableDisplayCol.colId()];
|
||||||
|
formatter = field.visibleColFormatter();
|
||||||
|
}
|
||||||
|
// Manage column that are lists
|
||||||
|
if (isList(newColLabel)) {
|
||||||
|
newColLabel = newColLabel[1];
|
||||||
|
}
|
||||||
|
if (typeof newColLabel === 'string') {
|
||||||
|
newColLabel = newColLabel.trim();
|
||||||
|
}
|
||||||
|
// Check value is not empty but accept 0 and false as valid values
|
||||||
|
if (newColLabel !== null && newColLabel !== undefined && newColLabel !== "") {
|
||||||
|
return [...acc, ['ModifyColumn', colId, {"label": formatter.formatAny(newColLabel)}]];
|
||||||
|
}
|
||||||
|
return acc
|
||||||
|
}, []);
|
||||||
|
this.tableModel.sendTableActions(actions, "Use as table headers");
|
||||||
|
};
|
||||||
|
|
||||||
GridView.prototype.renameColumn = function(index) {
|
GridView.prototype.renameColumn = function(index) {
|
||||||
this.currentEditingColumnIndex(index);
|
this.currentEditingColumnIndex(index);
|
||||||
};
|
};
|
||||||
@ -1974,6 +2008,9 @@ GridView.prototype._getCellContextMenuOptions = function() {
|
|||||||
this.viewSection.disableAddRemoveRows() ||
|
this.viewSection.disableAddRemoveRows() ||
|
||||||
this.getSelection().onlyAddRowSelected()
|
this.getSelection().onlyAddRowSelected()
|
||||||
),
|
),
|
||||||
|
disableMakeHeadersFromRow: Boolean (
|
||||||
|
this.gristDoc.isReadonly.get() || this.getSelection().rowIds.length !== 1 || this.getSelection().onlyAddRowSelected()
|
||||||
|
),
|
||||||
isViewSorted: this.viewSection.activeSortSpec.peek().length > 0,
|
isViewSorted: this.viewSection.activeSortSpec.peek().length > 0,
|
||||||
numRows: this.getSelection().rowIds.length,
|
numRows: this.getSelection().rowIds.length,
|
||||||
};
|
};
|
||||||
|
@ -84,6 +84,7 @@ export type CommandName =
|
|||||||
| 'deleteRecords'
|
| 'deleteRecords'
|
||||||
| 'insertFieldBefore'
|
| 'insertFieldBefore'
|
||||||
| 'insertFieldAfter'
|
| 'insertFieldAfter'
|
||||||
|
| 'makeHeadersFromRow'
|
||||||
| 'renameField'
|
| 'renameField'
|
||||||
| 'hideFields'
|
| 'hideFields'
|
||||||
| 'hideCardFields'
|
| 'hideCardFields'
|
||||||
@ -562,6 +563,10 @@ export const groups: CommendGroupDef[] = [{
|
|||||||
name: 'insertFieldAfter',
|
name: 'insertFieldAfter',
|
||||||
keys: ['Alt+='],
|
keys: ['Alt+='],
|
||||||
desc: 'Insert a new column, after the currently selected one'
|
desc: 'Insert a new column, after the currently selected one'
|
||||||
|
}, {
|
||||||
|
name: 'makeHeadersFromRow',
|
||||||
|
keys: ['Mod+Shift+H'],
|
||||||
|
desc: 'Use currently selected line as table headers'
|
||||||
}, {
|
}, {
|
||||||
name: 'renameField',
|
name: 'renameField',
|
||||||
keys: ['Ctrl+m'],
|
keys: ['Ctrl+m'],
|
||||||
|
@ -8,6 +8,7 @@ const t = makeT('RowContextMenu');
|
|||||||
export interface IRowContextMenu {
|
export interface IRowContextMenu {
|
||||||
disableInsert: boolean;
|
disableInsert: boolean;
|
||||||
disableDelete: boolean;
|
disableDelete: boolean;
|
||||||
|
disableMakeHeadersFromRow: boolean;
|
||||||
disableShowRecordCard: boolean;
|
disableShowRecordCard: boolean;
|
||||||
isViewSorted: boolean;
|
isViewSorted: boolean;
|
||||||
numRows: number;
|
numRows: number;
|
||||||
@ -16,6 +17,7 @@ export interface IRowContextMenu {
|
|||||||
export function RowContextMenu({
|
export function RowContextMenu({
|
||||||
disableInsert,
|
disableInsert,
|
||||||
disableDelete,
|
disableDelete,
|
||||||
|
disableMakeHeadersFromRow,
|
||||||
disableShowRecordCard,
|
disableShowRecordCard,
|
||||||
isViewSorted,
|
isViewSorted,
|
||||||
numRows
|
numRows
|
||||||
@ -51,6 +53,11 @@ export function RowContextMenu({
|
|||||||
menuItemCmd(allCommands.duplicateRows, t('Duplicate rows', { count: numRows }),
|
menuItemCmd(allCommands.duplicateRows, t('Duplicate rows', { count: numRows }),
|
||||||
dom.cls('disabled', disableInsert || numRows === 0)),
|
dom.cls('disabled', disableInsert || numRows === 0)),
|
||||||
);
|
);
|
||||||
|
result.push(
|
||||||
|
menuDivider(),
|
||||||
|
menuItemCmd(allCommands.makeHeadersFromRow, t("Use as table headers"),
|
||||||
|
dom.cls('disabled', disableMakeHeadersFromRow)),
|
||||||
|
);
|
||||||
result.push(
|
result.push(
|
||||||
menuDivider(),
|
menuDivider(),
|
||||||
// TODO: should show `Delete ${num} rows` when multiple are selected
|
// TODO: should show `Delete ${num} rows` when multiple are selected
|
||||||
|
@ -665,7 +665,8 @@
|
|||||||
"Insert row": "Insert row",
|
"Insert row": "Insert row",
|
||||||
"Insert row above": "Insert row above",
|
"Insert row above": "Insert row above",
|
||||||
"Insert row below": "Insert row below",
|
"Insert row below": "Insert row below",
|
||||||
"View as card": "View as card"
|
"View as card": "View as card",
|
||||||
|
"Use as table headers": "Use as table headers"
|
||||||
},
|
},
|
||||||
"SelectionSummary": {
|
"SelectionSummary": {
|
||||||
"Copied to clipboard": "Copied to clipboard"
|
"Copied to clipboard": "Copied to clipboard"
|
||||||
|
@ -72,11 +72,22 @@ describe('RowMenu', function() {
|
|||||||
assert.isFalse(await driver.find('.grist-floating-menu').isPresent());
|
assert.isFalse(await driver.find('.grist-floating-menu').isPresent());
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('can rename headers from the selected line', async function() {
|
||||||
|
assert.notEqual(await gu.getColumnHeader({col: 0}).getText(), await gu.getCell(0, 1).getText());
|
||||||
|
assert.notEqual(await gu.getColumnHeader({col: 1}).getText(), await gu.getCell(1, 1).getText());
|
||||||
|
await (await gu.openRowMenu(1)).findContent('li', /Use as table headers/).click();
|
||||||
|
await gu.waitForServer();
|
||||||
|
assert.equal(await gu.getColumnHeader({col: 0}).getText(), await gu.getCell(0, 1).getText());
|
||||||
|
assert.equal(await gu.getColumnHeader({col: 1}).getText(), await gu.getCell(1, 1).getText());
|
||||||
|
});
|
||||||
|
|
||||||
it('should work even when no columns are visible', async function() {
|
it('should work even when no columns are visible', async function() {
|
||||||
// Previously, a bug would cause an error to be thrown instead.
|
// Previously, a bug would cause an error to be thrown instead.
|
||||||
await gu.openColumnMenu('A', 'Hide column');
|
await gu.openColumnMenu({col: 0}, 'Hide column');
|
||||||
await gu.openColumnMenu('B', 'Hide column');
|
// After hiding the first column, the second one will be the new first column.
|
||||||
|
await gu.openColumnMenu({col: 0}, 'Hide column');
|
||||||
await assertRowMenuOpensAndCloses();
|
await assertRowMenuOpensAndCloses();
|
||||||
await assertRowMenuOpensWithRightClick();
|
await assertRowMenuOpensWithRightClick();
|
||||||
});
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
|
Loading…
Reference in New Issue
Block a user