From f789d64f6352136c1bc30a016512456273050559 Mon Sep 17 00:00:00 2001 From: Fabrizio Antonangeli Date: Fri, 14 Jun 2024 18:05:13 +0200 Subject: [PATCH] kie-issues#1060: Create Sonataflow management console webapp (#24) * Add WorkflowDefinitions page * Add WorkflowForm page * add WorkflowInstances * Add WorkflowDetails * add TriggerCloudEvent * Apply PR: NO-ISSUE: Add url package everywhere stream-http is used #2301 * add MonitoringPage * Renamed pages * rm EmptyPage * Fix lint warnings * styles * Monitoring webapp configuration * Commit defaultEnvJson * Configured monitoring-webapp and HashRouter * Add sonataflow-realm.json * kie-issues#1173: Retrieve workflow definitions from data index instead of openapi.json (#2302) Co-authored-by: Guilherme Caponetto <638737+caponetto@users.noreply.github.com> * Aligned the code to pull #2302 * Removed use of sonataflowOpenApiBaseUrl * Fix merge errors --------- Co-authored-by: Paulo Martins Co-authored-by: Guilherme Caponetto <638737+caponetto@users.noreply.github.com> --- .gitignore | 3 + .../build/defaultEnvJson.js | 39 + .../dev/config/sonataflow-realm.json | 1996 +++++++++++++++++ .../package.json | 21 +- .../MonitoringReport.dash.yml | 300 +++ .../WorkflowDetails.dash.yml | 255 +++ .../resources/monitoring-webapp/setup.js | 36 + ...ess-workflow-combined-editor-envelope.html | 42 + ...less-workflow-diagram-editor-envelope.html | 42 + ...verless-workflow-text-editor-envelope.html | 42 + .../src/alerts/Alerts.tsx | 194 ++ .../src/alerts/GlobalAlertsContext.tsx | 125 ++ .../ManagementConsole/ManagementConsole.tsx | 34 +- .../ManagementConsoleNav.tsx | 28 +- .../ManagementConsoleRoutes.tsx | 32 +- .../MonitoringContainer.tsx} | 27 +- .../pages/MonitoringPage/MonitoringPage.tsx | 180 ++ .../TriggerCloudEventPage.tsx | 118 + .../WorkflowDefinitionsPage.tsx | 91 + .../WorkflowDetailsPage.tsx | 113 + .../WorkflowFormPage/WorkflowFormPage.tsx | 159 ++ .../WorkflowInstancesPage.tsx | 78 + .../src/components/styles.css | 33 + ...erlessWorkflowCombinedEditorEnvelopeApp.ts | 42 + ...verlessWorkflowDiagramEditorEnvelopeApp.ts | 45 + ...ServerlessWorkflowTextEditorEnvelopeApp.ts | 39 + .../src/index.tsx | 2 +- .../src/navigation/Routes.ts | 138 ++ .../webpack.config.js | 69 +- pnpm-lock.yaml | 326 ++- repo/graph.dot | 2 + repo/graph.json | 10 + 32 files changed, 4539 insertions(+), 122 deletions(-) create mode 100644 packages/sonataflow-management-console-webapp/build/defaultEnvJson.js create mode 100644 packages/sonataflow-management-console-webapp/dev/config/sonataflow-realm.json create mode 100644 packages/sonataflow-management-console-webapp/resources/monitoring-webapp/MonitoringReport.dash.yml create mode 100644 packages/sonataflow-management-console-webapp/resources/monitoring-webapp/WorkflowDetails.dash.yml create mode 100644 packages/sonataflow-management-console-webapp/resources/monitoring-webapp/setup.js create mode 100644 packages/sonataflow-management-console-webapp/resources/serverless-workflow-combined-editor-envelope.html create mode 100644 packages/sonataflow-management-console-webapp/resources/serverless-workflow-diagram-editor-envelope.html create mode 100644 packages/sonataflow-management-console-webapp/resources/serverless-workflow-text-editor-envelope.html create mode 100644 packages/sonataflow-management-console-webapp/src/alerts/Alerts.tsx create mode 100644 packages/sonataflow-management-console-webapp/src/alerts/GlobalAlertsContext.tsx rename packages/sonataflow-management-console-webapp/src/components/{pages/EmptyPage.tsx => containers/MonitoringContainer/MonitoringContainer.tsx} (56%) create mode 100644 packages/sonataflow-management-console-webapp/src/components/pages/MonitoringPage/MonitoringPage.tsx create mode 100644 packages/sonataflow-management-console-webapp/src/components/pages/TriggerCloudEventPage/TriggerCloudEventPage.tsx create mode 100644 packages/sonataflow-management-console-webapp/src/components/pages/WorkflowDefinitionsPage/WorkflowDefinitionsPage.tsx create mode 100644 packages/sonataflow-management-console-webapp/src/components/pages/WorkflowDetailsPage/WorkflowDetailsPage.tsx create mode 100644 packages/sonataflow-management-console-webapp/src/components/pages/WorkflowFormPage/WorkflowFormPage.tsx create mode 100644 packages/sonataflow-management-console-webapp/src/components/pages/WorkflowInstancesPage/WorkflowInstancesPage.tsx create mode 100644 packages/sonataflow-management-console-webapp/src/envelope/ServerlessWorkflowCombinedEditorEnvelopeApp.ts create mode 100644 packages/sonataflow-management-console-webapp/src/envelope/ServerlessWorkflowDiagramEditorEnvelopeApp.ts create mode 100644 packages/sonataflow-management-console-webapp/src/envelope/ServerlessWorkflowTextEditorEnvelopeApp.ts create mode 100644 packages/sonataflow-management-console-webapp/src/navigation/Routes.ts diff --git a/.gitignore b/.gitignore index bdb41c4ceef..9b259d87f11 100644 --- a/.gitignore +++ b/.gitignore @@ -74,6 +74,9 @@ package-lock.json ## runtime-tools-management-console-webapp !packages/runtime-tools-management-console-webapp/build +## sonataflow-management-console-webapp +!packages/sonataflow-management-console-webapp/build + ## vscode-* **/.vscode-test/ **/.vscode-test-web/ diff --git a/packages/sonataflow-management-console-webapp/build/defaultEnvJson.js b/packages/sonataflow-management-console-webapp/build/defaultEnvJson.js new file mode 100644 index 00000000000..4a5d2ce8f53 --- /dev/null +++ b/packages/sonataflow-management-console-webapp/build/defaultEnvJson.js @@ -0,0 +1,39 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +const { env: buildEnv } = require("../env"); + +const version = require("../package.json").version; + +module.exports = { + defaultEnvJson: { + // RUNTIME_TOOLS_MANAGEMENT_CONSOLE_KOGITO_ENV_MODE: buildEnv.runtimeToolsManagementConsoleWebapp.kogitoEnvMode, + RUNTIME_TOOLS_MANAGEMENT_CONSOLE_KOGITO_APP_NAME: "Management Console", + RUNTIME_TOOLS_MANAGEMENT_CONSOLE_KOGITO_APP_VERSION: version, + KOGITO_CONSOLES_KEYCLOAK_DISABLE_HEALTH_CHECK: false, + KOGITO_CONSOLES_KEYCLOAK_UPDATE_TOKEN_VALIDITY: 30, + KOGITO_CONSOLES_KEYCLOAK_HEALTH_CHECK_URL: + "http://localhost:8280/auth/realms/kogito/.well-known/openid-configuration", + KOGITO_CONSOLES_KEYCLOAK_REALM: "kogito", + KOGITO_CONSOLES_KEYCLOAK_URL: "http://localhost:8280/auth", + KOGITO_CONSOLES_KEYCLOAK_CLIENT_ID: "kogito-console-react", + SONATAFLOW_DATA_INDEX_URL: buildEnv.sonataflowManagementConsoleWebapp.sonataflowDataIndexUrl, + SONATAFLOW_OPENAPIBASE_URL: buildEnv.sonataflowManagementConsoleWebapp.sonataflowOpenApiBaseUrl, + }, +}; diff --git a/packages/sonataflow-management-console-webapp/dev/config/sonataflow-realm.json b/packages/sonataflow-management-console-webapp/dev/config/sonataflow-realm.json new file mode 100644 index 00000000000..1969c55cad9 --- /dev/null +++ b/packages/sonataflow-management-console-webapp/dev/config/sonataflow-realm.json @@ -0,0 +1,1996 @@ +{ + "realm": "kogito", + "notBefore": 0, + "revokeRefreshToken": false, + "refreshTokenMaxReuse": 0, + "accessTokenLifespan": 300, + "accessTokenLifespanForImplicitFlow": 900, + "ssoSessionIdleTimeout": 1800, + "ssoSessionMaxLifespan": 36000, + "ssoSessionIdleTimeoutRememberMe": 0, + "ssoSessionMaxLifespanRememberMe": 0, + "offlineSessionIdleTimeout": 2592000, + "offlineSessionMaxLifespanEnabled": false, + "offlineSessionMaxLifespan": 5184000, + "accessCodeLifespan": 60, + "accessCodeLifespanUserAction": 300, + "accessCodeLifespanLogin": 1800, + "actionTokenGeneratedByAdminLifespan": 43200, + "actionTokenGeneratedByUserLifespan": 300, + "enabled": true, + "sslRequired": "external", + "registrationAllowed": false, + "registrationEmailAsUsername": false, + "rememberMe": false, + "verifyEmail": false, + "loginWithEmailAllowed": true, + "duplicateEmailsAllowed": false, + "resetPasswordAllowed": false, + "editUsernameAllowed": false, + "bruteForceProtected": false, + "permanentLockout": false, + "maxFailureWaitSeconds": 900, + "minimumQuickLoginWaitSeconds": 60, + "waitIncrementSeconds": 60, + "quickLoginCheckMilliSeconds": 1000, + "maxDeltaTimeSeconds": 43200, + "failureFactor": 30, + "roles": { + "realm": [ + { + "name": "confidential", + "composite": false, + "clientRole": false, + "containerId": "11d78bf6-6d10-4484-baba-a1388379d68b", + "attributes": {} + }, + { + "name": "uma_authorization", + "description": "${role_uma_authorization}", + "composite": false, + "clientRole": false, + "containerId": "11d78bf6-6d10-4484-baba-a1388379d68b", + "attributes": {} + }, + { + "name": "admin", + "composite": false, + "clientRole": false, + "containerId": "11d78bf6-6d10-4484-baba-a1388379d68b", + "attributes": {} + }, + { + "name": "user", + "composite": false, + "clientRole": false, + "containerId": "11d78bf6-6d10-4484-baba-a1388379d68b", + "attributes": {} + }, + { + "name": "offline_access", + "description": "${role_offline-access}", + "composite": false, + "clientRole": false, + "containerId": "11d78bf6-6d10-4484-baba-a1388379d68b", + "attributes": {} + } + ], + "client": { + "realm-management": [ + { + "name": "manage-identity-providers", + "description": "${role_manage-identity-providers}", + "composite": false, + "clientRole": true, + "containerId": "376bd940-e50a-4495-80fc-9c6c07312748", + "attributes": {} + }, + { + "name": "impersonation", + "description": "${role_impersonation}", + "composite": false, + "clientRole": true, + "containerId": "376bd940-e50a-4495-80fc-9c6c07312748", + "attributes": {} + }, + { + "name": "view-identity-providers", + "description": "${role_view-identity-providers}", + "composite": false, + "clientRole": true, + "containerId": "376bd940-e50a-4495-80fc-9c6c07312748", + "attributes": {} + }, + { + "name": "view-realm", + "description": "${role_view-realm}", + "composite": false, + "clientRole": true, + "containerId": "376bd940-e50a-4495-80fc-9c6c07312748", + "attributes": {} + }, + { + "name": "query-users", + "description": "${role_query-users}", + "composite": false, + "clientRole": true, + "containerId": "376bd940-e50a-4495-80fc-9c6c07312748", + "attributes": {} + }, + { + "name": "manage-clients", + "description": "${role_manage-clients}", + "composite": false, + "clientRole": true, + "containerId": "376bd940-e50a-4495-80fc-9c6c07312748", + "attributes": {} + }, + { + "name": "manage-events", + "description": "${role_manage-events}", + "composite": false, + "clientRole": true, + "containerId": "376bd940-e50a-4495-80fc-9c6c07312748", + "attributes": {} + }, + { + "name": "realm-admin", + "description": "${role_realm-admin}", + "composite": true, + "composites": { + "client": { + "realm-management": [ + "impersonation", + "manage-identity-providers", + "view-identity-providers", + "view-realm", + "query-users", + "manage-clients", + "manage-events", + "manage-realm", + "view-authorization", + "manage-authorization", + "view-users", + "create-client", + "query-clients", + "query-groups", + "manage-users", + "view-clients", + "view-events", + "query-realms" + ] + } + }, + "clientRole": true, + "containerId": "376bd940-e50a-4495-80fc-9c6c07312748", + "attributes": {} + }, + { + "name": "manage-realm", + "description": "${role_manage-realm}", + "composite": false, + "clientRole": true, + "containerId": "376bd940-e50a-4495-80fc-9c6c07312748", + "attributes": {} + }, + { + "name": "view-authorization", + "description": "${role_view-authorization}", + "composite": false, + "clientRole": true, + "containerId": "376bd940-e50a-4495-80fc-9c6c07312748", + "attributes": {} + }, + { + "name": "manage-authorization", + "description": "${role_manage-authorization}", + "composite": false, + "clientRole": true, + "containerId": "376bd940-e50a-4495-80fc-9c6c07312748", + "attributes": {} + }, + { + "name": "create-client", + "description": "${role_create-client}", + "composite": false, + "clientRole": true, + "containerId": "376bd940-e50a-4495-80fc-9c6c07312748", + "attributes": {} + }, + { + "name": "view-users", + "description": "${role_view-users}", + "composite": true, + "composites": { + "client": { + "realm-management": ["query-groups", "query-users"] + } + }, + "clientRole": true, + "containerId": "376bd940-e50a-4495-80fc-9c6c07312748", + "attributes": {} + }, + { + "name": "query-clients", + "description": "${role_query-clients}", + "composite": false, + "clientRole": true, + "containerId": "376bd940-e50a-4495-80fc-9c6c07312748", + "attributes": {} + }, + { + "name": "query-groups", + "description": "${role_query-groups}", + "composite": false, + "clientRole": true, + "containerId": "376bd940-e50a-4495-80fc-9c6c07312748", + "attributes": {} + }, + { + "name": "manage-users", + "description": "${role_manage-users}", + "composite": false, + "clientRole": true, + "containerId": "376bd940-e50a-4495-80fc-9c6c07312748", + "attributes": {} + }, + { + "name": "view-clients", + "description": "${role_view-clients}", + "composite": true, + "composites": { + "client": { + "realm-management": ["query-clients"] + } + }, + "clientRole": true, + "containerId": "376bd940-e50a-4495-80fc-9c6c07312748", + "attributes": {} + }, + { + "name": "view-events", + "description": "${role_view-events}", + "composite": false, + "clientRole": true, + "containerId": "376bd940-e50a-4495-80fc-9c6c07312748", + "attributes": {} + }, + { + "name": "query-realms", + "description": "${role_query-realms}", + "composite": false, + "clientRole": true, + "containerId": "376bd940-e50a-4495-80fc-9c6c07312748", + "attributes": {} + } + ], + "security-admin-console": [], + "admin-cli": [], + "kogito-service": [ + { + "name": "uma_protection", + "composite": false, + "clientRole": true, + "containerId": "0ac5df91-e044-4051-bd03-106a3a5fb9cc", + "attributes": {} + } + ], + "broker": [ + { + "name": "read-token", + "description": "${role_read-token}", + "composite": false, + "clientRole": true, + "containerId": "53d4fe53-a039-471e-886a-28eddc950e95", + "attributes": {} + } + ], + "account": [ + { + "name": "view-profile", + "description": "${role_view-profile}", + "composite": false, + "clientRole": true, + "containerId": "e55e1234-38fa-432d-8d90-39f5e024688d", + "attributes": {} + }, + { + "name": "manage-account", + "description": "${role_manage-account}", + "composite": true, + "composites": { + "client": { + "account": ["manage-account-links"] + } + }, + "clientRole": true, + "containerId": "e55e1234-38fa-432d-8d90-39f5e024688d", + "attributes": {} + }, + { + "name": "manage-account-links", + "description": "${role_manage-account-links}", + "composite": false, + "clientRole": true, + "containerId": "e55e1234-38fa-432d-8d90-39f5e024688d", + "attributes": {} + } + ] + } + }, + "groups": [], + "defaultRoles": ["uma_authorization", "offline_access"], + "requiredCredentials": ["password"], + "otpPolicyType": "totp", + "otpPolicyAlgorithm": "HmacSHA1", + "otpPolicyInitialCounter": 0, + "otpPolicyDigits": 6, + "otpPolicyLookAheadWindow": 1, + "otpPolicyPeriod": 30, + "otpSupportedApplications": ["FreeOTP", "Google Authenticator"], + "scopeMappings": [ + { + "clientScope": "offline_access", + "roles": ["offline_access"] + } + ], + "clients": [ + { + "clientId": "account", + "name": "${client_account}", + "baseUrl": "/auth/realms/kogito/account", + "surrogateAuthRequired": false, + "enabled": true, + "clientAuthenticatorType": "client-secret", + "secret": "0136c3ef-0dfd-4b13-a6d0-2c8b6358edec", + "defaultRoles": ["view-profile", "manage-account"], + "redirectUris": ["/auth/realms/kogito/account/*"], + "webOrigins": [], + "notBefore": 0, + "bearerOnly": false, + "consentRequired": false, + "standardFlowEnabled": true, + "implicitFlowEnabled": false, + "directAccessGrantsEnabled": false, + "serviceAccountsEnabled": false, + "publicClient": false, + "frontchannelLogout": false, + "protocol": "openid-connect", + "attributes": {}, + "authenticationFlowBindingOverrides": {}, + "fullScopeAllowed": false, + "nodeReRegistrationTimeout": 0, + "defaultClientScopes": ["web-origins", "role_list", "profile", "roles", "email"], + "optionalClientScopes": ["address", "phone", "offline_access", "microprofile-jwt"] + }, + { + "clientId": "admin-cli", + "name": "${client_admin-cli}", + "surrogateAuthRequired": false, + "enabled": true, + "clientAuthenticatorType": "client-secret", + "secret": "a951803a-79c7-46a6-8197-e32835286971", + "redirectUris": [], + "webOrigins": [], + "notBefore": 0, + "bearerOnly": false, + "consentRequired": false, + "standardFlowEnabled": false, + "implicitFlowEnabled": false, + "directAccessGrantsEnabled": true, + "serviceAccountsEnabled": false, + "publicClient": true, + "frontchannelLogout": false, + "protocol": "openid-connect", + "attributes": {}, + "authenticationFlowBindingOverrides": {}, + "fullScopeAllowed": false, + "nodeReRegistrationTimeout": 0, + "defaultClientScopes": ["web-origins", "role_list", "profile", "roles", "email"], + "optionalClientScopes": ["address", "phone", "offline_access", "microprofile-jwt"] + }, + { + "clientId": "broker", + "name": "${client_broker}", + "surrogateAuthRequired": false, + "enabled": true, + "clientAuthenticatorType": "client-secret", + "secret": "e1f7edd7-e15c-43b4-8736-ff8204d16836", + "redirectUris": [], + "webOrigins": [], + "notBefore": 0, + "bearerOnly": false, + "consentRequired": false, + "standardFlowEnabled": true, + "implicitFlowEnabled": false, + "directAccessGrantsEnabled": false, + "serviceAccountsEnabled": false, + "publicClient": false, + "frontchannelLogout": false, + "protocol": "openid-connect", + "attributes": {}, + "authenticationFlowBindingOverrides": {}, + "fullScopeAllowed": false, + "nodeReRegistrationTimeout": 0, + "defaultClientScopes": ["web-origins", "role_list", "profile", "roles", "email"], + "optionalClientScopes": ["address", "phone", "offline_access", "microprofile-jwt"] + }, + { + "clientId": "kogito-frontend", + "rootUrl": "http://localhost:8082", + "adminUrl": "http://localhost:8082", + "surrogateAuthRequired": false, + "enabled": true, + "clientAuthenticatorType": "client-secret", + "secret": "secret", + "redirectUris": ["http://localhost:8082/*"], + "webOrigins": ["http://localhost:8082"], + "notBefore": 0, + "bearerOnly": false, + "consentRequired": false, + "standardFlowEnabled": true, + "implicitFlowEnabled": false, + "directAccessGrantsEnabled": true, + "serviceAccountsEnabled": false, + "publicClient": false, + "frontchannelLogout": false, + "protocol": "openid-connect", + "attributes": { + "saml.assertion.signature": "false", + "saml.force.post.binding": "false", + "saml.multivalued.roles": "false", + "saml.encrypt": "false", + "saml.server.signature": "false", + "saml.server.signature.keyinfo.ext": "false", + "exclude.session.state.from.auth.response": "false", + "saml_force_name_id_format": "false", + "saml.client.signature": "false", + "tls.client.certificate.bound.access.tokens": "false", + "saml.authnstatement": "false", + "display.on.consent.screen": "false", + "saml.onetimeuse.condition": "false" + }, + "authenticationFlowBindingOverrides": {}, + "fullScopeAllowed": true, + "nodeReRegistrationTimeout": -1, + "defaultClientScopes": ["web-origins", "role_list", "profile", "roles", "email"], + "optionalClientScopes": ["address", "phone", "offline_access", "microprofile-jwt"], + "access": { + "view": true, + "configure": true, + "manage": true + } + }, + { + "clientId": "kogito-app", + "rootUrl": "http://localhost:8080", + "adminUrl": "http://localhost:8080", + "surrogateAuthRequired": false, + "enabled": true, + "clientAuthenticatorType": "client-secret", + "secret": "secret", + "redirectUris": ["http://localhost:8080/*"], + "webOrigins": ["*"], + "notBefore": 0, + "bearerOnly": false, + "consentRequired": false, + "standardFlowEnabled": true, + "implicitFlowEnabled": false, + "directAccessGrantsEnabled": true, + "serviceAccountsEnabled": false, + "publicClient": false, + "frontchannelLogout": false, + "protocol": "openid-connect", + "attributes": { + "saml.assertion.signature": "false", + "saml.force.post.binding": "false", + "saml.multivalued.roles": "false", + "saml.encrypt": "false", + "saml.server.signature": "false", + "saml.server.signature.keyinfo.ext": "false", + "exclude.session.state.from.auth.response": "false", + "saml_force_name_id_format": "false", + "saml.client.signature": "false", + "tls.client.certificate.bound.access.tokens": "false", + "saml.authnstatement": "false", + "display.on.consent.screen": "false", + "saml.onetimeuse.condition": "false" + }, + "authenticationFlowBindingOverrides": {}, + "fullScopeAllowed": true, + "nodeReRegistrationTimeout": -1, + "defaultClientScopes": ["web-origins", "role_list", "profile", "roles", "email"], + "optionalClientScopes": ["address", "phone", "offline_access", "microprofile-jwt"], + "access": { + "view": true, + "configure": true, + "manage": true + } + }, + { + "clientId": "kogito-service", + "rootUrl": "", + "surrogateAuthRequired": false, + "enabled": true, + "clientAuthenticatorType": "client-secret", + "secret": "secret", + "redirectUris": ["*"], + "webOrigins": ["*"], + "notBefore": 0, + "bearerOnly": false, + "consentRequired": false, + "standardFlowEnabled": true, + "implicitFlowEnabled": false, + "directAccessGrantsEnabled": true, + "serviceAccountsEnabled": true, + "authorizationServicesEnabled": true, + "publicClient": false, + "frontchannelLogout": false, + "protocol": "openid-connect", + "attributes": {}, + "authenticationFlowBindingOverrides": {}, + "fullScopeAllowed": true, + "nodeReRegistrationTimeout": -1, + "protocolMappers": [ + { + "name": "Client ID", + "protocol": "openid-connect", + "protocolMapper": "oidc-usersessionmodel-note-mapper", + "consentRequired": false, + "config": { + "user.session.note": "clientId", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "clientId", + "jsonType.label": "String" + } + }, + { + "name": "Client IP Address", + "protocol": "openid-connect", + "protocolMapper": "oidc-usersessionmodel-note-mapper", + "consentRequired": false, + "config": { + "user.session.note": "clientAddress", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "clientAddress", + "jsonType.label": "String" + } + }, + { + "name": "Client Host", + "protocol": "openid-connect", + "protocolMapper": "oidc-usersessionmodel-note-mapper", + "consentRequired": false, + "config": { + "user.session.note": "clientHost", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "clientHost", + "jsonType.label": "String" + } + } + ], + "defaultClientScopes": ["web-origins", "role_list", "profile", "roles", "email"], + "optionalClientScopes": ["address", "phone", "offline_access", "microprofile-jwt"], + "authorizationSettings": { + "allowRemoteResourceManagement": true, + "policyEnforcementMode": "ENFORCING", + "resources": [ + { + "name": "User Resource", + "ownerManagedAccess": false, + "attributes": {}, + "_id": "df1b74a9-3f10-499d-a581-368de48e512b", + "uris": ["/api/users/*"] + }, + { + "name": "Administration Resource", + "ownerManagedAccess": false, + "attributes": {}, + "_id": "7124e2f1-e6dc-44b4-87ab-24b010090b97", + "uris": ["/api/admin/*"] + } + ], + "policies": [ + { + "name": "Any User Policy", + "description": "Any user granted with the user role can access something", + "type": "role", + "logic": "POSITIVE", + "decisionStrategy": "UNANIMOUS", + "config": { + "roles": "[{\"id\":\"user\",\"required\":false}]" + } + }, + { + "name": "Only Administrators", + "description": "Only administrators can access", + "type": "role", + "logic": "POSITIVE", + "decisionStrategy": "UNANIMOUS", + "config": { + "roles": "[{\"id\":\"admin\",\"required\":false}]" + } + }, + { + "name": "User Resource Permission", + "type": "resource", + "logic": "POSITIVE", + "decisionStrategy": "UNANIMOUS", + "config": { + "resources": "[\"User Resource\"]", + "applyPolicies": "[\"Any User Policy\"]" + } + }, + { + "name": "Administration Resource Permission", + "type": "resource", + "logic": "POSITIVE", + "decisionStrategy": "UNANIMOUS", + "config": { + "resources": "[\"Administration Resource\"]", + "applyPolicies": "[\"Only Administrators\"]" + } + } + ], + "scopes": [], + "decisionStrategy": "UNANIMOUS" + } + }, + { + "clientId": "kogito-console-react", + "rootUrl": "http://localhost:9025", + "adminUrl": "http://localhost:9025/", + "baseUrl": "http://localhost:9025/", + "surrogateAuthRequired": false, + "enabled": true, + "clientAuthenticatorType": "client-secret", + "secret": "**********", + "redirectUris": ["*"], + "webOrigins": ["*"], + "notBefore": 0, + "bearerOnly": false, + "consentRequired": false, + "standardFlowEnabled": true, + "implicitFlowEnabled": false, + "directAccessGrantsEnabled": false, + "serviceAccountsEnabled": false, + "publicClient": true, + "frontchannelLogout": false, + "protocol": "openid-connect", + "attributes": { + "saml.assertion.signature": "false", + "saml.force.post.binding": "false", + "saml.multivalued.roles": "false", + "saml.encrypt": "false", + "saml.server.signature": "false", + "saml.server.signature.keyinfo.ext": "false", + "exclude.session.state.from.auth.response": "false", + "saml_force_name_id_format": "false", + "saml.client.signature": "false", + "tls.client.certificate.bound.access.tokens": "false", + "saml.authnstatement": "false", + "display.on.consent.screen": "false", + "saml.onetimeuse.condition": "false" + }, + "authenticationFlowBindingOverrides": {}, + "fullScopeAllowed": true, + "nodeReRegistrationTimeout": -1, + "defaultClientScopes": ["web-origins", "role_list", "profile", "roles", "email"], + "optionalClientScopes": ["address", "phone", "offline_access", "microprofile-jwt"] + }, + { + "clientId": "kogito-console-quarkus", + "rootUrl": "http://localhost:8380", + "adminUrl": "http://localhost:8380/", + "baseUrl": "http://localhost:8380/", + "surrogateAuthRequired": false, + "enabled": true, + "clientAuthenticatorType": "client-secret", + "secret": "**********", + "redirectUris": ["http://localhost:8380/*"], + "webOrigins": ["*"], + "notBefore": 0, + "bearerOnly": false, + "consentRequired": false, + "standardFlowEnabled": true, + "implicitFlowEnabled": false, + "directAccessGrantsEnabled": false, + "serviceAccountsEnabled": false, + "publicClient": true, + "frontchannelLogout": false, + "protocol": "openid-connect", + "attributes": { + "saml.assertion.signature": "false", + "saml.force.post.binding": "false", + "saml.multivalued.roles": "false", + "saml.encrypt": "false", + "saml.server.signature": "false", + "saml.server.signature.keyinfo.ext": "false", + "exclude.session.state.from.auth.response": "false", + "saml_force_name_id_format": "false", + "saml.client.signature": "false", + "tls.client.certificate.bound.access.tokens": "false", + "saml.authnstatement": "false", + "display.on.consent.screen": "false", + "saml.onetimeuse.condition": "false" + }, + "authenticationFlowBindingOverrides": {}, + "fullScopeAllowed": true, + "nodeReRegistrationTimeout": -1, + "protocolMappers": [ + { + "name": "groups", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-realm-role-mapper", + "consentRequired": false, + "config": { + "multivalued": "true", + "user.attribute": "foo", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "groups", + "jsonType.label": "String" + } + } + ], + "defaultClientScopes": ["web-origins", "role_list", "profile", "roles", "email"], + "optionalClientScopes": ["address", "phone", "offline_access", "microprofile-jwt"] + }, + { + "clientId": "kogito-jobs-service", + "rootUrl": "http://localhost:8080", + "adminUrl": "http://localhost:8080", + "surrogateAuthRequired": false, + "enabled": true, + "clientAuthenticatorType": "client-secret", + "secret": "secret", + "redirectUris": ["http://localhost:8080/*"], + "webOrigins": ["http://localhost:8080"], + "notBefore": 0, + "bearerOnly": false, + "consentRequired": false, + "standardFlowEnabled": true, + "implicitFlowEnabled": false, + "directAccessGrantsEnabled": true, + "serviceAccountsEnabled": false, + "publicClient": false, + "frontchannelLogout": false, + "protocol": "openid-connect", + "attributes": { + "saml.assertion.signature": "false", + "saml.force.post.binding": "false", + "saml.multivalued.roles": "false", + "saml.encrypt": "false", + "saml.server.signature": "false", + "saml.server.signature.keyinfo.ext": "false", + "exclude.session.state.from.auth.response": "false", + "saml_force_name_id_format": "false", + "saml.client.signature": "false", + "tls.client.certificate.bound.access.tokens": "false", + "saml.authnstatement": "false", + "display.on.consent.screen": "false", + "saml.onetimeuse.condition": "false" + }, + "authenticationFlowBindingOverrides": {}, + "fullScopeAllowed": true, + "nodeReRegistrationTimeout": -1, + "defaultClientScopes": ["web-origins", "role_list", "profile", "roles", "email"], + "optionalClientScopes": ["address", "phone", "offline_access", "microprofile-jwt"], + "access": { + "view": true, + "configure": true, + "manage": true + } + }, + { + "clientId": "realm-management", + "name": "${client_realm-management}", + "surrogateAuthRequired": false, + "enabled": true, + "clientAuthenticatorType": "client-secret", + "secret": "c41b709a-a012-4c69-89d7-4f926dba0619", + "redirectUris": [], + "webOrigins": [], + "notBefore": 0, + "bearerOnly": true, + "consentRequired": false, + "standardFlowEnabled": true, + "implicitFlowEnabled": false, + "directAccessGrantsEnabled": false, + "serviceAccountsEnabled": false, + "publicClient": false, + "frontchannelLogout": false, + "protocol": "openid-connect", + "attributes": {}, + "authenticationFlowBindingOverrides": {}, + "fullScopeAllowed": false, + "nodeReRegistrationTimeout": 0, + "defaultClientScopes": ["web-origins", "role_list", "profile", "roles", "email"], + "optionalClientScopes": ["address", "phone", "offline_access", "microprofile-jwt"] + }, + { + "clientId": "security-admin-console", + "name": "${client_security-admin-console}", + "baseUrl": "/auth/admin/kogito/console/index.html", + "surrogateAuthRequired": false, + "enabled": true, + "clientAuthenticatorType": "client-secret", + "secret": "e571b211-2550-475d-b87f-116ff54091ee", + "redirectUris": ["/auth/admin/kogito/console/*"], + "webOrigins": [], + "notBefore": 0, + "bearerOnly": false, + "consentRequired": false, + "standardFlowEnabled": true, + "implicitFlowEnabled": false, + "directAccessGrantsEnabled": false, + "serviceAccountsEnabled": false, + "publicClient": true, + "frontchannelLogout": false, + "protocol": "openid-connect", + "attributes": {}, + "authenticationFlowBindingOverrides": {}, + "fullScopeAllowed": false, + "nodeReRegistrationTimeout": 0, + "protocolMappers": [ + { + "name": "locale", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "userinfo.token.claim": "true", + "user.attribute": "locale", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "locale", + "jsonType.label": "String" + } + } + ], + "defaultClientScopes": ["web-origins", "role_list", "profile", "roles", "email"], + "optionalClientScopes": ["address", "phone", "offline_access", "microprofile-jwt"] + } + ], + "clientScopes": [ + { + "name": "address", + "description": "OpenID Connect built-in scope: address", + "protocol": "openid-connect", + "attributes": { + "include.in.token.scope": "true", + "display.on.consent.screen": "true", + "consent.screen.text": "${addressScopeConsentText}" + }, + "protocolMappers": [ + { + "name": "address", + "protocol": "openid-connect", + "protocolMapper": "oidc-address-mapper", + "consentRequired": false, + "config": { + "user.attribute.formatted": "formatted", + "user.attribute.country": "country", + "user.attribute.postal_code": "postal_code", + "userinfo.token.claim": "true", + "user.attribute.street": "street", + "id.token.claim": "true", + "user.attribute.region": "region", + "access.token.claim": "true", + "user.attribute.locality": "locality" + } + } + ] + }, + { + "name": "email", + "description": "OpenID Connect built-in scope: email", + "protocol": "openid-connect", + "attributes": { + "include.in.token.scope": "true", + "display.on.consent.screen": "true", + "consent.screen.text": "${emailScopeConsentText}" + }, + "protocolMappers": [ + { + "name": "email", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-property-mapper", + "consentRequired": false, + "config": { + "userinfo.token.claim": "true", + "user.attribute": "email", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "email", + "jsonType.label": "String" + } + }, + { + "name": "email verified", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-property-mapper", + "consentRequired": false, + "config": { + "userinfo.token.claim": "true", + "user.attribute": "emailVerified", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "email_verified", + "jsonType.label": "boolean" + } + } + ] + }, + { + "name": "microprofile-jwt", + "description": "Microprofile - JWT built-in scope", + "protocol": "openid-connect", + "attributes": { + "include.in.token.scope": "true", + "display.on.consent.screen": "false" + }, + "protocolMappers": [ + { + "name": "upn", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-property-mapper", + "consentRequired": false, + "config": { + "userinfo.token.claim": "true", + "user.attribute": "username", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "upn", + "jsonType.label": "String" + } + }, + { + "name": "groups", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-realm-role-mapper", + "consentRequired": false, + "config": { + "multivalued": "true", + "user.attribute": "foo", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "groups", + "jsonType.label": "String" + } + } + ] + }, + { + "name": "offline_access", + "description": "OpenID Connect built-in scope: offline_access", + "protocol": "openid-connect", + "attributes": { + "consent.screen.text": "${offlineAccessScopeConsentText}", + "display.on.consent.screen": "true" + } + }, + { + "name": "phone", + "description": "OpenID Connect built-in scope: phone", + "protocol": "openid-connect", + "attributes": { + "include.in.token.scope": "true", + "display.on.consent.screen": "true", + "consent.screen.text": "${phoneScopeConsentText}" + }, + "protocolMappers": [ + { + "name": "phone number verified", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "userinfo.token.claim": "true", + "user.attribute": "phoneNumberVerified", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "phone_number_verified", + "jsonType.label": "boolean" + } + }, + { + "name": "phone number", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "userinfo.token.claim": "true", + "user.attribute": "phoneNumber", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "phone_number", + "jsonType.label": "String" + } + } + ] + }, + { + "name": "profile", + "description": "OpenID Connect built-in scope: profile", + "protocol": "openid-connect", + "attributes": { + "include.in.token.scope": "true", + "display.on.consent.screen": "true", + "consent.screen.text": "${profileScopeConsentText}" + }, + "protocolMappers": [ + { + "name": "nickname", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "userinfo.token.claim": "true", + "user.attribute": "nickname", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "nickname", + "jsonType.label": "String" + } + }, + { + "name": "zoneinfo", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "userinfo.token.claim": "true", + "user.attribute": "zoneinfo", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "zoneinfo", + "jsonType.label": "String" + } + }, + { + "name": "updated at", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "userinfo.token.claim": "true", + "user.attribute": "updatedAt", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "updated_at", + "jsonType.label": "String" + } + }, + { + "name": "birthdate", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "userinfo.token.claim": "true", + "user.attribute": "birthdate", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "birthdate", + "jsonType.label": "String" + } + }, + { + "name": "given name", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-property-mapper", + "consentRequired": false, + "config": { + "userinfo.token.claim": "true", + "user.attribute": "firstName", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "given_name", + "jsonType.label": "String" + } + }, + { + "name": "full name", + "protocol": "openid-connect", + "protocolMapper": "oidc-full-name-mapper", + "consentRequired": false, + "config": { + "id.token.claim": "true", + "access.token.claim": "true", + "userinfo.token.claim": "true" + } + }, + { + "name": "middle name", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "userinfo.token.claim": "true", + "user.attribute": "middleName", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "middle_name", + "jsonType.label": "String" + } + }, + { + "name": "username", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-property-mapper", + "consentRequired": false, + "config": { + "userinfo.token.claim": "true", + "user.attribute": "username", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "preferred_username", + "jsonType.label": "String" + } + }, + { + "name": "family name", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-property-mapper", + "consentRequired": false, + "config": { + "userinfo.token.claim": "true", + "user.attribute": "lastName", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "family_name", + "jsonType.label": "String" + } + }, + { + "name": "gender", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "userinfo.token.claim": "true", + "user.attribute": "gender", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "gender", + "jsonType.label": "String" + } + }, + { + "name": "picture", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "userinfo.token.claim": "true", + "user.attribute": "picture", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "picture", + "jsonType.label": "String" + } + }, + { + "name": "locale", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "userinfo.token.claim": "true", + "user.attribute": "locale", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "locale", + "jsonType.label": "String" + } + }, + { + "name": "profile", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "userinfo.token.claim": "true", + "user.attribute": "profile", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "profile", + "jsonType.label": "String" + } + }, + { + "name": "website", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "userinfo.token.claim": "true", + "user.attribute": "website", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "website", + "jsonType.label": "String" + } + } + ] + }, + { + "name": "role_list", + "description": "SAML role list", + "protocol": "saml", + "attributes": { + "consent.screen.text": "${samlRoleListScopeConsentText}", + "display.on.consent.screen": "true" + }, + "protocolMappers": [ + { + "name": "role list", + "protocol": "saml", + "protocolMapper": "saml-role-list-mapper", + "consentRequired": false, + "config": { + "single": "false", + "attribute.nameformat": "Basic", + "attribute.name": "Role" + } + } + ] + }, + { + "name": "roles", + "description": "OpenID Connect scope for add user roles to the access token", + "protocol": "openid-connect", + "attributes": { + "include.in.token.scope": "false", + "display.on.consent.screen": "true", + "consent.screen.text": "${rolesScopeConsentText}" + }, + "protocolMappers": [ + { + "name": "realm roles", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-realm-role-mapper", + "consentRequired": false, + "config": { + "user.attribute": "foo", + "access.token.claim": "true", + "claim.name": "realm_access.roles", + "jsonType.label": "String", + "multivalued": "true" + } + }, + { + "name": "audience resolve", + "protocol": "openid-connect", + "protocolMapper": "oidc-audience-resolve-mapper", + "consentRequired": false, + "config": {} + }, + { + "name": "client roles", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-client-role-mapper", + "consentRequired": false, + "config": { + "user.attribute": "foo", + "access.token.claim": "true", + "claim.name": "resource_access.${client_id}.roles", + "jsonType.label": "String", + "multivalued": "true" + } + } + ] + }, + { + "name": "web-origins", + "description": "OpenID Connect scope for add allowed web origins to the access token", + "protocol": "openid-connect", + "attributes": { + "include.in.token.scope": "false", + "display.on.consent.screen": "false", + "consent.screen.text": "" + }, + "protocolMappers": [ + { + "name": "allowed web origins", + "protocol": "openid-connect", + "protocolMapper": "oidc-allowed-origins-mapper", + "consentRequired": false, + "config": {} + } + ] + } + ], + "defaultDefaultClientScopes": ["role_list", "profile", "email", "roles", "web-origins"], + "defaultOptionalClientScopes": ["offline_access", "address", "phone", "microprofile-jwt"], + "browserSecurityHeaders": { + "contentSecurityPolicyReportOnly": "", + "xContentTypeOptions": "nosniff", + "xRobotsTag": "none", + "xFrameOptions": "SAMEORIGIN", + "xXSSProtection": "1; mode=block", + "contentSecurityPolicy": "frame-src 'self'; frame-ancestors 'self'; object-src 'none';", + "strictTransportSecurity": "max-age=31536000; includeSubDomains" + }, + "smtpServer": {}, + "eventsEnabled": false, + "eventsListeners": ["jboss-logging"], + "enabledEventTypes": [], + "adminEventsEnabled": false, + "adminEventsDetailsEnabled": false, + "components": { + "org.keycloak.services.clientregistration.policy.ClientRegistrationPolicy": [ + { + "name": "Allowed Protocol Mapper Types", + "providerId": "allowed-protocol-mappers", + "subType": "anonymous", + "subComponents": {}, + "config": { + "allowed-protocol-mapper-types": [ + "oidc-full-name-mapper", + "saml-user-attribute-mapper", + "saml-user-property-mapper", + "oidc-address-mapper", + "saml-role-list-mapper", + "oidc-sha256-pairwise-sub-mapper", + "oidc-usermodel-attribute-mapper", + "oidc-usermodel-property-mapper" + ] + } + }, + { + "name": "Allowed Client Scopes", + "providerId": "allowed-client-templates", + "subType": "authenticated", + "subComponents": {}, + "config": { + "allow-default-scopes": ["true"] + } + }, + { + "name": "Allowed Client Scopes", + "providerId": "allowed-client-templates", + "subType": "anonymous", + "subComponents": {}, + "config": { + "allow-default-scopes": ["true"] + } + }, + { + "name": "Trusted Hosts", + "providerId": "trusted-hosts", + "subType": "anonymous", + "subComponents": {}, + "config": { + "host-sending-registration-request-must-match": ["true"], + "client-uris-must-match": ["true"] + } + }, + { + "name": "Full Scope Disabled", + "providerId": "scope", + "subType": "anonymous", + "subComponents": {}, + "config": {} + }, + { + "name": "Max Clients Limit", + "providerId": "max-clients", + "subType": "anonymous", + "subComponents": {}, + "config": { + "max-clients": ["200"] + } + }, + { + "name": "Consent Required", + "providerId": "consent-required", + "subType": "anonymous", + "subComponents": {}, + "config": {} + }, + { + "name": "Allowed Protocol Mapper Types", + "providerId": "allowed-protocol-mappers", + "subType": "authenticated", + "subComponents": {}, + "config": { + "allowed-protocol-mapper-types": [ + "saml-user-attribute-mapper", + "oidc-full-name-mapper", + "saml-role-list-mapper", + "saml-user-property-mapper", + "oidc-usermodel-attribute-mapper", + "oidc-address-mapper", + "oidc-usermodel-property-mapper", + "oidc-sha256-pairwise-sub-mapper" + ] + } + } + ], + "org.keycloak.keys.KeyProvider": [ + { + "name": "rsa-generated", + "providerId": "rsa-generated", + "subComponents": {}, + "config": { + "privateKey": [ + "MIIEowIBAAKCAQEAn5T13suF8mlS+pJXp0U1bto41nW55wpcs+Rps8ZVCRyJKWqzwSCYnI7lm0rB2wBpAAO4OPoj1zlmVoFmBPsDU9Xf7rjsJb5LIzIQDCZY44aSDZt6RR+gakPiQvlzHyW/RozYpngDJF7TsTD7rdRF1xQ4RprfBF8fwK/xsU7pxbeom5xDHZhz3fiw8s+7UdbmnazDHfAjU58aUrLGgVRfUsuoHjtsptYlOIXEifaeMetXZE+HhqLYRHQPDap5fbBJl773Trosn7N9nmzN4x1xxGj9So21WC5UboQs9sAIVgizc4omjZ5Y4RN9HLH7G4YwJctNntzmnJhDui9zAO+zSQIDAQABAoIBADi+F7rTtVoft0Cfnok8o6Y58/HVxHdxiMryUd95iy0FN4RBi48FTx6D9QKFz25Ws/8sU2n3D51srIXf1u24b1N0/f39RQKaqk7mcyxOylaEuBQcj5pah4ihgKd92UBfBKdKV5LBo6RgD3e2yhbiHr8+UlBQqzH7vOef6Bm6zIbfmi3N88swAJhP0YizRZFklsbmLsK6nkwyro00CHJvPVKSBbM+ad+/zIBsLw56MvNngB5TuFguUgoljd6M1T2z4utmZGlTUqrfE1onAVLJZoGnRohyIr7dJEg6YxWR70PxsgmkDKyeRvet9P1trO0n+OSprusfrC3cHJStabap1V0CgYEA1A/CtsqTnjdYYsB19eumZgdpzUgNc/YEAzZ/OWb8yTLoB2ncci+63A1rXHUXAqJFY7vtjn5mxv7SuASNbUrzq+6KfZvC1x9XEtnczqT/ypunNfxmIZuj8Nuu6vtURguZ8kPPwdkI8toTizRFeRE5ZDBvoQryiEVYugfHaHT5vzsCgYEAwKWODwquI0Lv9BuwdNVrBXQpkKh3ZfYOA7i9xvhxlM7xUu8OMCwwCPn3r7vrW5APjTqX4h330mJ44SLEs+7gbCUs4BbJBLA6g0ChlHa9PTkxp6tk2nDF/B34fxiZSRkE85L+d+at0Dc3hnlzLCJCzJawGpoPniPU9e4w0p4dN0sCgYAsGnMGjS8SUrRhJWHjGXVr9tK8TOXvXhULjgP7rj2Yoqu7Dvs4DFEyft/7RKbad2EzEtyfLA64CDtO5jN7rYDsGxpWcVSeZPg5BXJ0z8AbJTArfCjJiJMZ/rZsTIUEZFlKF2xYBolj6JLz+pUQTtK+0YwF1D8ItFN1rTR9twZSDQKBgQC6sPXNX+VH6LuPTjIf1x8CxwLs3EXxOpV0R9kp9GRl+HJnk6GlT30xhcThufQo5KAdllXQXIhoiuNoEoCbevhj9Vbax1oBQCNERSMRNEzKAx46xd9TzYwgeo7x5E3QR/3DaoVOfu+cY5ZcrF/PulgP2kxJS1mtQD5GIpGP2oinpwKBgGqiqTFPqRcelx76vBvTU+Jp1zM62T4AotbMrSQR/oUvqHe5Ytj/SbZx+wbbHAiyGgV700Mosyviik83YEAbR3kdOPjgYvAJJW2Y3jEMdQ7MwriXz8XLh5BGmYfVjkSOJXed9ua9WlYLKOJeXXv191BbDvrx5NXuJyVVU4vJx3YZ" + ], + "certificate": [ + "MIICnTCCAYUCBgFp4EYIrjANBgkqhkiG9w0BAQsFADASMRAwDgYDVQQDDAdwcm90ZWFuMB4XDTE5MDQwMjIyNTYxOVoXDTI5MDQwMjIyNTc1OVowEjEQMA4GA1UEAwwHcHJvdGVhbjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAJ+U9d7LhfJpUvqSV6dFNW7aONZ1uecKXLPkabPGVQkciSlqs8EgmJyO5ZtKwdsAaQADuDj6I9c5ZlaBZgT7A1PV3+647CW+SyMyEAwmWOOGkg2bekUfoGpD4kL5cx8lv0aM2KZ4AyRe07Ew+63URdcUOEaa3wRfH8Cv8bFO6cW3qJucQx2Yc934sPLPu1HW5p2swx3wI1OfGlKyxoFUX1LLqB47bKbWJTiFxIn2njHrV2RPh4ai2ER0Dw2qeX2wSZe+9066LJ+zfZ5szeMdccRo/UqNtVguVG6ELPbACFYIs3OKJo2eWOETfRyx+xuGMCXLTZ7c5pyYQ7ovcwDvs0kCAwEAATANBgkqhkiG9w0BAQsFAAOCAQEAVtmRKDb4OK5iSA46tagMBkp6L7WuPpCWuHGWwobEP+BecYsShW7zP3s12oA8SNSwbhvu0CRqgzxhuypgf3hKQFVU153Erv4hzkj+8S0s5LR/ZE7tDNY2lzJ3yQKXy3Md7EkuzzvOZ50MTrcSKAanWq/ZW1OTnrtGymj5zGJnTg7mMnJzEIGePxkvPu/QdchiPBLqxfZYm1jsFGY25djOC3N/KmVcRVmPRGuu6D8tBFHlKoPfZYPdbMvsvs24aupHKRcZ+ofTCpK+2Qo8c0pSSqeEYHGmuGqC6lC6ozxtxSABPO9Q1R1tZBU7Kg5HvXUwwmoVS3EGub46YbHqbmWMLg==" + ], + "priority": ["100"] + } + }, + { + "name": "hmac-generated", + "providerId": "hmac-generated", + "subComponents": {}, + "config": { + "kid": ["96afd00e-85cf-4d35-b18e-061d3813d8b2"], + "secret": ["qBFGKdUGf6xDgKphnRfoFzIzaFHJW4bYnZ9MinPFzN38X5_ctq-2u1q5RdZzeJukXvk2biHB8_s3DxWmmLZFsA"], + "priority": ["100"], + "algorithm": ["HS256"] + } + }, + { + "name": "aes-generated", + "providerId": "aes-generated", + "subComponents": {}, + "config": { + "kid": ["b04473d3-8395-4016-b455-19a9e951106b"], + "secret": ["x68mMOVdz3qKWzltzReV0g"], + "priority": ["100"] + } + } + ] + }, + "internationalizationEnabled": false, + "supportedLocales": [], + "authenticationFlows": [ + { + "alias": "Handle Existing Account", + "description": "Handle what to do if there is existing account with same email/username like authenticated identity provider", + "providerId": "basic-flow", + "topLevel": false, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "idp-confirm-link", + "requirement": "REQUIRED", + "priority": 10, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "authenticator": "idp-email-verification", + "requirement": "ALTERNATIVE", + "priority": 20, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "requirement": "ALTERNATIVE", + "priority": 30, + "flowAlias": "Verify Existing Account by Re-authentication", + "userSetupAllowed": false, + "autheticatorFlow": true + } + ] + }, + { + "alias": "Verify Existing Account by Re-authentication", + "description": "Reauthentication of existing account", + "providerId": "basic-flow", + "topLevel": false, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "idp-username-password-form", + "requirement": "REQUIRED", + "priority": 10, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "authenticator": "auth-otp-form", + "requirement": "OPTIONAL", + "priority": 20, + "userSetupAllowed": false, + "autheticatorFlow": false + } + ] + }, + { + "alias": "browser", + "description": "browser based authentication", + "providerId": "basic-flow", + "topLevel": true, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "auth-cookie", + "requirement": "ALTERNATIVE", + "priority": 10, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "authenticator": "auth-spnego", + "requirement": "DISABLED", + "priority": 20, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "authenticator": "identity-provider-redirector", + "requirement": "ALTERNATIVE", + "priority": 25, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "requirement": "ALTERNATIVE", + "priority": 30, + "flowAlias": "forms", + "userSetupAllowed": false, + "autheticatorFlow": true + } + ] + }, + { + "alias": "clients", + "description": "Base authentication for clients", + "providerId": "client-flow", + "topLevel": true, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "client-secret", + "requirement": "ALTERNATIVE", + "priority": 10, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "authenticator": "client-jwt", + "requirement": "ALTERNATIVE", + "priority": 20, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "authenticator": "client-secret-jwt", + "requirement": "ALTERNATIVE", + "priority": 30, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "authenticator": "client-x509", + "requirement": "ALTERNATIVE", + "priority": 40, + "userSetupAllowed": false, + "autheticatorFlow": false + } + ] + }, + { + "alias": "direct grant", + "description": "OpenID Connect Resource Owner Grant", + "providerId": "basic-flow", + "topLevel": true, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "direct-grant-validate-username", + "requirement": "REQUIRED", + "priority": 10, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "authenticator": "direct-grant-validate-password", + "requirement": "REQUIRED", + "priority": 20, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "authenticator": "direct-grant-validate-otp", + "requirement": "OPTIONAL", + "priority": 30, + "userSetupAllowed": false, + "autheticatorFlow": false + } + ] + }, + { + "alias": "docker auth", + "description": "Used by Docker clients to authenticate against the IDP", + "providerId": "basic-flow", + "topLevel": true, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "docker-http-basic-authenticator", + "requirement": "REQUIRED", + "priority": 10, + "userSetupAllowed": false, + "autheticatorFlow": false + } + ] + }, + { + "alias": "first broker login", + "description": "Actions taken after first broker login with identity provider account, which is not yet linked to any Keycloak account", + "providerId": "basic-flow", + "topLevel": true, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticatorConfig": "review profile config", + "authenticator": "idp-review-profile", + "requirement": "REQUIRED", + "priority": 10, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "authenticatorConfig": "create unique user config", + "authenticator": "idp-create-user-if-unique", + "requirement": "ALTERNATIVE", + "priority": 20, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "requirement": "ALTERNATIVE", + "priority": 30, + "flowAlias": "Handle Existing Account", + "userSetupAllowed": false, + "autheticatorFlow": true + } + ] + }, + { + "alias": "forms", + "description": "Username, password, otp and other auth forms.", + "providerId": "basic-flow", + "topLevel": false, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "auth-username-password-form", + "requirement": "REQUIRED", + "priority": 10, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "authenticator": "auth-otp-form", + "requirement": "OPTIONAL", + "priority": 20, + "userSetupAllowed": false, + "autheticatorFlow": false + } + ] + }, + { + "alias": "http challenge", + "description": "An authentication flow based on challenge-response HTTP Authentication Schemes", + "providerId": "basic-flow", + "topLevel": true, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "no-cookie-redirect", + "requirement": "REQUIRED", + "priority": 10, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "authenticator": "basic-auth", + "requirement": "REQUIRED", + "priority": 20, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "authenticator": "basic-auth-otp", + "requirement": "DISABLED", + "priority": 30, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "authenticator": "auth-spnego", + "requirement": "DISABLED", + "priority": 40, + "userSetupAllowed": false, + "autheticatorFlow": false + } + ] + }, + { + "alias": "registration", + "description": "registration flow", + "providerId": "basic-flow", + "topLevel": true, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "registration-page-form", + "requirement": "REQUIRED", + "priority": 10, + "flowAlias": "registration form", + "userSetupAllowed": false, + "autheticatorFlow": true + } + ] + }, + { + "alias": "registration form", + "description": "registration form", + "providerId": "form-flow", + "topLevel": false, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "registration-user-creation", + "requirement": "REQUIRED", + "priority": 20, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "authenticator": "registration-profile-action", + "requirement": "REQUIRED", + "priority": 40, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "authenticator": "registration-password-action", + "requirement": "REQUIRED", + "priority": 50, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "authenticator": "registration-recaptcha-action", + "requirement": "DISABLED", + "priority": 60, + "userSetupAllowed": false, + "autheticatorFlow": false + } + ] + }, + { + "alias": "reset credentials", + "description": "Reset credentials for a user if they forgot their password or something", + "providerId": "basic-flow", + "topLevel": true, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "reset-credentials-choose-user", + "requirement": "REQUIRED", + "priority": 10, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "authenticator": "reset-credential-email", + "requirement": "REQUIRED", + "priority": 20, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "authenticator": "reset-password", + "requirement": "REQUIRED", + "priority": 30, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "authenticator": "reset-otp", + "requirement": "OPTIONAL", + "priority": 40, + "userSetupAllowed": false, + "autheticatorFlow": false + } + ] + }, + { + "alias": "saml ecp", + "description": "SAML ECP Profile Authentication Flow", + "providerId": "basic-flow", + "topLevel": true, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "http-basic-authenticator", + "requirement": "REQUIRED", + "priority": 10, + "userSetupAllowed": false, + "autheticatorFlow": false + } + ] + } + ], + "authenticatorConfig": [ + { + "alias": "create unique user config", + "config": { + "require.password.update.after.registration": "false" + } + }, + { + "alias": "review profile config", + "config": { + "update.profile.on.first.login": "missing" + } + } + ], + "requiredActions": [ + { + "alias": "CONFIGURE_TOTP", + "name": "Configure OTP", + "providerId": "CONFIGURE_TOTP", + "enabled": true, + "defaultAction": false, + "priority": 10, + "config": {} + }, + { + "alias": "terms_and_conditions", + "name": "Terms and Conditions", + "providerId": "terms_and_conditions", + "enabled": false, + "defaultAction": false, + "priority": 20, + "config": {} + }, + { + "alias": "UPDATE_PASSWORD", + "name": "Update Password", + "providerId": "UPDATE_PASSWORD", + "enabled": true, + "defaultAction": false, + "priority": 30, + "config": {} + }, + { + "alias": "UPDATE_PROFILE", + "name": "Update Profile", + "providerId": "UPDATE_PROFILE", + "enabled": true, + "defaultAction": false, + "priority": 40, + "config": {} + }, + { + "alias": "VERIFY_EMAIL", + "name": "Verify Email", + "providerId": "VERIFY_EMAIL", + "enabled": true, + "defaultAction": false, + "priority": 50, + "config": {} + } + ], + "browserFlow": "browser", + "registrationFlow": "registration", + "directGrantFlow": "direct grant", + "resetCredentialsFlow": "reset credentials", + "clientAuthenticationFlow": "clients", + "dockerAuthenticationFlow": "docker auth", + "attributes": { + "_browser_header.xXSSProtection": "1; mode=block", + "_browser_header.xFrameOptions": "SAMEORIGIN", + "_browser_header.strictTransportSecurity": "max-age=31536000; includeSubDomains", + "permanentLockout": "false", + "quickLoginCheckMilliSeconds": "1000", + "_browser_header.xRobotsTag": "none", + "maxFailureWaitSeconds": "900", + "minimumQuickLoginWaitSeconds": "60", + "failureFactor": "30", + "actionTokenGeneratedByUserLifespan": "300", + "maxDeltaTimeSeconds": "43200", + "_browser_header.xContentTypeOptions": "nosniff", + "offlineSessionMaxLifespan": "5184000", + "actionTokenGeneratedByAdminLifespan": "43200", + "_browser_header.contentSecurityPolicyReportOnly": "", + "bruteForceProtected": "false", + "_browser_header.contentSecurityPolicy": "frame-src 'self'; frame-ancestors 'self'; object-src 'none';", + "waitIncrementSeconds": "60", + "offlineSessionMaxLifespanEnabled": "false" + }, + "users": [ + { + "username": "admin", + "enabled": true, + "totp": false, + "emailVerified": false, + "credentials": [ + { + "type": "password", + "hashedSaltedValue": "NICTtwsvSxJ5hL8hLAuleDUv9jwZcuXgxviMXvR++cciyPtiIEStEaJUyfA9DOir59awjPrHOumsclPVjNBplA==", + "salt": "T/2P5o5oxFJUEk68BRURRg==", + "hashIterations": 27500, + "counter": 0, + "algorithm": "pbkdf2-sha256", + "digits": 0, + "period": 0, + "createdDate": 1554245879354, + "config": {} + } + ], + "disableableCredentialTypes": ["password"], + "requiredActions": [], + "realmRoles": ["admin", "confidential", "user"], + "notBefore": 0, + "groups": [] + }, + { + "username": "alice", + "enabled": true, + "totp": false, + "emailVerified": false, + "credentials": [ + { + "type": "password", + "hashedSaltedValue": "A3okqV2T/ybXTVEgKfosoSjP8Yc9IZbFP/SY4cEd6hag7TABQrQ6nUSuwagGt96l8cw1DTijO75PqX6uiTXMzw==", + "salt": "sl4mXx6T9FypPH/s9TngfQ==", + "hashIterations": 27500, + "counter": 0, + "algorithm": "pbkdf2-sha256", + "digits": 0, + "period": 0, + "createdDate": 1554245879116, + "config": {} + } + ], + "disableableCredentialTypes": ["password"], + "requiredActions": [], + "realmRoles": ["user"], + "notBefore": 0, + "groups": [] + }, + { + "username": "jdoe", + "enabled": true, + "totp": false, + "emailVerified": false, + "credentials": [ + { + "type": "password", + "hashedSaltedValue": "JV3DUNLjqOadjbBOtC4rvacQI553CGaDGAzBS8MR5ReCr7SwF3E6CsW3T7/XO8ITZAsch8+A/6loeuCoVLLJrg==", + "salt": "uCbOH7HZtyDtMd0E9DG/nw==", + "hashIterations": 27500, + "counter": 0, + "algorithm": "pbkdf2-sha256", + "digits": 0, + "period": 0, + "createdDate": 1554245879227, + "config": {} + } + ], + "disableableCredentialTypes": ["password"], + "requiredActions": [], + "realmRoles": ["confidential", "user"], + "notBefore": 0, + "groups": [] + } + ], + "keycloakVersion": "6.0.0", + "userManagedAccessAllowed": false +} diff --git a/packages/sonataflow-management-console-webapp/package.json b/packages/sonataflow-management-console-webapp/package.json index daaf1bc006f..4c96cca125b 100644 --- a/packages/sonataflow-management-console-webapp/package.json +++ b/packages/sonataflow-management-console-webapp/package.json @@ -24,6 +24,10 @@ "test": "run-script-if --ignore-errors \"$(build-env tests.ignoreFailures)\" --bool \"$(build-env tests.run)\" --then \"jest --silent --verbose --passWithNoTests\"" }, "dependencies": { + "@kie-tools-core/editor": "workspace:*", + "@kie-tools-core/keyboard-shortcuts": "workspace:*", + "@kie-tools-core/react-hooks": "workspace:*", + "@kie-tools/dashbuilder-client": "workspace:*", "@kie-tools/runtime-tools-components": "workspace:*", "@kie-tools/runtime-tools-process-enveloped-components": "workspace:*", "@kie-tools/runtime-tools-process-gateway-api": "workspace:*", @@ -31,6 +35,12 @@ "@kie-tools/runtime-tools-shared-enveloped-components": "workspace:*", "@kie-tools/runtime-tools-shared-gateway-api": "workspace:*", "@kie-tools/runtime-tools-shared-webapp-components": "workspace:*", + "@kie-tools/runtime-tools-swf-gateway-api": "workspace:*", + "@kie-tools/runtime-tools-swf-webapp-components": "workspace:*", + "@kie-tools/serverless-workflow-combined-editor": "workspace:*", + "@kie-tools/serverless-workflow-diagram-editor-assets": "workspace:*", + "@kie-tools/serverless-workflow-diagram-editor-envelope": "workspace:*", + "@kie-tools/serverless-workflow-text-editor": "workspace:*", "@patternfly/patternfly": "^4.224.2", "@patternfly/react-core": "^4.276.6", "apollo-cache-inmemory": "1.6.6", @@ -38,9 +48,10 @@ "apollo-link-context": "^1.0.20", "apollo-link-error": "1.1.13", "apollo-link-http": "1.5.17", - "axios": "^1.6.4", + "axios": "^1.6.8", "graphql": "14.3.1", "history": "^4.9.0", + "monaco-editor": "^0.39.0", "react": "^17.0.2", "react-apollo": "3.1.3", "react-apollo-hooks": "^0.5.0", @@ -81,8 +92,9 @@ "css-minimizer-webpack-plugin": "^5.0.1", "enzyme": "^3.11.0", "enzyme-to-json": "^3.6.2", - "express": "^4.18.2", + "express": "^4.19.2", "file-loader": "^6.2.0", + "filemanager-webpack-plugin": "^7.0.0", "html-webpack-plugin": "^5.3.2", "https-browserify": "^1.0.0", "identity-obj-proxy": "^3.0.0", @@ -90,11 +102,13 @@ "jest-junit": "^14.0.0", "lodash": "^4.17.21", "mini-css-extract-plugin": "^2.7.6", + "monaco-editor-webpack-plugin": "^7.0.1", + "node-polyfill-webpack-plugin": "^2.0.1", "nodemon": "^2.0.22", "rimraf": "^3.0.2", "sass-loader": "^12.3.0", "serve": "^12.0.1", - "start-server-and-test": "^1.12.1", + "start-server-and-test": "^2.0.3", "stream-http": "^3.2.0", "style-loader": "^2.0.0", "svg-url-loader": "^8.0.0", @@ -102,6 +116,7 @@ "ts-loader": "^9.4.2", "tsconfig-paths-webpack-plugin": "^3.5.2", "typescript": "^4.6.2", + "url": "^0.11.3", "url-loader": "^4.1.1", "uuid": "^8.3.2", "waait": "^1.0.5", diff --git a/packages/sonataflow-management-console-webapp/resources/monitoring-webapp/MonitoringReport.dash.yml b/packages/sonataflow-management-console-webapp/resources/monitoring-webapp/MonitoringReport.dash.yml new file mode 100644 index 00000000000..e52c0081322 --- /dev/null +++ b/packages/sonataflow-management-console-webapp/resources/monitoring-webapp/MonitoringReport.dash.yml @@ -0,0 +1,300 @@ +properties: + dataIndexUrl: ${dataIndexUrl} + # seconds + refresh: 10 + + # cards size (change the template for width) + cardsHeight: 80 +global: + allowUrlProperties: true + settings: + refresh: + interval: ${refresh} + columns: + - id: Total + pattern: "#" + html: + html: >- +
+

