mirror of
https://github.com/ansible/awx.git
synced 2026-05-08 18:07:36 -02:30
rework removeParams
This commit is contained in:
@@ -36,6 +36,53 @@ export function parseQueryString(config, queryString) {
|
|||||||
return addDefaultsToObject(config, params);
|
return addDefaultsToObject(config, params);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function stringToObject(config, qs) {
|
||||||
|
const params = {};
|
||||||
|
qs.replace(/^\?/, '')
|
||||||
|
.split('&')
|
||||||
|
.map(s => s.split('='))
|
||||||
|
.forEach(([nsKey, rawValue]) => {
|
||||||
|
if (!nsKey || !namespaceMatches(config.namespace, nsKey)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const key = config.namespace
|
||||||
|
? decodeURIComponent(nsKey.substr(config.namespace.length + 1))
|
||||||
|
: decodeURIComponent(nsKey);
|
||||||
|
const value = parseValue(config, key, rawValue);
|
||||||
|
params[key] = mergeParam(params[key], value);
|
||||||
|
});
|
||||||
|
return params;
|
||||||
|
};
|
||||||
|
export { stringToObject as _stringToObject };
|
||||||
|
|
||||||
|
/**
|
||||||
|
* helper function to check the namespace of a param is what you expec
|
||||||
|
* @param {string} namespace to append to params
|
||||||
|
* @param {object} params object to append namespace to
|
||||||
|
* @return {object} params object with namespaced keys
|
||||||
|
*/
|
||||||
|
const namespaceMatches = (namespace, fieldname) => {
|
||||||
|
if (!namespace) return !fieldname.includes('.');
|
||||||
|
|
||||||
|
return fieldname.startsWith(`${namespace}.`);
|
||||||
|
};
|
||||||
|
|
||||||
|
function parseValue(config, key, rawValue) {
|
||||||
|
if (config.integerFields && config.integerFields.some(v => v === key)) {
|
||||||
|
return parseInt(rawValue, 10);
|
||||||
|
}
|
||||||
|
// TODO: parse dateFields into date format?
|
||||||
|
return decodeURIComponent(rawValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
function addDefaultsToObject(config, params) {
|
||||||
|
return {
|
||||||
|
...config.defaultParams,
|
||||||
|
...params,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
export { addDefaultsToObject as _addDefaultsToObject };
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Convert query param object to url query string
|
* Convert query param object to url query string
|
||||||
* Used to encode params for interacting with the api
|
* Used to encode params for interacting with the api
|
||||||
@@ -97,100 +144,13 @@ export const encodeNonDefaultQueryString = (config, params) => {
|
|||||||
.join('&');
|
.join('&');
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
|
||||||
* Removes params from the search string and returns the updated list of params
|
|
||||||
* @param {object} qs config object (used for getting defaults, current query params etc.)
|
|
||||||
* @param {object} object with params from existing search
|
|
||||||
* @param {object} object with new params to remove
|
|
||||||
* @return {object} query param object
|
|
||||||
*/
|
|
||||||
export function removeParams(config, oldParams, paramsToRemove) {
|
|
||||||
const paramsEntries = [];
|
|
||||||
Object.entries(oldParams).forEach(([key, value]) => {
|
|
||||||
if (Array.isArray(value)) {
|
|
||||||
value.forEach(val => {
|
|
||||||
paramsEntries.push([key, val]);
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
paramsEntries.push([key, value]);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
const paramsToRemoveEntries = Object.entries(paramsToRemove);
|
|
||||||
const remainingEntries = paramsEntries.filter(
|
|
||||||
([key, value]) =>
|
|
||||||
paramsToRemoveEntries.filter(
|
|
||||||
([newKey, newValue]) => key === newKey && value === newValue
|
|
||||||
).length === 0
|
|
||||||
);
|
|
||||||
const remainingObject = arrayToObject(remainingEntries);
|
|
||||||
const defaultEntriesLeftover = Object.entries(config.defaultParams).filter(
|
|
||||||
([key]) => !remainingObject[key]
|
|
||||||
);
|
|
||||||
const finalParamsEntries = remainingEntries;
|
|
||||||
defaultEntriesLeftover.forEach(value => {
|
|
||||||
finalParamsEntries.push(value);
|
|
||||||
});
|
|
||||||
return arrayToObject(finalParamsEntries);
|
|
||||||
}
|
|
||||||
|
|
||||||
const stringToObject = (config, qs) => {
|
|
||||||
const params = {};
|
|
||||||
qs.replace(/^\?/, '')
|
|
||||||
.split('&')
|
|
||||||
.map(s => s.split('='))
|
|
||||||
.forEach(([nsKey, rawValue]) => {
|
|
||||||
if (!nsKey || !namespaceMatches(config.namespace, nsKey)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const key = decodeURIComponent(nsKey.substr(config.namespace.length + 1));
|
|
||||||
const value = parseValue(config, key, rawValue);
|
|
||||||
params[key] = mergeParam(params[key], value);
|
|
||||||
});
|
|
||||||
return params;
|
|
||||||
};
|
|
||||||
export { stringToObject as _stringToObject };
|
|
||||||
|
|
||||||
function parseValue(config, key, rawValue) {
|
|
||||||
if (config.integerFields && config.integerFields.some(v => v === key)) {
|
|
||||||
return parseInt(rawValue, 10);
|
|
||||||
}
|
|
||||||
// TODO: parse dateFields into date format?
|
|
||||||
return decodeURIComponent(rawValue);
|
|
||||||
}
|
|
||||||
|
|
||||||
function addDefaultsToObject(config, params) {
|
|
||||||
return {
|
|
||||||
...config.defaultParams,
|
|
||||||
...params,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
export { addDefaultsToObject as _addDefaultsToObject };
|
|
||||||
|
|
||||||
/**
|
|
||||||
* helper function used to convert from
|
|
||||||
* Object.entries format ([ [ key, value ], ... ]) to object
|
|
||||||
* @param {array} array in the format [ [ key, value ], ...]
|
|
||||||
* @return {object} object in the forms { key: value, ... }
|
|
||||||
*/
|
|
||||||
const arrayToObject = entriesArr =>
|
|
||||||
entriesArr.reduce((acc, [key, value]) => {
|
|
||||||
if (acc[key] && Array.isArray(acc[key])) {
|
|
||||||
acc[key].push(value);
|
|
||||||
} else if (acc[key]) {
|
|
||||||
acc[key] = [acc[key], value];
|
|
||||||
} else {
|
|
||||||
acc[key] = value;
|
|
||||||
}
|
|
||||||
return acc;
|
|
||||||
}, {});
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* helper function to namespace params object
|
* helper function to namespace params object
|
||||||
* @param {string} namespace to append to params
|
* @param {string} namespace to append to params
|
||||||
* @param {object} params object to append namespace to
|
* @param {object} params object to append namespace to
|
||||||
* @return {object} params object with namespaced keys
|
* @return {object} params object with namespaced keys
|
||||||
*/
|
*/
|
||||||
const namespaceParams = (namespace, params = {}) => {
|
const namespaceParams = (namespace, params) => {
|
||||||
if (!namespace) return params;
|
if (!namespace) return params;
|
||||||
|
|
||||||
const namespaced = {};
|
const namespaced = {};
|
||||||
@@ -198,19 +158,7 @@ const namespaceParams = (namespace, params = {}) => {
|
|||||||
namespaced[`${namespace}.${key}`] = params[key];
|
namespaced[`${namespace}.${key}`] = params[key];
|
||||||
});
|
});
|
||||||
|
|
||||||
return namespaced || {};
|
return namespaced;
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* helper function to check the namespace of a param is what you expec
|
|
||||||
* @param {string} namespace to append to params
|
|
||||||
* @param {object} params object to append namespace to
|
|
||||||
* @return {object} params object with namespaced keys
|
|
||||||
*/
|
|
||||||
const namespaceMatches = (namespace, fieldname) => {
|
|
||||||
if (!namespace) return !fieldname.includes('.');
|
|
||||||
|
|
||||||
return fieldname.startsWith(`${namespace}.`);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -234,6 +182,45 @@ const paramValueIsEqual = (one, two) => {
|
|||||||
return isEqual;
|
return isEqual;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Removes params from the search string and returns the updated list of params
|
||||||
|
* @param {object} qs config object (used for getting defaults, current query params etc.)
|
||||||
|
* @param {object} object with params from existing search
|
||||||
|
* @param {object} object with new params to remove
|
||||||
|
* @return {object} query param object
|
||||||
|
*/
|
||||||
|
export function removeParams(config, oldParams, paramsToRemove) {
|
||||||
|
const updated = {
|
||||||
|
...config.defaultParams,
|
||||||
|
};
|
||||||
|
Object.keys(oldParams).forEach(key => {
|
||||||
|
const value = removeParam(oldParams[key], paramsToRemove[key]);
|
||||||
|
if (value) {
|
||||||
|
updated[key] = value;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return updated;
|
||||||
|
}
|
||||||
|
|
||||||
|
function removeParam(oldVal, deleteVal) {
|
||||||
|
if (oldVal === deleteVal) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
if (Array.isArray(deleteVal)) {
|
||||||
|
return deleteVal.reduce(removeParam, oldVal);
|
||||||
|
}
|
||||||
|
if (Array.isArray(oldVal)) {
|
||||||
|
const index = oldVal.indexOf(deleteVal);
|
||||||
|
if (index > -1) {
|
||||||
|
oldVal.splice(index, 1);
|
||||||
|
}
|
||||||
|
if (oldVal.length === 1) {
|
||||||
|
return oldVal[0];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return oldVal;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Merge old and new params together, joining values into arrays where necessary
|
* Merge old and new params together, joining values into arrays where necessary
|
||||||
* @param {object} namespaced params object of old params
|
* @param {object} namespaced params object of old params
|
||||||
@@ -264,7 +251,7 @@ function mergeParam(oldVal, newVal) {
|
|||||||
if (Array.isArray(oldVal)) {
|
if (Array.isArray(oldVal)) {
|
||||||
merged = oldVal.concat(newVal);
|
merged = oldVal.concat(newVal);
|
||||||
} else {
|
} else {
|
||||||
merged = ([oldVal]).concat(newVal);
|
merged = [oldVal].concat(newVal);
|
||||||
}
|
}
|
||||||
return dedupeArray(merged);
|
return dedupeArray(merged);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ import {
|
|||||||
encodeNonDefaultQueryString,
|
encodeNonDefaultQueryString,
|
||||||
parseQueryString,
|
parseQueryString,
|
||||||
getQSConfig,
|
getQSConfig,
|
||||||
addParams,
|
|
||||||
removeParams,
|
removeParams,
|
||||||
_stringToObject,
|
_stringToObject,
|
||||||
_addDefaultsToObject,
|
_addDefaultsToObject,
|
||||||
@@ -286,6 +285,19 @@ describe('qs (qs.js)', () => {
|
|||||||
baz: ['one', 'two', 'three'],
|
baz: ['one', 'two', 'three'],
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('should handle non-namespaced params', () => {
|
||||||
|
const config = {
|
||||||
|
namespace: null,
|
||||||
|
defaultParams: { page: 1, page_size: 15 },
|
||||||
|
integerFields: ['page', 'page_size'],
|
||||||
|
};
|
||||||
|
const query = '?item.baz=bar&page=3';
|
||||||
|
expect(parseQueryString(config, query)).toEqual({
|
||||||
|
page: 3,
|
||||||
|
page_size: 15,
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('removeParams', () => {
|
describe('removeParams', () => {
|
||||||
@@ -296,8 +308,8 @@ describe('qs (qs.js)', () => {
|
|||||||
integerFields: ['page', 'page_size'],
|
integerFields: ['page', 'page_size'],
|
||||||
};
|
};
|
||||||
const oldParams = { baz: 'bar', page: 3, bag: 'boom', page_size: 15 };
|
const oldParams = { baz: 'bar', page: 3, bag: 'boom', page_size: 15 };
|
||||||
const newParams = { bag: 'boom' };
|
const toRemove = { bag: 'boom' };
|
||||||
expect(removeParams(config, oldParams, newParams)).toEqual({
|
expect(removeParams(config, oldParams, toRemove)).toEqual({
|
||||||
baz: 'bar',
|
baz: 'bar',
|
||||||
page: 3,
|
page: 3,
|
||||||
page_size: 15,
|
page_size: 15,
|
||||||
@@ -311,8 +323,8 @@ describe('qs (qs.js)', () => {
|
|||||||
integerFields: ['page', 'page_size'],
|
integerFields: ['page', 'page_size'],
|
||||||
};
|
};
|
||||||
const oldParams = { baz: ['bar', 'bang'], page: 3, page_size: 15 };
|
const oldParams = { baz: ['bar', 'bang'], page: 3, page_size: 15 };
|
||||||
const newParams = { baz: 'bar' };
|
const toRemove = { baz: 'bar' };
|
||||||
expect(removeParams(config, oldParams, newParams)).toEqual({
|
expect(removeParams(config, oldParams, toRemove)).toEqual({
|
||||||
baz: 'bang',
|
baz: 'bang',
|
||||||
page: 3,
|
page: 3,
|
||||||
page_size: 15,
|
page_size: 15,
|
||||||
@@ -330,14 +342,33 @@ describe('qs (qs.js)', () => {
|
|||||||
page: 3,
|
page: 3,
|
||||||
page_size: 15,
|
page_size: 15,
|
||||||
};
|
};
|
||||||
const newParams = { baz: 'bar' };
|
const toRemove = { baz: 'bar' };
|
||||||
expect(removeParams(config, oldParams, newParams)).toEqual({
|
expect(removeParams(config, oldParams, toRemove)).toEqual({
|
||||||
baz: ['bang', 'bust'],
|
baz: ['bang', 'bust'],
|
||||||
page: 3,
|
page: 3,
|
||||||
page_size: 15,
|
page_size: 15,
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('should remove multiple values from query params (array -> smaller array)', () => {
|
||||||
|
const config = {
|
||||||
|
namespace: null,
|
||||||
|
defaultParams: { page: 1, page_size: 15 },
|
||||||
|
integerFields: ['page', 'page_size'],
|
||||||
|
};
|
||||||
|
const oldParams = {
|
||||||
|
baz: ['bar', 'bang', 'bust'],
|
||||||
|
page: 3,
|
||||||
|
page_size: 15,
|
||||||
|
};
|
||||||
|
const toRemove = { baz: ['bang', 'bar'] };
|
||||||
|
expect(removeParams(config, oldParams, toRemove)).toEqual({
|
||||||
|
baz: 'bust',
|
||||||
|
page: 3,
|
||||||
|
page_size: 15,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
test('should reset query params that have default keys back to default values', () => {
|
test('should reset query params that have default keys back to default values', () => {
|
||||||
const config = {
|
const config = {
|
||||||
namespace: null,
|
namespace: null,
|
||||||
@@ -345,8 +376,8 @@ describe('qs (qs.js)', () => {
|
|||||||
integerFields: ['page', 'page_size'],
|
integerFields: ['page', 'page_size'],
|
||||||
};
|
};
|
||||||
const oldParams = { baz: ['bar', 'bang'], page: 3, page_size: 15 };
|
const oldParams = { baz: ['bar', 'bang'], page: 3, page_size: 15 };
|
||||||
const newParams = { page: 3 };
|
const toRemove = { page: 3 };
|
||||||
expect(removeParams(config, oldParams, newParams)).toEqual({
|
expect(removeParams(config, oldParams, toRemove)).toEqual({
|
||||||
baz: ['bar', 'bang'],
|
baz: ['bar', 'bang'],
|
||||||
page: 1,
|
page: 1,
|
||||||
page_size: 15,
|
page_size: 15,
|
||||||
@@ -365,8 +396,8 @@ describe('qs (qs.js)', () => {
|
|||||||
page: 3,
|
page: 3,
|
||||||
page_size: 15,
|
page_size: 15,
|
||||||
};
|
};
|
||||||
const newParams = { baz: 'bust', pat: 'pal' };
|
const toRemove = { baz: 'bust', pat: 'pal' };
|
||||||
expect(removeParams(config, oldParams, newParams)).toEqual({
|
expect(removeParams(config, oldParams, toRemove)).toEqual({
|
||||||
baz: ['bar', 'bang'],
|
baz: ['bar', 'bang'],
|
||||||
page: 3,
|
page: 3,
|
||||||
page_size: 15,
|
page_size: 15,
|
||||||
@@ -380,8 +411,8 @@ describe('qs (qs.js)', () => {
|
|||||||
integerFields: ['page', 'page_size'],
|
integerFields: ['page', 'page_size'],
|
||||||
};
|
};
|
||||||
const oldParams = { baz: 'bar', page: 3, page_size: 15 };
|
const oldParams = { baz: 'bar', page: 3, page_size: 15 };
|
||||||
const newParams = { baz: 'bar' };
|
const toRemove = { baz: 'bar' };
|
||||||
expect(removeParams(config, oldParams, newParams)).toEqual({
|
expect(removeParams(config, oldParams, toRemove)).toEqual({
|
||||||
page: 3,
|
page: 3,
|
||||||
page_size: 15,
|
page_size: 15,
|
||||||
});
|
});
|
||||||
@@ -394,8 +425,8 @@ describe('qs (qs.js)', () => {
|
|||||||
integerFields: ['page', 'page_size'],
|
integerFields: ['page', 'page_size'],
|
||||||
};
|
};
|
||||||
const oldParams = { baz: 'bar', page: 1, page_size: 15 };
|
const oldParams = { baz: 'bar', page: 1, page_size: 15 };
|
||||||
const newParams = { baz: 'bar' };
|
const toRemove = { baz: 'bar' };
|
||||||
expect(removeParams(config, oldParams, newParams)).toEqual({
|
expect(removeParams(config, oldParams, toRemove)).toEqual({
|
||||||
page: 1,
|
page: 1,
|
||||||
page_size: 15,
|
page_size: 15,
|
||||||
});
|
});
|
||||||
@@ -408,8 +439,8 @@ describe('qs (qs.js)', () => {
|
|||||||
integerFields: ['page', 'page_size'],
|
integerFields: ['page', 'page_size'],
|
||||||
};
|
};
|
||||||
const oldParams = { baz: ['bar', 'bang'], page: 3, page_size: 15 };
|
const oldParams = { baz: ['bar', 'bang'], page: 3, page_size: 15 };
|
||||||
const newParams = { baz: 'bar' };
|
const toRemove = { baz: 'bar' };
|
||||||
expect(removeParams(config, oldParams, newParams)).toEqual({
|
expect(removeParams(config, oldParams, toRemove)).toEqual({
|
||||||
baz: 'bang',
|
baz: 'bang',
|
||||||
page: 3,
|
page: 3,
|
||||||
page_size: 15,
|
page_size: 15,
|
||||||
@@ -427,8 +458,8 @@ describe('qs (qs.js)', () => {
|
|||||||
page: 3,
|
page: 3,
|
||||||
page_size: 15,
|
page_size: 15,
|
||||||
};
|
};
|
||||||
const newParams = { baz: 'bar' };
|
const toRemove = { baz: 'bar' };
|
||||||
expect(removeParams(config, oldParams, newParams)).toEqual({
|
expect(removeParams(config, oldParams, toRemove)).toEqual({
|
||||||
baz: ['bang', 'bust'],
|
baz: ['bang', 'bust'],
|
||||||
page: 3,
|
page: 3,
|
||||||
page_size: 15,
|
page_size: 15,
|
||||||
@@ -442,14 +473,34 @@ describe('qs (qs.js)', () => {
|
|||||||
integerFields: ['page', 'page_size'],
|
integerFields: ['page', 'page_size'],
|
||||||
};
|
};
|
||||||
const oldParams = { baz: ['bar', 'bang'], page: 3, page_size: 15 };
|
const oldParams = { baz: ['bar', 'bang'], page: 3, page_size: 15 };
|
||||||
const newParams = { page: 3 };
|
const toRemove = { page: 3 };
|
||||||
expect(removeParams(config, oldParams, newParams)).toEqual({
|
expect(removeParams(config, oldParams, toRemove)).toEqual({
|
||||||
baz: ['bar', 'bang'],
|
baz: ['bar', 'bang'],
|
||||||
page: 1,
|
page: 1,
|
||||||
page_size: 15,
|
page_size: 15,
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('should retain long array values', () => {
|
||||||
|
const config = {
|
||||||
|
namespace: 'item',
|
||||||
|
defaultParams: { page: 1, page_size: 15 },
|
||||||
|
integerFields: ['page', 'page_size'],
|
||||||
|
};
|
||||||
|
const oldParams = {
|
||||||
|
baz: ['one', 'two', 'three'],
|
||||||
|
page: 3,
|
||||||
|
bag: 'boom',
|
||||||
|
page_size: 15,
|
||||||
|
};
|
||||||
|
const toRemove = { bag: 'boom' };
|
||||||
|
expect(removeParams(config, oldParams, toRemove)).toEqual({
|
||||||
|
baz: ['one', 'two', 'three'],
|
||||||
|
page: 3,
|
||||||
|
page_size: 15,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
test('should remove multiple namespaced params', () => {
|
test('should remove multiple namespaced params', () => {
|
||||||
const config = {
|
const config = {
|
||||||
namespace: 'item',
|
namespace: 'item',
|
||||||
@@ -462,8 +513,8 @@ describe('qs (qs.js)', () => {
|
|||||||
page: 3,
|
page: 3,
|
||||||
page_size: 15,
|
page_size: 15,
|
||||||
};
|
};
|
||||||
const newParams = { baz: 'bust', pat: 'pal' };
|
const toRemove = { baz: 'bust', pat: 'pal' };
|
||||||
expect(removeParams(config, oldParams, newParams)).toEqual({
|
expect(removeParams(config, oldParams, toRemove)).toEqual({
|
||||||
baz: ['bar', 'bang'],
|
baz: ['bar', 'bang'],
|
||||||
page: 3,
|
page: 3,
|
||||||
page_size: 15,
|
page_size: 15,
|
||||||
@@ -645,7 +696,7 @@ describe('qs (qs.js)', () => {
|
|||||||
page: 3,
|
page: 3,
|
||||||
page_size: 15,
|
page_size: 15,
|
||||||
});
|
});
|
||||||
})
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('replaceParams', () => {
|
describe('replaceParams', () => {
|
||||||
|
|||||||
Reference in New Issue
Block a user