diff --git a/pkg/handlers/troubleshoot.go b/pkg/handlers/troubleshoot.go index e81a46b227..d345212aca 100644 --- a/pkg/handlers/troubleshoot.go +++ b/pkg/handlers/troubleshoot.go @@ -58,6 +58,7 @@ type ResponseSupportBundle struct { Status string `json:"status"` CreatedAt time.Time `json:"createdAt"` UploadedAt *time.Time `json:"uploadedAt"` + SharedAt *time.Time `json:"sharedAt"` IsArchived bool `json:"isArchived"` Analysis *types.SupportBundleAnalysis `json:"analysis"` } @@ -200,6 +201,7 @@ func (h *Handler) ListSupportBundles(w http.ResponseWriter, r *http.Request) { CreatedAt: bundle.CreatedAt, UploadedAt: bundle.UploadedAt, IsArchived: bundle.IsArchived, + SharedAt: bundle.SharedAt, Analysis: analysis, } diff --git a/web/src/components/troubleshoot/SupportBundleList.jsx b/web/src/components/troubleshoot/SupportBundleList.jsx index 429953691e..8864641a46 100644 --- a/web/src/components/troubleshoot/SupportBundleList.jsx +++ b/web/src/components/troubleshoot/SupportBundleList.jsx @@ -97,6 +97,7 @@ class SupportBundleList extends React.Component { key={bundle.id} bundle={bundle} watchSlug={watch.slug} + refetchBundleList={this.listSupportBundles} /> )) ); diff --git a/web/src/components/troubleshoot/SupportBundleRow.jsx b/web/src/components/troubleshoot/SupportBundleRow.jsx index 55f79ed455..529fb6357f 100644 --- a/web/src/components/troubleshoot/SupportBundleRow.jsx +++ b/web/src/components/troubleshoot/SupportBundleRow.jsx @@ -1,19 +1,20 @@ import * as React from "react"; import { withRouter } from "react-router-dom"; -import ReactTooltip from "react-tooltip" import Loader from "../shared/Loader"; import dayjs from "dayjs"; import filter from "lodash/filter"; -import sortBy from "lodash/sortBy"; import isEmpty from "lodash/isEmpty"; -import { Utilities, parseIconUri } from "../../utilities/utilities"; +import { Utilities } from "../../utilities/utilities"; import download from "downloadjs"; // import { VendorUtilities } from "../../utilities/VendorUtilities"; class SupportBundleRow extends React.Component { state = { downloadingBundle: false, - downloadBundleErrMsg: "" + downloadBundleErrMsg: "", + errorInsights: [], + warningInsights: [], + otherInsights: [] } renderSharedContext = () => { @@ -33,6 +34,12 @@ class SupportBundleRow extends React.Component { // return shareContext; } + componentDidMount() { + if (this.props.bundle) { + this.buildInsights(); + } + } + handleBundleClick = (bundle) => { const { watchSlug } = this.props; this.props.history.push(`/app/${watchSlug}/troubleshoot/analyze/${bundle.slug}`) @@ -72,21 +79,46 @@ class SupportBundleRow extends React.Component { }) } - renderInsightIcon = (bundle, i, insight) => { - if (insight.icon) { - const iconObj = parseIconUri(insight.icon); - return ( -
- ) - } else { - return ( - - ) - } + sendBundleToVendor = async (bundleSlug) => { + this.setState({ sendingBundle: true, sendingBundleErrMsg: "", downloadBundleErrMsg: "" }); + fetch(`${window.env.API_ENDPOINT}/troubleshoot/app/${this.props.match.params.slug}/supportbundle/${bundleSlug}/share`, { + method: "POST", + headers: { + "Authorization": Utilities.getToken(), + } + }) + .then(async (result) => { + if (!result.ok) { + this.setState({ sendingBundle: false, sendingBundleErrMsg: `Unable to send bundle to vendor: Status ${result.status}, please try again.` }); + return; + } + await this.props.refetchBundleList(); + this.setState({ sendingBundle: false, sendingBundleErrMsg: "" }); + }) + .catch(err => { + console.log(err); + this.setState({ sendingBundle: false, sendingBundleErrMsg: err ? `Unable to send bundle to vendor: ${err.message}` : "Something went wrong, please try again." }); + }) + } + + buildInsights = () => { + const { bundle } = this.props; + if (!bundle || !bundle.analysis.insights) return; + const errorInsights = filter(bundle.analysis.insights, ["severity", "error"]); + const warningInsights = filter(bundle.analysis.insights, ["severity", "warn"]); + const otherInsights = filter(bundle.analysis.insights, (item) => { + return item.severity === null || item.severity === "info" || item.severity === "debug" + }); + this.setState({ + errorInsights, + warningInsights, + otherInsights + }); } render() { const { bundle } = this.props; + const { errorInsights, warningInsights, otherInsights } = this.state; if (!bundle) { return null; @@ -129,19 +161,24 @@ class SupportBundleRow extends React.Component { } -
+
{bundle?.analysis?.insights?.length ? -
- {sortBy(filter(bundle?.analysis?.insights, (i) => i.severity !== "debug"), ["desiredPosition"]).map((insight, i) => { - return ( -
- {this.renderInsightIcon(bundle, i, insight)} - - {insight.detail} - -
- ) - })} +
+ {errorInsights.length > 0 && + + {errorInsights.length} error{errorInsights.length > 1 ? "s" : ""} found + + } + {warningInsights.length > 0 && + + {warningInsights.length} warning{warningInsights.length > 1 ? "s" : ""} found + + } + {otherInsights.length > 0 && + + {otherInsights.length} informational and debugging insight{otherInsights.length > 1 ? "s" : ""} found + + }
: noInsightsMessage @@ -149,12 +186,23 @@ class SupportBundleRow extends React.Component {
+ {this.state.sendingBundleErrMsg &&

{this.state.sendingBundleErrMsg}

} + {this.props.bundle.sharedAt ? +
+ + Sent to vendor on {Utilities.dateFormat(bundle.sharedAt, "MM/DD/YYYY")} +
+ : this.state.sendingBundle ? + + : + this.sendBundleToVendor(this.props.bundle.slug)}>Send bundle to vendor + } {this.state.downloadBundleErrMsg &&

{this.state.downloadBundleErrMsg}

} {this.state.downloadingBundle ? : - this.downloadBundle(bundle)}>Download bundle + this.downloadBundle(bundle)}>Download bundle }
diff --git a/web/src/images/main_spritesheet.svg b/web/src/images/main_spritesheet.svg index ecafc0092b..df8991b8cb 100644 --- a/web/src/images/main_spritesheet.svg +++ b/web/src/images/main_spritesheet.svg @@ -2744,12 +2744,24 @@ - - + + - - + + + + + + + + + + + + + + diff --git a/web/src/scss/utilities/icons.scss b/web/src/scss/utilities/icons.scss index c6e0ac1128..636783018d 100644 --- a/web/src/scss/utilities/icons.scss +++ b/web/src/scss/utilities/icons.scss @@ -1034,3 +1034,18 @@ width: 12px; height: 11px; } +.icon.u-bundleInsightErrIcon { + background-position: -278px -603px; + width: 15px; + height: 15px; +} +.icon.u-bundleInsightWarningIcon { + background-position: -278px -620px; + width: 15px; + height: 14px; +} +.icon.u-bundleInsightOtherIcon { + background-position: -278px -586px; + width: 15px; + height: 15px; +}