Skip to content

Commit

Permalink
Update labels and descriptions on the template export
Browse files Browse the repository at this point in the history
- Update styling of the export
    - Headers and description
- Add support for rich text on label and description
- Hide options sheet
- Rename 'headingType' to 'rowType'
- Append 4 new lines on text area to set initial height but also expand
  on content
  • Loading branch information
tnagorra committed Oct 25, 2024
1 parent 2714dbb commit e7a1f3e
Show file tree
Hide file tree
Showing 4 changed files with 456 additions and 104 deletions.
60 changes: 54 additions & 6 deletions app/src/utils/importTemplate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,53 @@ import {
mapToMap,
randomString,
} from '@togglecorp/fujs';
import { type CellRichTextValue } from 'exceljs';

function parseRichText(value: undefined): undefined;
function parseRichText(value: string): string | CellRichTextValue
function parseRichText(value: string | undefined): string | CellRichTextValue | undefined
function parseRichText(value: string | undefined): string | CellRichTextValue | undefined {
if (isNotDefined(value)) {
return value;
}

const tagRegex = /(<\/?[bui]>)/;
const tokens = value.split(tagRegex);

if (tokens.length === 1) {
return value;
}

const richText:CellRichTextValue['richText'] = [];

const stack: string[] = [];

const openTagRegex = /(<[bui]>)/;
const closeTagRegex = /(<\/[bui]>)/;

tokens.forEach((token) => {
if (token.match(openTagRegex)) {
stack.push(token);
return;
}
if (token.match(closeTagRegex)) {
// TODO: Check correctness by checking closeTag with last openTag
stack.pop();
return;
}
richText.push({
font: {
bold: stack.includes('<b>'),
italic: stack.includes('<i>'),
underline: stack.includes('<u>'),
},
text: token,
});
});
// TODO: Check correctness to check that stack is empty

return { richText };
}

type ValidationType = string | number | boolean | 'textArea';
type TypeToLiteral<T extends ValidationType> = T extends string
Expand Down Expand Up @@ -99,6 +146,7 @@ export type TemplateSchema<
| SelectField<ExtractValidation<VALUE>, OPTIONS_MAPPING>)
);

// NOTE: Not adding richtext support on heading
interface HeadingTemplateField {
type: 'heading';
name: string | number | boolean;
Expand All @@ -112,9 +160,9 @@ type ObjectKey = string | number | symbol;
type InputTemplateField = {
type: 'input';
name: string | number | boolean;
label: string;
label: string | CellRichTextValue;
outlineLevel: number;
description?: string;
description?: string | CellRichTextValue;
headingBefore?: string;
} & ({
dataValidation: 'list';
Expand Down Expand Up @@ -188,8 +236,8 @@ export function createImportTemplate<
const field = {
type: 'input',
name: fieldName,
label: schema.label,
description: schema.description,
label: parseRichText(schema.label),
description: parseRichText(schema.description),
dataValidation: (schema.validation === 'number' || schema.validation === 'date' || schema.validation === 'integer' || schema.validation === 'textArea')
? schema.validation
: undefined,
Expand All @@ -204,8 +252,8 @@ export function createImportTemplate<
const field = {
type: 'input',
name: fieldName,
label: schema.label,
description: schema.description,
label: parseRichText(schema.label),
description: parseRichText(schema.description),
outlineLevel,
dataValidation: 'list',
optionsKey: schema.optionsKey,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import { stringValueSelector } from '@ifrc-go/ui/utils';
import {
isDefined,
isNotDefined,
isTruthyString,
listToGroupList,
listToMap,
mapToList,
Expand Down Expand Up @@ -139,7 +140,7 @@ async function generateTemplate(
};

const optionsWorksheet = workbook.addWorksheet('options');
// optionsWorksheet.state = 'veryHidden';
optionsWorksheet.state = 'veryHidden';
const optionKeys = Object.keys(optionsMap) as (keyof (typeof optionsMap))[];

optionsWorksheet.columns = optionKeys.map((key) => (
Expand Down Expand Up @@ -191,26 +192,26 @@ async function generateTemplate(
tabGroupedTemplateActions.forEach(({ actions, worksheet }) => {
let lastHeadingIndex = 0;
actions.forEach((templateAction, i) => {
const row = i + ROW_OFFSET;

if (templateAction.type === 'heading') {
addHeadingRow(
worksheet,
i + ROW_OFFSET,
row,
templateAction.outlineLevel,
String(templateAction.name),
templateAction.label,
templateAction.description,
);
worksheet.mergeCells(i + ROW_OFFSET, 1, i + ROW_OFFSET, 3);
worksheet.mergeCells(row, 1, row, 3);
lastHeadingIndex = i + 1;
} else if (templateAction.type === 'input') {
// NOTE: Determines the headingType based on the index
// position relative to the last heading, list heading is for list section.
const headingType = (i - lastHeadingIndex) % 2 === 0 ? 'listHeading' : 'heading';
const rowType = (i - lastHeadingIndex) % 2 === 0 ? 'alt' : 'normal';
if (templateAction.dataValidation === 'list') {
addInputRow(
headingType,
rowType,
worksheet,
i + ROW_OFFSET,
row,
templateAction.outlineLevel,
String(templateAction.name),
templateAction.label,
Expand All @@ -220,23 +221,36 @@ async function generateTemplate(
optionsWorksheet,
);
} else if (templateAction.dataValidation === 'textArea') {
// NOTE: Adding 4 new-lines to add height while also
// supporting expand
let { label } = templateAction;
if (typeof label === 'string' && isTruthyString(label)) {
label += '\n\n\n\n';
} else if (typeof label === 'object' && label.richText.length > 0) {
label = {
...label,
richText: [
...label.richText,
{ text: '\n\n\n\n' },
],
};
}

addInputRow(
headingType,
rowType,
worksheet,
i + ROW_OFFSET,
row,
templateAction.outlineLevel,
String(templateAction.name),
templateAction.label,
label,
templateAction.description,
'text',
);
const row = worksheet.getRow(i + ROW_OFFSET);
row.height = 100;
} else {
addInputRow(
headingType,
rowType,
worksheet,
i + ROW_OFFSET,
row,
templateAction.outlineLevel,
String(templateAction.name),
templateAction.label,
Expand Down
Loading

0 comments on commit e7a1f3e

Please sign in to comment.