From 20baa4bddaa17ce14d41fb30c523b707d1f621e8 Mon Sep 17 00:00:00 2001 From: Yaxue Guo <37635744+yaxue1123@users.noreply.github.com> Date: Tue, 16 May 2023 16:17:32 -0400 Subject: [PATCH] Bug/prod portal resource display issue (#261) * #260: updated site parser to handle site workers in Maint/ PreMaint * #260: added maintenance worker table to site detail page" * #260: replaced mock data with API data * #257: disabled auto-refresh-token function * #255: minor wording fixe * #260: removed console logs * #260: fixed table site link --- package-lock.json | 2 +- package.json | 2 +- src/components/Experiment/Slices.jsx | 2 +- src/components/Resource/SiteDetailPage.jsx | 31 +++++++++++++- src/components/Resource/SummaryTable.jsx | 9 ++--- src/pages/Help.jsx | 8 ++-- src/services/parser/sitesParser.js | 47 +++++++++++++++++++++- src/services/portalData.json | 2 +- src/utils/clearLocalStorage.js | 1 - src/utils/manageTokens.js | 43 +------------------- 10 files changed, 86 insertions(+), 61 deletions(-) diff --git a/package-lock.json b/package-lock.json index f1215067..3c0101bb 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "fabric-portal", - "version": "1.4.5", + "version": "1.4.6", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index e2c68c3f..47610e00 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "fabric-portal", - "version": "1.4.5", + "version": "1.4.6", "private": true, "dependencies": { "@fortawesome/fontawesome-svg-core": "^1.2.32", diff --git a/src/components/Experiment/Slices.jsx b/src/components/Experiment/Slices.jsx index e0c3317c..db65e759 100644 --- a/src/components/Experiment/Slices.jsx +++ b/src/components/Experiment/Slices.jsx @@ -210,7 +210,7 @@ class Slices extends React.Component { :

- We couldn't find your slices. Please create slices in Portal or   + We couldn't find any slices belonging to you. Please create slices in Portal or   {

}
-

Basic Information

+

Basic Information

{ @@ -111,8 +111,35 @@ const SiteDetailPage = props => {
+ { + data.workers.length > 0 &&
+

Workers in Maintenance

+ + + + + + + + + { + data.workers.map((worker, index) => { + return ( + + + + + + + ) + }) + } + +
Worker NameStatusDeadlineExpected End Time
{Object.keys(worker)[0]}{statusMapping[Object.values(worker)[0].state].state}{Object.values(worker)[0].deadline ? utcToLocalTimeParser(Object.values(worker)[0].deadline) : "Unknown"}{Object.values(worker)[0].expected_end ? utcToLocalTimeParser(Object.values(worker)[0].expected_end) : "Unknown"}
+
+ }
-

Resource Availabilities

+

Resource Availabilities

(
+ to={`/sites/${resource.id}`} + state={{ data: resource }} + > {resource.name} { diff --git a/src/pages/Help.jsx b/src/pages/Help.jsx index da1ac18c..c5e9b831 100644 --- a/src/pages/Help.jsx +++ b/src/pages/Help.jsx @@ -31,8 +31,8 @@ export default class Help extends React.Component{
Experiment Issues

For technical assistance with your experiments, please search in our Knowledge Base or - the Forum. If you are unable to fix the problem on your - own, please post a question in the appropriate section of our Forum. + the Forums. If you are unable to fix the problem on your + own, please post a question in the appropriate section of our Forums.

@@ -40,7 +40,7 @@ export default class Help extends React.Component{ - Forum + Forums
@@ -76,7 +76,7 @@ export default class Help extends React.Component{ beta

- Haven't found an answer to your question on the Forum or Knowledge Base? Set up time with members of the FABRIC Team during their Office Hours. + Haven't found an answer to your question on the Forums or Knowledge Base? Set up time with members of the FABRIC Team during their Office Hours.

diff --git a/src/services/parser/sitesParser.js b/src/services/parser/sitesParser.js index df03e1d2..901f82fb 100644 --- a/src/services/parser/sitesParser.js +++ b/src/services/parser/sitesParser.js @@ -1,3 +1,5 @@ +import { object } from "prop-types"; + const getSiteColor = (status) => { if (status === "Active") { // Color: "primary" for "active" sites @@ -13,6 +15,31 @@ const getSiteColor = (status) => { } } +const retrieveWorkers = (maintenance) => { + const workers = []; + let status = "PreMaint"; + for (const [key, value] of Object.entries(maintenance)) { + workers.push({ + [key]: value + }); + // if all workers are in PreMaint state, then PreMaint as the site state + // if a Maint worker exists, mark the site as in Maint too + if (value.state === "Maint") { + status = "Maint"; + } + } + + // status is an object. e.g. { state: "Maint", deadline: null, expected_end: null } + return { + workers: workers, + siteStatus: { + state: status, + deadline: null, + expected_end: null + } + } +} + export default function parseSites(data, acronymToShortName) { let abqm_elements = JSON.parse(data.model); const nodes = abqm_elements.nodes; @@ -31,7 +58,17 @@ export default function parseSites(data, acronymToShortName) { site.location = node.Location; // site.location = JSON.parse(node.Location)["postal"]; /************ retrieve site status in site node. ************/ - site.status = JSON.parse(node.MaintenanceInfo)[node.Name]; + const maintenance = JSON.parse(node.MaintenanceInfo); + if (maintenance[node.Name]) { + // the site is active or the maintenance is at site level + site.status = maintenance[node.Name]; + site.workers = []; + } else { + // the maintenance is at worker level + const parsedMaintInfo = retrieveWorkers(maintenance); + site.status = parsedMaintInfo.siteStatus; + site.workers = parsedMaintInfo.workers; + } /************ retrieve site capacity in site node. ************/ const siteCapacityTypes = { "CPU": "cpu", @@ -82,7 +119,13 @@ export default function parseSites(data, acronymToShortName) { } parsedSites.push(site); - siteColorMapping[site.name] = getSiteColor(site.status.state); + + try { + siteColorMapping[site.name] = getSiteColor(site.status.state); + } catch(err) { + console.log(`This site cannot be parsed correctly: ${site}`); + } + siteNames.push(acronymToShortName[site.name]); siteAcronyms.push(site.name); } diff --git a/src/services/portalData.json b/src/services/portalData.json index 601d38a0..612f9850 100644 --- a/src/services/portalData.json +++ b/src/services/portalData.json @@ -1,5 +1,5 @@ { - "version": "1.4.4", + "version": "1.4.6", "defaultFacility": "FABRIC", "facilityOptions": ["FABRIC"], "sliverKeyLimit": 10, diff --git a/src/utils/clearLocalStorage.js b/src/utils/clearLocalStorage.js index 0ab0df95..3fe96d7d 100644 --- a/src/utils/clearLocalStorage.js +++ b/src/utils/clearLocalStorage.js @@ -11,5 +11,4 @@ export default function clearLocalStorage() { localStorage.removeItem("countdownTimerIntervalId"); localStorage.removeItem("sessionTimeoutIntervalId1"); localStorage.removeItem("sessionTimeoutIntervalId2"); - localStorage.removeItem("refreshTokenIntervalId"); } diff --git a/src/utils/manageTokens.js b/src/utils/manageTokens.js index e1fc10d5..255ad5e9 100644 --- a/src/utils/manageTokens.js +++ b/src/utils/manageTokens.js @@ -1,21 +1,7 @@ -import { createIdToken, refreshToken, revokeToken } from "../services/credentialManagerService.js"; -import { default as portalData } from "../services/portalData.json"; +import { createIdToken } from "../services/credentialManagerService.js"; import { toast } from "react-toastify"; -const autoRevokeTokens = async () => { - try { - await revokeToken(localStorage.getItem("refreshToken")); - } catch (err) { - console.log("Failed to revoke token."); - } -} - export const autoCreateTokens = async (projectId) => { - // clear previous autoRefreshToken interval if there is any - if (localStorage.getItem("refreshTokenIntervalId")) { - clearInterval(localStorage.getItem("refreshTokenIntervalId")); - } - try { // call credential manager to generate tokens. // parameters: project and scope, "all" for both by default. @@ -23,36 +9,9 @@ export const autoCreateTokens = async (projectId) => { localStorage.setItem("idToken", res["data"][0].id_token); localStorage.setItem("refreshToken", res["data"][0].refresh_token); - // Auto refresh token every 55min - const refreshTokenIntervalId = setInterval(() => { - if(localStorage.getItem("refreshTokenIntervalId")) { - clearInterval(localStorage.getItem("refreshTokenIntervalId")); - } - autoRefreshTokens(projectId); - } - , portalData["autoRefreshTokenInterval"]); - localStorage.setItem("refreshTokenIntervalId", refreshTokenIntervalId); return res["data"][0]; } catch (err) { toast.error("Unable to obtain authentication token, the likely reason is you are not a member of any projects."); } -} - -export const autoRefreshTokens = async (projectId) => { - const oldRefreshToken = localStorage.getItem("refreshToken"); - try { - const { data: res } = await refreshToken(projectId, "all", oldRefreshToken); - localStorage.setItem("idToken", res["data"][0].id_token); - localStorage.setItem("refreshToken", res["data"][0].refresh_token); - } catch (err) { - toast.error("Failed to refresh necessary tokens to view slice information. Please try again later."); - // if refresh_token isn't working either - // start over by calling create_token when user reloads the page - // 1. call cm revoke_token with old refresh token - autoRevokeTokens(); - // 2. clear id_token and refresh_token in local storage - localStorage.removeItem("idToken"); - localStorage.removeItem("refreshToken"); - } } \ No newline at end of file