${value}

+

${title}

+
+datasets: + - uuid: nodes + expression: >- + $.data.ProcessInstances.( + $map(nodes, function($n){ + [processId,$n.type, $n.name, $n.exit ? $toMillis($n.exit) - $toMillis($n.enter) : -1] + }); + ) + url: ${dataIndexUrl}/?query=%7BProcessInstances%7BprocessId%20nodes%7B%20nodeId%20type%20name%20enter%20exit%20%7D%7D%7D%0A + columns: + - id: workflowId + - id: type + - id: name + - id: time + type: number + - uuid: workflows + expression: >- + $.data.ProcessInstances.[ id, businessKey ? businessKey : "", processId, processName, state, $fromMillis($toMillis(start)), $fromMillis($toMillis(lastUpdate)), end ? $toMillis(end) - $toMillis(start) : -1, error ? error.message : ""] + url: ${dataIndexUrl}/?query=%7BProcessInstances%7Bid%20processId%20businessKey%20processName%20serviceUrl%20state%20start%20end%20lastUpdate%20error%20%7Bmessage%7D%7D%7D%0A + columns: + - id: id + - id: businessKey + - id: workflowId + - id: workflowName + - id: state + - id: startDate + type: DATE + - id: lastUpdate + type: DATE + - id: duration + type: number + - id: errorMessage +pages: + - properties: + margin-left: 5px + rows: + - columns: + - span: "11" + components: + - html: "Filter" + properties: + font-weight: bolder + - properties: + width: "150px" + margin-bottom: "20px" + settings: + type: SELECTOR + filter: + notification: true + lookup: + uuid: workflows + group: + - columnGroup: + source: workflowId + functions: + - source: workflowId + column: Workflow + - properties: + margin-left: 30px + text-align: center + columns: + - span: 2 + components: + - settings: + type: METRIC + html: + javascript: document.getElementById(${this}.id + "Icon").className = "fa fa-cubes"; + filter: + listening: true + general: + title: Workflows + lookup: + uuid: workflows + group: + - functions: + - source: Total + function: COUNT + - span: 2 + properties: + color: blue + components: + - settings: + type: METRIC + html: + javascript: document.getElementById(${this}.id + "Icon").className = "fa fa-check"; + filter: + listening: true + general: + title: Completed + lookup: + uuid: workflows + filter: + - column: state + function: EQUALS_TO + args: + - COMPLETED + group: + - functions: + - source: Total + function: COUNT + - span: 2 + properties: + color: green + components: + - settings: + type: METRIC + html: + javascript: document.getElementById(${this}.id + "Icon").className = "pficon pficon-ok"; + filter: + listening: true + general: + title: Active + lookup: + uuid: workflows + filter: + - column: state + function: EQUALS_TO + args: + - ACTIVE + group: + - functions: + - source: Total + function: COUNT + - span: 2 + properties: + color: orange + components: + - settings: + type: METRIC + html: + javascript: document.getElementById(${this}.id + "Icon").className = "fa fa-clock-o"; + filter: + listening: true + general: + title: Pending + lookup: + uuid: workflows + filter: + - column: state + function: EQUALS_TO + args: + - PENDING + group: + - functions: + - source: Total + function: COUNT + - span: 2 + properties: + color: orange + components: + - settings: + type: METRIC + html: + javascript: document.getElementById(${this}.id + "Icon").className = "fa fa-ban"; + filter: + listening: true + general: + title: Aborted + lookup: + uuid: workflows + filter: + - column: state + function: EQUALS_TO + args: + - ABORTED + group: + - functions: + - source: Total + function: COUNT + - span: 2 + properties: + color: red + components: + - settings: + type: METRIC + html: + javascript: document.getElementById(${this}.id + "Icon").className = "pficon-error-circle-o"; + filter: + listening: true + general: + title: Error + lookup: + uuid: workflows + filter: + - column: state + function: EQUALS_TO + args: + - ERROR + group: + - functions: + - source: Total + function: COUNT + - columns: + - components: + - html: "
" + - columns: + - components: + - settings: + type: barchart + general: + title: Functions and States Average Duration + chart: + resizable: true + extraConfiguration: >- + { + "yAxis": { + "name": "Time (ms)", + "nameLocation": "middle", + "nameGap": "45", + "nameTextStyle": { + "fontStyle": "italic" + } + } + } + filter: + listening: true + lookup: + uuid: nodes + filter: + - column: name + function: NOT_IN + args: + - EmbeddedStart + - EmbeddedEnd + - Script + - column: type + function: NOT_IN + args: + - Join + sort: + - column: Time (ms) + order: DESCENDING + group: + - columnGroup: + source: name + functions: + - source: name + - source: time + function: AVERAGE + column: Time (ms) + - columns: + - components: + - html:

