Last active
August 23, 2018 07:06
-
-
Save ericzakariasson/29ba0c145329747044d432f84dcf9348 to your computer and use it in GitHub Desktop.
Custom query string formatter for use in input fields
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* 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