Skip to content

Instantly share code, notes, and snippets.

@ericzakariasson
Last active August 23, 2018 07:06
Show Gist options
  • Save ericzakariasson/29ba0c145329747044d432f84dcf9348 to your computer and use it in GitHub Desktop.
Save ericzakariasson/29ba0c145329747044d432f84dcf9348 to your computer and use it in GitHub Desktop.
Custom query string formatter for use in input fields
/* Declare shortcuts and types */
const fieldMap = {
a: {
name: 'address',
type: String
},
s: {
name: 'approved',
type: Boolean,
relation: {
g: 'true',
eg: 'false',
}
},
d: {
name: 'date',
type: Date,
}
}
/* Actual values, eg React state */
export const fieldModel = {
address: '',
approved: '',
date: null,
}
/*
* If the state differs from the fieldModel, remove the differnce.
* Useful if you have UI state mixed with input state
*/
function filterDataObject(dataObj) {
const filteredData = { ...dataObj };
const difference = Object.keys(filteredData).filter(field => !Object.keys(fieldModel).includes(field));
difference.forEach(diff => delete filteredData[diff]);
return filteredData;
}
/* Parse the value to the desired type declared in fieldMap */
function parseValue(short, value) {
const field = fieldMap[short];
switch (field.type) {
case String:
return value;
case Date:
return new Date(value)
case Boolean:
const bool = field.relation[value];
return bool
default:
return value;
}
}
/* Format the value for display */
function formatValue(short, value) {
const field = fieldMap[short];
switch (field.type) {
case String:
/* Wrap string which includes whitespace in quotes */
if (value.includes(' ')) {
return `"${value}"`
}
return value;
case Date:
return new Date(value).toLocaleDateString();
case Boolean:
const { relation } = field;
/* Replaces the actual value with the declared format in fieldMap */
const relationValue = Object.keys(relation).find(key => relation[key].toString() === value.toString());
return relationValue
default:
return value;
}
}
let relations = [];
Object.keys(fieldMap)
.forEach(short => {
if (fieldMap[short].hasOwnProperty('relation')) {
Object.keys(fieldMap[short].relation).forEach(rel => relations.push(rel))
}
})
export function parseQuery(qs) {
/*
* For custom formats, including:
* String inside quotes, eg "Sample text"
* Date in format of YYYY-MM-DD
* Custom relation declared in fieldMap,
*/
const regex = new RegExp(`(\\w{1,4}):(".*?"|\\d{4}-\\d{2}-\\d{2}|\\w{6}\\d{4}|${relations.join('|')}|[^\\s\\d]+|\\w+)`, 'gi');
/* Returns default values */
if (!regex.test(qs)) {
return fieldModel;
}
const matches = qs.match(regex);
const params = matches.map(match => {
const split = match.split(':');
const short = split[0];
const valueWithUnknownType = split[1].replace(/"/g, '');
const value = parseValue(short, valueWithUnknownType);
return { short, value }
});
const parsed = params.reduce((dataObj, param) => {
const key = fieldMap[param.short].name;
dataObj[key] = param.value;
return dataObj
}, {})
return parsed
}
const shortMap = Object.keys(fieldMap).reduce((mapObj, short) => {
const name = fieldMap[short].name;
mapObj[name] = short;
return mapObj;
}, {})
export function stringifyQuery(data) {
const checkedData = filterDataObject(data);
const qs = Object.keys(checkedData)
.map(key => {
const value = checkedData[key];
if (value) {
const short = shortMap[key];
const formattedValue = formatValue(short, value);
return `${short}:${formattedValue}`
}
return null;
})
.filter(param => {
return (param !== null) && (param !== undefined)
})
.join(' ');
return qs;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment