Merge branch 'main' into update-workflow-json
This commit is contained in:
commit
3c04dd8325
|
@ -806,18 +806,12 @@ def process_instance_list(
|
|||
ProcessInstanceModel.start_in_seconds.desc(), ProcessInstanceModel.id.desc() # type: ignore
|
||||
).paginate(page=page, per_page=per_page, error_out=False)
|
||||
|
||||
# TODO need to look into test failures when the results from result_dict is
|
||||
# used instead of the process instances
|
||||
|
||||
# substitution_variables = request.args.to_dict()
|
||||
# result_dict = process_instance_report.generate_report(
|
||||
# process_instances.items, substitution_variables
|
||||
# )
|
||||
|
||||
# results = result_dict["results"]
|
||||
# report_metadata = result_dict["report_metadata"]
|
||||
|
||||
results = process_instances.items
|
||||
results = list(
|
||||
map(
|
||||
ProcessInstanceService.serialize_flat_with_task_data,
|
||||
process_instances.items,
|
||||
)
|
||||
)
|
||||
report_metadata = process_instance_report.report_metadata
|
||||
|
||||
response_json = {
|
||||
|
|
|
@ -315,3 +315,22 @@ class ProcessInstanceService:
|
|||
)
|
||||
|
||||
return task
|
||||
|
||||
@staticmethod
|
||||
def serialize_flat_with_task_data(
|
||||
process_instance: ProcessInstanceModel,
|
||||
) -> dict[str, Any]:
|
||||
"""serialize_flat_with_task_data."""
|
||||
results = {}
|
||||
try:
|
||||
original_status = process_instance.status
|
||||
processor = ProcessInstanceProcessor(process_instance)
|
||||
process_instance.data = processor.get_current_data()
|
||||
results = process_instance.serialized_flat
|
||||
# this process seems to mutate the status of the process_instance which
|
||||
# can result in different results than expected from process_instance_list,
|
||||
# so set the status back to the expected value
|
||||
results["status"] = original_status
|
||||
except ApiError:
|
||||
results = process_instance.serialized
|
||||
return results
|
||||
|
|
|
@ -24,7 +24,6 @@
|
|||
"@rjsf/mui": "^5.0.0-beta.13",
|
||||
"@rjsf/utils": "^5.0.0-beta.13",
|
||||
"@rjsf/validator-ajv6": "^5.0.0-beta.13",
|
||||
"@rjsf/validator-ajv8": "^5.0.0-beta.13",
|
||||
"@tanstack/react-table": "^8.2.2",
|
||||
"@testing-library/jest-dom": "^5.16.4",
|
||||
"@testing-library/react": "^13.3.0",
|
||||
|
@ -4950,23 +4949,6 @@
|
|||
"@rjsf/utils": "^5.0.0-beta.1"
|
||||
}
|
||||
},
|
||||
"node_modules/@rjsf/validator-ajv8": {
|
||||
"version": "5.0.0-beta.13",
|
||||
"resolved": "https://registry.npmjs.org/@rjsf/validator-ajv8/-/validator-ajv8-5.0.0-beta.13.tgz",
|
||||
"integrity": "sha512-/hrYbiwgCvEqw1Z7YZTWvd+ZAiX5vSN0WAI2hJTJTqKuCTcIH0fqNDCaOg3FBR38BL7seZrUmibIUcPU66iJ1w==",
|
||||
"dependencies": {
|
||||
"ajv-formats": "^2.1.1",
|
||||
"ajv8": "npm:ajv@^8.11.0",
|
||||
"lodash": "^4.17.15",
|
||||
"lodash-es": "^4.17.15"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=14"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@rjsf/utils": "^5.0.0-beta.12"
|
||||
}
|
||||
},
|
||||
"node_modules/@rollup/plugin-babel": {
|
||||
"version": "5.3.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/plugin-babel/-/plugin-babel-5.3.1.tgz",
|
||||
|
@ -6840,27 +6822,6 @@
|
|||
"ajv": "^6.9.1"
|
||||
}
|
||||
},
|
||||
"node_modules/ajv8": {
|
||||
"name": "ajv",
|
||||
"version": "8.11.2",
|
||||
"resolved": "https://registry.npmjs.org/ajv/-/ajv-8.11.2.tgz",
|
||||
"integrity": "sha512-E4bfmKAhGiSTvMfL1Myyycaub+cUEU2/IvpylXkUu7CHBkBj1f/ikdzbD7YQ6FKUbixDxeYvB/xY4fvyroDlQg==",
|
||||
"dependencies": {
|
||||
"fast-deep-equal": "^3.1.1",
|
||||
"json-schema-traverse": "^1.0.0",
|
||||
"require-from-string": "^2.0.2",
|
||||
"uri-js": "^4.2.2"
|
||||
},
|
||||
"funding": {
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/epoberezkin"
|
||||
}
|
||||
},
|
||||
"node_modules/ajv8/node_modules/json-schema-traverse": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz",
|
||||
"integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug=="
|
||||
},
|
||||
"node_modules/ansi-align": {
|
||||
"version": "3.0.1",
|
||||
"resolved": "https://registry.npmjs.org/ansi-align/-/ansi-align-3.0.1.tgz",
|
||||
|
@ -19562,9 +19523,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/loader-utils": {
|
||||
"version": "2.0.2",
|
||||
"resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.2.tgz",
|
||||
"integrity": "sha512-TM57VeHptv569d/GKh6TAYdzKblwDNiumOdkFnejjD0XwTH87K90w3O7AiJRqdQoXygvi1VQTJTLGhJl7WqA7A==",
|
||||
"version": "2.0.4",
|
||||
"resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.4.tgz",
|
||||
"integrity": "sha512-xXqpXoINfFhgua9xiqD8fPFHgkoq1mmmpE92WlDbm9rNRd/EbRb+Gqf908T2DMfuHjjJlksiK2RbHVOdD/MqSw==",
|
||||
"dependencies": {
|
||||
"big.js": "^5.2.2",
|
||||
"emojis-list": "^3.0.0",
|
||||
|
@ -23934,9 +23895,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/react-dev-utils/node_modules/loader-utils": {
|
||||
"version": "3.2.0",
|
||||
"resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-3.2.0.tgz",
|
||||
"integrity": "sha512-HVl9ZqccQihZ7JM85dco1MvO9G+ONvxoGa9rkhzFsneGLKSUg1gJf9bWzhRhcvm2qChhWpebQhP44qxjKIUCaQ==",
|
||||
"version": "3.2.1",
|
||||
"resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-3.2.1.tgz",
|
||||
"integrity": "sha512-ZvFw1KWS3GVyYBYb7qkmRM/WwL2TQQBxgCK62rlvm4WpVQ23Nb4tYjApUlfjrEGvOs7KHEsmyUn75OHZrJMWPw==",
|
||||
"engines": {
|
||||
"node": ">= 12.13.0"
|
||||
}
|
||||
|
@ -25031,25 +24992,14 @@
|
|||
}
|
||||
},
|
||||
"node_modules/recursive-readdir": {
|
||||
"version": "2.2.2",
|
||||
"resolved": "https://registry.npmjs.org/recursive-readdir/-/recursive-readdir-2.2.2.tgz",
|
||||
"integrity": "sha512-nRCcW9Sj7NuZwa2XvH9co8NPeXUBhZP7CRKJtU+cS6PW9FpCIFoI5ib0NT1ZrbNuPoRy0ylyCaUL8Gih4LSyFg==",
|
||||
"version": "2.2.3",
|
||||
"resolved": "https://registry.npmjs.org/recursive-readdir/-/recursive-readdir-2.2.3.tgz",
|
||||
"integrity": "sha512-8HrF5ZsXk5FAH9dgsx3BlUer73nIhuj+9OrQwEbLTPOBzGkL1lsFCR01am+v+0m2Cmbs1nP12hLDl5FA7EszKA==",
|
||||
"dependencies": {
|
||||
"minimatch": "3.0.4"
|
||||
"minimatch": "^3.0.5"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/recursive-readdir/node_modules/minimatch": {
|
||||
"version": "3.0.4",
|
||||
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
|
||||
"integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==",
|
||||
"dependencies": {
|
||||
"brace-expansion": "^1.1.7"
|
||||
},
|
||||
"engines": {
|
||||
"node": "*"
|
||||
"node": ">=6.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/redent": {
|
||||
|
@ -26103,9 +26053,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/serve": {
|
||||
"version": "14.0.1",
|
||||
"resolved": "https://registry.npmjs.org/serve/-/serve-14.0.1.tgz",
|
||||
"integrity": "sha512-tNGwxl27FwA8TbmMQqN0jTaSx8/trL532qZsJHX1VdiEIjjtMJHCs7AFS6OvtC7cTHOvmjXqt5yczejU6CV2Xg==",
|
||||
"version": "14.1.1",
|
||||
"resolved": "https://registry.npmjs.org/serve/-/serve-14.1.1.tgz",
|
||||
"integrity": "sha512-7RhRDEirZ7Qyee4QWhBHO9qRtjIGsIPGecDDPzNzlOsjDiZWcq36GS8FioVJAuJPVJBBDTsGp33WWOO4B9A82g==",
|
||||
"dependencies": {
|
||||
"@zeit/schemas": "2.21.0",
|
||||
"ajv": "8.11.0",
|
||||
|
@ -26116,7 +26066,7 @@
|
|||
"clipboardy": "3.0.0",
|
||||
"compression": "1.7.4",
|
||||
"is-port-reachable": "4.0.0",
|
||||
"serve-handler": "6.1.3",
|
||||
"serve-handler": "6.1.5",
|
||||
"update-check": "1.5.4"
|
||||
},
|
||||
"bin": {
|
||||
|
@ -26127,15 +26077,15 @@
|
|||
}
|
||||
},
|
||||
"node_modules/serve-handler": {
|
||||
"version": "6.1.3",
|
||||
"resolved": "https://registry.npmjs.org/serve-handler/-/serve-handler-6.1.3.tgz",
|
||||
"integrity": "sha512-FosMqFBNrLyeiIDvP1zgO6YoTzFYHxLDEIavhlmQ+knB2Z7l1t+kGLHkZIDN7UVWqQAmKI3D20A6F6jo3nDd4w==",
|
||||
"version": "6.1.5",
|
||||
"resolved": "https://registry.npmjs.org/serve-handler/-/serve-handler-6.1.5.tgz",
|
||||
"integrity": "sha512-ijPFle6Hwe8zfmBxJdE+5fta53fdIY0lHISJvuikXB3VYFafRjMRpOffSPvCYsbKyBA7pvy9oYr/BT1O3EArlg==",
|
||||
"dependencies": {
|
||||
"bytes": "3.0.0",
|
||||
"content-disposition": "0.5.2",
|
||||
"fast-url-parser": "1.1.3",
|
||||
"mime-types": "2.1.18",
|
||||
"minimatch": "3.0.4",
|
||||
"minimatch": "3.1.2",
|
||||
"path-is-inside": "1.0.2",
|
||||
"path-to-regexp": "2.2.1",
|
||||
"range-parser": "1.2.0"
|
||||
|
@ -26160,17 +26110,6 @@
|
|||
"node": ">= 0.6"
|
||||
}
|
||||
},
|
||||
"node_modules/serve-handler/node_modules/minimatch": {
|
||||
"version": "3.0.4",
|
||||
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
|
||||
"integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==",
|
||||
"dependencies": {
|
||||
"brace-expansion": "^1.1.7"
|
||||
},
|
||||
"engines": {
|
||||
"node": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/serve-index": {
|
||||
"version": "1.9.1",
|
||||
"resolved": "https://registry.npmjs.org/serve-index/-/serve-index-1.9.1.tgz",
|
||||
|
@ -30730,9 +30669,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/webpack/node_modules/loader-utils": {
|
||||
"version": "1.4.0",
|
||||
"resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.4.0.tgz",
|
||||
"integrity": "sha512-qH0WSMBtn/oHuwjy/NucEgbx5dbxxnxup9s4PVXJUDHZBQY+s0NWA9rJf53RBnQZxfch7euUui7hpoAPvALZdA==",
|
||||
"version": "1.4.2",
|
||||
"resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.4.2.tgz",
|
||||
"integrity": "sha512-I5d00Pd/jwMD2QCduo657+YM/6L3KZu++pmX9VFncxaxvHcru9jx1lBaFft+r4Mt2jK0Yhp41XlRAihzPxHNCg==",
|
||||
"dependencies": {
|
||||
"big.js": "^5.2.2",
|
||||
"emojis-list": "^3.0.0",
|
||||
|
@ -34883,17 +34822,6 @@
|
|||
"lodash-es": "^4.17.15"
|
||||
}
|
||||
},
|
||||
"@rjsf/validator-ajv8": {
|
||||
"version": "5.0.0-beta.13",
|
||||
"resolved": "https://registry.npmjs.org/@rjsf/validator-ajv8/-/validator-ajv8-5.0.0-beta.13.tgz",
|
||||
"integrity": "sha512-/hrYbiwgCvEqw1Z7YZTWvd+ZAiX5vSN0WAI2hJTJTqKuCTcIH0fqNDCaOg3FBR38BL7seZrUmibIUcPU66iJ1w==",
|
||||
"requires": {
|
||||
"ajv-formats": "^2.1.1",
|
||||
"ajv8": "npm:ajv@^8.11.0",
|
||||
"lodash": "^4.17.15",
|
||||
"lodash-es": "^4.17.15"
|
||||
}
|
||||
},
|
||||
"@rollup/plugin-babel": {
|
||||
"version": "5.3.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/plugin-babel/-/plugin-babel-5.3.1.tgz",
|
||||
|
@ -36367,24 +36295,6 @@
|
|||
"integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==",
|
||||
"requires": {}
|
||||
},
|
||||
"ajv8": {
|
||||
"version": "npm:ajv@8.11.2",
|
||||
"resolved": "https://registry.npmjs.org/ajv/-/ajv-8.11.2.tgz",
|
||||
"integrity": "sha512-E4bfmKAhGiSTvMfL1Myyycaub+cUEU2/IvpylXkUu7CHBkBj1f/ikdzbD7YQ6FKUbixDxeYvB/xY4fvyroDlQg==",
|
||||
"requires": {
|
||||
"fast-deep-equal": "^3.1.1",
|
||||
"json-schema-traverse": "^1.0.0",
|
||||
"require-from-string": "^2.0.2",
|
||||
"uri-js": "^4.2.2"
|
||||
},
|
||||
"dependencies": {
|
||||
"json-schema-traverse": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz",
|
||||
"integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug=="
|
||||
}
|
||||
}
|
||||
},
|
||||
"ansi-align": {
|
||||
"version": "3.0.1",
|
||||
"resolved": "https://registry.npmjs.org/ansi-align/-/ansi-align-3.0.1.tgz",
|
||||
|
@ -45991,9 +45901,9 @@
|
|||
"integrity": "sha512-Jsmr89RcXGIwivFY21FcRrisYZfvLMTWx5kOLc+JTxtpBOG6xML0vzbc6SEQG2FO9/4Fc3wW4LVcB5DmGflaRw=="
|
||||
},
|
||||
"loader-utils": {
|
||||
"version": "2.0.2",
|
||||
"resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.2.tgz",
|
||||
"integrity": "sha512-TM57VeHptv569d/GKh6TAYdzKblwDNiumOdkFnejjD0XwTH87K90w3O7AiJRqdQoXygvi1VQTJTLGhJl7WqA7A==",
|
||||
"version": "2.0.4",
|
||||
"resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.4.tgz",
|
||||
"integrity": "sha512-xXqpXoINfFhgua9xiqD8fPFHgkoq1mmmpE92WlDbm9rNRd/EbRb+Gqf908T2DMfuHjjJlksiK2RbHVOdD/MqSw==",
|
||||
"requires": {
|
||||
"big.js": "^5.2.2",
|
||||
"emojis-list": "^3.0.0",
|
||||
|
@ -48988,9 +48898,9 @@
|
|||
"integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ=="
|
||||
},
|
||||
"loader-utils": {
|
||||
"version": "3.2.0",
|
||||
"resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-3.2.0.tgz",
|
||||
"integrity": "sha512-HVl9ZqccQihZ7JM85dco1MvO9G+ONvxoGa9rkhzFsneGLKSUg1gJf9bWzhRhcvm2qChhWpebQhP44qxjKIUCaQ=="
|
||||
"version": "3.2.1",
|
||||
"resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-3.2.1.tgz",
|
||||
"integrity": "sha512-ZvFw1KWS3GVyYBYb7qkmRM/WwL2TQQBxgCK62rlvm4WpVQ23Nb4tYjApUlfjrEGvOs7KHEsmyUn75OHZrJMWPw=="
|
||||
},
|
||||
"supports-color": {
|
||||
"version": "7.2.0",
|
||||
|
@ -49765,21 +49675,11 @@
|
|||
}
|
||||
},
|
||||
"recursive-readdir": {
|
||||
"version": "2.2.2",
|
||||
"resolved": "https://registry.npmjs.org/recursive-readdir/-/recursive-readdir-2.2.2.tgz",
|
||||
"integrity": "sha512-nRCcW9Sj7NuZwa2XvH9co8NPeXUBhZP7CRKJtU+cS6PW9FpCIFoI5ib0NT1ZrbNuPoRy0ylyCaUL8Gih4LSyFg==",
|
||||
"version": "2.2.3",
|
||||
"resolved": "https://registry.npmjs.org/recursive-readdir/-/recursive-readdir-2.2.3.tgz",
|
||||
"integrity": "sha512-8HrF5ZsXk5FAH9dgsx3BlUer73nIhuj+9OrQwEbLTPOBzGkL1lsFCR01am+v+0m2Cmbs1nP12hLDl5FA7EszKA==",
|
||||
"requires": {
|
||||
"minimatch": "3.0.4"
|
||||
},
|
||||
"dependencies": {
|
||||
"minimatch": {
|
||||
"version": "3.0.4",
|
||||
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
|
||||
"integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==",
|
||||
"requires": {
|
||||
"brace-expansion": "^1.1.7"
|
||||
}
|
||||
}
|
||||
"minimatch": "^3.0.5"
|
||||
}
|
||||
},
|
||||
"redent": {
|
||||
|
@ -50593,9 +50493,9 @@
|
|||
}
|
||||
},
|
||||
"serve": {
|
||||
"version": "14.0.1",
|
||||
"resolved": "https://registry.npmjs.org/serve/-/serve-14.0.1.tgz",
|
||||
"integrity": "sha512-tNGwxl27FwA8TbmMQqN0jTaSx8/trL532qZsJHX1VdiEIjjtMJHCs7AFS6OvtC7cTHOvmjXqt5yczejU6CV2Xg==",
|
||||
"version": "14.1.1",
|
||||
"resolved": "https://registry.npmjs.org/serve/-/serve-14.1.1.tgz",
|
||||
"integrity": "sha512-7RhRDEirZ7Qyee4QWhBHO9qRtjIGsIPGecDDPzNzlOsjDiZWcq36GS8FioVJAuJPVJBBDTsGp33WWOO4B9A82g==",
|
||||
"requires": {
|
||||
"@zeit/schemas": "2.21.0",
|
||||
"ajv": "8.11.0",
|
||||
|
@ -50606,7 +50506,7 @@
|
|||
"clipboardy": "3.0.0",
|
||||
"compression": "1.7.4",
|
||||
"is-port-reachable": "4.0.0",
|
||||
"serve-handler": "6.1.3",
|
||||
"serve-handler": "6.1.5",
|
||||
"update-check": "1.5.4"
|
||||
},
|
||||
"dependencies": {
|
||||
|
@ -50634,15 +50534,15 @@
|
|||
}
|
||||
},
|
||||
"serve-handler": {
|
||||
"version": "6.1.3",
|
||||
"resolved": "https://registry.npmjs.org/serve-handler/-/serve-handler-6.1.3.tgz",
|
||||
"integrity": "sha512-FosMqFBNrLyeiIDvP1zgO6YoTzFYHxLDEIavhlmQ+knB2Z7l1t+kGLHkZIDN7UVWqQAmKI3D20A6F6jo3nDd4w==",
|
||||
"version": "6.1.5",
|
||||
"resolved": "https://registry.npmjs.org/serve-handler/-/serve-handler-6.1.5.tgz",
|
||||
"integrity": "sha512-ijPFle6Hwe8zfmBxJdE+5fta53fdIY0lHISJvuikXB3VYFafRjMRpOffSPvCYsbKyBA7pvy9oYr/BT1O3EArlg==",
|
||||
"requires": {
|
||||
"bytes": "3.0.0",
|
||||
"content-disposition": "0.5.2",
|
||||
"fast-url-parser": "1.1.3",
|
||||
"mime-types": "2.1.18",
|
||||
"minimatch": "3.0.4",
|
||||
"minimatch": "3.1.2",
|
||||
"path-is-inside": "1.0.2",
|
||||
"path-to-regexp": "2.2.1",
|
||||
"range-parser": "1.2.0"
|
||||
|
@ -50660,14 +50560,6 @@
|
|||
"requires": {
|
||||
"mime-db": "~1.33.0"
|
||||
}
|
||||
},
|
||||
"minimatch": {
|
||||
"version": "3.0.4",
|
||||
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
|
||||
"integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==",
|
||||
"requires": {
|
||||
"brace-expansion": "^1.1.7"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -54022,9 +53914,9 @@
|
|||
}
|
||||
},
|
||||
"loader-utils": {
|
||||
"version": "1.4.0",
|
||||
"resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.4.0.tgz",
|
||||
"integrity": "sha512-qH0WSMBtn/oHuwjy/NucEgbx5dbxxnxup9s4PVXJUDHZBQY+s0NWA9rJf53RBnQZxfch7euUui7hpoAPvALZdA==",
|
||||
"version": "1.4.2",
|
||||
"resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.4.2.tgz",
|
||||
"integrity": "sha512-I5d00Pd/jwMD2QCduo657+YM/6L3KZu++pmX9VFncxaxvHcru9jx1lBaFft+r4Mt2jK0Yhp41XlRAihzPxHNCg==",
|
||||
"requires": {
|
||||
"big.js": "^5.2.2",
|
||||
"emojis-list": "^3.0.0",
|
||||
|
|
|
@ -17,9 +17,13 @@ import {
|
|||
import { Logout, Login } from '@carbon/icons-react';
|
||||
import { useEffect, useState } from 'react';
|
||||
import { useLocation } from 'react-router-dom';
|
||||
import { Can } from '@casl/react';
|
||||
// @ts-expect-error TS(2307) FIXME: Cannot find module '../logo.svg' or its correspond... Remove this comment to see the full error message
|
||||
import logo from '../logo.svg';
|
||||
import UserService from '../services/UserService';
|
||||
import { useUriListForPermissions } from '../hooks/UriListForPermissions';
|
||||
import { PermissionsToCheck } from '../interfaces';
|
||||
import { usePermissionFetcher } from '../hooks/PermissionService';
|
||||
|
||||
// for ref: https://react-bootstrap.github.io/components/navbar/
|
||||
export default function NavigationBar() {
|
||||
|
@ -34,6 +38,14 @@ export default function NavigationBar() {
|
|||
const location = useLocation();
|
||||
const [activeKey, setActiveKey] = useState<string>('');
|
||||
|
||||
const { targetUris } = useUriListForPermissions();
|
||||
const permissionRequestData: PermissionsToCheck = {
|
||||
[targetUris.authenticationListPath]: ['GET'],
|
||||
[targetUris.messageInstanceListPath]: ['GET'],
|
||||
[targetUris.secretListPath]: ['GET'],
|
||||
};
|
||||
const { ability } = usePermissionFetcher(permissionRequestData);
|
||||
|
||||
useEffect(() => {
|
||||
let newActiveKey = '/admin/process-groups';
|
||||
if (location.pathname.match(/^\/admin\/messages\b/)) {
|
||||
|
@ -84,6 +96,42 @@ export default function NavigationBar() {
|
|||
);
|
||||
};
|
||||
|
||||
const configurationElement = () => {
|
||||
return (
|
||||
<Can
|
||||
I="GET"
|
||||
a={targetUris.authenticationListPath}
|
||||
ability={ability}
|
||||
passThrough
|
||||
>
|
||||
{(authenticationAllowed: boolean) => {
|
||||
return (
|
||||
<Can
|
||||
I="GET"
|
||||
a={targetUris.secretListPath}
|
||||
ability={ability}
|
||||
passThrough
|
||||
>
|
||||
{(secretAllowed: boolean) => {
|
||||
if (secretAllowed || authenticationAllowed) {
|
||||
return (
|
||||
<HeaderMenuItem
|
||||
href="/admin/configuration"
|
||||
isCurrentPage={isActivePage('/admin/configuration')}
|
||||
>
|
||||
Configuration
|
||||
</HeaderMenuItem>
|
||||
);
|
||||
}
|
||||
return null;
|
||||
}}
|
||||
</Can>
|
||||
);
|
||||
}}
|
||||
</Can>
|
||||
);
|
||||
};
|
||||
|
||||
const headerMenuItems = () => {
|
||||
return (
|
||||
<>
|
||||
|
@ -103,18 +151,15 @@ export default function NavigationBar() {
|
|||
>
|
||||
Process Instances
|
||||
</HeaderMenuItem>
|
||||
<HeaderMenuItem
|
||||
href="/admin/messages"
|
||||
isCurrentPage={isActivePage('/admin/messages')}
|
||||
>
|
||||
Messages
|
||||
</HeaderMenuItem>
|
||||
<HeaderMenuItem
|
||||
href="/admin/configuration"
|
||||
isCurrentPage={isActivePage('/admin/configuration')}
|
||||
>
|
||||
Configuration
|
||||
</HeaderMenuItem>
|
||||
<Can I="GET" a={targetUris.messageInstanceListPath} ability={ability}>
|
||||
<HeaderMenuItem
|
||||
href="/admin/messages"
|
||||
isCurrentPage={isActivePage('/admin/messages')}
|
||||
>
|
||||
Messages
|
||||
</HeaderMenuItem>
|
||||
</Can>
|
||||
{configurationElement()}
|
||||
<HeaderMenuItem
|
||||
href="/admin/process-instances/reports"
|
||||
isCurrentPage={isActivePage('/admin/process-instances/reports')}
|
||||
|
@ -125,7 +170,7 @@ export default function NavigationBar() {
|
|||
);
|
||||
};
|
||||
|
||||
if (activeKey) {
|
||||
if (activeKey && ability) {
|
||||
return (
|
||||
<HeaderContainer
|
||||
render={({ isSideNavExpanded, onClickSideNavExpand }: any) => (
|
||||
|
|
|
@ -20,12 +20,16 @@ import {
|
|||
TableHeader,
|
||||
TableHead,
|
||||
TableRow,
|
||||
TimePicker,
|
||||
// @ts-ignore
|
||||
} from '@carbon/react';
|
||||
import { PROCESS_STATUSES, DATE_FORMAT, DATE_FORMAT_CARBON } from '../config';
|
||||
import {
|
||||
convertDateStringToSeconds,
|
||||
convertSecondsToFormattedDate,
|
||||
convertDateAndTimeStringsToSeconds,
|
||||
convertDateObjectToFormattedHoursMinutes,
|
||||
convertSecondsToFormattedDateString,
|
||||
convertSecondsToFormattedDateTime,
|
||||
convertSecondsToFormattedTimeHoursMinutes,
|
||||
getPageInfoFromSearchParams,
|
||||
getProcessModelFullIdentifierFromSearchParams,
|
||||
modifyProcessModelPath,
|
||||
|
@ -49,6 +53,10 @@ type OwnProps = {
|
|||
perPageOptions?: number[];
|
||||
};
|
||||
|
||||
interface dateParameters {
|
||||
[key: string]: ((..._args: any[]) => any)[];
|
||||
}
|
||||
|
||||
export default function ProcessInstanceListTable({
|
||||
filtersEnabled = true,
|
||||
processModelFullIdentifier,
|
||||
|
@ -66,11 +74,20 @@ export default function ProcessInstanceListTable({
|
|||
|
||||
const oneHourInSeconds = 3600;
|
||||
const oneMonthInSeconds = oneHourInSeconds * 24 * 30;
|
||||
const [startFrom, setStartFrom] = useState<string>('');
|
||||
const [startTo, setStartTo] = useState<string>('');
|
||||
const [endFrom, setEndFrom] = useState<string>('');
|
||||
const [endTo, setEndTo] = useState<string>('');
|
||||
const [startFromDate, setStartFromDate] = useState<string>('');
|
||||
const [startToDate, setStartToDate] = useState<string>('');
|
||||
const [endFromDate, setEndFromDate] = useState<string>('');
|
||||
const [endToDate, setEndToDate] = useState<string>('');
|
||||
const [startFromTime, setStartFromTime] = useState<string>('');
|
||||
const [startToTime, setStartToTime] = useState<string>('');
|
||||
const [endFromTime, setEndFromTime] = useState<string>('');
|
||||
const [endToTime, setEndToTime] = useState<string>('');
|
||||
const [showFilterOptions, setShowFilterOptions] = useState<boolean>(false);
|
||||
const [startFromTimeInvalid, setStartFromTimeInvalid] =
|
||||
useState<boolean>(false);
|
||||
const [startToTimeInvalid, setStartToTimeInvalid] = useState<boolean>(false);
|
||||
const [endFromTimeInvalid, setEndFromTimeInvalid] = useState<boolean>(false);
|
||||
const [endToTimeInvalid, setEndToTimeInvalid] = useState<boolean>(false);
|
||||
|
||||
const setErrorMessage = (useContext as any)(ErrorContext)[1];
|
||||
|
||||
|
@ -86,14 +103,23 @@ export default function ProcessInstanceListTable({
|
|||
const [processModelSelection, setProcessModelSelection] =
|
||||
useState<ProcessModel | null>(null);
|
||||
|
||||
const parametersToAlwaysFilterBy = useMemo(() => {
|
||||
const dateParametersToAlwaysFilterBy: dateParameters = useMemo(() => {
|
||||
return {
|
||||
start_from: setStartFrom,
|
||||
start_to: setStartTo,
|
||||
end_from: setEndFrom,
|
||||
end_to: setEndTo,
|
||||
start_from: [setStartFromDate, setStartFromTime],
|
||||
start_to: [setStartToDate, setStartToTime],
|
||||
end_from: [setEndFromDate, setEndFromTime],
|
||||
end_to: [setEndToDate, setEndToTime],
|
||||
};
|
||||
}, [setStartFrom, setStartTo, setEndFrom, setEndTo]);
|
||||
}, [
|
||||
setStartFromDate,
|
||||
setStartFromTime,
|
||||
setStartToDate,
|
||||
setStartToTime,
|
||||
setEndFromDate,
|
||||
setEndFromTime,
|
||||
setEndToDate,
|
||||
setEndToTime,
|
||||
]);
|
||||
|
||||
const parametersToGetFromSearchParams = useMemo(() => {
|
||||
return {
|
||||
|
@ -130,19 +156,27 @@ export default function ProcessInstanceListTable({
|
|||
queryParamString += `&user_filter=${userAppliedFilter}`;
|
||||
}
|
||||
|
||||
Object.keys(parametersToAlwaysFilterBy).forEach((paramName: string) => {
|
||||
// @ts-expect-error TS(7053) FIXME:
|
||||
const functionToCall = parametersToAlwaysFilterBy[paramName];
|
||||
const searchParamValue = searchParams.get(paramName);
|
||||
if (searchParamValue) {
|
||||
queryParamString += `&${paramName}=${searchParamValue}`;
|
||||
const dateString = convertSecondsToFormattedDate(
|
||||
searchParamValue as any
|
||||
);
|
||||
functionToCall(dateString);
|
||||
setShowFilterOptions(true);
|
||||
Object.keys(dateParametersToAlwaysFilterBy).forEach(
|
||||
(paramName: string) => {
|
||||
const dateFunctionToCall =
|
||||
dateParametersToAlwaysFilterBy[paramName][0];
|
||||
const timeFunctionToCall =
|
||||
dateParametersToAlwaysFilterBy[paramName][1];
|
||||
const searchParamValue = searchParams.get(paramName);
|
||||
if (searchParamValue) {
|
||||
queryParamString += `&${paramName}=${searchParamValue}`;
|
||||
const dateString = convertSecondsToFormattedDateString(
|
||||
searchParamValue as any
|
||||
);
|
||||
dateFunctionToCall(dateString);
|
||||
const timeString = convertSecondsToFormattedTimeHoursMinutes(
|
||||
searchParamValue as any
|
||||
);
|
||||
timeFunctionToCall(timeString);
|
||||
setShowFilterOptions(true);
|
||||
}
|
||||
}
|
||||
});
|
||||
);
|
||||
|
||||
Object.keys(parametersToGetFromSearchParams).forEach(
|
||||
(paramName: string) => {
|
||||
|
@ -211,7 +245,7 @@ export default function ProcessInstanceListTable({
|
|||
params,
|
||||
oneMonthInSeconds,
|
||||
oneHourInSeconds,
|
||||
parametersToAlwaysFilterBy,
|
||||
dateParametersToAlwaysFilterBy,
|
||||
parametersToGetFromSearchParams,
|
||||
filtersEnabled,
|
||||
paginationQueryParamPrefix,
|
||||
|
@ -219,16 +253,25 @@ export default function ProcessInstanceListTable({
|
|||
perPageOptions,
|
||||
]);
|
||||
|
||||
// This sets the filter data using the saved reports returned from the initial instance_list query.
|
||||
// This could probably be merged into the main useEffect but it works here now.
|
||||
useEffect(() => {
|
||||
const filters = processInstanceFilters as any;
|
||||
Object.keys(parametersToAlwaysFilterBy).forEach((paramName: string) => {
|
||||
// @ts-expect-error TS(7053) FIXME:
|
||||
const functionToCall = parametersToAlwaysFilterBy[paramName];
|
||||
Object.keys(dateParametersToAlwaysFilterBy).forEach((paramName: string) => {
|
||||
const dateFunctionToCall = dateParametersToAlwaysFilterBy[paramName][0];
|
||||
const timeFunctionToCall = dateParametersToAlwaysFilterBy[paramName][1];
|
||||
const paramValue = filters[paramName];
|
||||
functionToCall('');
|
||||
dateFunctionToCall('');
|
||||
timeFunctionToCall('');
|
||||
if (paramValue) {
|
||||
const dateString = convertSecondsToFormattedDate(paramValue as any);
|
||||
functionToCall(dateString);
|
||||
const dateString = convertSecondsToFormattedDateString(
|
||||
paramValue as any
|
||||
);
|
||||
dateFunctionToCall(dateString);
|
||||
const timeString = convertSecondsToFormattedTimeHoursMinutes(
|
||||
paramValue as any
|
||||
);
|
||||
timeFunctionToCall(timeString);
|
||||
setShowFilterOptions(true);
|
||||
}
|
||||
});
|
||||
|
@ -253,7 +296,7 @@ export default function ProcessInstanceListTable({
|
|||
setProcessStatusSelection(processStatusSelectedArray);
|
||||
}, [
|
||||
processInstanceFilters,
|
||||
parametersToAlwaysFilterBy,
|
||||
dateParametersToAlwaysFilterBy,
|
||||
parametersToGetFromSearchParams,
|
||||
processModelAvailableItems,
|
||||
]);
|
||||
|
@ -285,10 +328,22 @@ export default function ProcessInstanceListTable({
|
|||
);
|
||||
let queryParamString = `per_page=${perPage}&page=${page}&user_filter=true`;
|
||||
|
||||
const startFromSeconds = convertDateStringToSeconds(startFrom);
|
||||
const endFromSeconds = convertDateStringToSeconds(endFrom);
|
||||
const startToSeconds = convertDateStringToSeconds(startTo);
|
||||
const endToSeconds = convertDateStringToSeconds(endTo);
|
||||
const startFromSeconds = convertDateAndTimeStringsToSeconds(
|
||||
startFromDate,
|
||||
startFromTime || '00:00:00'
|
||||
);
|
||||
const startToSeconds = convertDateAndTimeStringsToSeconds(
|
||||
startToDate,
|
||||
startToTime || '00:00:00'
|
||||
);
|
||||
const endFromSeconds = convertDateAndTimeStringsToSeconds(
|
||||
endFromDate,
|
||||
endFromTime || '00:00:00'
|
||||
);
|
||||
const endToSeconds = convertDateAndTimeStringsToSeconds(
|
||||
endToDate,
|
||||
endToTime || '00:00:00'
|
||||
);
|
||||
if (isTrueComparison(startFromSeconds, '>', startToSeconds)) {
|
||||
setErrorMessage({
|
||||
message: '"Start date from" cannot be after "start date to"',
|
||||
|
@ -342,24 +397,50 @@ export default function ProcessInstanceListTable({
|
|||
labelString: any,
|
||||
name: any,
|
||||
initialDate: any,
|
||||
onChangeFunction: any
|
||||
initialTime: string,
|
||||
onChangeDateFunction: any,
|
||||
onChangeTimeFunction: any,
|
||||
timeInvalid: boolean,
|
||||
setTimeInvalid: any
|
||||
) => {
|
||||
return (
|
||||
<DatePicker dateFormat={DATE_FORMAT_CARBON} datePickerType="single">
|
||||
<DatePickerInput
|
||||
id={`date-picker-${name}`}
|
||||
placeholder={DATE_FORMAT}
|
||||
labelText={labelString}
|
||||
type="text"
|
||||
size="md"
|
||||
autocomplete="off"
|
||||
allowInput={false}
|
||||
onChange={(dateChangeEvent: any) => {
|
||||
onChangeFunction(dateChangeEvent.srcElement.value);
|
||||
<>
|
||||
<DatePicker dateFormat={DATE_FORMAT_CARBON} datePickerType="single">
|
||||
<DatePickerInput
|
||||
id={`date-picker-${name}`}
|
||||
placeholder={DATE_FORMAT}
|
||||
labelText={labelString}
|
||||
type="text"
|
||||
size="md"
|
||||
autocomplete="off"
|
||||
allowInput={false}
|
||||
onChange={(dateChangeEvent: any) => {
|
||||
if (!initialDate && !initialTime) {
|
||||
onChangeTimeFunction(
|
||||
convertDateObjectToFormattedHoursMinutes(new Date())
|
||||
);
|
||||
}
|
||||
onChangeDateFunction(dateChangeEvent.srcElement.value);
|
||||
}}
|
||||
value={initialDate}
|
||||
/>
|
||||
</DatePicker>
|
||||
<TimePicker
|
||||
invalid={timeInvalid}
|
||||
id="time-picker"
|
||||
labelText="Select a time"
|
||||
pattern="^([01]\d|2[0-3]):?([0-5]\d)$"
|
||||
value={initialTime}
|
||||
onChange={(event: any) => {
|
||||
if (event.srcElement.validity.valid) {
|
||||
setTimeInvalid(false);
|
||||
} else {
|
||||
setTimeInvalid(true);
|
||||
}
|
||||
onChangeTimeFunction(event.srcElement.value);
|
||||
}}
|
||||
value={initialDate}
|
||||
/>
|
||||
</DatePicker>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
|
@ -386,10 +467,14 @@ export default function ProcessInstanceListTable({
|
|||
const clearFilters = () => {
|
||||
setProcessModelSelection(null);
|
||||
setProcessStatusSelection([]);
|
||||
setStartFrom('');
|
||||
setStartTo('');
|
||||
setEndFrom('');
|
||||
setEndTo('');
|
||||
setStartFromDate('');
|
||||
setStartFromTime('');
|
||||
setStartToDate('');
|
||||
setStartToTime('');
|
||||
setEndFromDate('');
|
||||
setEndFromTime('');
|
||||
setEndToDate('');
|
||||
setEndToTime('');
|
||||
};
|
||||
|
||||
const filterOptions = () => {
|
||||
|
@ -415,18 +500,49 @@ export default function ProcessInstanceListTable({
|
|||
{dateComponent(
|
||||
'Start date from',
|
||||
'start-from',
|
||||
startFrom,
|
||||
setStartFrom
|
||||
startFromDate,
|
||||
startFromTime,
|
||||
setStartFromDate,
|
||||
setStartFromTime,
|
||||
startFromTimeInvalid,
|
||||
setStartFromTimeInvalid
|
||||
)}
|
||||
</Column>
|
||||
<Column md={4}>
|
||||
{dateComponent('Start date to', 'start-to', startTo, setStartTo)}
|
||||
{dateComponent(
|
||||
'Start date to',
|
||||
'start-to',
|
||||
startToDate,
|
||||
startToTime,
|
||||
setStartToDate,
|
||||
setStartToTime,
|
||||
startToTimeInvalid,
|
||||
setStartToTimeInvalid
|
||||
)}
|
||||
</Column>
|
||||
<Column md={4}>
|
||||
{dateComponent('End date from', 'end-from', endFrom, setEndFrom)}
|
||||
{dateComponent(
|
||||
'End date from',
|
||||
'end-from',
|
||||
endFromDate,
|
||||
endFromTime,
|
||||
setEndFromDate,
|
||||
setEndFromTime,
|
||||
endFromTimeInvalid,
|
||||
setEndFromTimeInvalid
|
||||
)}
|
||||
</Column>
|
||||
<Column md={4}>
|
||||
{dateComponent('End date to', 'end-to', endTo, setEndTo)}
|
||||
{dateComponent(
|
||||
'End date to',
|
||||
'end-to',
|
||||
endToDate,
|
||||
endToTime,
|
||||
setEndToDate,
|
||||
setEndToTime,
|
||||
endToTimeInvalid,
|
||||
setEndToTimeInvalid
|
||||
)}
|
||||
</Column>
|
||||
</Grid>
|
||||
<Grid fullWidth className="with-bottom-margin">
|
||||
|
@ -455,7 +571,7 @@ export default function ProcessInstanceListTable({
|
|||
|
||||
const buildTable = () => {
|
||||
const headerLabels: Record<string, string> = {
|
||||
id: 'Process Instance Id',
|
||||
id: 'Id',
|
||||
process_model_identifier: 'Process Model',
|
||||
start_in_seconds: 'Start Time',
|
||||
end_in_seconds: 'End Time',
|
||||
|
@ -493,7 +609,7 @@ export default function ProcessInstanceListTable({
|
|||
);
|
||||
};
|
||||
const formatSecondsForDisplay = (_row: any, seconds: any) => {
|
||||
return convertSecondsToFormattedDate(seconds) || '-';
|
||||
return convertSecondsToFormattedDateTime(seconds) || '-';
|
||||
};
|
||||
const defaultFormatter = (_row: any, value: any) => {
|
||||
return value;
|
||||
|
@ -530,7 +646,12 @@ export default function ProcessInstanceListTable({
|
|||
<TableHead>
|
||||
<TableRow>
|
||||
{headers.map((header: any) => (
|
||||
<TableHeader key={header}>{header}</TableHeader>
|
||||
<TableHeader
|
||||
key={header}
|
||||
title={header === 'Id' ? 'Process Instance Id' : null}
|
||||
>
|
||||
{header}
|
||||
</TableHeader>
|
||||
))}
|
||||
</TableRow>
|
||||
</TableHead>
|
||||
|
|
|
@ -18,5 +18,6 @@ export const PROCESS_STATUSES = [
|
|||
|
||||
// with time: yyyy-MM-dd HH:mm:ss
|
||||
export const DATE_TIME_FORMAT = 'yyyy-MM-dd HH:mm:ss';
|
||||
export const TIME_FORMAT_HOURS_MINUTES = 'HH:mm';
|
||||
export const DATE_FORMAT = 'yyyy-MM-dd';
|
||||
export const DATE_FORMAT_CARBON = 'Y-m-d';
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { convertSecondsToFormattedDate, slugifyString } from './helpers';
|
||||
import { convertSecondsToFormattedDateString, slugifyString } from './helpers';
|
||||
|
||||
test('it can slugify a string', () => {
|
||||
expect(slugifyString('hello---world_ and then Some such-')).toEqual(
|
||||
|
@ -7,6 +7,6 @@ test('it can slugify a string', () => {
|
|||
});
|
||||
|
||||
test('it can keep the correct date when converting seconds to date', () => {
|
||||
const dateString = convertSecondsToFormattedDate(1666325400);
|
||||
const dateString = convertSecondsToFormattedDateString(1666325400);
|
||||
expect(dateString).toEqual('2022-10-21');
|
||||
});
|
||||
|
|
|
@ -1,5 +1,9 @@
|
|||
import { format } from 'date-fns';
|
||||
import { DATE_TIME_FORMAT, DATE_FORMAT } from './config';
|
||||
import {
|
||||
DATE_TIME_FORMAT,
|
||||
DATE_FORMAT,
|
||||
TIME_FORMAT_HOURS_MINUTES,
|
||||
} from './config';
|
||||
import {
|
||||
DEFAULT_PER_PAGE,
|
||||
DEFAULT_PAGE,
|
||||
|
@ -42,27 +46,72 @@ export const convertDateToSeconds = (
|
|||
return null;
|
||||
};
|
||||
|
||||
export const convertDateObjectToFormattedString = (dateObject: Date) => {
|
||||
if (dateObject) {
|
||||
return format(dateObject, DATE_FORMAT);
|
||||
}
|
||||
return null;
|
||||
};
|
||||
|
||||
export const convertDateAndTimeStringsToDate = (
|
||||
dateString: string,
|
||||
timeString: string
|
||||
) => {
|
||||
if (dateString && timeString) {
|
||||
return new Date(`${dateString}T${timeString}`);
|
||||
}
|
||||
return null;
|
||||
};
|
||||
|
||||
export const convertDateAndTimeStringsToSeconds = (
|
||||
dateString: string,
|
||||
timeString: string
|
||||
) => {
|
||||
const dateObject = convertDateAndTimeStringsToDate(dateString, timeString);
|
||||
if (dateObject) {
|
||||
return convertDateToSeconds(dateObject);
|
||||
}
|
||||
return null;
|
||||
};
|
||||
|
||||
export const convertStringToDate = (dateString: string) => {
|
||||
if (dateString) {
|
||||
// add midnight time to the date so it c uses the correct date
|
||||
// after converting to timezone
|
||||
return new Date(`${dateString}T00:10:00`);
|
||||
return convertDateAndTimeStringsToSeconds(dateString, '00:10:00');
|
||||
};
|
||||
|
||||
export const convertSecondsToDateObject = (seconds: number) => {
|
||||
if (seconds) {
|
||||
return new Date(seconds * 1000);
|
||||
}
|
||||
return null;
|
||||
};
|
||||
|
||||
export const convertSecondsToFormattedDateTime = (seconds: number) => {
|
||||
if (seconds) {
|
||||
const dateObject = new Date(seconds * 1000);
|
||||
const dateObject = convertSecondsToDateObject(seconds);
|
||||
if (dateObject) {
|
||||
return format(dateObject, DATE_TIME_FORMAT);
|
||||
}
|
||||
return null;
|
||||
};
|
||||
|
||||
export const convertSecondsToFormattedDate = (seconds: number) => {
|
||||
if (seconds) {
|
||||
const dateObject = new Date(seconds * 1000);
|
||||
return format(dateObject, DATE_FORMAT);
|
||||
export const convertDateObjectToFormattedHoursMinutes = (dateObject: Date) => {
|
||||
if (dateObject) {
|
||||
return format(dateObject, TIME_FORMAT_HOURS_MINUTES);
|
||||
}
|
||||
return null;
|
||||
};
|
||||
|
||||
export const convertSecondsToFormattedTimeHoursMinutes = (seconds: number) => {
|
||||
const dateObject = convertSecondsToDateObject(seconds);
|
||||
if (dateObject) {
|
||||
return convertDateObjectToFormattedHoursMinutes(dateObject);
|
||||
}
|
||||
return null;
|
||||
};
|
||||
|
||||
export const convertSecondsToFormattedDateString = (seconds: number) => {
|
||||
const dateObject = convertSecondsToDateObject(seconds);
|
||||
if (dateObject) {
|
||||
return convertDateObjectToFormattedString(dateObject);
|
||||
}
|
||||
return null;
|
||||
};
|
||||
|
@ -148,3 +197,16 @@ export const getGroupFromModifiedModelId = (modifiedId: string) => {
|
|||
export const splitProcessModelId = (processModelId: string) => {
|
||||
return processModelId.split('/');
|
||||
};
|
||||
|
||||
export const refreshAtInterval = (
|
||||
interval: number,
|
||||
timeout: number,
|
||||
func: Function
|
||||
) => {
|
||||
const intervalRef = setInterval(() => func(), interval * 1000);
|
||||
const timeoutRef = setTimeout(
|
||||
() => clearInterval(intervalRef),
|
||||
timeout * 1000
|
||||
);
|
||||
return [intervalRef, timeoutRef];
|
||||
};
|
||||
|
|
|
@ -3,6 +3,7 @@ import { useParams } from 'react-router-dom';
|
|||
export const useUriListForPermissions = () => {
|
||||
const params = useParams();
|
||||
const targetUris = {
|
||||
authenticationListPath: `/v1.0/authentications`,
|
||||
messageInstanceListPath: '/v1.0/messages',
|
||||
processGroupListPath: '/v1.0/process-groups',
|
||||
processGroupShowPath: `/v1.0/process-groups/${params.process_group_id}`,
|
||||
|
@ -12,6 +13,7 @@ export const useUriListForPermissions = () => {
|
|||
processModelFileCreatePath: `/v1.0/process-models/${params.process_model_id}/files`,
|
||||
processModelFileShowPath: `/v1.0/process-models/${params.process_model_id}/files/${params.file_name}`,
|
||||
processModelShowPath: `/v1.0/process-models/${params.process_model_id}`,
|
||||
secretListPath: `/v1.0/secrets`,
|
||||
};
|
||||
|
||||
return { targetUris };
|
||||
|
|
|
@ -2,11 +2,15 @@ import { useContext, useEffect, useState } from 'react';
|
|||
import { Route, Routes, useLocation, useNavigate } from 'react-router-dom';
|
||||
// @ts-ignore
|
||||
import { Tabs, TabList, Tab } from '@carbon/react';
|
||||
import { Can } from '@casl/react';
|
||||
import ErrorContext from '../contexts/ErrorContext';
|
||||
import SecretList from './SecretList';
|
||||
import SecretNew from './SecretNew';
|
||||
import SecretShow from './SecretShow';
|
||||
import AuthenticationList from './AuthenticationList';
|
||||
import { useUriListForPermissions } from '../hooks/UriListForPermissions';
|
||||
import { PermissionsToCheck } from '../interfaces';
|
||||
import { usePermissionFetcher } from '../hooks/PermissionService';
|
||||
|
||||
export default function Configuration() {
|
||||
const location = useLocation();
|
||||
|
@ -14,6 +18,13 @@ export default function Configuration() {
|
|||
const [selectedTabIndex, setSelectedTabIndex] = useState<number>(0);
|
||||
const navigate = useNavigate();
|
||||
|
||||
const { targetUris } = useUriListForPermissions();
|
||||
const permissionRequestData: PermissionsToCheck = {
|
||||
[targetUris.authenticationListPath]: ['GET'],
|
||||
[targetUris.secretListPath]: ['GET'],
|
||||
};
|
||||
const { ability } = usePermissionFetcher(permissionRequestData);
|
||||
|
||||
useEffect(() => {
|
||||
setErrorMessage(null);
|
||||
let newSelectedTabIndex = 0;
|
||||
|
@ -27,12 +38,18 @@ export default function Configuration() {
|
|||
<>
|
||||
<Tabs selectedIndex={selectedTabIndex}>
|
||||
<TabList aria-label="List of tabs">
|
||||
<Tab onClick={() => navigate('/admin/configuration/secrets')}>
|
||||
Secrets
|
||||
</Tab>
|
||||
<Tab onClick={() => navigate('/admin/configuration/authentications')}>
|
||||
Authentications
|
||||
</Tab>
|
||||
<Can I="GET" a={targetUris.secretListPath} ability={ability}>
|
||||
<Tab onClick={() => navigate('/admin/configuration/secrets')}>
|
||||
Secrets
|
||||
</Tab>
|
||||
</Can>
|
||||
<Can I="GET" a={targetUris.authenticationListPath} ability={ability}>
|
||||
<Tab
|
||||
onClick={() => navigate('/admin/configuration/authentications')}
|
||||
>
|
||||
Authentications
|
||||
</Tab>
|
||||
</Can>
|
||||
</TabList>
|
||||
</Tabs>
|
||||
<br />
|
||||
|
|
|
@ -5,7 +5,7 @@ import { Link, useParams, useSearchParams } from 'react-router-dom';
|
|||
import PaginationForTable from '../components/PaginationForTable';
|
||||
import ProcessBreadcrumb from '../components/ProcessBreadcrumb';
|
||||
import {
|
||||
convertSecondsToFormattedDate,
|
||||
convertSecondsToFormattedDateString,
|
||||
getPageInfoFromSearchParams,
|
||||
modifyProcessModelPath,
|
||||
unModifyProcessModelPath,
|
||||
|
@ -68,7 +68,9 @@ export default function MessageInstanceList() {
|
|||
<td>{rowToUse.failure_cause || '-'}</td>
|
||||
<td>{rowToUse.status}</td>
|
||||
<td>
|
||||
{convertSecondsToFormattedDate(rowToUse.created_at_in_seconds)}
|
||||
{convertSecondsToFormattedDateString(
|
||||
rowToUse.created_at_in_seconds
|
||||
)}
|
||||
</td>
|
||||
</tr>
|
||||
);
|
||||
|
|
|
@ -6,11 +6,14 @@ import PaginationForTable from '../components/PaginationForTable';
|
|||
import {
|
||||
getPageInfoFromSearchParams,
|
||||
modifyProcessModelPath,
|
||||
refreshAtInterval,
|
||||
} from '../helpers';
|
||||
import HttpService from '../services/HttpService';
|
||||
import { PaginationObject, RecentProcessModel } from '../interfaces';
|
||||
|
||||
const PER_PAGE_FOR_TASKS_ON_HOME_PAGE = 5;
|
||||
const REFRESH_INTERVAL = 10;
|
||||
const REFRESH_TIMEOUT = 600;
|
||||
|
||||
export default function MyTasks() {
|
||||
const [searchParams] = useSearchParams();
|
||||
|
@ -18,18 +21,23 @@ export default function MyTasks() {
|
|||
const [pagination, setPagination] = useState<PaginationObject | null>(null);
|
||||
|
||||
useEffect(() => {
|
||||
const { page, perPage } = getPageInfoFromSearchParams(
|
||||
searchParams,
|
||||
PER_PAGE_FOR_TASKS_ON_HOME_PAGE
|
||||
);
|
||||
const setTasksFromResult = (result: any) => {
|
||||
setTasks(result.results);
|
||||
setPagination(result.pagination);
|
||||
const getTasks = () => {
|
||||
const { page, perPage } = getPageInfoFromSearchParams(
|
||||
searchParams,
|
||||
PER_PAGE_FOR_TASKS_ON_HOME_PAGE
|
||||
);
|
||||
const setTasksFromResult = (result: any) => {
|
||||
setTasks(result.results);
|
||||
setPagination(result.pagination);
|
||||
};
|
||||
HttpService.makeCallToBackend({
|
||||
path: `/tasks?per_page=${perPage}&page=${page}`,
|
||||
successCallback: setTasksFromResult,
|
||||
});
|
||||
};
|
||||
HttpService.makeCallToBackend({
|
||||
path: `/tasks?per_page=${perPage}&page=${page}`,
|
||||
successCallback: setTasksFromResult,
|
||||
});
|
||||
|
||||
getTasks();
|
||||
refreshAtInterval(REFRESH_INTERVAL, REFRESH_TIMEOUT, getTasks);
|
||||
}, [searchParams]);
|
||||
|
||||
let recentProcessModels: RecentProcessModel[] = [];
|
||||
|
|
|
@ -6,9 +6,9 @@ import PaginationForTable from '../components/PaginationForTable';
|
|||
import ProcessBreadcrumb from '../components/ProcessBreadcrumb';
|
||||
import {
|
||||
getPageInfoFromSearchParams,
|
||||
convertSecondsToFormattedDate,
|
||||
modifyProcessModelPath,
|
||||
unModifyProcessModelPath,
|
||||
convertSecondsToFormattedDateTime,
|
||||
} from '../helpers';
|
||||
import HttpService from '../services/HttpService';
|
||||
|
||||
|
@ -49,7 +49,7 @@ export default function ProcessInstanceLogList() {
|
|||
data-qa="process-instance-show-link"
|
||||
to={`/admin/process-models/${modifiedProcessModelId}/process-instances/${rowToUse.process_instance_id}/${rowToUse.spiff_step}`}
|
||||
>
|
||||
{convertSecondsToFormattedDate(rowToUse.timestamp)}
|
||||
{convertSecondsToFormattedDateTime(rowToUse.timestamp)}
|
||||
</Link>
|
||||
</td>
|
||||
</tr>
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import { useContext, useEffect, useState } from 'react';
|
||||
import { Link, useNavigate, useParams } from 'react-router-dom';
|
||||
import { useNavigate, useParams } from 'react-router-dom';
|
||||
|
||||
// FIXME: npm install @rjsf/validator-ajv8 and use it as soon as
|
||||
// rawErrors is fixed.
|
||||
|
@ -9,8 +9,14 @@ import { Link, useNavigate, useParams } from 'react-router-dom';
|
|||
// https://github.com/rjsf-team/react-jsonschema-form/blob/main/docs/api-reference/uiSchema.md talks about rawErrors
|
||||
import validator from '@rjsf/validator-ajv6';
|
||||
|
||||
// @ts-ignore
|
||||
import { Button, Stack } from '@carbon/react';
|
||||
import {
|
||||
TabList,
|
||||
Tab,
|
||||
Tabs,
|
||||
Grid,
|
||||
Column,
|
||||
// @ts-ignore
|
||||
} from '@carbon/react';
|
||||
|
||||
import ReactMarkdown from 'react-markdown';
|
||||
import remarkGfm from 'remark-gfm';
|
||||
|
@ -73,39 +79,52 @@ export default function TaskShow() {
|
|||
|
||||
const buildTaskNavigation = () => {
|
||||
let userTasksElement;
|
||||
let selectedTabIndex = 0;
|
||||
if (userTasks) {
|
||||
userTasksElement = (userTasks as any).map(function getUserTasksElement(
|
||||
userTask: any
|
||||
userTask: any,
|
||||
index: number
|
||||
) {
|
||||
const taskUrl = `/tasks/${params.process_instance_id}/${userTask.id}`;
|
||||
if (userTask.id === params.task_id) {
|
||||
return <span>{userTask.name}</span>;
|
||||
selectedTabIndex = index;
|
||||
return <Tab selected>{userTask.title}</Tab>;
|
||||
}
|
||||
if (userTask.state === 'COMPLETED') {
|
||||
return (
|
||||
<Link to={taskUrl} data-qa={`form-nav-${userTask.name}`}>
|
||||
{userTask.name}
|
||||
</Link>
|
||||
<Tab
|
||||
onClick={() => navigate(taskUrl)}
|
||||
data-qa={`form-nav-${userTask.name}`}
|
||||
>
|
||||
{userTask.title}
|
||||
</Tab>
|
||||
);
|
||||
}
|
||||
if (userTask.state === 'FUTURE') {
|
||||
return <span style={{ color: 'red' }}>{userTask.name}</span>;
|
||||
return <Tab disabled>{userTask.title}</Tab>;
|
||||
}
|
||||
if (userTask.state === 'READY') {
|
||||
return (
|
||||
<Link to={taskUrl} data-qa={`form-nav-${userTask.name}`}>
|
||||
{userTask.name} - Current
|
||||
</Link>
|
||||
<Tab
|
||||
onClick={() => navigate(taskUrl)}
|
||||
data-qa={`form-nav-${userTask.name}`}
|
||||
>
|
||||
{userTask.title}
|
||||
</Tab>
|
||||
);
|
||||
}
|
||||
return null;
|
||||
});
|
||||
}
|
||||
return (
|
||||
<Stack orientation="horizontal" gap={3}>
|
||||
<Button href="/tasks">Go Back To List</Button>
|
||||
{userTasksElement}
|
||||
</Stack>
|
||||
<Tabs
|
||||
title="Steps in this process instance involving people"
|
||||
selectedIndex={selectedTabIndex}
|
||||
>
|
||||
<TabList aria-label="List of tabs" contained>
|
||||
{userTasksElement}
|
||||
</TabList>
|
||||
</Tabs>
|
||||
);
|
||||
};
|
||||
|
||||
|
@ -149,15 +168,19 @@ export default function TaskShow() {
|
|||
}
|
||||
|
||||
return (
|
||||
<Form
|
||||
formData={taskData}
|
||||
onSubmit={handleFormSubmit}
|
||||
schema={jsonSchema}
|
||||
uiSchema={formUiSchema}
|
||||
validator={validator}
|
||||
>
|
||||
{reactFragmentToHideSubmitButton}
|
||||
</Form>
|
||||
<Grid fullWidth condensed>
|
||||
<Column md={5} lg={8} sm={4}>
|
||||
<Form
|
||||
formData={taskData}
|
||||
onSubmit={handleFormSubmit}
|
||||
schema={jsonSchema}
|
||||
uiSchema={formUiSchema}
|
||||
validator={validator}
|
||||
>
|
||||
{reactFragmentToHideSubmitButton}
|
||||
</Form>
|
||||
</Column>
|
||||
</Grid>
|
||||
);
|
||||
};
|
||||
|
||||
|
@ -175,7 +198,7 @@ export default function TaskShow() {
|
|||
);
|
||||
};
|
||||
|
||||
if (task) {
|
||||
if (task && userTasks) {
|
||||
const taskToUse = task as any;
|
||||
let statusString = '';
|
||||
if (taskToUse.state !== 'READY') {
|
||||
|
|
|
@ -82,6 +82,9 @@ export default function BaseInputTemplate<
|
|||
} else if (schema && schema.title) {
|
||||
labelToUse = schema.title;
|
||||
}
|
||||
if (required) {
|
||||
labelToUse = `${labelToUse}*`;
|
||||
}
|
||||
|
||||
let invalid = false;
|
||||
let errorMessageForField = null;
|
||||
|
|
Loading…
Reference in New Issue