Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 13 additions & 7 deletions static/js/publisher/release.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import thunk from "redux-thunk";
import { HTML5Backend } from "react-dnd-html5-backend";
import { Provider } from "react-redux";
import { DndProvider } from "react-dnd";
import { QueryClient, QueryClientProvider } from "react-query";
import ReleasesController from "./release/releasesController";
import releases from "./release/reducers";
import { ReleasesData, ChannelMap, Track, Options } from "./types/releaseTypes"
Expand Down Expand Up @@ -34,19 +35,24 @@ const initReleases = (
},
composeEnhancers(applyMiddleware(thunk))
);

const queryClient = new QueryClient();

const container = document.querySelector(id);
if (!container) throw new Error(`Container with id ${id} not found`);
const root = createRoot(container);
root.render(
<Provider store={store}>
<DndProvider backend={HTML5Backend}>
<ReleasesController
snapName={snapName}
releasesData={releasesData}
channelMap={channelMap}
// @ts-expect-error
options={options}
/>
<QueryClientProvider client={queryClient}>
<ReleasesController
snapName={snapName}
releasesData={releasesData}
channelMap={channelMap}
// @ts-expect-error
options={options}
/>
</QueryClientProvider>
</DndProvider>
</Provider>
);
Expand Down
154 changes: 69 additions & 85 deletions static/js/publisher/release/components/releasesHeading.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import React, { useEffect, useState } from "react";
import React, { useState } from "react";
import { useQuery } from "react-query";
import PropTypes from "prop-types";
import { connect } from "react-redux";
import {
Expand All @@ -18,7 +19,6 @@ import {
validatePhasingPercentage,
resizeAsidePanel,
numericalSort,
getTrackGuardrails,
getPackageMetadata,
} from "../helpers";

Expand Down Expand Up @@ -75,60 +75,43 @@ function ReleasesHeading(props) {
const [versionPattern, setVersionPattern] = useState("");
const [phasingPercentage, setPhasingPercentage] = useState("");
const [phasingPercentageError, setPhasingPercentageError] = useState("");
const [trackGuardrailsStatus, setTrackGuardrailsStatus] = useState(null);
const [guardrailsLoading, setGuardrailsLoading] = useState(true);

const isTrackNameFilled = trackName.trim().length > 0;
const [isLoading, setIsLoading] = useState(false);
const [notification, setNotification] = useState(null);

const [storedTracks, setStoredTracks] = useState([]);

// Fetch tracks once
useEffect(() => {
const fetchTracks = async () => {
try {
const snapMetadata = await getPackageMetadata(props.snapName);
if (snapMetadata.tracks) {
setStoredTracks(snapMetadata.tracks);
}
} catch (error) {
console.error("Failed to fetch tracks:", error.message);
}
};
const { data, guardrailsLoading, error } = useQuery(
["snapData", props.snapName],
async () => {
const response = await getPackageMetadata(props.snapName);
return response;
},
{ enabled: !!props.snapName },
);

fetchTracks();
}, [props.snapName]);
const storedTracks = data?.tracks || [];
const trackGuardrailsData = data?.["track-guardrails"];

// Update track info when currentTrack changes
const trackInfo = storedTracks.find(
(track) => track.name === props.currentTrack,
);
const currentTrackVersionPattern = trackInfo?.["version-pattern"] || null;
const currentPhasingPercentage =
trackInfo?.["automatic-phasing-percentage"] || null;

useEffect(() => {
const fetchTrackGuardrails = async () => {
try {
const response = await getTrackGuardrails(props.snapName);
if (response["track-guardrails"].length === 0) {
setTrackGuardrailsStatus("request");
} else if (response["track-guardrails"].length > 0) {
setTrackGuardrailsStatus("add");
} else if (response["error"]) {
setTrackGuardrailsStatus("error");
}
} catch (error) {
console.error("Error:", error.message);
setTrackGuardrailsStatus("error");
} finally {
setGuardrailsLoading(false);
}
};
let trackGuardrailsStatus = null;

fetchTrackGuardrails();
}, [props.snapName]);
if (guardrailsLoading) {
trackGuardrailsStatus = null;
} else if (error) {
trackGuardrailsStatus = "error";
} else if (!trackGuardrailsData) {
trackGuardrailsStatus = "no-guardrails";
} else if (trackGuardrailsData.length === 0) {
trackGuardrailsStatus = "request";
} else {
trackGuardrailsStatus = "add";
}

const handleTrackNameChange = (event) => {
setTrackNameError("");
Expand Down Expand Up @@ -240,50 +223,51 @@ function ReleasesHeading(props) {
</div>
))}
</div>
{trackGuardrailsStatus !== "error" && (
<div className="track-button-wrapper">
{guardrailsLoading ? (
<div>
<Icon
name="spinner"
className="u-animation--spin"
/>
&nbsp;Loading...
</div>
) : (
<div className="track-button">
{trackGuardrailsStatus === "request" && (
<Button
className="p-button has-icon new-track-button"
onClick={() => {
openRequestTrackSidePanel();
if (isOpen) {
handleToggle();
}
}}
>
<i className="p-icon--plus"></i>
<span>Request track</span>
</Button>
)}
{trackGuardrailsStatus === "add" && (
<Button
className="p-button has-icon new-track-button"
onClick={() => {
openAddTrackSidePanel();
if (isOpen) {
handleToggle();
}
}}
>
<i className="p-icon--plus"></i>
<span>Add track</span>
</Button>
)}
</div>
)}
</div>
)}
{trackGuardrailsStatus !== "error" &&
trackGuardrailsStatus !== "no-guardrails" && (
<div className="track-button-wrapper">
{guardrailsLoading ? (
<div>
<Icon
name="spinner"
className="u-animation--spin"
/>
&nbsp;Loading...
</div>
) : (
<div className="track-button">
{trackGuardrailsStatus === "request" && (
<Button
className="p-button has-icon new-track-button"
onClick={() => {
openRequestTrackSidePanel();
if (isOpen) {
handleToggle();
}
}}
>
<i className="p-icon--plus"></i>
<span>Request track</span>
</Button>
)}
{trackGuardrailsStatus === "add" && (
<Button
className="p-button has-icon new-track-button"
onClick={() => {
openAddTrackSidePanel();
if (isOpen) {
handleToggle();
}
}}
>
<i className="p-icon--plus"></i>
<span>Add track</span>
</Button>
)}
</div>
)}
</div>
)}
</div>
)}
</div>
Expand Down
6 changes: 3 additions & 3 deletions static/js/publisher/release/helpers.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import {
getRevisionsArchitectures,
isSameVersion,
jsonClone,
getTrackGuardrails,
getPackageMetadata,
} from "./helpers";

