mirror of
https://github.com/keycloak/keycloak.git
synced 2025-12-21 06:20:05 -06:00
Workflows now use YAML instead of JSON.
Closes #43665 Signed-off-by: Stan Silvert <ssilvert@redhat.com>
This commit is contained in:
@@ -3593,8 +3593,8 @@ workflows=Workflows
|
||||
titleWorkflows=Workflows
|
||||
workflowsExplain=Workflows empower administrators to automate the management of realm resources through time-based or event-based policies.
|
||||
createWorkflow=Create workflow
|
||||
workflowJSON=Workflow JSON
|
||||
workflowJsonHelp=The JSON representation of the workflow.
|
||||
workflowYAML=Workflow YAML
|
||||
workflowYAMLHelp=The YAML representation of the workflow.
|
||||
emptyWorkflows=No workflows
|
||||
emptyWorkflowsInstructions=There are no workflows in this realm. Please create a workflow to get started.
|
||||
workflowCreated=The workflow has been created.
|
||||
|
||||
@@ -109,7 +109,8 @@
|
||||
"react-i18next": "^16.0.1",
|
||||
"react-router-dom": "^6.30.1",
|
||||
"reactflow": "^11.11.4",
|
||||
"use-react-router-breadcrumbs": "^4.0.1"
|
||||
"use-react-router-breadcrumbs": "^4.0.1",
|
||||
"yaml": "^2.8.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@axe-core/playwright": "^4.10.2",
|
||||
|
||||
@@ -13,6 +13,7 @@ import {
|
||||
} from "react-hook-form";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { Link, useNavigate } from "react-router-dom";
|
||||
import yaml from "yaml";
|
||||
import { useAdminClient } from "../admin-client";
|
||||
import {
|
||||
HelpItem,
|
||||
@@ -33,7 +34,7 @@ import { ViewHeader } from "../components/view-header/ViewHeader";
|
||||
import WorkflowRepresentation from "libs/keycloak-admin-client/lib/defs/workflowRepresentation";
|
||||
|
||||
type AttributeForm = {
|
||||
workflowJSON: string;
|
||||
workflowYAML: string;
|
||||
};
|
||||
|
||||
export default function WorkflowDetailForm() {
|
||||
@@ -47,7 +48,7 @@ export default function WorkflowDetailForm() {
|
||||
const form = useForm<AttributeForm>({
|
||||
mode: "onChange",
|
||||
defaultValues: {
|
||||
workflowJSON: "",
|
||||
workflowYAML: "",
|
||||
},
|
||||
});
|
||||
const { control, handleSubmit, setValue } = form;
|
||||
@@ -72,13 +73,13 @@ export default function WorkflowDetailForm() {
|
||||
workflowToSet.name = `${workflow.name} -- ${t("copy")}`;
|
||||
}
|
||||
|
||||
setValue("workflowJSON", JSON.stringify(workflowToSet, null, 2));
|
||||
setValue("workflowYAML", yaml.stringify(workflowToSet));
|
||||
},
|
||||
[mode, id, setValue, t],
|
||||
);
|
||||
|
||||
const validateWorkflowJSON = (jsonStr: string): WorkflowRepresentation => {
|
||||
const json = JSON.parse(jsonStr);
|
||||
const validateworkflowYAML = (yamlStr: string): WorkflowRepresentation => {
|
||||
const json: WorkflowRepresentation = yaml.parse(yamlStr);
|
||||
if (!json.name) {
|
||||
throw new Error(t("workflowNameRequired"));
|
||||
}
|
||||
@@ -87,8 +88,8 @@ export default function WorkflowDetailForm() {
|
||||
|
||||
const onUpdate: SubmitHandler<AttributeForm> = async (data) => {
|
||||
try {
|
||||
const json = validateWorkflowJSON(data.workflowJSON);
|
||||
await adminClient.workflows.update({ id: json.id! }, json);
|
||||
const json = validateworkflowYAML(data.workflowYAML);
|
||||
await adminClient.workflows.update({ id }, json);
|
||||
addAlert(t("workflowUpdated"), AlertVariant.success);
|
||||
} catch (error) {
|
||||
addError("workflowUpdateError", error);
|
||||
@@ -97,8 +98,10 @@ export default function WorkflowDetailForm() {
|
||||
|
||||
const onCreate: SubmitHandler<AttributeForm> = async (data) => {
|
||||
try {
|
||||
const json = validateWorkflowJSON(data.workflowJSON);
|
||||
await adminClient.workflows.create(json);
|
||||
await adminClient.workflows.createAsYaml({
|
||||
realm,
|
||||
yaml: data.workflowYAML,
|
||||
});
|
||||
addAlert(t("workflowCreated"), AlertVariant.success);
|
||||
navigate(toWorkflows({ realm }));
|
||||
} catch (error) {
|
||||
@@ -136,10 +139,10 @@ export default function WorkflowDetailForm() {
|
||||
fineGrainedAccess={true}
|
||||
>
|
||||
<FormGroup
|
||||
label={t("workflowJSON")}
|
||||
label={t("workflowYAML")}
|
||||
labelIcon={
|
||||
<HelpItem
|
||||
helpText={t("workflowJsonHelp")}
|
||||
helpText={t("workflowYAMLHelp")}
|
||||
fieldLabelId="code"
|
||||
/>
|
||||
}
|
||||
@@ -147,15 +150,15 @@ export default function WorkflowDetailForm() {
|
||||
isRequired
|
||||
>
|
||||
<Controller
|
||||
name="workflowJSON"
|
||||
name="workflowYAML"
|
||||
control={control}
|
||||
render={({ field }) => (
|
||||
<CodeEditor
|
||||
id="workflowJSON"
|
||||
data-testid="workflowJSON"
|
||||
id="workflowYAML"
|
||||
data-testid="workflowYAML"
|
||||
value={field.value}
|
||||
onChange={field.onChange}
|
||||
language="json"
|
||||
language="yaml"
|
||||
height={600}
|
||||
/>
|
||||
)}
|
||||
|
||||
@@ -3,6 +3,7 @@ import {
|
||||
Button,
|
||||
ButtonVariant,
|
||||
PageSection,
|
||||
Switch,
|
||||
} from "@patternfly/react-core";
|
||||
import {
|
||||
Action,
|
||||
@@ -46,17 +47,17 @@ export default function WorkflowsSection() {
|
||||
);
|
||||
};
|
||||
|
||||
const toggleEnabled = async (workflowJSON: WorkflowRepresentation) => {
|
||||
workflowJSON.enabled = !(workflowJSON.enabled ?? true);
|
||||
|
||||
const toggleEnabled = async (workflow: WorkflowRepresentation) => {
|
||||
const enabled = !(workflow.enabled ?? true);
|
||||
const workflowToUpdate = { ...workflow, enabled };
|
||||
try {
|
||||
await adminClient.workflows.update(
|
||||
{ id: workflowJSON.id! },
|
||||
workflowJSON,
|
||||
{ id: workflow.id! },
|
||||
workflowToUpdate,
|
||||
);
|
||||
|
||||
addAlert(
|
||||
workflowJSON.enabled ? t("workflowEnabled") : t("workflowDisabled"),
|
||||
workflowToUpdate.enabled ? t("workflowEnabled") : t("workflowDisabled"),
|
||||
AlertVariant.success,
|
||||
);
|
||||
refresh();
|
||||
@@ -127,9 +128,14 @@ export default function WorkflowsSection() {
|
||||
{
|
||||
name: "status",
|
||||
displayKey: "status",
|
||||
cellRenderer: (row: WorkflowRepresentation) => {
|
||||
return (row.enabled ?? true) ? t("enabled") : t("disabled");
|
||||
},
|
||||
cellRenderer: (workflow: WorkflowRepresentation) => (
|
||||
<Switch
|
||||
label={t("enabled")}
|
||||
labelOff={t("disabled")}
|
||||
isChecked={workflow.enabled ?? true}
|
||||
onChange={() => toggleEnabled(workflow)}
|
||||
/>
|
||||
),
|
||||
},
|
||||
]}
|
||||
actions={[
|
||||
@@ -149,16 +155,6 @@ export default function WorkflowsSection() {
|
||||
);
|
||||
},
|
||||
} as Action<WorkflowRepresentation>,
|
||||
{
|
||||
title: t("changeStatus"),
|
||||
tooltipProps: {
|
||||
content: t("changeStatusTooltip"),
|
||||
},
|
||||
onRowClick: (workflow) => {
|
||||
setSelectedWorkflow(workflow);
|
||||
void toggleEnabled(workflow);
|
||||
},
|
||||
} as Action<WorkflowRepresentation>,
|
||||
]}
|
||||
loader={loader}
|
||||
ariaLabelKey="workflows"
|
||||
|
||||
@@ -40,9 +40,20 @@ export class Workflows extends Resource<{ realm?: string }> {
|
||||
|
||||
public create = this.makeRequest<WorkflowRepresentation, { id: string }>({
|
||||
method: "POST",
|
||||
headers: { "Content-Type": "application/json" },
|
||||
returnResourceIdInLocationHeader: { field: "id" },
|
||||
});
|
||||
|
||||
public createAsYaml = this.makeRequest<
|
||||
{ realm: string; yaml: string },
|
||||
{ id: string }
|
||||
>({
|
||||
method: "POST",
|
||||
headers: { "Content-Type": "application/yaml", Accept: "application/yaml" },
|
||||
returnResourceIdInLocationHeader: { field: "id" },
|
||||
payloadKey: "yaml",
|
||||
});
|
||||
|
||||
public delById = this.makeRequest<{ id: string }, void>({
|
||||
method: "DELETE",
|
||||
path: "/{id}",
|
||||
|
||||
4
js/pnpm-lock.yaml
generated
4
js/pnpm-lock.yaml
generated
@@ -222,6 +222,9 @@ importers:
|
||||
use-react-router-breadcrumbs:
|
||||
specifier: ^4.0.1
|
||||
version: 4.0.1(react-router-dom@6.30.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react@18.3.1)
|
||||
yaml:
|
||||
specifier: ^2.8.1
|
||||
version: 2.8.1
|
||||
devDependencies:
|
||||
'@axe-core/playwright':
|
||||
specifier: ^4.10.2
|
||||
@@ -5141,6 +5144,7 @@ snapshots:
|
||||
react-router-dom: 6.30.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
|
||||
reactflow: 11.11.4(@types/react@18.3.23)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
|
||||
use-react-router-breadcrumbs: 4.0.1(react-router-dom@6.30.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react@18.3.1)
|
||||
yaml: 2.8.1
|
||||
transitivePeerDependencies:
|
||||
- '@babel/runtime'
|
||||
- '@types/react'
|
||||
|
||||
Reference in New Issue
Block a user