From bc20fff2757fc154b46b57e48f8b655fdd4595b1 Mon Sep 17 00:00:00 2001
From: Yaxue Guo <37635744+yaxue1123@users.noreply.github.com>
Date: Tue, 16 Jan 2024 15:18:53 -0500
Subject: [PATCH] Hotfix/v1.6.0 (#314)
* #313: added spinner for deleting slice
* #313: added delete/ extend slice function to slice viewer error boundary component
* #313: lifted state up for slice viewer error boundary component
* #313: updated homepage carousel for more responsive design
---
package.json | 2 +-
src/components/Footer.jsx | 2 +-
src/components/Home/Carousel.jsx | 20 ++++-
src/components/Home/Partners.jsx | 2 +-
.../Project/Personnel/ProjectTokenHolders.jsx | 11 +--
src/components/Resource/DetailTable.jsx | 4 +-
src/components/Resource/SummaryTable.jsx | 4 +-
src/components/SliceViewer/SideNodes.jsx | 4 +-
.../SliceViewer/SliceViewerErrorBoundary.jsx | 77 ++++---------------
src/pages/SliceViewer.jsx | 17 ++--
src/services/mockData/fakeAnnoucements.js | 2 +-
src/services/portalData.json | 2 +-
src/styles/App.scss | 33 +++++++-
13 files changed, 88 insertions(+), 92 deletions(-)
diff --git a/package.json b/package.json
index 8ac6485e..3a401c87 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "fabric-portal",
- "version": "1.6.0",
+ "version": "1.6.1",
"private": true,
"dependencies": {
"@fortawesome/fontawesome-svg-core": "^1.2.32",
diff --git a/src/components/Footer.jsx b/src/components/Footer.jsx
index b88ab101..49f875a5 100644
--- a/src/components/Footer.jsx
+++ b/src/components/Footer.jsx
@@ -20,7 +20,7 @@ class Footer extends React.Component {
Acceptable Use Policy
Cookie Policy
- Privacy Policy
+ {/* Privacy Policy */}
Branding Resources
diff --git a/src/components/Home/Carousel.jsx b/src/components/Home/Carousel.jsx
index d09667df..bfee31a6 100644
--- a/src/components/Home/Carousel.jsx
+++ b/src/components/Home/Carousel.jsx
@@ -1,6 +1,5 @@
import React from "react";
import { getActiveCarouselItems } from "../../services/announcementService";
-import { toast } from "react-toastify";
import Parser from 'html-react-parser';
class Carousel extends React.Component {
@@ -8,13 +7,28 @@ class Carousel extends React.Component {
items: [],
};
+ placeholderItems = [
+ {
+ "announcement_type": "carousel",
+ "background_image_url": "https://github.com/fabric-testbed/fabric-portal/assets/37635744/f2365fff-d40e-4204-9a74-a4697ddefc08",
+ "button": "Learn More",
+ "content": "Build Community: Inspire others with your research, discover collaborators, and find opportunities to showcase your project. Conduct Experiments: Take advantage of FABRIC resources to design, deploy, execute, and monitor your experiments. Browse the Library: Learn more about FABRIC through publications and user documentation. Discover additional complimentary facilities and testbeds to expand your research. ",
+ "is_active": true,
+ "link": "https://portal.fabric-testbed.net/about/about-fabric",
+ "sequence": 1,
+ "start_date": "2023-11-02 18:49:51.339756+00:00",
+ "title": "FABRIC Portal is your guide, helping make your experiment a success.",
+ "uuid": "e0d53c5f-0922-4e3d-8f43-8cd520921ea4"
+ }
+ ]
+
async componentDidMount() {
try {
const { data: res } = await getActiveCarouselItems();
let items = res.results;
this.setState({ items });
} catch (err) {
- toast.error("Failed to load carousel items. Please reload this page.");
+ this.setState({ items: this.placeholderItems });
}
}
@@ -49,7 +63,7 @@ class Carousel extends React.Component {
items && items.length > 0 && items.map((item, index) =>
-
+
{item.title}
diff --git a/src/components/Home/Partners.jsx b/src/components/Home/Partners.jsx
index 7f80b1f7..94421a0c 100644
--- a/src/components/Home/Partners.jsx
+++ b/src/components/Home/Partners.jsx
@@ -57,7 +57,7 @@ const Partners = () => {
Our Partners
FABRIC is made possible by collaborations with the following organizations.
-
+
Long-lived Token Holders
- {"Users running long-lived experiments supported by unattended automated tools can now request non-renewable long-lived API Tokens (lifetime up to 5 weeks)."}
+ {"Users running long-lived experiments supported by unattended automated tools can now request non-renewable long-lived API Tokens (lifetime up to 9 weeks)."}
{"For more information, please read this guide article: "}
:
- {`This project has no ${personnelType}.`}
+ {`This project has no long-lived ${personnelType}.`}
}
-
- {
- token_holders.length === 0 && !isFO &&
-
- {`This project has no ${personnelType}.`}
-
- }
{
!isTokenHolder && !isFO && !projectExpired &&
{
},
"PreMaint": {
state: "Pre-Maintenance",
- colorName: "info",
+ colorName: "warning",
colorHex: "#ffb670",
labelColorHex: "#212529"
},
"PartMaint": {
state: "Partial Maintenance",
- colorName: "info",
+ colorName: "warning",
colorHex: "#ffb670",
labelColorHex: "#212529"
},
diff --git a/src/components/Resource/SummaryTable.jsx b/src/components/Resource/SummaryTable.jsx
index 749da420..d7a26a5a 100644
--- a/src/components/Resource/SummaryTable.jsx
+++ b/src/components/Resource/SummaryTable.jsx
@@ -24,7 +24,7 @@ class SummaryTable extends Component {
{
resource.status && resource.status.state === "PreMaint" &&
-
+
Pre-Maintenance
@@ -32,7 +32,7 @@ class SummaryTable extends Component {
{
resource.status && resource.status.state === "PartMaint" &&
-
+
Partial Maintenance
diff --git a/src/components/SliceViewer/SideNodes.jsx b/src/components/SliceViewer/SideNodes.jsx
index fbe5c4b3..44527312 100644
--- a/src/components/SliceViewer/SideNodes.jsx
+++ b/src/components/SliceViewer/SideNodes.jsx
@@ -326,12 +326,12 @@ class SideNodes extends React.Component {
}
{
- selectedSite.status.state === "PreMaint" &&
+ selectedSite.status.state === "PreMaint" &&
Pre-Maintenance
}
{
- selectedSite.status.state === "PartMaint" &&
+ selectedSite.status.state === "PartMaint" &&
Partial Maintenance
}
diff --git a/src/components/SliceViewer/SliceViewerErrorBoundary.jsx b/src/components/SliceViewer/SliceViewerErrorBoundary.jsx
index e5421ca0..d2b2e7c7 100644
--- a/src/components/SliceViewer/SliceViewerErrorBoundary.jsx
+++ b/src/components/SliceViewer/SliceViewerErrorBoundary.jsx
@@ -1,22 +1,20 @@
import { Component } from "react";
import CopyButton from "../common/CopyButton";
import { Link } from "react-router-dom";
-// import DeleteModal from "../common/DeleteModal";
+import DeleteModal from "../common/DeleteModal";
import { toast } from "react-toastify";
import { default as portalData } from "../../services/portalData.json";
import sleep from "../../utils/sleep";
-import moment from 'moment';
-import { deleteSlice, extendSlice } from "../../services/sliceService.js";
+import { deleteSlice} from "../../services/sliceService.js";
import { OverlayTrigger, Tooltip } from 'react-bootstrap';
-// import Calendar from "../../components/common/Calendar";
+import Calendar from "../../components/common/Calendar";
import utcToLocalTimeParser from "../../utils/utcToLocalTimeParser.js";
export default class SliceViewerErrorBoundary extends Component {
constructor(props) {
super(props);
this.state = {
- hasError: false,
- leaseEndTime: this.props.slice.lease_end_time
+ hasError: false
};
}
@@ -36,51 +34,13 @@ export default class SliceViewerErrorBoundary extends Component {
}
}
- handleLeaseEndChange = (value) => {
- const inputTime = moment(value).format();
- // input format e.g. 2022-05-25T10:49:03-04:00
- // output format should be 2022-05-25 10:49:03 -0400
- const date = inputTime.substring(0, 10);
- const time = inputTime.substring(11, 19);
- const offset = inputTime.substring(19).replace(":", "");
- const outputTime = [date, time, offset].join(" ");
- this.setState({ leaseEndTime: outputTime });
- }
-
- handleSliceExtend = async () => {
- this.setState({
- showSpinner: true,
- spinnerText: "Extending slice..."
- })
- try {
- const { slice, leaseEndTime } = this.state;
- await extendSlice(slice.slice_id, leaseEndTime);
- // toast message to users when the api call is successfully done.
- toast.success("Slice has been successfully renewed.");
- await sleep(1000);
- window.location.reload();
- } catch (err) {
- toast.error("Failed to renew the slice.");
- this.setState({
- leaseEndTime: this.state.slice.lease_end_time,
- showSpinner: false,
- spinnerText: ""
- });
- }
- }
-
handleDeleteSlice = async (id) => {
try {
await deleteSlice(id);
// toast message to users when the api call is successfully done.
toast.success("Slice deleted successfully.");
- // change slice state to Dead.
- this.setState(prevState => ({
- slice: {
- ...prevState.slice,
- "state": "Dead"
- }
- }))
+ await sleep(1000);
+ window.location.reload();
} catch (err) {
toast.error("Failed to delete the slice.");
}
@@ -88,7 +48,7 @@ export default class SliceViewerErrorBoundary extends Component {
render() {
const { hasError } = this.state;
- const { slice } = this.props;
+ const { slice, leaseEndTime } = this.props;
const stateColors = {
"Nascent": "primary-dark",
@@ -131,7 +91,7 @@ export default class SliceViewerErrorBoundary extends Component {
- {/* {
+ {
["StableOK", "ModifyOK", "StableError", "ModifyError"].includes(slice.state) &&
this.handleDeleteSlice(slice.slice_id)}
/>
- } */}
+ }
Lease End at
- {/* {
+ {
slice.state === "StableOK" &&
- } */}
+ }
-
- {utcToLocalTimeParser(this.props.slice.lease_end_time)}
-
- {/* {
+ {
slice.state !=="StableOK" &&
{utcToLocalTimeParser(leaseEndTime)}
- } */}
- {/* {
+ }
+ {
leaseEndTime && slice.state ==="StableOK" &&
- } */}
+ }
diff --git a/src/pages/SliceViewer.jsx b/src/pages/SliceViewer.jsx
index ccc803a6..d630b828 100644
--- a/src/pages/SliceViewer.jsx
+++ b/src/pages/SliceViewer.jsx
@@ -79,17 +79,13 @@ class SliceViewer extends Component {
}
handleDeleteSlice = async (id) => {
+ this.setState({ showSpinner: true, spinnerText: "Deleting Slice" });
try {
await deleteSlice(id);
// toast message to users when the api call is successfully done.
toast.success("Slice deleted successfully.");
- // change slice state to Dead.
- this.setState(prevState => ({
- slice: {
- ...prevState.slice,
- "state": "Dead"
- }
- }))
+ await sleep(1000);
+ window.location.reload();
} catch (err) {
toast.error("Failed to delete the slice.");
}
@@ -159,7 +155,12 @@ class SliceViewer extends Component {
let showSlice = !showSpinner && hasProject;
return(
-
+
We are pleased to announce the deployment of Release 1.6 of our software stack on FABRIC production infrastructure. The new features include:
Long-lived tokens: users with long-lived token permissions can now create tokens with a lifetime up to 5 weeks. POA (Perform Operational Action) Add/Remove SSH Keys: users can request to add/remove SSH keys to/from the slivers using POA API. Internet2 AL2S/CloudConnect updated as per new AL2S API. List Resources enhanced to return more granular information for sites including the resource information per worker on each site. ",
+ "content": "We are pleased to announce the deployment of Release 1.6 of our software stack on FABRIC production infrastructure. The new features include:
Long-lived tokens: users with long-lived token permissions can now create tokens with a lifetime up to 9 weeks. POA (Perform Operational Action) Add/Remove SSH Keys: users can request to add/remove SSH keys to/from the slivers using POA API. Internet2 AL2S/CloudConnect updated as per new AL2S API. List Resources enhanced to return more granular information for sites including the resource information per worker on each site. ",
"display_date": "2024-01-11 00:00:00+00:00",
"is_active": true,
"link": "https://learn.fabric-testbed.net/knowledge-base/fabric-testbed-release-1-6/",
diff --git a/src/services/portalData.json b/src/services/portalData.json
index 6b4e5e0d..9424dbc6 100644
--- a/src/services/portalData.json
+++ b/src/services/portalData.json
@@ -1,5 +1,5 @@
{
- "version": "1.6.0",
+ "version": "1.6.1",
"defaultFacility": "FABRIC",
"facilityOptions": ["FABRIC"],
"keyLimit": 10,
diff --git a/src/styles/App.scss b/src/styles/App.scss
index c76d483d..36a1ab92 100644
--- a/src/styles/App.scss
+++ b/src/styles/App.scss
@@ -126,6 +126,18 @@ h1, h2, h3, h4, h5, h6 {
padding: 3px 10px !important;
}
+.homepage-carousel-content {
+ display: none;
+}
+
+.carousel-caption {
+ width: 80%;
+}
+
+.carousel-caption-content h3 {
+ font-size: 1.5rem;
+}
+
@media (min-width: 992px) {
.navbar-expand-lg .navbar-nav .nav-link {
margin-top: 0px !important;
@@ -137,6 +149,10 @@ h1, h2, h3, h4, h5, h6 {
}
@media only screen and (min-width: 768px) {
+ .homepage-carousel-content {
+ display: block;
+ }
+
.app-footer {
height: 22rem;
}
@@ -156,7 +172,12 @@ h1, h2, h3, h4, h5, h6 {
}
.carousel-caption h3 {
- font-size: 1.25rem;
+ font-size: 1.5rem;
+ }
+
+ .homepage-carousel-content {
+ font-size: .8rem;
+ line-height: 125%;
}
.carousel-caption p {
@@ -190,6 +211,11 @@ h1, h2, h3, h4, h5, h6 {
font-size: 1.75rem;
}
+ .homepage-carousel-content {
+ font-size: 1rem;
+ line-height: 175%;
+ }
+
.carousel-caption p {
font-size: 1rem;
line-height: 175%;
@@ -836,6 +862,11 @@ ul,
flex-direction: row;
align-items: flex-end;
justify-content: center;
+ flex-wrap: wrap;
+}
+
+.homepage-partner-logo-containter img {
+ margin-top: 1.5rem;
}
.homepage-scroll-container {