Workflow List

+ - columns: + - components: + - settings: + component: table + external: + width: 100% + height: 500px + filter: + listening: true + lookup: + uuid: workflows + sort: + - column: lastUpdate + order: DESCENDING + group: + - columnsGroup: + source: workflowId + functions: + - source: id + column: Instance ID + - source: businessKey + column: Business Key + - source: workflowId + column: ID + - source: workflowName + column: Name + - source: state + column: State + - source: startDate + column: Start Date + - source: lastUpdate + column: Last Update + - source: duration + column: Duration + - source: errorMessage + column: Error Message diff --git a/packages/sonataflow-management-console-webapp/resources/monitoring-webapp/WorkflowDetails.dash.yml b/packages/sonataflow-management-console-webapp/resources/monitoring-webapp/WorkflowDetails.dash.yml new file mode 100644 index 00000000000..efb8e0d9b20 --- /dev/null +++ b/packages/sonataflow-management-console-webapp/resources/monitoring-webapp/WorkflowDetails.dash.yml @@ -0,0 +1,255 @@ +properties: + dataIndexUrl: ${dataIndexUrl} + # charts size + chartsWidth: 95% + chartsHeight: 450px + + cardsHeight: 80 + cardsWidth: 90% + + workflowId: c1722210-c0ba-4449-a007-f1725fd8afe4 + +global: + allowUrlProperties: true + settings: + html: + html: >- +
+