global.fetch = jest.fn();
Expand Down Expand Up @@ -131,7 +131,7 @@ describe("getTrackGuardrails", () => {
}),
});

const result = await getTrackGuardrails("test-snap");
const result = await getPackageMetadata("test-snap");
expect(result).toStrictEqual({ "track-guardrails": ["example-guardrail"] });
});

Expand All @@ -146,7 +146,7 @@ describe("getTrackGuardrails", () => {
}),
});

const result = await getTrackGuardrails("test-snap");
const result = await getPackageMetadata("test-snap");
expect(result).toStrictEqual({ "track-guardrails": [] });
});
});
7 changes: 1 addition & 6 deletions static/js/publisher/release/helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ export function validatePhasingPercentage(value: string) {

export function resizeAsidePanel(panelType: string) {
useEffect(() => {
function adjustAsidePanelHeight() {
const adjustAsidePanelHeight = () => {
const targetComponent = document.querySelector("#main-content");
let asidePanel;

Expand Down Expand Up @@ -175,8 +175,3 @@ export async function getPackageMetadata(snap: string) {
return { "error": e };
}
}

export async function getTrackGuardrails(snap: string) {
const snapMetadata: any = await getPackageMetadata(snap);
return { "track-guardrails": snapMetadata["track-guardrails"] };
}
Loading