From 740b4635a67ae5883b701b49d35b33f7b3745571 Mon Sep 17 00:00:00 2001 From: Martchus Date: Mon, 22 Mar 2021 16:51:57 +0100 Subject: [PATCH] Reflect state of package search in URL --- srv/static/js/ajaxhelper.js | 13 ++++++- srv/static/js/buildactionspage.js | 20 ++++------- srv/static/js/packagedetailspage.js | 19 +++++----- srv/static/js/packagesearchpage.js | 55 +++++++++++++++++++++++++++-- srv/static/js/singlepage.js | 18 ++++++++++ srv/static/js/utils.js | 4 +-- 6 files changed, 101 insertions(+), 28 deletions(-) diff --git a/srv/static/js/ajaxhelper.js b/srv/static/js/ajaxhelper.js index 66ac0f6..e9c0780 100644 --- a/srv/static/js/ajaxhelper.js +++ b/srv/static/js/ajaxhelper.js @@ -35,9 +35,20 @@ function queryRoute(method, path, callback) /// \brief Makes an AJAX query for the specified form. function startFormQuery(formId, handler) +{ + return startFormQueryEx(formId, handler).ajaxRequest; +} + +/// \brief Makes an AJAX query for the specified form. +function startFormQueryEx(formId, handler) { const form = document.getElementById(formId); - return queryRoute(form.method, form.getAttribute('action') + makeFormQueryParameter(form), handler); + const params = makeFormQueryParameter(form); + return { + ajaxRequest: queryRoute(form.method, form.getAttribute('action') + params, handler), + form: form, + params, params, + }; } /// \brief Returns the query parameter for the specified \a form element. diff --git a/srv/static/js/buildactionspage.js b/srv/static/js/buildactionspage.js index ecb3e58..f1ad69a 100644 --- a/srv/static/js/buildactionspage.js +++ b/srv/static/js/buildactionspage.js @@ -302,7 +302,7 @@ function showBuildActions(ajaxRequest) return renderLink(value, row, function() { queryBuildActionDetails(row.id); return false; - }, 'Show details', undefined, '#build-action-details-section&' + row.id); + }, 'Show details', undefined, '#build-action-details-section?' + row.id); }, taskName: function (value) { if (!value) { @@ -397,20 +397,14 @@ function showBuildActions(ajaxRequest) function switchToBuildActionDetails(buildActionIds) { sections['build-action-details'].state.ids = buildActionIds; - window.preventSectionInitializer = true; - if (!Array.isArray(buildActionIds) || buildActionIds.length === 0) { - window.location.hash = '#build-action-details-section'; - } else { - window.location.hash = '#build-action-details-section&' + encodeURIComponent(buildActionIds.join(',')); - } - window.preventSectionInitializer = false; + updateHashPreventingSectionInitializer(!Array.isArray(buildActionIds) || buildActionIds.length === 0 + ? '#build-action-details-section' + : '#build-action-details-section?' + encodeURIComponent(buildActionIds.join(','))); } function switchToBuildActions() { - window.preventSectionInitializer = true; - window.location.hash = '#build-action-section'; - window.preventSectionInitializer = false; + updateHashPreventingSectionInitializer('#build-action-section'); } function showBuildActionDetails(ajaxRequest) @@ -734,7 +728,7 @@ function renderUpdateInfoWithCheckbox(id, packageName, newPackageName, versionIn packageNameLink.target = '_blank'; from = 'AUR'; } else { - packageNameLink.href = '#package-details-section&' + encodeURIComponent(newVersion.db + '@' + newVersion.arch + '/' + newPackageName); + packageNameLink.href = '#package-details-section?' + encodeURIComponent(newVersion.db + '@' + newVersion.arch + '/' + newPackageName); } packageNameLink.appendChild(document.createTextNode(newPackageName)); if (newPackageName !== packageName) { @@ -892,7 +886,7 @@ function initBuildActionDetails(sectionElement, sectionData, newHashParts) if (!newHashParts.length) { if (hasCurrentlyBuildActions) { window.preventHandlingHashChange = true; - window.location.hash = '#build-action-details-section&' + encodeURIComponent(currentBuildActionIds.join(',')); + window.location.hash = '#build-action-details-section?' + encodeURIComponent(currentBuildActionIds.join(',')); window.preventHandlingHashChange = false; } return true; diff --git a/srv/static/js/packagedetailspage.js b/srv/static/js/packagedetailspage.js index c203906..cab2342 100644 --- a/srv/static/js/packagedetailspage.js +++ b/srv/static/js/packagedetailspage.js @@ -4,9 +4,7 @@ function initPackageDetails(sectionElement, sectionData, newPackages) const hasNewPackages = newPackages.length >= 1; if (!hasNewPackages) { if (currentPackage !== undefined) { - window.preventHandlingHashChange = true; - window.location.hash = '#package-details-section&' + encodeURIComponent(currentPackage); - window.preventHandlingHashChange = false; + updateHashPreventingChangeHandler('#package-details-section?' + encodeURIComponent(currentPackage)); } return true; } @@ -15,7 +13,10 @@ function initPackageDetails(sectionElement, sectionData, newPackages) return true; } const packageParts = packageStr.split('/'); - const package = {db: packageParts[0], name: packageParts[1]}; + const package = { + db: packageParts[0], + name: packageParts[1] + }; queryRoute('GET', '/packages?details=1&name=' + encodeURIComponent(packageStr), function(ajaxRequest) { showPackageDetails(ajaxRequest, package); }); @@ -37,9 +38,7 @@ function queryPackageDetails(value, row) function switchToPackageDetails(packageID) { sections['package-details'].state.package = packageID; - window.preventSectionInitializer = true; - window.location.hash = '#package-details-section&' + encodeURIComponent(packageID); - window.preventSectionInitializer = false; + updateHashPreventingSectionInitializer('#package-details-section?' + encodeURIComponent(packageID)); } function showPackageDetails(ajaxRequest, row) @@ -83,8 +82,8 @@ function renderPackage(package, withoutBasics) db: function(value, row) { return document.createTextNode(makeRepoName(value, row.dbArch)); }, - upstreamUrl: function (value, row) { - return renderLink(value, row, function (value) { + upstreamUrl: function(value, row) { + return renderLink(value, row, function(value) { window.open(value); }); }, @@ -99,7 +98,7 @@ function renderPackage(package, withoutBasics) libdepends: renderArrayAsCommaSeparatedString, 'sourceInfo.makeDependencies': renderDependency, 'sourceInfo.checkDependencies': renderDependency, - 'packageInfo.arch': function (value, row) { + 'packageInfo.arch': function(value, row) { const sourceInfo = row.sourceInfo; const sourceArchs = sourceInfo !== undefined ? sourceInfo.archs : undefined; if (Array.isArray(sourceArchs) && sourceArchs.length) { diff --git a/srv/static/js/packagesearchpage.js b/srv/static/js/packagesearchpage.js index f810131..efd9ad4 100644 --- a/srv/static/js/packagesearchpage.js +++ b/srv/static/js/packagesearchpage.js @@ -1,6 +1,57 @@ +function initPackageSearch(sectionElement, sectionData, newParams) +{ + const currentParams = sectionData.state.params; + const hasNewParams = newParams.length >= 1; + if (!hasNewParams) { + if (currentParams !== undefined) { + updateHashPreventingChangeHandler('#package-search-section' + currentParams); + } + return true; + } + const searchParams = sections['package-search'].state.params = '?' + newParams[0]; + if (currentParams === searchParams) { + return true; + } + if (!window.globalInfo) { + window.functionsPostponedUntilGlobalInfo.push(searchForPackagesFromParams.bind(this, searchParams)); + } else { + searchForPackagesFromParams(searchParams); + } + return true; +} + +function searchForPackagesFromParams(searchParams) +{ + const params = new URLSearchParams(searchParams); + const form = document.getElementById('package-search-form'); + form.reset(); + params.forEach(function(value, key) { + const formElement = form[key]; + if (!formElement) { + return; + } + if (formElement.multiple) { + Array.from(formElement.options).forEach(function(optionElement) { + if (optionElement.value === value) { + optionElement.selected = true; + return; + } + }); + } else { + formElement.value = value; + } + }); + const res = startFormQueryEx('package-search-form', showPackageSearchResults); + sections['package-search'].state.params = res.params; + return res; +} + function searchForPackages() { - return startFormQuery('package-search-form', showPackageSearchResults); + const res = startFormQueryEx('package-search-form', showPackageSearchResults); + const params = sections['package-search'].state.params = res.params; + updateHashPreventingSectionInitializer('#package-search-section' + params); + return res.ajaxRequest; } function showPackageSearchResults(ajaxRequest) @@ -19,7 +70,7 @@ function showPackageSearchResults(ajaxRequest) customRenderer: { name: function (value, row) { return renderLink(value, row, queryPackageDetails, 'Show package details', undefined, - '#package-details-section&' + encodeURIComponent(row.db + (row.dbArch ? '@' + row.dbArch : '') + '/' + value)); + '#package-details-section?' + encodeURIComponent(row.db + (row.dbArch ? '@' + row.dbArch : '') + '/' + value)); }, checkbox: function(value, row) { return renderCheckBoxForTableRow(value, row, function(row) { diff --git a/srv/static/js/singlepage.js b/srv/static/js/singlepage.js index ed19db9..1a6890f 100644 --- a/srv/static/js/singlepage.js +++ b/srv/static/js/singlepage.js @@ -41,10 +41,28 @@ function handleHashChange() }); } +/// \brief Updates the #hash without triggering the handler. +function updateHashPreventingChangeHandler(newHash) +{ + window.preventHandlingHashChange = true; + window.location.hash = newHash; + window.preventHandlingHashChange = false; +} + +/// \brief Updates the #hash without triggering the section initializer. +function updateHashPreventingSectionInitializer(newHash) +{ + window.preventSectionInitializer = true; + window.location.hash = newHash; + window.preventSectionInitializer = false; +} + const sections = { 'global': { }, 'package-search': { + initializer: initPackageSearch, + state: {params: undefined}, }, 'package-details': { initializer: initPackageDetails, diff --git a/srv/static/js/utils.js b/srv/static/js/utils.js index 6ffc5da..f4708f3 100644 --- a/srv/static/js/utils.js +++ b/srv/static/js/utils.js @@ -1,7 +1,7 @@ function splitHashParts() { const currentHash = location.hash.substr(1); - const hashParts = currentHash.split('&'); + const hashParts = currentHash.split('?'); for (let i = 0, len = hashParts.length; i != len; ++i) { hashParts[i] = decodeURIComponent(hashParts[i]); } @@ -11,7 +11,7 @@ function splitHashParts() function hashAsObject() { const hashObject = {}; - location.hash.substr(1).split('&').forEach(function(hashPart) { + location.hash.substr(1).split('?').forEach(function(hashPart) { const parts = hashPart.split('=', 2); if (parts.length < 1) { return;