Skip to content
Open
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
3 changes: 3 additions & 0 deletions public/locales/de-DE/translation.json
Original file line number Diff line number Diff line change
Expand Up @@ -440,6 +440,9 @@
"empty-response": "Leere Antwort",
"form-preview": "Formularvorschau",
"raw-data-json": "Rohdaten (JSON)",
"actions": "Deployment-Aktionen",
"redeploy": "Erneut deployen",
"redeploy-success": "Deployment erneut bereitgestellt.",
"sort": {
"deploymentTime": "Deployment-Zeit",
"name": "Name",
Expand Down
3 changes: 3 additions & 0 deletions public/locales/en-US/translation.json
Original file line number Diff line number Diff line change
Expand Up @@ -440,6 +440,9 @@
"empty-response": "Empty response",
"form-preview": "Form preview",
"raw-data-json": "Raw data (JSON)",
"actions": "Deployment Actions",
"redeploy": "Redeploy",
"redeploy-success": "Deployment redeployed.",
"sort": {
"deploymentTime": "Deployment time",
"name": "Name",
Expand Down
7 changes: 5 additions & 2 deletions src/api/resources/deployment.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { GET, DELETE, GET_TEXT } from '../helper.jsx'
import { GET, DELETE, GET_TEXT, POST } from '../helper.jsx'

/**
* Fetches deployments sorted by deployment time, sets the first as selected
Expand Down Expand Up @@ -33,12 +33,15 @@ const get_deployment_resource = (state, deployment_id, resource_id) =>
const delete_deployment = (state, deployment_id, params = {}) =>
DELETE(`/deployment/${deployment_id}?${new URLSearchParams(params).toString()}`, null, state, state.api.deployment.delete)

const redeploy_deployment = (state, deployment_id) =>
POST(`/deployment/${deployment_id}/redeploy`, {}, state, state.api.deployment.redeploy)

const deployment = {
all: get_deployments,
resources: get_deployment_resources,
resource: get_deployment_resource,
delete: delete_deployment
delete: delete_deployment,
redeploy: redeploy_deployment,
}

export default deployment
13 changes: 12 additions & 1 deletion src/api/resources/deployment.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,10 @@ vi.mock("../helper.jsx", () => ({
GET: vi.fn(),
DELETE: vi.fn(),
GET_TEXT: vi.fn(),
POST: vi.fn(),
}));

import { GET, DELETE, GET_TEXT } from "../helper.jsx";
import { GET, DELETE, GET_TEXT, POST } from "../helper.jsx";
import { create_mock_state, expect_api_call } from "../../test/helpers.js";
import deployment from "./deployment.js";

Expand Down Expand Up @@ -65,4 +66,14 @@ describe("api/resources/deployment", () => {
signal: state.api.deployment.delete,
});
});

it("redeploy() POSTs the selected deployment", () => {
deployment.redeploy(state, "dep-1");
expect_api_call(POST, {
url: "/deployment/dep-1/redeploy",
body: {},
state,
signal: state.api.deployment.redeploy,
});
});
});
27 changes: 26 additions & 1 deletion src/pages/Deployments.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -216,7 +216,8 @@ const DeploymentsList = () => {

const ResourcesList = () => {
const state = useContext(AppState),
{ params } = useRoute(),
{ params, query } = useRoute(),
{ route } = useLocation(),
[t] = useTranslation();

if (!params.deployment_id) {
Expand All @@ -227,6 +228,30 @@ const ResourcesList = () => {

return (
<div>
<section>
<h3>{t("deployments.actions")}</h3>
<RequestState
signal={state.api.deployment.redeploy}
on_nothing={() => null}
on_success={() => <p class="success">{t("deployments.redeploy-success")}</p>}
/>
<div class="button-group">
<button
type="button"
onClick={() =>
void Promise.resolve(
engine_rest.deployment.redeploy(state, params.deployment_id),
).then(() => {
load_deployments(state, query);
const deployment_id = state.api.deployment.redeploy.value?.data?.id;
if (deployment_id) route(`/deployments/${deployment_id}`, true);
})
}
>
{t("deployments.redeploy")}
</button>
</div>
</section>
<table>
<thead>
<tr>
Expand Down
20 changes: 19 additions & 1 deletion src/pages/Deployments.test.jsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { describe, it, expect, vi, beforeEach, afterEach } from "vitest";
import { h } from "preact";
import { render, cleanup } from "@testing-library/preact";
import { render, cleanup, fireEvent } from "@testing-library/preact";

// Spy all engine_rest API functions but keep RequestState/RESPONSE_STATE real.
vi.mock("../api/engine_rest.jsx", async (importOriginal) => {
Expand Down Expand Up @@ -101,6 +101,24 @@ describe("DeploymentsPage", () => {
expect(link.getAttribute("href")).toBe("/deployments/dep1/process.bpmn");
});

it("redeploys the active deployment", async () => {
mockParams = { deployment_id: "dep1" };
engine_rest.deployment.redeploy.mockImplementationOnce(() => {
signal_response(state.api.deployment.redeploy, { id: "dep2" });
return Promise.resolve(state.api.deployment.redeploy.value);
});
const { getByText } = renderPage(state);

fireEvent.click(getByText("deployments.redeploy"));
await Promise.resolve();

expect(engine_rest.deployment.redeploy).toHaveBeenCalled();
expect(engine_rest.deployment.redeploy.mock.lastCall[0]).toBe(state);
expect(engine_rest.deployment.redeploy.mock.lastCall[1]).toBe("dep1");
expect(engine_rest.deployment.all).toHaveBeenCalled();
expect(routeFn).toHaveBeenCalledWith("/deployments/dep2", true);
});

it("fetches resource content + definition + instance count when a resource is selected", () => {
mockParams = { deployment_id: "dep1", resource_name: "process.bpmn" };
signal_response(state.api.deployment.resources, [
Expand Down
1 change: 1 addition & 0 deletions src/state.js
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,7 @@ const createAppState = () => {
resources: signal(null),
resource: signal(null),
delete: signal(null),
redeploy: signal(null),
saved_filters: signal(null),
},
decision: {
Expand Down