Skip to content

Commit

Permalink
[REF] helpers: introduce getUniqueText
Browse files Browse the repository at this point in the history
This commit adds the helper `getUniqueText`. This helper is used
to generate a unique text based on the given text and the existing
texts.

closes #5392

Task: 4440233
Signed-off-by: Rémi Rahir (rar) <[email protected]>
  • Loading branch information
pro-odoo committed Dec 31, 2024
1 parent e8c979c commit 37f2328
Show file tree
Hide file tree
Showing 11 changed files with 79 additions and 67 deletions.
19 changes: 19 additions & 0 deletions src/helpers/misc.ts
Original file line number Diff line number Diff line change
Expand Up @@ -653,3 +653,22 @@ export function transpose2dPOJO<T>(
}
return result;
}

export function getUniqueText(
text: string,
texts: string[],
options: {
compute?: (text: string, increment: number) => string;
start?: number;
computeFirstOne?: boolean;
} = {}
): string {
const compute = options.compute ?? ((text, i) => `${text} (${i})`);
const computeFirstOne = options.computeFirstOne ?? false;
let i = options.start ?? 1;
let newText = computeFirstOne ? compute(text, i) : text;
while (texts.includes(newText)) {
newText = compute(text, i++);
}
return newText;
}
12 changes: 5 additions & 7 deletions src/helpers/pivot/spreadsheet_pivot/spreadsheet_pivot.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ import {
import { InitPivotParams, Pivot } from "../../../types/pivot_runtime";
import { toXC } from "../../coordinates";
import { formatValue, isDateTimeFormat } from "../../format/format";
import { deepEquals, isDefined } from "../../misc";
import { deepEquals, getUniqueText, isDefined } from "../../misc";
import {
AGGREGATORS_FN,
areDomainArgsFieldsValid,
Expand Down Expand Up @@ -457,12 +457,10 @@ export class SpreadsheetPivot implements Pivot<SpreadsheetPivotRuntimeDefinition
* Take cares of double names
*/
private findName(name: string, fields: PivotFields) {
let increment = 1;
const initialName = name;
while (name in fields) {
name = `${initialName}${++increment}`;
}
return name;
return getUniqueText(name, Object.keys(fields), {
compute: (name, i) => `${name}${i}`,
start: 2,
});
}

private extractDataEntriesFromRange(range: Range): DataEntries {
Expand Down
2 changes: 2 additions & 0 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ import {
deepEquals,
expandZoneOnInsertion,
formatValue,
getUniqueText,
isDefined,
isInside,
isMarkdownLink,
Expand Down Expand Up @@ -340,6 +341,7 @@ export const helpers = {
areDomainArgsFieldsValid,
splitReference,
sanitizeSheetName,
getUniqueText,
};

export const links = {
Expand Down
11 changes: 4 additions & 7 deletions src/migrations/migration_steps.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { BACKGROUND_CHART_COLOR, FORMULA_REF_IDENTIFIER } from "../constants";
import { getItemId, sanitizeSheetName } from "../helpers";
import { getItemId, getUniqueText, sanitizeSheetName } from "../helpers";
import { toXC } from "../helpers/coordinates";
import { getMaxObjectId } from "../helpers/pivot/pivot_helpers";
import { DEFAULT_TABLE_CONFIG } from "../helpers/table_presets";
Expand Down Expand Up @@ -112,12 +112,9 @@ migrationStepRegistry
const oldName = sheet.name;
sanitizeSheetName;
const escapedName: string = sanitizeSheetName(oldName, "_");
let i = 1;
let newName = escapedName;
while (namesTaken.includes(newName)) {
newName = `${escapedName}${i}`;
i++;
}
const newName = getUniqueText(escapedName, namesTaken, {
compute: (name, i) => `${name}${i}`,
});
sheet.name = newName;
namesTaken.push(newName);

Expand Down
20 changes: 6 additions & 14 deletions src/plugins/core/sheet.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { FORBIDDEN_SHEETNAME_CHARS_IN_EXCEL_REGEX } from "../../constants";
import {
createDefaultRows,
deepCopy,
getUniqueText,
getUnquotedSheetName,
groupConsecutive,
includesAll,
Expand Down Expand Up @@ -429,14 +430,11 @@ export class SheetPlugin extends CorePlugin<SheetState> implements SheetState {
}

getNextSheetName(baseName = "Sheet"): string {
let i = 1;
const names = this.orderedSheetIds.map(this.getSheetName.bind(this));
let name = `${baseName}${i}`;
while (names.includes(name)) {
name = `${baseName}${i}`;
i++;
}
return name;
return getUniqueText(baseName, names, {
compute: (name, i) => `${name}${i}`,
computeFirstOne: true,
});
}

getSheetSize(sheetId: UID): ZoneDimension {
Expand Down Expand Up @@ -760,15 +758,9 @@ export class SheetPlugin extends CorePlugin<SheetState> implements SheetState {
}

private getDuplicateSheetName(sheetName: string) {
let i = 1;
const names = this.orderedSheetIds.map(this.getSheetName.bind(this));
const baseName = _t("Copy of %s", sheetName);
let name = baseName.toString();
while (names.includes(name)) {
name = `${baseName} (${i})`;
i++;
}
return name;
return getUniqueText(baseName.toString(), names);
}

private deleteSheet(sheet: Sheet) {
Expand Down
13 changes: 3 additions & 10 deletions src/plugins/core/table_style.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { toHex } from "../../helpers";
import { getUniqueText, toHex } from "../../helpers";
import {
DEFAULT_TABLE_CONFIG,
TABLE_PRESETS,
Expand Down Expand Up @@ -88,15 +88,8 @@ export class TableStylePlugin extends CorePlugin<TableStylesState> implements Ta

getNewCustomTableStyleName(): string {
let name = _t("Custom Table Style");
const styleNames = new Set(Object.values(this.styles).map((style) => style.displayName));
if (!styleNames.has(name)) {
return name;
}
let i = 2;
while (styleNames.has(`${name} ${i}`)) {
i++;
}
return `${name} ${i}`;
const styleNames = Object.values(this.styles).map((style) => style.displayName);
return getUniqueText(name, styleNames, { compute: (name, i) => `${name} ${i}`, start: 2 });
}

isTableStyleEditable(styleId: string): boolean {
Expand Down
11 changes: 4 additions & 7 deletions src/plugins/ui_core_views/pivot_ui.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { Token } from "../../formulas";
import { astToFormula } from "../../formulas/parser";
import { toScalar } from "../../functions/helper_matrices";
import { toBoolean } from "../../functions/helpers";
import { getUniqueText } from "../../helpers";
import {
getFirstPivotFunction,
getNumberOfPivotFunctions,
Expand Down Expand Up @@ -265,13 +266,9 @@ export class PivotUIPlugin extends UIPlugin {

generateNewCalculatedMeasureName(measures: PivotCoreMeasure[]) {
const existingMeasures = measures.map((m) => m.fieldName);
let i = 1;
let name = _t("Calculated measure %s", i);
while (existingMeasures.includes(name)) {
i++;
name = _t("Calculated measure %s", i);
}
return name;
return getUniqueText(_t("Calculated measure 1"), existingMeasures, {
compute: (name, i) => _t("Calculated measure %s", i),
});
}

getPivot(pivotId: UID) {
Expand Down
10 changes: 2 additions & 8 deletions src/plugins/ui_feature/insert_pivot.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { PIVOT_TABLE_CONFIG } from "../../constants";
import { sanitizeSheetName } from "../../helpers";
import { getUniqueText, sanitizeSheetName } from "../../helpers";
import { createPivotFormula } from "../../helpers/pivot/pivot_helpers";
import { SpreadsheetPivotTable } from "../../helpers/pivot/table_spreadsheet_pivot";
import { getZoneArea, positionToZone } from "../../helpers/zones";
Expand Down Expand Up @@ -112,15 +112,9 @@ export class InsertPivotPlugin extends UIPlugin {
}

private getPivotDuplicateSheetName(pivotName: string) {
let i = 1;
const names = this.getters.getSheetIds().map((id) => this.getters.getSheetName(id));
const sanitizedName = sanitizeSheetName(pivotName);
let name = sanitizedName;
while (names.includes(name)) {
name = `${sanitizedName} (${i})`;
i++;
}
return name;
return getUniqueText(sanitizedName, names);
}

insertPivotWithTable(
Expand Down
12 changes: 5 additions & 7 deletions src/plugins/ui_stateful/filter_evaluation.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import {
deepCopy,
getUniqueText,
positions,
range,
toLowerCase,
Expand Down Expand Up @@ -221,12 +222,9 @@ export class FilterEvaluationPlugin extends UIPlugin {
if (!colName) {
colName = `Column${colIndex}`;
}
let currentColName = colName;
let i = 2;
while (usedColNames.includes(currentColName)) {
currentColName = colName + String(i);
i++;
}
return currentColName;
return getUniqueText(colName, usedColNames, {
compute: (name, i) => colName + String(i),
start: 2,
});
}
}
13 changes: 6 additions & 7 deletions src/xlsx/xlsx_writer.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { DEFAULT_CELL_HEIGHT, DEFAULT_CELL_WIDTH } from "../constants";
import { escapeRegExp, toZone, zoneToDimension } from "../helpers";
import { escapeRegExp, getUniqueText, toZone, zoneToDimension } from "../helpers";
import { ExcelSheetData, ExcelWorkbookData } from "../types";
import {
XLSXExport,
Expand Down Expand Up @@ -376,14 +376,13 @@ function createRelRoot(): XLSXExportFile {
*/
export function fixLengthySheetNames(data: ExcelWorkbookData): ExcelWorkbookData {
const nameMapping: Record<string, string> = {};
const newNames = new Set<string>();
const newNames: string[] = [];
for (const sheet of data.sheets) {
let newName = sheet.name.slice(0, 31);
let i = 1;
while (newNames.has(newName)) {
newName = newName.slice(0, 31 - String(i).length) + i++;
}
newNames.add(newName);
newName = getUniqueText(newName, newNames, {
compute: (name, i) => name.slice(0, 31 - String(i).length) + i,
});
newNames.push(newName);
if (newName !== sheet.name) {
nameMapping[sheet.name] = newName;
sheet.name = newName;
Expand Down
23 changes: 23 additions & 0 deletions tests/helpers/misc_helpers.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import {
DateTime,
deepCopy,
deepEquals,
getUniqueText,
groupConsecutive,
isConsecutive,
lazy,
Expand Down Expand Up @@ -275,3 +276,25 @@ describe("Memoize", () => {
expect(memoizedFn.name).toEqual("smile (memoized)");
});
});

describe("getUniqueText", () => {
test("with no existing text", () => {
expect(getUniqueText("a", [])).toEqual("a");
});

test("with existing text", () => {
expect(getUniqueText("a", ["a", "a (1)"])).toEqual("a (2)");
});

test("with custom compute", () => {
expect(getUniqueText("a", ["a", "a 1"], { compute: (t, i) => `${t} ${i}` })).toEqual("a 2");
});

test("with computeFirstOne", () => {
expect(getUniqueText("a", [], { computeFirstOne: true })).toEqual("a (1)");
});

test("with start", () => {
expect(getUniqueText("a", ["a"], { start: 2 })).toEqual("a (2)");
});
});

0 comments on commit 37f2328

Please sign in to comment.