From 908263df5033af6f67d245f79e7218eb2e75463d Mon Sep 17 00:00:00 2001 From: "Keith J. Grant" Date: Wed, 19 May 2021 13:23:46 -0700 Subject: [PATCH] Rewrite updateQueryString to preserve namespaces * Refactors ActivityStream to use updateQueryString --- .../screens/ActivityStream/ActivityStream.jsx | 17 ++++----- awx/ui_next/src/util/qs.js | 37 +++++++++++++++---- awx/ui_next/src/util/qs.test.js | 26 +++++++++++-- 3 files changed, 58 insertions(+), 22 deletions(-) diff --git a/awx/ui_next/src/screens/ActivityStream/ActivityStream.jsx b/awx/ui_next/src/screens/ActivityStream/ActivityStream.jsx index b7751118d2..7b1b885dcd 100644 --- a/awx/ui_next/src/screens/ActivityStream/ActivityStream.jsx +++ b/awx/ui_next/src/screens/ActivityStream/ActivityStream.jsx @@ -22,8 +22,7 @@ import useRequest from '../../util/useRequest'; import { getQSConfig, parseQueryString, - replaceParams, - encodeNonDefaultQueryString, + updateQueryString, } from '../../util/qs'; import { ActivityStreamAPI } from '../../api'; @@ -96,16 +95,14 @@ function ActivityStream() { }, [fetchActivityStream]); const pushHistoryState = urlParamsToAdd => { - let searchParams = parseQueryString(QS_CONFIG, location.search); - searchParams = replaceParams(searchParams, { page: 1 }); - const encodedParams = encodeNonDefaultQueryString(QS_CONFIG, searchParams, { + const pageOneQs = updateQueryString(QS_CONFIG, location.search, { + page: 1, + }); + const qs = updateQueryString(null, pageOneQs, { type: urlParamsToAdd.get('type'), }); - history.push( - encodedParams - ? `${location.pathname}?${encodedParams}` - : location.pathname - ); + + history.push(qs ? `${location.pathname}?${qs}` : location.pathname); }; return ( diff --git a/awx/ui_next/src/util/qs.js b/awx/ui_next/src/util/qs.js index f3eaaa6cd1..5f066cca7e 100644 --- a/awx/ui_next/src/util/qs.js +++ b/awx/ui_next/src/util/qs.js @@ -266,12 +266,33 @@ export function replaceParams(oldParams, newParams) { * @return {string} url query string */ export function updateQueryString(config, queryString, newParams) { - const oldParams = parseQueryString(config, queryString); - const updatedParams = replaceParams(oldParams, newParams); - const nonNamespacedParams = parseQueryString({}, queryString); - return encodeNonDefaultQueryString( - config, - updatedParams, - nonNamespacedParams - ); + const allParams = parseFullQueryString(queryString); + const { namespace = null, defaultParams = {} } = config || {}; + Object.keys(newParams).forEach(key => { + const val = newParams[key]; + const fullKey = namespace ? `${namespace}.${key}` : key; + if (val === null || val === defaultParams[key]) { + delete allParams[fullKey]; + } else { + allParams[fullKey] = newParams[key]; + } + }); + return encodeQueryString(allParams); +} + +function parseFullQueryString(queryString) { + const allParams = {}; + queryString + .replace(/^\?/, '') + .split('&') + .map(s => s.split('=')) + .forEach(([rawKey, rawValue]) => { + if (!rawKey) { + return; + } + const key = decodeURIComponent(rawKey); + const value = decodeURIComponent(rawValue); + allParams[key] = mergeParam(allParams[key], value); + }); + return allParams; } diff --git a/awx/ui_next/src/util/qs.test.js b/awx/ui_next/src/util/qs.test.js index aa90f3ed3b..e4a48f1b90 100644 --- a/awx/ui_next/src/util/qs.test.js +++ b/awx/ui_next/src/util/qs.test.js @@ -858,6 +858,15 @@ describe('qs (qs.js)', () => { integerFields: ['page'], }; + test('should add param to empty query string', () => { + const newParams = { + page: 3, + }; + expect(updateQueryString(config, '', newParams)).toEqual( + 'template.page=3' + ); + }); + test('should update namespaced param', () => { const query = 'template.name__icontains=workflow&template.page=2'; const newParams = { @@ -910,16 +919,25 @@ describe('qs (qs.js)', () => { ); }); - // This fix needed after we're confident refactoring components - // to use updateQueryString provides equivalent functionality - test.skip('should not alter params of other namespaces', () => { + test('should update non-namespaced param', () => { + const query = + 'activity_stream.name__icontains=workflow&activity_stream.page=2'; + const newParams = { + type: 'job', + }; + expect(updateQueryString(null, query, newParams)).toEqual( + 'activity_stream.name__icontains=workflow&activity_stream.page=2&type=job' + ); + }); + + test('should not alter params of other namespaces', () => { const query = 'template.name__icontains=workflow&template.page=2&credential.page=3'; const newParams = { page: 3, }; expect(updateQueryString(config, query, newParams)).toEqual( - 'template.name__icontains=workflow&template.page=3&credential.page=3' + 'credential.page=3&template.name__icontains=workflow&template.page=3' ); }); });