${value}

+

${title}

+
+datasets: + - uuid: nodes + expression: >- + $.data.ProcessInstances.( + $start := $min(nodes.($toMillis(enter))); + $end := $max(nodes.(exit ? $toMillis(exit) : -1)) - $start; + $map(nodes, function($n) { + [ + processId, + state, + id, + start, + 0, + $end , + $end / 2, + variables, + $n.type, + $n.name, + $n.nodeId, + $toMillis($n.enter), + $toMillis($n.enter) - $start, + $n.exit ? $toMillis($n.exit) - $start : -1, + $n.exit ? $toMillis($n.exit) - $toMillis($n.enter) : -1 + ] + }); + ) + url: ${dataIndexUrl}/?query=%7BProcessInstances(where%3A%7Bid%3A%7Bin%3A%20%5B"${workflowId}"%5D%7D%7D)%7BprocessId%20state%20id%20start%20lastUpdate%20variables%20nodes%20%7Bid%20nodeId%20name%20type%20enter%20exit%7D%7D%7D%0A + columns: + - id: workflowId + type: label + - id: state + type: label + - id: id + type: label + - id: workflowStartDate + type: date + - id: start + type: label + - id: end + type: number + - id: middle + type: label + - id: variables + type: label + - id: type + type: label + - id: name + type: label + - id: nodeId + type: number + - id: nodeStartMillis + type: number + - id: nodeStart + type: number + - id: nodeEnd + type: number + - id: duration + type: label +pages: + - properties: + margin-left: 10px + rows: + - columns: + - components: + - settings: + type: METRIC + general: + title: State + html: + html: >- + ${value} ${workflowId} + columns: + - id: end + pattern: "#" + lookup: + uuid: nodes + group: + - functions: + - source: workflowId + - columns: + - span: 4 + components: + - settings: + type: METRIC + general: + title: Start + html: + javascript: >- + document.getElementById(${this}.id + "Icon").className = "fa fa-calendar"; + columns: + - id: end + pattern: "#" + lookup: + uuid: nodes + group: + - functions: + - source: workflowStartDate + - span: 4 + components: + - settings: + type: METRIC + general: + title: State + html: + javascript: >- + if ( "${value}" === "ERROR") { + ${this}.style.color = 'red'; + document.getElementById(${this}.id + "Icon").className = "pficon-error-circle-o"; + } + else if ( "${value}" === "COMPLETED") { + ${this}.style.color = 'blue'; + document.getElementById(${this}.id + "Icon").className = "fa fa-check"; + } else if ( "${value}" === "ACTIVE") { + ${this}.style.color = 'green'; + document.getElementById(${this}.id + "Icon").className = "pficon pficon-on-running"; + } else { + document.getElementById(${this}.id + "Icon").className = ""; + } + columns: + - id: end + pattern: "#" + lookup: + uuid: nodes + group: + - functions: + - source: state + - span: 4 + components: + - settings: + type: METRIC + general: + title: Duration (ms) + html: + javascript: >- + document.getElementById(${this}.id + "Icon").className = "fa fa-clock-o"; + columns: + - id: end + pattern: "#" + lookup: + uuid: nodes + group: + - functions: + - source: end + - columns: + - components: + - settings: + component: echarts + echarts: + option: >- + { + "xAxis":{ + "position": "top", + "type": "value" + }, + "yAxis": { + "type": "category" + }, + "series":[ + { + "itemStyle": { + "color": "#b8f2c5", + "opacity": "0.5" + }, + "emphasis" : { + "disabled": "true" + }, + "tooltip": { + "formatter": "{b}" + }, + "type":"boxplot", + "name": "Duration", + "encode":{ + "x": ["start", "nodeStart", "middle", "nodeEnd", "end"], + "y": "name", + "itemName": ["Node Duration"] + } + }, + { + "name": "detail", + "type": "scatter", + "symbolSize": "0", + "tooltip": { + "trigger": "none" + }, + "label": { + "show": "true", + "position": "right", + "align": "left", + "verticalAlign": "middle", + "fontSize": "15", + "formatter": "{@duration} ms", + "fontWeight": "bolder" + }, + "emphasis" : { + "disabled": "true" + }, + "itemStyle": { + "color": "#d00000" + }, + "encode": { + "x": "nodeStart", + "y": "name", + "label": "Duration", + "itemName": "Duration" + } + } + ] + } + external: + width: "${chartsWidth}" + height: "${chartsHeight}" + filter: + listening: "true" + lookup: + uuid: nodes + filter: + - column: name + function: NOT_IN + args: + - EmbeddedStart + - EmbeddedEnd + - Script + - column: type + function: NOT_IN + args: + - Join + - column: nodeEnd + function: NOT_IN + args: + - -1 + sort: + - column: nodeStartMillis + order: DESCENDING + - column: nodeId + order: DESCENDING diff --git a/packages/sonataflow-management-console-webapp/resources/monitoring-webapp/setup.js b/packages/sonataflow-management-console-webapp/resources/monitoring-webapp/setup.js new file mode 100644 index 00000000000..95972bb4668 --- /dev/null +++ b/packages/sonataflow-management-console-webapp/resources/monitoring-webapp/setup.js @@ -0,0 +1,36 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +dashbuilder = { + /* + // possible modes are EDITOR and CLIENT - if dashboards is set then CLIENT mode is assumed + mode: "CLIENT", + // The list of client dashboards - if CLIENT mode is used and no list is provided, than the dashboard "dashboard.yml" will be attempted to load. If no dashboard is found, then client opens for upload. + // The dashboard can also be an URL + dashboards: [ "dashboard1.yaml", "dashboard2.json"], + + // base path to look for dashboards. Default is / + path: "/path", + + // Set this as true to always hide the nav bar + hideNavBar: true +*/ + hideNavBar: true, + dashboards: ["MonitoringReport.dash.yml", "WorkflowDetails.dash.yml"], +}; diff --git a/packages/sonataflow-management-console-webapp/resources/serverless-workflow-combined-editor-envelope.html b/packages/sonataflow-management-console-webapp/resources/serverless-workflow-combined-editor-envelope.html new file mode 100644 index 00000000000..eab79b10728 --- /dev/null +++ b/packages/sonataflow-management-console-webapp/resources/serverless-workflow-combined-editor-envelope.html @@ -0,0 +1,42 @@ + + + + + + + + + + + + + +
+ + + diff --git a/packages/sonataflow-management-console-webapp/resources/serverless-workflow-diagram-editor-envelope.html b/packages/sonataflow-management-console-webapp/resources/serverless-workflow-diagram-editor-envelope.html new file mode 100644 index 00000000000..47735939a29 --- /dev/null +++ b/packages/sonataflow-management-console-webapp/resources/serverless-workflow-diagram-editor-envelope.html @@ -0,0 +1,42 @@ + + + + + + + + + + + + + +
+ + + diff --git a/packages/sonataflow-management-console-webapp/resources/serverless-workflow-text-editor-envelope.html b/packages/sonataflow-management-console-webapp/resources/serverless-workflow-text-editor-envelope.html new file mode 100644 index 00000000000..b3c3bd478ad --- /dev/null +++ b/packages/sonataflow-management-console-webapp/resources/serverless-workflow-text-editor-envelope.html @@ -0,0 +1,42 @@ + + + + + + + + + + + + + +
+ + + diff --git a/packages/sonataflow-management-console-webapp/src/alerts/Alerts.tsx b/packages/sonataflow-management-console-webapp/src/alerts/Alerts.tsx new file mode 100644 index 00000000000..4d172967489 --- /dev/null +++ b/packages/sonataflow-management-console-webapp/src/alerts/Alerts.tsx @@ -0,0 +1,194 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import * as React from "react"; +import { useCallback, useEffect, useImperativeHandle, useMemo, useState } from "react"; +import { AlertGroup } from "@patternfly/react-core/dist/js/components/AlertGroup"; + +type MapValueType = A extends Map ? V : never; + +export type AlertDelegate = ( + args: { close: () => void; secondsUntilAutoClose?: number } & Partial, + staticArgs: T +) => React.ReactNode; + +export interface AlertAutoCloseArgs { + durationInSeconds: number; +} + +export interface AlertsController { + closeAll(): void; + show(key: string, staticArgs: unknown): void; + close(key: string): void; + set(key: string, alertDelegate: AlertDelegate, autoCloseArgs?: AlertAutoCloseArgs): void; +} + +const AUTO_CLOSE_ALERTS_REFRESH_RATE_IN_MS = 1000; + +type AlertControl = { + alertDelegate: AlertDelegate; + autoCloseArgs?: AlertAutoCloseArgs; + isShowing: boolean; + lastShowedAt?: Date; + staticArgs: unknown; +}; + +type AlertsProps = { + className?: string; +}; + +export const Alerts = React.forwardRef((props, forwardedRef) => { + const [alerts, setAlerts] = useState(new Map()); + const [autoCloseAlertsControl, setAutoCloseAlertsControl] = useState( + new Map }>() + ); + + const changeValueForKeys = useCallback( + (prev: typeof alerts, keys: string[], args: Partial>) => { + const newAlerts = new Map(prev); + for (const key of keys) { + newAlerts.set(key, { ...newAlerts.get(key)!, ...args }); + } + return newAlerts; + }, + [] + ); + + const imperativeHandle = useMemo(() => { + return { + closeAll: () => { + setAlerts((prev) => changeValueForKeys(prev, [...prev.keys()], { isShowing: false })); + }, + close: (key) => { + setAlerts((prev) => (prev.has(key) ? changeValueForKeys(prev, [key], { isShowing: false }) : prev)); + }, + show: (key, staticArgs) => { + setAlerts((prev) => + prev.has(key) + ? changeValueForKeys(prev, [key], { isShowing: true, lastShowedAt: new Date(), staticArgs }) + : prev + ); + }, + set: (key, alertDelegate, autoCloseArgs) => { + setAlerts((prev) => { + const next = new Map(prev); + next.set(key, { + alertDelegate, + isShowing: prev.get(key)?.isShowing ?? false, + lastShowedAt: prev.get(key)?.lastShowedAt, + staticArgs: prev.get(key)?.staticArgs, + autoCloseArgs, + }); + return next; + }); + }, + }; + }, [changeValueForKeys]); + + useImperativeHandle(forwardedRef, () => imperativeHandle, [imperativeHandle]); + + const startRefreshingAlertWithKey = useCallback( + (k: string) => { + return setInterval(() => { + setAutoCloseAlertsControl((prev) => { + const next = new Map(prev); + const prevAlert = prev.get(k)!; + + if (prevAlert.secondsLeft > 1) { + next.set(k, { ...prevAlert, secondsLeft: prevAlert.secondsLeft - 1 }); + } else { + imperativeHandle.close(k); + } + + return next; + }); + }, AUTO_CLOSE_ALERTS_REFRESH_RATE_IN_MS); + }, + [imperativeHandle] + ); + + useEffect(() => { + setAutoCloseAlertsControl((prev) => { + const next = new Map(prev); + [...alerts.entries()].forEach(([k, v]) => { + if (v.isShowing && prev.has(k) && v.autoCloseArgs) { + next.set(k, { secondsLeft: v.autoCloseArgs.durationInSeconds, interval: prev.get(k)!.interval }); + } + // + else if (v.isShowing && !prev.has(k) && v.autoCloseArgs) { + const interval = startRefreshingAlertWithKey(k); + next.set(k, { secondsLeft: v.autoCloseArgs.durationInSeconds, interval }); + } + // + else if (!v.isShowing) { + const saved = prev.get(k); + if (saved) { + clearInterval(saved.interval); + next.delete(k); + } + } + }); + return next; + }); + }, [alerts, startRefreshingAlertWithKey]); + + return ( + +
+ {[...alerts.entries()] + .filter(([_, { isShowing }]) => isShowing) + .sort(([_, a], [__, b]) => a.lastShowedAt!.getTime() - b.lastShowedAt!.getTime()) // show newest at the bottom + .map(([key, { alertDelegate, autoCloseArgs, staticArgs }]) => ( + + {alertDelegate( + { + close: () => imperativeHandle.close(key), + secondsUntilAutoClose: + autoCloseAlertsControl.get(key)?.secondsLeft ?? autoCloseArgs?.durationInSeconds, + durationInSeconds: autoCloseArgs?.durationInSeconds, + }, + staticArgs + )} +
+
+ ))} +
+
+ ); +}); + +export function useAlert( + alertsController: AlertsController | undefined, + delegate: AlertDelegate, + autoCloseArgs?: AlertAutoCloseArgs +) { + const key = useMemo(() => `${Math.random()}`, []); + + useEffect(() => { + alertsController?.set(key, delegate, autoCloseArgs); + }, [alertsController, key, delegate, autoCloseArgs]); + + return useMemo( + () => ({ + close: () => alertsController?.close(key), + show: (staticArgs: T) => alertsController?.show(key, staticArgs), + }), + [alertsController, key] + ); +} diff --git a/packages/sonataflow-management-console-webapp/src/alerts/GlobalAlertsContext.tsx b/packages/sonataflow-management-console-webapp/src/alerts/GlobalAlertsContext.tsx new file mode 100644 index 00000000000..74c2d06bece --- /dev/null +++ b/packages/sonataflow-management-console-webapp/src/alerts/GlobalAlertsContext.tsx @@ -0,0 +1,125 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import * as React from "react"; +import { useContext, createContext, PropsWithChildren, useMemo, useCallback } from "react"; +import { useController } from "@kie-tools-core/react-hooks/dist/useController"; +import { AlertAutoCloseArgs, AlertDelegate, Alerts, AlertsController } from "./Alerts"; + +export interface GlobalAlertsContextType { + alerts: AlertsController | undefined; + alertsRef: (controller: AlertsController) => void; +} + +export interface GlobalAlertsDispatchContextType { + closeAll(): void; + close(key: string): void; + show(key: string, staticArgs: unknown): void; + set( + key: string, + alertDelegate: AlertDelegate, + autoCloseArgs?: AlertAutoCloseArgs + ): { + close: () => void | undefined; + show: (staticArgs?: unknown) => void | undefined; + }; +} + +export const GlobalAlertsContext = createContext({} as any); +export const GlobalAlertsDispatchContext = createContext({} as any); + +export function GlobalAlertsContextProvider(props: PropsWithChildren<{}>) { + const [alerts, alertsRef] = useController(); + + const value = useMemo( + () => ({ + alerts, + alertsRef, + }), + [alerts, alertsRef] + ); + + const closeAll = useCallback(() => { + alerts?.closeAll(); + }, [alerts]); + + const close = useCallback( + (key: string) => { + alerts?.close(key); + }, + [alerts] + ); + + const show = useCallback( + (key: string, staticArgs: unknown) => { + alerts?.show(key, staticArgs); + }, + [alerts] + ); + + const set = useCallback( + (key: string, alertDelegate: AlertDelegate, autoCloseArgs?: AlertAutoCloseArgs) => { + // This setTimeout is a hack to block a setState from hapenning while Alerts is still rendering + setTimeout(() => { + return alerts?.set(key, alertDelegate, autoCloseArgs); + }); + + return { + close: () => alerts?.close(key), + show: (staticArgs: unknown) => alerts?.show(key, staticArgs), + }; + }, + [alerts] + ); + + const dispatch = useMemo( + () => ({ + closeAll, + close, + show, + set, + }), + [close, closeAll, set, show] + ); + + return ( + + + + {props.children} + + + ); +} + +export function useGlobalAlertsContext() { + return useContext(GlobalAlertsContext); +} + +export function useGlobalAlertsDispatchContext() { + return useContext(GlobalAlertsDispatchContext); +} + +export function useGlobalAlert(delegate: AlertDelegate, autoCloseArgs?: AlertAutoCloseArgs) { + const { set } = useGlobalAlertsDispatchContext(); + + const key = useMemo(() => `${Math.random()}`, []); + + return set(key, delegate, autoCloseArgs); +} diff --git a/packages/sonataflow-management-console-webapp/src/components/console/ManagementConsole/ManagementConsole.tsx b/packages/sonataflow-management-console-webapp/src/components/console/ManagementConsole/ManagementConsole.tsx index a8231c34638..956f1ca73e1 100644 --- a/packages/sonataflow-management-console-webapp/src/components/console/ManagementConsole/ManagementConsole.tsx +++ b/packages/sonataflow-management-console-webapp/src/components/console/ManagementConsole/ManagementConsole.tsx @@ -18,16 +18,22 @@ */ import * as React from "react"; import { useCallback } from "react"; -import { BrowserRouter as Router, Route, Switch } from "react-router-dom"; +import { HashRouter as Router, Route, Switch } from "react-router-dom"; import { ApolloProvider } from "react-apollo"; import { ApolloClient } from "apollo-client"; -import ManagementConsoleNav from "../ManagementConsoleNav/ManagementConsoleNav"; -import managementConsoleLogo from "../../../static/sonataflowManagementConsoleLogo.svg"; import { KogitoAppContextProvider, UserContext, } from "@kie-tools/runtime-tools-components/dist/contexts/KogitoAppContext"; import { PageLayout } from "@kie-tools/runtime-tools-components/dist/components/PageLayout"; +import { WorkflowListContextProviderWithApolloClient } from "@kie-tools/runtime-tools-swf-webapp-components/dist/WorkflowList"; +import { WorkflowDefinitionListContextProviderWithApolloClient } from "@kie-tools/runtime-tools-swf-webapp-components/dist/WorkflowDefinitionList"; +import { WorkflowFormContextProvider } from "@kie-tools/runtime-tools-swf-webapp-components/dist/WorkflowForm"; +import { WorkflowDetailsContextProviderWithApolloClient } from "@kie-tools/runtime-tools-swf-webapp-components/dist/WorkflowDetails"; +import { CloudEventFormContextProvider } from "@kie-tools/runtime-tools-swf-webapp-components/dist/CloudEventForm"; +import ManagementConsoleNav from "../ManagementConsoleNav/ManagementConsoleNav"; +import managementConsoleLogo from "../../../static/sonataflowManagementConsoleLogo.svg"; +import { GlobalAlertsContextProvider } from "../../../alerts/GlobalAlertsContext"; interface IOwnProps { apolloClient: ApolloClient; @@ -58,11 +64,23 @@ const ManagementConsole: React.FC = ({ apolloClient, userContext, chi return ( - - - - - + + + + + + + + + + + + + + + + + ); diff --git a/packages/sonataflow-management-console-webapp/src/components/console/ManagementConsoleNav/ManagementConsoleNav.tsx b/packages/sonataflow-management-console-webapp/src/components/console/ManagementConsoleNav/ManagementConsoleNav.tsx index 254d35c9c30..b43619a0760 100644 --- a/packages/sonataflow-management-console-webapp/src/components/console/ManagementConsoleNav/ManagementConsoleNav.tsx +++ b/packages/sonataflow-management-console-webapp/src/components/console/ManagementConsoleNav/ManagementConsoleNav.tsx @@ -20,6 +20,7 @@ import * as React from "react"; import { Nav, NavItem, NavList } from "@patternfly/react-core/dist/js/components/Nav"; import { Link } from "react-router-dom"; import { ouiaAttribute } from "@kie-tools/runtime-tools-components/dist/ouiaTools"; +import { routes } from "../../../navigation/Routes"; interface IOwnProps { pathname: string; @@ -31,33 +32,30 @@ const ManagementConsoleNav: React.FC = ({ pathname }) => { - + Workflow Instances - + Workflow Definitions - - - Trigger Cloud Event - - - - + + Monitoring diff --git a/packages/sonataflow-management-console-webapp/src/components/console/ManagementConsoleRoutes/ManagementConsoleRoutes.tsx b/packages/sonataflow-management-console-webapp/src/components/console/ManagementConsoleRoutes/ManagementConsoleRoutes.tsx index c77e2f17755..eb2e873c0b5 100644 --- a/packages/sonataflow-management-console-webapp/src/components/console/ManagementConsoleRoutes/ManagementConsoleRoutes.tsx +++ b/packages/sonataflow-management-console-webapp/src/components/console/ManagementConsoleRoutes/ManagementConsoleRoutes.tsx @@ -18,16 +18,36 @@ */ import * as React from "react"; import { Redirect, Route, Switch } from "react-router-dom"; -import EmptyPage from "../../pages/EmptyPage"; +import { routes } from "../../../navigation/Routes"; +import { TriggerCloudEventPage } from "../../pages/TriggerCloudEventPage/TriggerCloudEventPage"; +import MonitoringPage from "../../pages/MonitoringPage/MonitoringPage"; +import { WorkflowDefinitionsPage } from "../../pages/WorkflowDefinitionsPage/WorkflowDefinitionsPage"; +import { WorkflowInstancesPage } from "../../pages/WorkflowInstancesPage/WorkflowInstancesPage"; +import { WorkflowDetailsPage } from "../../pages/WorkflowDetailsPage/WorkflowDetailsPage"; +import { WorkflowFormPage } from "../../pages/WorkflowFormPage/WorkflowFormPage"; const ManagementConsoleRoutes: React.FC = () => { return ( - } /> - - - - + } + /> + + + + {({ match }) => } + + + {({ match }) => } + + + + + + + ); }; diff --git a/packages/sonataflow-management-console-webapp/src/components/pages/EmptyPage.tsx b/packages/sonataflow-management-console-webapp/src/components/containers/MonitoringContainer/MonitoringContainer.tsx similarity index 56% rename from packages/sonataflow-management-console-webapp/src/components/pages/EmptyPage.tsx rename to packages/sonataflow-management-console-webapp/src/components/containers/MonitoringContainer/MonitoringContainer.tsx index dd6afc53846..6f99804e576 100644 --- a/packages/sonataflow-management-console-webapp/src/components/pages/EmptyPage.tsx +++ b/packages/sonataflow-management-console-webapp/src/components/containers/MonitoringContainer/MonitoringContainer.tsx @@ -1,4 +1,4 @@ -/** +/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information @@ -7,7 +7,7 @@ * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an @@ -16,18 +16,19 @@ * specific language governing permissions and limitations * under the License. */ -import * as React from "react"; -import { RouteComponentProps } from "react-router-dom"; -import { StaticContext } from "react-router"; -import * as H from "history"; -import "../styles.css"; -import { OUIAProps } from "@kie-tools/runtime-tools-components/dist/ouiaTools"; -// eslint-disable-next-line @typescript-eslint/no-empty-interface -interface MatchProps {} +import React from "react"; +import { Dashboard, MonitoringView } from "@kie-tools/runtime-tools-shared-enveloped-components/dist/monitoring"; -const EmptyPage: React.FC & OUIAProps> = (props) => { - return <>Empty Page; +interface Props { + dataIndexUrl?: string; + dashboard?: Dashboard; + workflow?: string; +} + +const MonitoringContainer: React.FC = ({ workflow, dashboard, dataIndexUrl }) => { + const _dashboard = dashboard || Dashboard.MONITORING; + return ; }; -export default EmptyPage; +export default MonitoringContainer; diff --git a/packages/sonataflow-management-console-webapp/src/components/pages/MonitoringPage/MonitoringPage.tsx b/packages/sonataflow-management-console-webapp/src/components/pages/MonitoringPage/MonitoringPage.tsx new file mode 100644 index 00000000000..8a08b3e5343 --- /dev/null +++ b/packages/sonataflow-management-console-webapp/src/components/pages/MonitoringPage/MonitoringPage.tsx @@ -0,0 +1,180 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import React, { ReactText, useCallback, useEffect, useState } from "react"; +import { Toolbar, ToolbarContent, ToolbarGroup, ToolbarItem } from "@patternfly/react-core/dist/js/components/Toolbar"; +import { Select, SelectOption, SelectVariant } from "@patternfly/react-core/dist/js/components/Select"; +import { Tab, Tabs, TabTitleText } from "@patternfly/react-core/dist/js/components/Tabs"; +import { Card } from "@patternfly/react-core/dist/js/components/Card"; +import { PageSection } from "@patternfly/react-core/dist/js/components/Page"; +import { + OUIAProps, + ouiaPageTypeAndObjectId, + componentOuiaProps, +} from "@kie-tools/runtime-tools-components/dist/ouiaTools"; +import { PageSectionHeader } from "@kie-tools/runtime-tools-components/dist/components/PageSectionHeader"; +import MonitoringContainer from "../../containers/MonitoringContainer/MonitoringContainer"; +import { + KogitoEmptyState, + KogitoEmptyStateType, +} from "@kie-tools/runtime-tools-components/dist/components/KogitoEmptyState"; +import "../../styles.css"; +import { WorkflowInstance, WorkflowInstanceState } from "@kie-tools/runtime-tools-swf-gateway-api/dist/types"; +import { Dashboard } from "@kie-tools/runtime-tools-shared-enveloped-components/dist/monitoring"; +import { + WorkflowListGatewayApi, + useWorkflowListGatewayApi, +} from "@kie-tools/runtime-tools-swf-webapp-components/dist/WorkflowList"; +import { OrderBy } from "@kie-tools/runtime-tools-shared-gateway-api/dist/types"; + +interface Props { + dataIndexUrl?: string; +} +const MonitoringPage: React.FC = ({ ouiaId, ouiaSafe, dataIndexUrl }) => { + const gatewayApi: WorkflowListGatewayApi = useWorkflowListGatewayApi(); + const [hasWorkflow, setHasWorkflow] = useState(false); + const [loading, setLoading] = useState(true); + const [openWorkflowSelect, setOpenWorkflowSelect] = useState(false); + const [dashboard, setDashboard] = useState(Dashboard.MONITORING); + const [workflowList, setWorkflowList] = useState([]); + const [selectedWorkflow, setSelectedWorkflow] = useState(); + const [activeTabKey, setActiveTabKey] = useState(0); + + const initialLoad = useCallback( + () => + gatewayApi.initialLoad( + { + status: [ + WorkflowInstanceState.Aborted, + WorkflowInstanceState.Active, + WorkflowInstanceState.Completed, + WorkflowInstanceState.Error, + WorkflowInstanceState.Suspended, + ], + businessKey: [], + }, + { start: OrderBy.DESC } + ), + [gatewayApi] + ); + + const loadWorkflowList = useCallback(() => { + gatewayApi.query(0, 1000).then((list) => { + setSelectedWorkflow(list[0]); + setWorkflowList(list); + }); + }, [gatewayApi]); + + useEffect(() => { + const intervaId = setInterval(() => { + if (!hasWorkflow) { + initialLoad(); + gatewayApi.query(0, 1).then((list) => { + if (list.length > 0) { + setHasWorkflow(true); + loadWorkflowList(); + } + setLoading(false); + }); + } + }, 500); + return () => clearInterval(intervaId); + }, [hasWorkflow, loading, gatewayApi, initialLoad, loadWorkflowList]); + + useEffect(() => { + if (dashboard === Dashboard.DETAILS) { + loadWorkflowList(); + } + }, [dashboard, loadWorkflowList]); + + useEffect(() => { + return ouiaPageTypeAndObjectId("monitoring"); + }); + + return ( + + + {hasWorkflow ? ( + <> + { + setActiveTabKey(tabIndex); + const dashboard = tabIndex === 0 ? Dashboard.MONITORING : Dashboard.DETAILS; + setDashboard(dashboard); + loadWorkflowList(); + }} + isBox + variant="light300" + style={{ + background: "white", + }} + > + Summary}> + Workflows}> + + + + {dashboard === Dashboard.DETAILS && ( + + + + + + + + + + )} + + + + + ) : ( + + )} + + ); +}; + +export default MonitoringPage; diff --git a/packages/sonataflow-management-console-webapp/src/components/pages/TriggerCloudEventPage/TriggerCloudEventPage.tsx b/packages/sonataflow-management-console-webapp/src/components/pages/TriggerCloudEventPage/TriggerCloudEventPage.tsx new file mode 100644 index 00000000000..f2f97533081 --- /dev/null +++ b/packages/sonataflow-management-console-webapp/src/components/pages/TriggerCloudEventPage/TriggerCloudEventPage.tsx @@ -0,0 +1,118 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import React, { useCallback } from "react"; +import { Page, PageSection } from "@patternfly/react-core/dist/js/components/Page"; +import { Text, TextContent, TextVariants } from "@patternfly/react-core/dist/js/components/Text"; +import { CloudEventFormContainer } from "@kie-tools/runtime-tools-swf-webapp-components/dist/CloudEventFormContainer"; +import { Alert, AlertActionCloseButton } from "@patternfly/react-core/dist/js/components/Alert"; +import { useGlobalAlert } from "../../../alerts/GlobalAlertsContext"; +import { WorkflowDefinition } from "@kie-tools/runtime-tools-swf-gateway-api/dist/types"; +import { useHistory } from "react-router"; + +const PAGE_TITLE = "Trigger Cloud Event"; +const KUBESMARTS_CLOUD_SOURCE = "/local/kubesmarts"; + +export function TriggerCloudEventPage() { + const history = useHistory(); + const workflowDefinition: WorkflowDefinition = (history.location.state as any)["workflowDefinition"]; + + const triggerEventSuccessAlert = useGlobalAlert<{ message: string }>( + useCallback(({ close }, { message }) => { + return ( + } + /> + ); + }, []), + { durationInSeconds: 5 } + ); + + const startWorkflowErrorAlert = useGlobalAlert<{ message: string }>( + useCallback(({ close }, { message }) => { + return ( + + Something went wrong while triggering your workflow. +
+ {`Reason: ${message}`} + + } + aria-live="polite" + data-testid="alert-upload-error" + actionClose={} + /> + ); + }, []), + { durationInSeconds: 5 } + ); + + const onStartWorkflowError = useCallback( + (error) => { + const message = error?.message || "Unknown error. More details in the developer tools console."; + startWorkflowErrorAlert.show({ message }); + }, + [startWorkflowErrorAlert] + ); + + const onTriggerEventSuccessAlert = useCallback(() => { + triggerEventSuccessAlert.show({ message: "The cloud event has been successfully triggered." }); + }, [triggerEventSuccessAlert]); + + const onTriggerStartCloudEventSuccess = useCallback( + (businessKey: string) => { + triggerEventSuccessAlert.show({ + message: `A workflow with business key ${businessKey} has been successfully triggered.`, + }); + }, + [triggerEventSuccessAlert] + ); + + return ( + + + + {PAGE_TITLE} + + Trigger a cloud event to start new workflow instances or to send HTTP Cloud Events to active workflow + instances that are waiting for an event to advance. + + + + + + + + + ); +} diff --git a/packages/sonataflow-management-console-webapp/src/components/pages/WorkflowDefinitionsPage/WorkflowDefinitionsPage.tsx b/packages/sonataflow-management-console-webapp/src/components/pages/WorkflowDefinitionsPage/WorkflowDefinitionsPage.tsx new file mode 100644 index 00000000000..39a32fde1f3 --- /dev/null +++ b/packages/sonataflow-management-console-webapp/src/components/pages/WorkflowDefinitionsPage/WorkflowDefinitionsPage.tsx @@ -0,0 +1,91 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import React, { useCallback } from "react"; +import { WorkflowDefinitionListContainer } from "@kie-tools/runtime-tools-swf-webapp-components/dist/WorkflowDefinitionListContainer"; +import { Card } from "@patternfly/react-core/dist/esm/components/Card"; +import { Page, PageSection } from "@patternfly/react-core/dist/js/components/Page"; +import { Text, TextContent, TextVariants } from "@patternfly/react-core/dist/js/components/Text"; +import { useHistory } from "react-router"; +import { routes } from "../../../navigation/Routes"; +import { WorkflowDefinition } from "@kie-tools/runtime-tools-swf-gateway-api/dist/types"; +import { CloudEventPageSource } from "@kie-tools/runtime-tools-swf-webapp-components/dist/CloudEventForm"; + +const PAGE_TITLE = "Workflow Definitions"; + +export function WorkflowDefinitionsPage() { + const history = useHistory(); + + const onOpenWorkflowForm = useCallback( + (workflowDefinition: WorkflowDefinition) => { + history.push({ + pathname: routes.runtimeToolsWorkflowForm.path({ workflowName: workflowDefinition.workflowName }), + state: { + workflowDefinition: { + workflowName: workflowDefinition.workflowName, + endpoint: workflowDefinition.endpoint, + serviceUrl: workflowDefinition.serviceUrl, + }, + }, + }); + }, + [history] + ); + + const onOpenTriggerCloudEventForWorkflow = useCallback( + (workflowDefinition: WorkflowDefinition) => { + history.push({ + pathname: routes.runtimeToolsTriggerCloudEventForWorkflowDefinition.path({ + workflowName: workflowDefinition.workflowName, + }), + state: { + workflowDefinition: { + workflowName: workflowDefinition.workflowName, + endpoint: workflowDefinition.endpoint, + serviceUrl: workflowDefinition.serviceUrl, + }, + source: CloudEventPageSource.DEFINITIONS, + }, + }); + }, + [history] + ); + + return ( + + + + {PAGE_TITLE} + + Start new workflow instances from the SonataFlow service linked in your Runtime Tools settings. + + + + + + + + + + + ); +} diff --git a/packages/sonataflow-management-console-webapp/src/components/pages/WorkflowDetailsPage/WorkflowDetailsPage.tsx b/packages/sonataflow-management-console-webapp/src/components/pages/WorkflowDetailsPage/WorkflowDetailsPage.tsx new file mode 100644 index 00000000000..249d103ca98 --- /dev/null +++ b/packages/sonataflow-management-console-webapp/src/components/pages/WorkflowDetailsPage/WorkflowDetailsPage.tsx @@ -0,0 +1,113 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import React, { useCallback, useEffect, useState } from "react"; +import { KogitoSpinner } from "@kie-tools/runtime-tools-components/dist/components/KogitoSpinner"; +import { ServerErrors } from "@kie-tools/runtime-tools-components/dist/components/ServerErrors"; +import { ouiaPageTypeAndObjectId } from "@kie-tools/runtime-tools-components/dist/ouiaTools"; +import { WorkflowInstance } from "@kie-tools/runtime-tools-swf-gateway-api/dist/types"; +import { + WorkflowDetailsGatewayApi, + useWorkflowDetailsGatewayApi, +} from "@kie-tools/runtime-tools-swf-webapp-components/dist/WorkflowDetails"; +import { WorkflowDetailsContainer } from "@kie-tools/runtime-tools-swf-webapp-components/dist/WorkflowDetailsContainer"; +import { Card } from "@patternfly/react-core/dist/js/components/Card"; +import { Page, PageSection } from "@patternfly/react-core/dist/js/components/Page"; +import { Text, TextContent, TextVariants } from "@patternfly/react-core/dist/js/components/Text"; +import { Bullseye } from "@patternfly/react-core/dist/js/layouts/Bullseye"; +import { useHistory } from "react-router"; +import { routes } from "../../../navigation/Routes"; + +const PAGE_TITLE = "Workflow Details"; + +interface WorkflowListContainerProps { + workflowId: string; +} +export function WorkflowDetailsPage(props: WorkflowListContainerProps) { + const history = useHistory(); + const gatewayApi: WorkflowDetailsGatewayApi = useWorkflowDetailsGatewayApi(); + + const [workflowInstance, setWorkflowInstance] = useState({} as WorkflowInstance); + const [isLoading, setIsLoading] = useState(false); + const [fetchError, setFetchError] = useState(""); + + useEffect(() => { + gatewayApi + .workflowDetailsQuery(props.workflowId) + .then((response) => { + setWorkflowInstance(response); + }) + .catch((error) => { + setFetchError(error); + }) + .finally(() => { + setIsLoading(false); + }); + }, [gatewayApi, props.workflowId]); + + useEffect(() => { + return ouiaPageTypeAndObjectId("workflow-details"); + }); + + const onOpenWorkflowInstanceDetails = useCallback( + (workflowId: string) => { + history.push(`/`); + history.push(routes.runtimeToolsWorkflowDetails.path({ workflowId })); + }, + [history] + ); + + return ( + + + + {PAGE_TITLE} + + Explore the execution status, details, timeline and variables of a workflow instance. + + + + + + {isLoading && ( + + + + )} + + {!isLoading && workflowInstance && Object.keys(workflowInstance).length > 0 && !fetchError ? ( + + ) : ( + <> + {fetchError.length > 0 && ( + + + + + + )} + + )} + + + ); +} diff --git a/packages/sonataflow-management-console-webapp/src/components/pages/WorkflowFormPage/WorkflowFormPage.tsx b/packages/sonataflow-management-console-webapp/src/components/pages/WorkflowFormPage/WorkflowFormPage.tsx new file mode 100644 index 00000000000..5dbe599717f --- /dev/null +++ b/packages/sonataflow-management-console-webapp/src/components/pages/WorkflowFormPage/WorkflowFormPage.tsx @@ -0,0 +1,159 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import React, { useCallback, useEffect, useRef } from "react"; +import { InlineEdit, InlineEditApi } from "@kie-tools/runtime-tools-components/dist/components/InlineEdit"; +import { ouiaPageTypeAndObjectId } from "@kie-tools/runtime-tools-components/dist/ouiaTools"; +import { WorkflowDefinition } from "@kie-tools/runtime-tools-swf-gateway-api/dist/types"; +import { + WorkflowFormGatewayApi, + useWorkflowFormGatewayApi, +} from "@kie-tools/runtime-tools-swf-webapp-components/dist/WorkflowForm"; +import { WorkflowFormContainer } from "@kie-tools/runtime-tools-swf-webapp-components/dist/WorkflowFormContainer"; +import { Alert, AlertActionCloseButton, AlertActionLink } from "@patternfly/react-core/dist/js/components/Alert"; +import { Card, CardBody } from "@patternfly/react-core/dist/js/components/Card"; +import { Page, PageSection } from "@patternfly/react-core/dist/js/components/Page"; +import { Text, TextContent, TextVariants } from "@patternfly/react-core/dist/js/components/Text"; +import { useHistory } from "react-router"; +import { routes } from "../../../navigation/Routes"; +import { useGlobalAlert } from "../../../alerts/GlobalAlertsContext"; + +const PAGE_TITLE = "Start new workflow"; + +export function WorkflowFormPage() { + const history = useHistory(); + const gatewayApi: WorkflowFormGatewayApi = useWorkflowFormGatewayApi(); + + const inlineEditRef = useRef(null); + + const workflowDefinition: WorkflowDefinition = (history.location.state as any)["workflowDefinition"]; + + const onResetForm = useCallback(() => { + gatewayApi.setBusinessKey(""); + inlineEditRef.current!.reset(); + }, [gatewayApi]); + + const getBusinessKey = () => { + return gatewayApi.getBusinessKey(); + }; + + useEffect(() => { + onResetForm(); + return ouiaPageTypeAndObjectId("workflow-form"); + }, [onResetForm]); + + const startWorkflowSuccessAlert = useGlobalAlert<{ workflowId: string }>( + useCallback( + ({ close }, { workflowId }) => { + const viewDetails = () => { + history.push({ + pathname: routes.runtimeToolsWorkflowDetails.path({ workflowId }), + }); + close(); + }; + + return ( + } + actionLinks={ + <> + {"View details"} + {"Ignore"} + + } + /> + ); + }, + [history] + ), + { durationInSeconds: 5 } + ); + + const startWorkflowErrorAlert = useGlobalAlert<{ message: string }>( + useCallback(({ close }, { message }) => { + return ( + + Something went wrong while triggering your workflow. +
+ {`Reason: ${message}`} + + } + aria-live="polite" + data-testid="alert-upload-error" + actionClose={} + /> + ); + }, []), + { durationInSeconds: 5 } + ); + + const onStartWorkflowError = useCallback( + (error: any) => { + const message = + error?.response?.data?.message + " " + error?.response?.data?.cause || + error?.message || + "Unknown error. More details in the developer tools console."; + startWorkflowErrorAlert.show({ message }); + }, + [startWorkflowErrorAlert] + ); + + const onStartWorkflowSuccess = useCallback( + (workflowId: string) => { + startWorkflowSuccessAlert.show({ workflowId }); + }, + [startWorkflowSuccessAlert] + ); + + return ( + + + + {PAGE_TITLE} + gatewayApi.setBusinessKey(bk)} + getBusinessKey={getBusinessKey} + /> + + + + + + + + + + + + ); +} diff --git a/packages/sonataflow-management-console-webapp/src/components/pages/WorkflowInstancesPage/WorkflowInstancesPage.tsx b/packages/sonataflow-management-console-webapp/src/components/pages/WorkflowInstancesPage/WorkflowInstancesPage.tsx new file mode 100644 index 00000000000..4c269fb966b --- /dev/null +++ b/packages/sonataflow-management-console-webapp/src/components/pages/WorkflowInstancesPage/WorkflowInstancesPage.tsx @@ -0,0 +1,78 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import React, { useCallback } from "react"; +import { Page, PageSection } from "@patternfly/react-core/dist/js/components/Page"; +import { Text, TextContent, TextVariants } from "@patternfly/react-core/dist/js/components/Text"; +import { WorkflowListContainer } from "@kie-tools/runtime-tools-swf-webapp-components/dist/WorkflowListContainer"; +import { CloudEventPageSource } from "@kie-tools/runtime-tools-swf-webapp-components/dist/CloudEventForm"; +import { useHistory } from "react-router"; +import { WorkflowListState } from "@kie-tools/runtime-tools-swf-gateway-api/dist/types"; +import { routes } from "../../../navigation/Routes"; + +const PAGE_TITLE = "Workflow Instances"; + +export function WorkflowInstancesPage() { + const history = useHistory(); + + const initialState: WorkflowListState = history.location && (history.location.state as WorkflowListState); + + const onOpenWorkflowDetails = useCallback( + (args: { workflowId: string; state: WorkflowListState }) => { + history.push({ + pathname: routes.runtimeToolsWorkflowDetails.path({ workflowId: args.workflowId }), + state: args.state, + }); + }, + [history] + ); + + const onOpenTriggerCloudEventForWorkflow = useCallback( + (workflowId: string) => { + history.push({ + pathname: routes.runtimeToolsTriggerCloudEventForWorkflow.path({ workflowId }), + state: { + source: CloudEventPageSource.INSTANCES, + }, + }); + }, + [history] + ); + + return ( + + + + {PAGE_TITLE} + + List and view workflows from the Data Index linked in your Runtime Tools settings. + + + + + + + + + ); +} diff --git a/packages/sonataflow-management-console-webapp/src/components/styles.css b/packages/sonataflow-management-console-webapp/src/components/styles.css index 85329643754..aa2fb0be83e 100644 --- a/packages/sonataflow-management-console-webapp/src/components/styles.css +++ b/packages/sonataflow-management-console-webapp/src/components/styles.css @@ -20,3 +20,36 @@ height: 100%; position: relative; } + +.kogito--global-alert-container { + top: 30px; +} + +.kogito--alert-container { + position: fixed; + display: flex; + width: 100%; + justify-content: center; + align-items: center; + pointer-events: none; + z-index: 99999; +} + +.kogito--alert-list { + max-width: 700px; + min-width: 200px; + z-index: 999999; + position: absolute; + display: block; + left: 50%; + transform: translateX(-50%); +} + +.kogito--alert-container .pf-c-alert { + pointer-events: visible; +} + +.Dev-ui__card-size, +.Dev-ui__custom-dashboard-viewer > div { + height: 100%; +} diff --git a/packages/sonataflow-management-console-webapp/src/envelope/ServerlessWorkflowCombinedEditorEnvelopeApp.ts b/packages/sonataflow-management-console-webapp/src/envelope/ServerlessWorkflowCombinedEditorEnvelopeApp.ts new file mode 100644 index 00000000000..346a4e5c03e --- /dev/null +++ b/packages/sonataflow-management-console-webapp/src/envelope/ServerlessWorkflowCombinedEditorEnvelopeApp.ts @@ -0,0 +1,42 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import * as EditorEnvelope from "@kie-tools-core/editor/dist/envelope"; +import { NoOpKeyboardShortcutsService } from "@kie-tools-core/keyboard-shortcuts/dist/envelope"; +import { + ServerlessWorkflowCombinedEditorApi, + ServerlessWorkflowCombinedEditorChannelApi, + ServerlessWorkflowCombinedEditorEnvelopeApi, +} from "@kie-tools/serverless-workflow-combined-editor/dist/api"; +import { ServerlessWorkflowCombinedEditorFactory } from "@kie-tools/serverless-workflow-combined-editor/dist/editor"; +import { ServerlessWorkflowCombinedEditorEnvelopeApiImpl } from "@kie-tools/serverless-workflow-combined-editor/dist/envelope"; + +EditorEnvelope.initCustom< + ServerlessWorkflowCombinedEditorApi, + ServerlessWorkflowCombinedEditorEnvelopeApi, + ServerlessWorkflowCombinedEditorChannelApi +>({ + container: document.getElementById("swf-combined-editor-envelope-app")!, + bus: { postMessage: (message, targetOrigin, _) => window.parent.postMessage(message, targetOrigin!, _) }, + apiImplFactory: { + create: (args) => + new ServerlessWorkflowCombinedEditorEnvelopeApiImpl(args, new ServerlessWorkflowCombinedEditorFactory()), + }, + keyboardShortcutsService: new NoOpKeyboardShortcutsService(), +}); diff --git a/packages/sonataflow-management-console-webapp/src/envelope/ServerlessWorkflowDiagramEditorEnvelopeApp.ts b/packages/sonataflow-management-console-webapp/src/envelope/ServerlessWorkflowDiagramEditorEnvelopeApp.ts new file mode 100644 index 00000000000..94729de8599 --- /dev/null +++ b/packages/sonataflow-management-console-webapp/src/envelope/ServerlessWorkflowDiagramEditorEnvelopeApp.ts @@ -0,0 +1,45 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import * as EditorEnvelope from "@kie-tools-core/editor/dist/envelope"; +import { + ServerlessWorkflowDiagramEditorChannelApi, + ServerlessWorkflowDiagramEditorEnvelopeApi, +} from "@kie-tools/serverless-workflow-diagram-editor-envelope/dist/api"; +import { + ServerlessWorkflowDiagramEditor, + ServerlessWorkflowDiagramEditorEnvelopeApiImpl, + ServerlessWorkflowDiagramEditorFactory, +} from "@kie-tools/serverless-workflow-diagram-editor-envelope/dist/envelope"; + +EditorEnvelope.initCustom< + ServerlessWorkflowDiagramEditor, + ServerlessWorkflowDiagramEditorEnvelopeApi, + ServerlessWorkflowDiagramEditorChannelApi +>({ + container: document.getElementById("swf-diagram-editor-envelope-app")!, + bus: { postMessage: (message, targetOrigin, _) => window.parent.postMessage(message, targetOrigin!, _) }, + apiImplFactory: { + create: (args) => + new ServerlessWorkflowDiagramEditorEnvelopeApiImpl( + args, + new ServerlessWorkflowDiagramEditorFactory({ shouldLoadResourcesDynamically: true }) + ), + }, +}); diff --git a/packages/sonataflow-management-console-webapp/src/envelope/ServerlessWorkflowTextEditorEnvelopeApp.ts b/packages/sonataflow-management-console-webapp/src/envelope/ServerlessWorkflowTextEditorEnvelopeApp.ts new file mode 100644 index 00000000000..39d4415c02e --- /dev/null +++ b/packages/sonataflow-management-console-webapp/src/envelope/ServerlessWorkflowTextEditorEnvelopeApp.ts @@ -0,0 +1,39 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import * as EditorEnvelope from "@kie-tools-core/editor/dist/envelope"; +import { + ServerlessWorkflowTextEditorApi, + ServerlessWorkflowTextEditorChannelApi, + ServerlessWorkflowTextEditorEnvelopeApi, +} from "@kie-tools/serverless-workflow-text-editor/dist/api"; +import { ServerlessWorkflowTextEditorFactory } from "@kie-tools/serverless-workflow-text-editor/dist/editor"; +import { ServerlessWorkflowTextEditorEnvelopeApiImpl } from "@kie-tools/serverless-workflow-text-editor/dist/envelope"; + +EditorEnvelope.initCustom< + ServerlessWorkflowTextEditorApi, + ServerlessWorkflowTextEditorEnvelopeApi, + ServerlessWorkflowTextEditorChannelApi +>({ + container: document.getElementById("swf-text-editor-envelope-app")!, + bus: { postMessage: (message, targetOrigin, _) => window.parent.postMessage(message, targetOrigin!, _) }, + apiImplFactory: { + create: (args) => new ServerlessWorkflowTextEditorEnvelopeApiImpl(args, new ServerlessWorkflowTextEditorFactory()), + }, +}); diff --git a/packages/sonataflow-management-console-webapp/src/index.tsx b/packages/sonataflow-management-console-webapp/src/index.tsx index 8055969e432..d7a490d2eb4 100644 --- a/packages/sonataflow-management-console-webapp/src/index.tsx +++ b/packages/sonataflow-management-console-webapp/src/index.tsx @@ -46,7 +46,7 @@ const onLoadFailure = (): void => { const appRender = async (ctx: UserContext) => { const httpLink = new HttpLink({ - uri: window["DATA_INDEX_ENDPOINT"], + uri: window["SONATAFLOW_DATA_INDEX_URL"], }); const fallbackUI = onError(({ networkError }: any) => { if (networkError && networkError.stack === "TypeError: Failed to fetch") { diff --git a/packages/sonataflow-management-console-webapp/src/navigation/Routes.ts b/packages/sonataflow-management-console-webapp/src/navigation/Routes.ts new file mode 100644 index 00000000000..030b7ab5963 --- /dev/null +++ b/packages/sonataflow-management-console-webapp/src/navigation/Routes.ts @@ -0,0 +1,138 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +const IS_HASH_ROUTER = true; +const SETTINGS_ROUTE = "/settings"; + +export enum QueryParams { + SETTINGS = "settings", + URL = "url", + BRANCH = "branch", + REMOVE_REMOTE = "removeRemote", + RENAME_WORKSPACE = "renameWorkspace", + SAMPLE_ID = "sampleId", + SAMPLES_CATEGORY = "category", + FILTERS = "filters", + SORT_BY = "sortBy", +} + +export enum PathParams { + EXTENSION = "extension", + WORKSPACE_ID = "workspaceId", + FILE_RELATIVE_PATH = "fileRelativePath", + WORKFLOW_ID = "workflowId", + WORKFLOW_NAME = "workflowName", +} + +export class Route< + T extends { + pathParams?: any; + queryParams?: any; + } +> { + constructor(private readonly pathDelegate: (pathParams: { [k in T["pathParams"]]: string }) => string) {} + + public url(args: { + base?: string; + pathParams: { [k in T["pathParams"]]: string }; + queryParams?: Partial<{ [k in T["queryParams"]]: string }>; + }) { + const SEP = args.base?.endsWith("/") ? "" : "/"; + const HASH = IS_HASH_ROUTER ? "#" : ""; + const path = this.pathDelegate(args.pathParams); + const queryParams = args.queryParams ?? {}; + + if (!args.base && Object.keys(queryParams).length <= 0) { + return `${HASH}${path}`; + } + + if (!args.base) { + return `${HASH}${path}?${this.queryString(queryParams)}`; + } + + if (Object.keys(queryParams).length <= 0) { + return `${args.base}${SEP}${HASH}${path}`; + } + + return `${args.base}${SEP}${HASH}${path}?${this.queryString(queryParams)}`; + } + + public queryString(queryParams: Partial<{ [k in T["queryParams"]]: string }>) { + return decodeURIComponent(new URLSearchParams(queryParams as Record).toString()); + } + + public queryArgs(queryString: QueryParamsImpl): QueryParamsImpl { + return queryString; + } + + public path(pathParams: { [k in T["pathParams"]]: string }) { + return this.pathDelegate(pathParams); + } +} + +export interface QueryParamsImpl { + has(name: Q): boolean; + get(name: Q): string | undefined; + with(name: Q, value: string): QueryParamsImpl; + without(name: Q): QueryParamsImpl; + toString(): string; +} + +export function newQueryParamsImpl(queryString: string): QueryParamsImpl { + return { + has: (name) => new URLSearchParams(queryString).has(name), + get: (name) => { + const val = new URLSearchParams(queryString).get(name); + return !val ? undefined : decodeURIComponent(val); + }, + with: (name, value) => { + const urlSearchParams = new URLSearchParams(queryString); + urlSearchParams.set(name, value); + return newQueryParamsImpl(decodeURIComponent(urlSearchParams.toString())); + }, + without: (name) => { + const urlSearchParams = new URLSearchParams(queryString); + urlSearchParams.delete(name); + return newQueryParamsImpl(decodeURIComponent(urlSearchParams.toString())); + }, + toString: () => { + return decodeURIComponent(new URLSearchParams(queryString).toString()); + }, + }; +} + +export const routes = { + home: new Route<{}>(() => `/`), + runtimeToolsWorkflowInstances: new Route<{}>(() => `/WorkflowInstances`), + runtimeToolsWorkflowDefinitions: new Route<{}>(() => `/WorkflowDefinitions`), + runtimeToolsWorkflowDetails: new Route<{ + queryParams: QueryParams.FILTERS | QueryParams.SORT_BY; + pathParams: PathParams.WORKFLOW_ID; + }>(({ workflowId }) => `/WorkflowDetails/${workflowId}`), + runtimeToolsWorkflowForm: new Route<{ + pathParams: PathParams.WORKFLOW_NAME; + }>(({ workflowName }) => `/WorkflowDefinition/${workflowName}`), + runtimeToolsTriggerCloudEventForWorkflow: new Route<{ + pathParams: PathParams.WORKFLOW_ID; + }>(({ workflowId }) => `/WorkflowInstances/${workflowId}`), + runtimeToolsTriggerCloudEventForWorkflowDefinition: new Route<{ + pathParams: PathParams.WORKFLOW_NAME; + }>(({ workflowName }) => `/WorkflowDefinition/${workflowName}/trigger-cloud-event`), + monitoring: new Route<{}>(() => `/Monitoring`), +}; diff --git a/packages/sonataflow-management-console-webapp/webpack.config.js b/packages/sonataflow-management-console-webapp/webpack.config.js index 67356295d18..d54c626e099 100644 --- a/packages/sonataflow-management-console-webapp/webpack.config.js +++ b/packages/sonataflow-management-console-webapp/webpack.config.js @@ -19,9 +19,13 @@ const path = require("path"); const { merge } = require("webpack-merge"); -const common = require("@kie-tools-core/webpack-base/webpack.common.config"); +const NodePolyfillPlugin = require("node-polyfill-webpack-plugin"); const HtmlWebpackPlugin = require("html-webpack-plugin"); +const MonacoWebpackPlugin = require("monaco-editor-webpack-plugin"); const CopyPlugin = require("copy-webpack-plugin"); +const FileManagerPlugin = require("filemanager-webpack-plugin"); +const common = require("@kie-tools-core/webpack-base/webpack.common.config"); +const swEditorAssets = require("@kie-tools/serverless-workflow-diagram-editor-assets"); const { env: buildEnv } = require("./env"); const { defaultEnvJson } = require("./build/defaultEnvJson"); @@ -31,6 +35,9 @@ module.exports = async (env) => { return merge(common(env), { entry: { index: path.resolve(__dirname, "src", "index.tsx"), + "serverless-workflow-combined-editor-envelope": "./src/envelope/ServerlessWorkflowCombinedEditorEnvelopeApp.ts", + "serverless-workflow-diagram-editor-envelope": "./src/envelope/ServerlessWorkflowDiagramEditorEnvelopeApp.ts", + "serverless-workflow-text-editor-envelope": "./src/envelope/ServerlessWorkflowTextEditorEnvelopeApp.ts", }, devServer: { static: { @@ -65,13 +72,65 @@ module.exports = async (env) => { }), new CopyPlugin({ patterns: [ + { from: "./resources", to: "./resources" }, + { + from: "./resources/serverless-workflow-combined-editor-envelope.html", + to: "./serverless-workflow-combined-editor-envelope.html", + }, + { + from: "./resources/serverless-workflow-diagram-editor-envelope.html", + to: "./serverless-workflow-diagram-editor-envelope.html", + }, + { + from: "./resources/serverless-workflow-text-editor-envelope.html", + to: "./serverless-workflow-text-editor-envelope.html", + }, + { + from: path.join(path.dirname(require.resolve("@kie-tools/dashbuilder-client/package.json")), "/dist"), + to: "./monitoring-webapp", + }, + { + from: "./resources/monitoring-webapp", + to: "./monitoring-webapp", + }, { from: "./src/static/env.json", to: "./env.json", transform: () => JSON.stringify(defaultEnvJson, null, 2), }, + { + from: swEditorAssets.swEditorPath(), + to: "./diagram", + globOptions: { ignore: ["**/WEB-INF/**/*", "**/*.html"] }, + }, + { + context: swEditorAssets.swEditorFontsPath(), + from: "fontawesome-webfont.*", + to: "./fonts", + force: true, + }, ], }), + new FileManagerPlugin({ + events: { + onEnd: { + mkdir: ["./dist/resources/webapp/"], + copy: [ + { source: "./dist/*.js", destination: "./dist/resources/webapp/" }, + { source: "./dist/*.map", destination: "./dist/resources/webapp/" }, + { source: "./dist/fonts", destination: "./dist/resources/webapp/fonts" }, + { + source: "./dist/monitoring-webapp", + destination: "./dist/resources/webapp/monitoring-webapp", + }, + ], + }, + }, + }), + new MonacoWebpackPlugin({ + languages: ["json"], + }), + new NodePolyfillPlugin(), ], module: { rules: [ @@ -82,7 +141,7 @@ module.exports = async (env) => { { test: /\.(svg|ttf|eot|woff|woff2)$/, use: { - loader: "file-loader", + loader: require.resolve("file-loader"), options: { // Limit at 50k. larger files emited into separate files limit: 5000, @@ -96,7 +155,7 @@ module.exports = async (env) => { include: (input) => input.indexOf("background-filter.svg") > 1, use: [ { - loader: "url-loader", + loader: require.resolve("url-loader"), options: { limit: 5000, outputPath: "svgs", @@ -109,7 +168,7 @@ module.exports = async (env) => { test: /\.svg$/, include: (input) => input.indexOf(BG_IMAGES_DIRNAME) > -1, use: { - loader: "svg-url-loader", + loader: require.resolve("svg-url-loader"), options: {}, }, }, @@ -117,7 +176,7 @@ module.exports = async (env) => { test: /\.(jpg|jpeg|png|gif)$/i, use: [ { - loader: "url-loader", + loader: require.resolve("url-loader"), options: { limit: 5000, outputPath: "images", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index a6f8c3f3bfe..aa4f540c5e9 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -11226,6 +11226,18 @@ importers: packages/sonataflow-management-console-webapp: dependencies: + "@kie-tools-core/editor": + specifier: workspace:* + version: link:../editor + "@kie-tools-core/keyboard-shortcuts": + specifier: workspace:* + version: link:../keyboard-shortcuts + "@kie-tools-core/react-hooks": + specifier: workspace:* + version: link:../react-hooks + "@kie-tools/dashbuilder-client": + specifier: workspace:* + version: link:../dashbuilder-client "@kie-tools/runtime-tools-components": specifier: workspace:* version: link:../runtime-tools-components @@ -11247,6 +11259,24 @@ importers: "@kie-tools/runtime-tools-shared-webapp-components": specifier: workspace:* version: link:../runtime-tools-shared-webapp-components + "@kie-tools/runtime-tools-swf-gateway-api": + specifier: workspace:* + version: link:../runtime-tools-swf-gateway-api + "@kie-tools/runtime-tools-swf-webapp-components": + specifier: workspace:* + version: link:../runtime-tools-swf-webapp-components + "@kie-tools/serverless-workflow-combined-editor": + specifier: workspace:* + version: link:../serverless-workflow-combined-editor + "@kie-tools/serverless-workflow-diagram-editor-assets": + specifier: workspace:* + version: link:../serverless-workflow-diagram-editor-assets + "@kie-tools/serverless-workflow-diagram-editor-envelope": + specifier: workspace:* + version: link:../serverless-workflow-diagram-editor-envelope + "@kie-tools/serverless-workflow-text-editor": + specifier: workspace:* + version: link:../serverless-workflow-text-editor "@patternfly/patternfly": specifier: ^4.224.2 version: 4.224.2 @@ -11269,7 +11299,7 @@ importers: specifier: 1.5.17 version: 1.5.17(graphql@14.3.1) axios: - specifier: ^1.6.4 + specifier: ^1.6.8 version: 1.6.8 graphql: specifier: 14.3.1 @@ -11277,6 +11307,9 @@ importers: history: specifier: ^4.9.0 version: 4.10.1 + monaco-editor: + specifier: ^0.39.0 + version: 0.39.0 react: specifier: ^17.0.2 version: 17.0.2 @@ -11393,11 +11426,14 @@ importers: specifier: ^3.6.2 version: 3.6.2(enzyme@3.11.0) express: - specifier: ^4.18.2 + specifier: ^4.19.2 version: 4.19.2 file-loader: specifier: ^6.2.0 version: 6.2.0(webpack@5.88.2(@swc/core@1.3.92)(webpack-cli@4.10.0)) + filemanager-webpack-plugin: + specifier: ^7.0.0 + version: 7.0.0(webpack@5.88.2(@swc/core@1.3.92)(webpack-cli@4.10.0)) html-webpack-plugin: specifier: ^5.3.2 version: 5.5.3(webpack@5.88.2(@swc/core@1.3.92)(webpack-cli@4.10.0)) @@ -11419,6 +11455,12 @@ importers: mini-css-extract-plugin: specifier: ^2.7.6 version: 2.8.1(webpack@5.88.2(@swc/core@1.3.92)(webpack-cli@4.10.0)) + monaco-editor-webpack-plugin: + specifier: ^7.0.1 + version: 7.0.1(monaco-editor@0.39.0)(monaco-yaml@4.0.4(monaco-editor@0.39.0))(webpack@5.88.2(@swc/core@1.3.92)(webpack-cli@4.10.0)) + node-polyfill-webpack-plugin: + specifier: ^2.0.1 + version: 2.0.1(webpack@5.88.2(@swc/core@1.3.92)(webpack-cli@4.10.0)) nodemon: specifier: ^2.0.22 version: 2.0.22 @@ -11432,8 +11474,8 @@ importers: specifier: ^12.0.1 version: 12.0.1 start-server-and-test: - specifier: ^1.12.1 - version: 1.15.5 + specifier: ^2.0.3 + version: 2.0.3 stream-http: specifier: ^3.2.0 version: 3.2.0 @@ -11455,6 +11497,9 @@ importers: typescript: specifier: ^4.6.2 version: 4.8.4 + url: + specifier: ^0.11.3 + version: 0.11.3 url-loader: specifier: ^4.1.1 version: 4.1.1(file-loader@6.2.0(webpack@5.88.2(@swc/core@1.3.92)(webpack-cli@4.10.0)))(webpack@5.88.2(@swc/core@1.3.92)(webpack-cli@4.10.0)) @@ -30838,13 +30883,6 @@ packages: resolution: { integrity: sha512-Kpij9riA+UNg7TnphqjH7/CzctQ/owJGNbFkfEeve4Z4uxT5+JapVLFXcsurIfN34gnTWZNJ/f7NMG0E8JDzTw== } - start-server-and-test@1.15.5: - resolution: - { integrity: sha512-o3EmkX0++GV+qsvIJ/OKWm3w91fD8uS/bPQVPrh/7loaxkpXSuAIHdnmN/P/regQK9eNAK76aBJcHt+OSTk+nA== } - engines: { node: ">=6" } - deprecated: this package has been deprecated - hasBin: true - start-server-and-test@2.0.3: resolution: { integrity: sha512-QsVObjfjFZKJE6CS6bSKNwWZCKBG6975/jKRPPGFfFh+yOQglSeGXiNWjzgQNXdphcBI9nXbyso9tPfX4YAUhg== } @@ -32366,12 +32404,6 @@ packages: resolution: { integrity: sha512-wp+unA4CpqxvBUKHHv8D86fK4jWByHAWyhEXXVHfVUZfK+16ylpj7hjQ58Z8j9ntu8XNukRQT8Fi5qbyJ8rkyw== } - wait-on@7.0.1: - resolution: - { integrity: sha512-9AnJE9qTjRQOlTZIldAaf/da2eW0eSRSgcqq85mXQja/DW3MriHxkpODDSUEg+Gri/rKEcXUZHe+cevvYItaog== } - engines: { node: ">=12.0.0" } - hasBin: true - wait-on@7.2.0: resolution: { integrity: sha512-wCQcHkRazgjG5XoAq9jbTMLpNIjoSlZslrJ2+N9MxDsGEv1HnFoVjOCexL0ESva7Y9cu350j+DWADdk54s4AFQ== } @@ -32851,11 +32883,6 @@ packages: { integrity: sha512-5kGSQrzDyjCk0BLuFfjkoUE9vYcoyrwZIZ+GnpOSM9vhkvPjItYiWJ1jpRSo0aU4QmsoNrFwDT4O7XS2UGcBQg== } engines: { node: ">= 12" } - yaml@2.0.1: - resolution: - { integrity: sha512-1NpAYQ3wjzIlMs0mgdBmYzLkFgWBIWrzYVDYfrixhoFNNgJ444/jT2kUT2sicRbJES3oQYRZugjB6Ro8SjKeFg== } - engines: { node: ">= 14" } - yaml@2.3.2: resolution: { integrity: sha512-N/lyzTPaJasoDmfV7YTrYCI0G/3ivm/9wdG0aHuheKowWQwGTsK0Eoiw6utmzAnI6pkJa0DUVygvp3spqqEKXg== } @@ -38415,7 +38442,7 @@ snapshots: jest-resolve: 26.6.2 jest-resolve-dependencies: 26.6.3 jest-runner: 26.6.3(ts-node@10.9.1(@swc/core@1.3.92)(@types/node@20.14.2)(typescript@4.8.4)) - jest-runtime: 26.6.3 + jest-runtime: 26.6.3(ts-node@10.9.1(@swc/core@1.3.92)(@types/node@20.14.2)(typescript@4.8.4)) jest-snapshot: 26.6.2 jest-util: 26.6.2 jest-validate: 26.6.2 @@ -38452,7 +38479,7 @@ snapshots: jest-resolve: 26.6.2 jest-resolve-dependencies: 26.6.3 jest-runner: 26.6.3(ts-node@10.9.1(@types/node@20.14.2)(typescript@4.8.4)) - jest-runtime: 26.6.3 + jest-runtime: 26.6.3(ts-node@10.9.1(@types/node@20.14.2)(typescript@4.8.4)) jest-snapshot: 26.6.2 jest-util: 26.6.2 jest-validate: 26.6.2 @@ -38489,7 +38516,7 @@ snapshots: jest-resolve: 26.6.2 jest-resolve-dependencies: 26.6.3 jest-runner: 26.6.3(ts-node@10.9.1(@types/node@20.14.2)) - jest-runtime: 26.6.3 + jest-runtime: 26.6.3(ts-node@10.9.1(@types/node@20.14.2)) jest-snapshot: 26.6.2 jest-util: 26.6.2 jest-validate: 26.6.2 @@ -38596,7 +38623,7 @@ snapshots: graceful-fs: 4.2.11 jest-haste-map: 26.6.2 jest-runner: 26.6.3(ts-node@10.9.1(@swc/core@1.3.92)(@types/node@20.14.2)(typescript@4.8.4)) - jest-runtime: 26.6.3 + jest-runtime: 26.6.3(ts-node@10.9.1(@swc/core@1.3.92)(@types/node@20.14.2)(typescript@4.8.4)) transitivePeerDependencies: - bufferutil - canvas @@ -38610,7 +38637,7 @@ snapshots: graceful-fs: 4.2.11 jest-haste-map: 26.6.2 jest-runner: 26.6.3(ts-node@10.9.1(@types/node@20.14.2)(typescript@4.8.4)) - jest-runtime: 26.6.3 + jest-runtime: 26.6.3(ts-node@10.9.1(@types/node@20.14.2)(typescript@4.8.4)) transitivePeerDependencies: - bufferutil - canvas @@ -38624,7 +38651,7 @@ snapshots: graceful-fs: 4.2.11 jest-haste-map: 26.6.2 jest-runner: 26.6.3(ts-node@10.9.1(@types/node@20.14.2)) - jest-runtime: 26.6.3 + jest-runtime: 26.6.3(ts-node@10.9.1(@types/node@20.14.2)) transitivePeerDependencies: - bufferutil - canvas @@ -40437,7 +40464,7 @@ snapshots: "@severlessworkflow/sdk-typescript@3.0.3": dependencies: - ajv: 8.11.0 + ajv: 8.12.0 js-yaml: 4.1.0 "@sideway/address@4.1.4": @@ -44390,13 +44417,6 @@ snapshots: transitivePeerDependencies: - debug - axios@0.27.2(debug@4.3.4): - dependencies: - follow-redirects: 1.15.6(debug@4.3.4) - form-data: 4.0.0 - transitivePeerDependencies: - - debug - axios@1.6.8: dependencies: follow-redirects: 1.15.6 @@ -49667,7 +49687,7 @@ snapshots: jest-environment-jsdom: 26.6.2 jest-environment-node: 26.6.2 jest-get-type: 26.3.0 - jest-jasmine2: 26.6.3 + jest-jasmine2: 26.6.3(ts-node@10.9.1(@swc/core@1.3.92)(@types/node@20.14.2)(typescript@4.8.4)) jest-regex-util: 26.0.0 jest-resolve: 26.6.2 jest-util: 26.6.2 @@ -49695,7 +49715,7 @@ snapshots: jest-environment-jsdom: 26.6.2 jest-environment-node: 26.6.2 jest-get-type: 26.3.0 - jest-jasmine2: 26.6.3 + jest-jasmine2: 26.6.3(ts-node@10.9.1(@types/node@20.14.2)(typescript@4.8.4)) jest-regex-util: 26.0.0 jest-resolve: 26.6.2 jest-util: 26.6.2 @@ -49723,7 +49743,7 @@ snapshots: jest-environment-jsdom: 26.6.2 jest-environment-node: 26.6.2 jest-get-type: 26.3.0 - jest-jasmine2: 26.6.3 + jest-jasmine2: 26.6.3(ts-node@10.9.1(@types/node@20.14.2)) jest-regex-util: 26.0.0 jest-resolve: 26.6.2 jest-util: 26.6.2 @@ -49867,6 +49887,87 @@ snapshots: transitivePeerDependencies: - supports-color + jest-jasmine2@26.6.3(ts-node@10.9.1(@swc/core@1.3.92)(@types/node@20.14.2)(typescript@4.8.4)): + dependencies: + "@babel/traverse": 7.23.9 + "@jest/environment": 26.6.2 + "@jest/source-map": 26.6.2 + "@jest/test-result": 26.6.2 + "@jest/types": 26.6.2 + "@types/node": 20.14.2 + chalk: 4.1.2 + co: 4.6.0 + expect: 26.6.2 + is-generator-fn: 2.1.0 + jest-each: 26.6.2 + jest-matcher-utils: 26.6.2 + jest-message-util: 26.6.2 + jest-runtime: 26.6.3(ts-node@10.9.1(@swc/core@1.3.92)(@types/node@20.14.2)(typescript@4.8.4)) + jest-snapshot: 26.6.2 + jest-util: 26.6.2 + pretty-format: 26.6.2 + throat: 5.0.0 + transitivePeerDependencies: + - bufferutil + - canvas + - supports-color + - ts-node + - utf-8-validate + + jest-jasmine2@26.6.3(ts-node@10.9.1(@types/node@20.14.2)(typescript@4.8.4)): + dependencies: + "@babel/traverse": 7.23.9 + "@jest/environment": 26.6.2 + "@jest/source-map": 26.6.2 + "@jest/test-result": 26.6.2 + "@jest/types": 26.6.2 + "@types/node": 20.14.2 + chalk: 4.1.2 + co: 4.6.0 + expect: 26.6.2 + is-generator-fn: 2.1.0 + jest-each: 26.6.2 + jest-matcher-utils: 26.6.2 + jest-message-util: 26.6.2 + jest-runtime: 26.6.3(ts-node@10.9.1(@types/node@20.14.2)(typescript@4.8.4)) + jest-snapshot: 26.6.2 + jest-util: 26.6.2 + pretty-format: 26.6.2 + throat: 5.0.0 + transitivePeerDependencies: + - bufferutil + - canvas + - supports-color + - ts-node + - utf-8-validate + + jest-jasmine2@26.6.3(ts-node@10.9.1(@types/node@20.14.2)): + dependencies: + "@babel/traverse": 7.23.9 + "@jest/environment": 26.6.2 + "@jest/source-map": 26.6.2 + "@jest/test-result": 26.6.2 + "@jest/types": 26.6.2 + "@types/node": 20.14.2 + chalk: 4.1.2 + co: 4.6.0 + expect: 26.6.2 + is-generator-fn: 2.1.0 + jest-each: 26.6.2 + jest-matcher-utils: 26.6.2 + jest-message-util: 26.6.2 + jest-runtime: 26.6.3(ts-node@10.9.1(@types/node@20.14.2)) + jest-snapshot: 26.6.2 + jest-util: 26.6.2 + pretty-format: 26.6.2 + throat: 5.0.0 + transitivePeerDependencies: + - bufferutil + - canvas + - supports-color + - ts-node + - utf-8-validate + jest-junit@14.0.0: dependencies: mkdirp: 1.0.4 @@ -49980,7 +50081,7 @@ snapshots: jest-leak-detector: 26.6.2 jest-message-util: 26.6.2 jest-resolve: 26.6.2 - jest-runtime: 26.6.3 + jest-runtime: 26.6.3(ts-node@10.9.1(@swc/core@1.3.92)(@types/node@20.14.2)(typescript@4.8.4)) jest-util: 26.6.2 jest-worker: 26.6.2 source-map-support: 0.5.21 @@ -50009,7 +50110,7 @@ snapshots: jest-leak-detector: 26.6.2 jest-message-util: 26.6.2 jest-resolve: 26.6.2 - jest-runtime: 26.6.3 + jest-runtime: 26.6.3(ts-node@10.9.1(@types/node@20.14.2)(typescript@4.8.4)) jest-util: 26.6.2 jest-worker: 26.6.2 source-map-support: 0.5.21 @@ -50038,7 +50139,7 @@ snapshots: jest-leak-detector: 26.6.2 jest-message-util: 26.6.2 jest-resolve: 26.6.2 - jest-runtime: 26.6.3 + jest-runtime: 26.6.3(ts-node@10.9.1(@types/node@20.14.2)) jest-util: 26.6.2 jest-worker: 26.6.2 source-map-support: 0.5.21 @@ -50082,6 +50183,114 @@ snapshots: transitivePeerDependencies: - supports-color + jest-runtime@26.6.3(ts-node@10.9.1(@swc/core@1.3.92)(@types/node@20.14.2)(typescript@4.8.4)): + dependencies: + "@jest/console": 26.6.2 + "@jest/environment": 26.6.2 + "@jest/fake-timers": 26.6.2 + "@jest/globals": 26.6.2 + "@jest/source-map": 26.6.2 + "@jest/test-result": 26.6.2 + "@jest/transform": 26.6.2 + "@jest/types": 26.6.2 + "@types/yargs": 15.0.4 + chalk: 4.1.2 + cjs-module-lexer: 0.6.0 + collect-v8-coverage: 1.0.1 + exit: 0.1.2 + glob: 7.2.3 + graceful-fs: 4.2.11 + jest-config: 26.6.3(ts-node@10.9.1(@swc/core@1.3.92)(@types/node@20.14.2)(typescript@4.8.4)) + jest-haste-map: 26.6.2 + jest-message-util: 26.6.2 + jest-mock: 26.6.2 + jest-regex-util: 26.0.0 + jest-resolve: 26.6.2 + jest-snapshot: 26.6.2 + jest-util: 26.6.2 + jest-validate: 26.6.2 + slash: 3.0.0 + strip-bom: 4.0.0 + yargs: 15.4.1 + transitivePeerDependencies: + - bufferutil + - canvas + - supports-color + - ts-node + - utf-8-validate + + jest-runtime@26.6.3(ts-node@10.9.1(@types/node@20.14.2)(typescript@4.8.4)): + dependencies: + "@jest/console": 26.6.2 + "@jest/environment": 26.6.2 + "@jest/fake-timers": 26.6.2 + "@jest/globals": 26.6.2 + "@jest/source-map": 26.6.2 + "@jest/test-result": 26.6.2 + "@jest/transform": 26.6.2 + "@jest/types": 26.6.2 + "@types/yargs": 15.0.4 + chalk: 4.1.2 + cjs-module-lexer: 0.6.0 + collect-v8-coverage: 1.0.1 + exit: 0.1.2 + glob: 7.2.3 + graceful-fs: 4.2.11 + jest-config: 26.6.3(ts-node@10.9.1(@types/node@20.14.2)(typescript@4.8.4)) + jest-haste-map: 26.6.2 + jest-message-util: 26.6.2 + jest-mock: 26.6.2 + jest-regex-util: 26.0.0 + jest-resolve: 26.6.2 + jest-snapshot: 26.6.2 + jest-util: 26.6.2 + jest-validate: 26.6.2 + slash: 3.0.0 + strip-bom: 4.0.0 + yargs: 15.4.1 + transitivePeerDependencies: + - bufferutil + - canvas + - supports-color + - ts-node + - utf-8-validate + + jest-runtime@26.6.3(ts-node@10.9.1(@types/node@20.14.2)): + dependencies: + "@jest/console": 26.6.2 + "@jest/environment": 26.6.2 + "@jest/fake-timers": 26.6.2 + "@jest/globals": 26.6.2 + "@jest/source-map": 26.6.2 + "@jest/test-result": 26.6.2 + "@jest/transform": 26.6.2 + "@jest/types": 26.6.2 + "@types/yargs": 15.0.4 + chalk: 4.1.2 + cjs-module-lexer: 0.6.0 + collect-v8-coverage: 1.0.1 + exit: 0.1.2 + glob: 7.2.3 + graceful-fs: 4.2.11 + jest-config: 26.6.3(ts-node@10.9.1(@types/node@20.14.2)) + jest-haste-map: 26.6.2 + jest-message-util: 26.6.2 + jest-mock: 26.6.2 + jest-regex-util: 26.0.0 + jest-resolve: 26.6.2 + jest-snapshot: 26.6.2 + jest-util: 26.6.2 + jest-validate: 26.6.2 + slash: 3.0.0 + strip-bom: 4.0.0 + yargs: 15.4.1 + transitivePeerDependencies: + - bufferutil + - canvas + - supports-color + - ts-node + - utf-8-validate + jest-serializer@25.5.0: dependencies: graceful-fs: 4.2.11 @@ -51383,14 +51592,14 @@ snapshots: monaco-editor-webpack-plugin@7.0.1(monaco-editor@0.39.0)(monaco-yaml@4.0.4(monaco-editor@0.39.0))(webpack@5.88.2(@swc/core@1.3.92)(webpack-cli@4.10.0)): dependencies: - loader-utils: 2.0.2 + loader-utils: 2.0.4 monaco-editor: 0.39.0 monaco-yaml: 4.0.4(monaco-editor@0.39.0) webpack: 5.88.2(@swc/core@1.3.92)(webpack-cli@4.10.0) monaco-editor-webpack-plugin@7.0.1(monaco-editor@0.39.0)(monaco-yaml@4.0.4(monaco-editor@0.39.0))(webpack@5.88.2(webpack-cli@4.10.0)): dependencies: - loader-utils: 2.0.2 + loader-utils: 2.0.4 monaco-editor: 0.39.0 monaco-yaml: 4.0.4(monaco-editor@0.39.0) webpack: 5.88.2(webpack-cli@4.10.0) @@ -51427,7 +51636,7 @@ snapshots: vscode-languageserver-textdocument: 1.0.7 vscode-languageserver-types: 3.17.2 vscode-uri: 3.0.7 - yaml: 2.0.1 + yaml: 2.3.2 mongo-object@0.1.4: {} @@ -54512,7 +54721,7 @@ snapshots: "@sinonjs/commons": 1.8.3 "@sinonjs/fake-timers": 7.1.2 "@sinonjs/samsam": 6.0.2 - diff: 5.0.0 + diff: 5.1.0 nise: 5.1.0 supports-color: 7.2.0 @@ -54768,19 +54977,6 @@ snapshots: as-table: 1.0.55 get-source: 2.0.12 - start-server-and-test@1.15.5: - dependencies: - arg: 5.0.2 - bluebird: 3.7.2 - check-more-types: 2.24.0 - debug: 4.3.4 - execa: 5.1.1 - lazy-ass: 1.6.0 - ps-tree: 1.2.0 - wait-on: 7.0.1(debug@4.3.4) - transitivePeerDependencies: - - supports-color - start-server-and-test@2.0.3: dependencies: arg: 5.0.2 @@ -56447,16 +56643,6 @@ snapshots: waait@1.0.5: {} - wait-on@7.0.1(debug@4.3.4): - dependencies: - axios: 0.27.2(debug@4.3.4) - joi: 17.12.0 - lodash: 4.17.21 - minimist: 1.2.8 - rxjs: 7.8.1 - transitivePeerDependencies: - - debug - wait-on@7.2.0: dependencies: axios: 1.6.8 @@ -57236,8 +57422,6 @@ snapshots: yaml@2.0.0-11: {} - yaml@2.0.1: {} - yaml@2.3.2: {} yargs-parser@18.1.3: diff --git a/repo/graph.dot b/repo/graph.dot index e805457f24a..b46dc0cc03d 100644 --- a/repo/graph.dot +++ b/repo/graph.dot @@ -539,8 +539,10 @@ digraph G { "@kie-tools/sonataflow-devmode-image" -> "@kie-tools/sonataflow-quarkus-devui" [ style = "dashed", color = "black" ]; "@kie-tools/sonataflow-image-common" -> "@kie-tools/python-venv" [ style = "dashed", color = "black" ]; "@kie-tools/sonataflow-image-common" -> "@kie-tools/root-env" [ style = "dashed", color = "black" ]; + "@kie-tools/sonataflow-management-console-webapp" -> "@kie-tools-core/react-hooks" [ style = "solid", color = "blue" ]; "@kie-tools/sonataflow-management-console-webapp" -> "@kie-tools/runtime-tools-process-webapp-components" [ style = "solid", color = "blue" ]; "@kie-tools/sonataflow-management-console-webapp" -> "@kie-tools/runtime-tools-shared-webapp-components" [ style = "solid", color = "blue" ]; + "@kie-tools/sonataflow-management-console-webapp" -> "@kie-tools/runtime-tools-swf-webapp-components" [ style = "solid", color = "blue" ]; "@kie-tools/sonataflow-operator" -> "@kie-tools/sonataflow-builder-image" [ style = "dashed", color = "black" ]; "@kie-tools/sonataflow-operator" -> "@kie-tools/sonataflow-devmode-image" [ style = "dashed", color = "black" ]; "@kie-tools/sonataflow-quarkus-devui" -> "@kie-tools/serverless-workflow-dev-ui-webapp" [ style = "dashed", color = "black" ]; diff --git a/repo/graph.json b/repo/graph.json index ac86c5c476f..0517d76faa3 100644 --- a/repo/graph.json +++ b/repo/graph.json @@ -1171,6 +1171,11 @@ "weight": 1 }, { "source": "swf-vscode-extension", "target": "@kie-tools/vscode-extension-common-test-helpers", "weight": 1 }, + { + "source": "@kie-tools/sonataflow-management-console-webapp", + "target": "@kie-tools-core/react-hooks", + "weight": 1 + }, { "source": "@kie-tools/sonataflow-management-console-webapp", "target": "@kie-tools/runtime-tools-process-webapp-components", @@ -1181,6 +1186,11 @@ "target": "@kie-tools/runtime-tools-shared-webapp-components", "weight": 1 }, + { + "source": "@kie-tools/sonataflow-management-console-webapp", + "target": "@kie-tools/runtime-tools-swf-webapp-components", + "weight": 1 + }, { "source": "vscode-extension-dashbuilder-editor", "target": "@kie-tools-core/vscode-extension", "weight": 1 }, { "source": "vscode-extension-dashbuilder-editor",