Skip to content

Commit

Permalink
fix: update htmlForFeature in skeleton (#215)
Browse files Browse the repository at this point in the history
  • Loading branch information
AdriSolid authored Mar 12, 2021
1 parent ee7c652 commit fbc20eb
Show file tree
Hide file tree
Showing 2 changed files with 131 additions and 7 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# CHANGELOG

## Not released
- Add improved htmlForFeature in skeleton [#215](https://github.com/CartoDB/carto-react-template/pull/215)

## 1.0.0-rc.1 (2021-03-11)
- Add cypress e2e tests in CI [#194](https://github.com/CartoDB/carto-react-template/pull/194)
Expand Down
137 changes: 130 additions & 7 deletions template-skeleton/template/src/utils/htmlForFeature.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,133 @@
export default function htmlForFeature(feature) {
import { currencyFormatter, numberFormatter } from 'utils/formatter';

const FORMATTER_TYPES = Object.freeze({
CURRENCY: 'currency',
NUMBER: 'number',
});

const formatterFunctions = {
[FORMATTER_TYPES.CURRENCY](value) {
const formatted = currencyFormatter(value);
return `${formatted.prefix}${formatted.value}`;
},
[FORMATTER_TYPES.NUMBER](value) {
return numberFormatter(value);
},
};

const DEFAULT_FORMATTER = {
type: '',
columns: [],
};

export default function htmlForFeature({
title,
feature,
formatter = DEFAULT_FORMATTER,
includeColumns = '*',
showColumnName = true,
}) {
if (!feature) {
throw new Error(`htmlForFeature needs "info.object" information`);
}

const propertyNames = Object.keys(feature.properties);

if (
formatter?.type &&
formatter?.columns &&
!isFormatterValid(propertyNames, formatter)
) {
return;
}

if (!includedColumnsAreValid(propertyNames, includeColumns)) {
return;
}

let html = '';
Object.keys(feature.properties).forEach((propertyName) => {
if (propertyName === 'layerName') return;
html = html.concat(
`<strong>${propertyName}</strong>: ${feature.properties[propertyName]}<br/>`
);
});

if (title) {
html = `<h3 style="margin: 0"><strong>${title}</strong></h3>`;
}

for (const name of propertyNames) {
if (
name !== 'layerName' &&
(includeColumns.includes(name) || includeColumns === '*')
) {
if (formatter?.columns.includes(name)) {
const formatterFunction = formatterFunctions[formatter.type];
html = generateHtml(feature, name, showColumnName, html, formatterFunction);
} else {
html = generateHtml(feature, name, showColumnName, html);
}
}
}

return html;
}

function generateHtml(
feature,
propertyName,
showColumnName,
html,
formatterFunction = (v) => v
) {
return html.concat(
`${showColumnName ? `<strong>${propertyName}</strong>: ` : ''}${formatterFunction(
feature.properties[propertyName]
)}<br/>`
);
}

function isFormatterValid(properties, formatter) {
const supportedTypes = Object.values(FORMATTER_TYPES);

if (!supportedTypes.includes(formatter.type)) {
throw new Error(
`"${formatter.type}" is not supported as formatter, use one of "${supportedTypes}"`
);
}

if (!isArrayOfStrings(formatter.columns)) {
throw new Error(`"formatter.columns" property needs to be an array of strings`);
}

for (const column of formatter.columns) {
if (!properties.includes(column)) {
throw new Error(
`"formatted.columns" property needs to be an array of existing feature columns`
);
}
}

return true;
}

function includedColumnsAreValid(properties, includeColumns) {
if (includeColumns === '*') {
return true;
}

if (!isArrayOfStrings(includeColumns)) {
throw new Error(
`"includeColumns" property needs to be an array of existing feature columns or "*"`
);
}

if (isArrayOfStrings(includeColumns)) {
for (const column of includeColumns) {
if (!properties.includes(column)) {
throw new Error('colums set in "includeColumns" should exist in picked feature');
}
}
}

return true;
}

function isArrayOfStrings(value) {
return Array.isArray(value) && value.length && value.every(String);
}

1 comment on commit fbc20eb

@vercel
Copy link

@vercel vercel bot commented on fbc20eb Mar 12, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.