Merge pull request #40 from sartography/feature/model_show_permi_page
Feature/model show permi page
This commit is contained in:
commit
36520c1c46
|
@ -258,7 +258,6 @@ paths:
|
||||||
description: The number of models to show per page. Defaults to page 10.
|
description: The number of models to show per page. Defaults to page 10.
|
||||||
schema:
|
schema:
|
||||||
type: integer
|
type: integer
|
||||||
# process_model_list
|
|
||||||
get:
|
get:
|
||||||
operationId: spiffworkflow_backend.routes.process_api_blueprint.process_model_list
|
operationId: spiffworkflow_backend.routes.process_api_blueprint.process_model_list
|
||||||
summary: Return a list of process models for a given process group
|
summary: Return a list of process models for a given process group
|
||||||
|
@ -273,9 +272,10 @@ paths:
|
||||||
type: array
|
type: array
|
||||||
items:
|
items:
|
||||||
$ref: "#/components/schemas/ProcessModel"
|
$ref: "#/components/schemas/ProcessModel"
|
||||||
# process_model_add
|
|
||||||
|
/process-models/{modified_process_group_id}:
|
||||||
post:
|
post:
|
||||||
operationId: spiffworkflow_backend.routes.process_api_blueprint.process_model_add
|
operationId: spiffworkflow_backend.routes.process_api_blueprint.process_model_create
|
||||||
summary: Creates a new process model with the given parameters.
|
summary: Creates a new process model with the given parameters.
|
||||||
tags:
|
tags:
|
||||||
- Process Models
|
- Process Models
|
||||||
|
@ -371,7 +371,7 @@ paths:
|
||||||
application/json:
|
application/json:
|
||||||
schema:
|
schema:
|
||||||
$ref: "#/components/schemas/OkTrue"
|
$ref: "#/components/schemas/OkTrue"
|
||||||
# process_model_list
|
|
||||||
/processes:
|
/processes:
|
||||||
get:
|
get:
|
||||||
operationId: spiffworkflow_backend.routes.process_api_blueprint.process_list
|
operationId: spiffworkflow_backend.routes.process_api_blueprint.process_list
|
||||||
|
|
|
@ -232,10 +232,10 @@ def process_group_show(
|
||||||
return make_response(jsonify(process_group), 200)
|
return make_response(jsonify(process_group), 200)
|
||||||
|
|
||||||
|
|
||||||
def process_model_add(
|
def process_model_create(
|
||||||
body: Dict[str, Union[str, bool, int]]
|
body: Dict[str, Union[str, bool, int]]
|
||||||
) -> flask.wrappers.Response:
|
) -> flask.wrappers.Response:
|
||||||
"""Add_process_model."""
|
"""Process_model_create."""
|
||||||
process_model_info = ProcessModelInfoSchema().load(body)
|
process_model_info = ProcessModelInfoSchema().load(body)
|
||||||
if process_model_info is None:
|
if process_model_info is None:
|
||||||
raise ApiError(
|
raise ApiError(
|
||||||
|
|
|
@ -701,11 +701,11 @@ class ProcessInstanceProcessor:
|
||||||
"bpmn_file_full_path_from_bpmn_process_identifier: bpmn_process_identifier is unexpectedly None"
|
"bpmn_file_full_path_from_bpmn_process_identifier: bpmn_process_identifier is unexpectedly None"
|
||||||
)
|
)
|
||||||
|
|
||||||
spec_reference = SpecReferenceCache.query.filter_by(
|
spec_reference = (
|
||||||
identifier=bpmn_process_identifier
|
SpecReferenceCache.query.filter_by(identifier=bpmn_process_identifier)
|
||||||
).filter_by(
|
.filter_by(type="process")
|
||||||
type='process'
|
.first()
|
||||||
).first()
|
)
|
||||||
bpmn_file_full_path = None
|
bpmn_file_full_path = None
|
||||||
if spec_reference is None:
|
if spec_reference is None:
|
||||||
bpmn_file_full_path = (
|
bpmn_file_full_path = (
|
||||||
|
@ -1021,7 +1021,7 @@ class ProcessInstanceProcessor:
|
||||||
spiff_logger = logging.getLogger("spiff")
|
spiff_logger = logging.getLogger("spiff")
|
||||||
for handler in spiff_logger.handlers:
|
for handler in spiff_logger.handlers:
|
||||||
if hasattr(handler, "bulk_insert_logs"):
|
if hasattr(handler, "bulk_insert_logs"):
|
||||||
handler.bulk_insert_logs() # type: ignoreidentifier
|
handler.bulk_insert_logs() # type: ignore
|
||||||
db.session.commit()
|
db.session.commit()
|
||||||
|
|
||||||
except WorkflowTaskExecException as we:
|
except WorkflowTaskExecException as we:
|
||||||
|
|
|
@ -240,11 +240,13 @@ class SpecFileService(FileSystemService):
|
||||||
SpecFileService.update_correlation_cache(ref)
|
SpecFileService.update_correlation_cache(ref)
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def clear_caches_for_file(file_name: str, process_model_info: ProcessModelInfo) -> None:
|
def clear_caches_for_file(
|
||||||
"""Clear all caches related to a file"""
|
file_name: str, process_model_info: ProcessModelInfo
|
||||||
db.session.query(SpecReferenceCache).\
|
) -> None:
|
||||||
filter(SpecReferenceCache.file_name == file_name).\
|
"""Clear all caches related to a file."""
|
||||||
filter(SpecReferenceCache.process_model_id == process_model_info.id).delete()
|
db.session.query(SpecReferenceCache).filter(
|
||||||
|
SpecReferenceCache.file_name == file_name
|
||||||
|
).filter(SpecReferenceCache.process_model_id == process_model_info.id).delete()
|
||||||
# fixme: likely the other caches should be cleared as well, but we don't have a clean way to do so yet.
|
# fixme: likely the other caches should be cleared as well, but we don't have a clean way to do so yet.
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
|
|
|
@ -143,7 +143,6 @@ class TestNestedGroups(BaseTest):
|
||||||
response = client.get( # noqa: F841
|
response = client.get( # noqa: F841
|
||||||
target_uri, headers=self.logged_in_headers(user)
|
target_uri, headers=self.logged_in_headers(user)
|
||||||
)
|
)
|
||||||
print("test_nested_groups")
|
|
||||||
|
|
||||||
def test_add_nested_group(
|
def test_add_nested_group(
|
||||||
self,
|
self,
|
||||||
|
@ -153,10 +152,6 @@ class TestNestedGroups(BaseTest):
|
||||||
with_super_admin_user: UserModel,
|
with_super_admin_user: UserModel,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Test_add_nested_group."""
|
"""Test_add_nested_group."""
|
||||||
# user = self.find_or_create_user()
|
|
||||||
# self.add_permissions_to_user(
|
|
||||||
# user, target_uri=target_uri, permission_names=["read", "create"]
|
|
||||||
# )
|
|
||||||
process_group_a = ProcessGroup(
|
process_group_a = ProcessGroup(
|
||||||
id="group_a",
|
id="group_a",
|
||||||
display_name="Group A",
|
display_name="Group A",
|
||||||
|
@ -194,16 +189,14 @@ class TestNestedGroups(BaseTest):
|
||||||
data=json.dumps(ProcessGroupSchema().dump(process_group_c)),
|
data=json.dumps(ProcessGroupSchema().dump(process_group_c)),
|
||||||
)
|
)
|
||||||
|
|
||||||
print("test_add_nested_group")
|
def test_process_model_create(
|
||||||
|
|
||||||
def test_process_model_add(
|
|
||||||
self,
|
self,
|
||||||
app: Flask,
|
app: Flask,
|
||||||
client: FlaskClient,
|
client: FlaskClient,
|
||||||
with_db_and_bpmn_file_cleanup: None,
|
with_db_and_bpmn_file_cleanup: None,
|
||||||
with_super_admin_user: UserModel,
|
with_super_admin_user: UserModel,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Test_process_model_add."""
|
"""Test_process_model_create."""
|
||||||
process_group_a = ProcessGroup(
|
process_group_a = ProcessGroup(
|
||||||
id="group_a",
|
id="group_a",
|
||||||
display_name="Group A",
|
display_name="Group A",
|
||||||
|
@ -242,7 +235,6 @@ class TestNestedGroups(BaseTest):
|
||||||
content_type="application/json",
|
content_type="application/json",
|
||||||
data=json.dumps(ProcessModelInfoSchema().dump(process_model)),
|
data=json.dumps(ProcessModelInfoSchema().dump(process_model)),
|
||||||
)
|
)
|
||||||
print("test_process_model_add")
|
|
||||||
|
|
||||||
def test_process_group_show(
|
def test_process_group_show(
|
||||||
self,
|
self,
|
||||||
|
|
|
@ -105,14 +105,14 @@ class TestProcessApi(BaseTest):
|
||||||
assert response.json is not None
|
assert response.json is not None
|
||||||
assert response.json == expected_response_body
|
assert response.json == expected_response_body
|
||||||
|
|
||||||
def test_process_model_add(
|
def test_process_model_create(
|
||||||
self,
|
self,
|
||||||
app: Flask,
|
app: Flask,
|
||||||
client: FlaskClient,
|
client: FlaskClient,
|
||||||
with_db_and_bpmn_file_cleanup: None,
|
with_db_and_bpmn_file_cleanup: None,
|
||||||
with_super_admin_user: UserModel,
|
with_super_admin_user: UserModel,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Test_add_new_process_model."""
|
"""Test_process_model_create."""
|
||||||
process_group_id = "test_process_group"
|
process_group_id = "test_process_group"
|
||||||
process_group_display_name = "Test Process Group"
|
process_group_display_name = "Test Process Group"
|
||||||
# creates the group directory, and the json file
|
# creates the group directory, and the json file
|
||||||
|
|
|
@ -119,22 +119,21 @@ class TestSpecFileService(BaseTest):
|
||||||
== self.call_activity_nested_relative_file_path
|
== self.call_activity_nested_relative_file_path
|
||||||
)
|
)
|
||||||
|
|
||||||
def test_change_the_identifier_cleans_up_cache (
|
def test_change_the_identifier_cleans_up_cache(
|
||||||
self,
|
self,
|
||||||
app: Flask,
|
app: Flask,
|
||||||
client: FlaskClient,
|
client: FlaskClient,
|
||||||
with_db_and_bpmn_file_cleanup: None,
|
with_db_and_bpmn_file_cleanup: None,
|
||||||
with_super_admin_user: UserModel,
|
with_super_admin_user: UserModel,
|
||||||
) -> None:
|
) -> None:
|
||||||
""" When a BPMN processes identifier is changed in a file, the old id
|
"""When a BPMN processes identifier is changed in a file, the old id is removed from the cache."""
|
||||||
is removed from the cache"""
|
|
||||||
old_identifier = "ye_old_identifier"
|
old_identifier = "ye_old_identifier"
|
||||||
process_id_lookup = SpecReferenceCache(
|
process_id_lookup = SpecReferenceCache(
|
||||||
identifier=old_identifier,
|
identifier=old_identifier,
|
||||||
relative_path=self.call_activity_nested_relative_file_path,
|
relative_path=self.call_activity_nested_relative_file_path,
|
||||||
file_name=self.bpmn_file_name,
|
file_name=self.bpmn_file_name,
|
||||||
process_model_id=f"{self.process_group_id}/{self.process_model_id}",
|
process_model_id=f"{self.process_group_id}/{self.process_model_id}",
|
||||||
type='process'
|
type="process",
|
||||||
)
|
)
|
||||||
db.session.add(process_id_lookup)
|
db.session.add(process_id_lookup)
|
||||||
db.session.commit()
|
db.session.commit()
|
||||||
|
@ -157,7 +156,6 @@ class TestSpecFileService(BaseTest):
|
||||||
== self.call_activity_nested_relative_file_path
|
== self.call_activity_nested_relative_file_path
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def test_load_reference_information(
|
def test_load_reference_information(
|
||||||
self,
|
self,
|
||||||
app: Flask,
|
app: Flask,
|
||||||
|
|
|
@ -36,6 +36,7 @@ module.exports = {
|
||||||
],
|
],
|
||||||
'react/react-in-jsx-scope': 'off',
|
'react/react-in-jsx-scope': 'off',
|
||||||
'react/require-default-props': 'off',
|
'react/require-default-props': 'off',
|
||||||
|
'import/prefer-default-export': 'off',
|
||||||
'no-unused-vars': [
|
'no-unused-vars': [
|
||||||
'error',
|
'error',
|
||||||
{
|
{
|
||||||
|
|
|
@ -24,7 +24,7 @@ export default function App() {
|
||||||
[errorMessage]
|
[errorMessage]
|
||||||
);
|
);
|
||||||
|
|
||||||
const ability = defineAbility((can: any) => {});
|
const ability = defineAbility(() => {});
|
||||||
|
|
||||||
let errorTag = null;
|
let errorTag = null;
|
||||||
if (errorMessage) {
|
if (errorMessage) {
|
||||||
|
|
|
@ -74,10 +74,7 @@ export default function ProcessModelForm({
|
||||||
if (hasErrors) {
|
if (hasErrors) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
let path = `/process-models`;
|
const path = `/process-models/${modifiedProcessModelPath}`;
|
||||||
if (mode === 'edit') {
|
|
||||||
path = `/process-models/${modifiedProcessModelPath}`;
|
|
||||||
}
|
|
||||||
let httpMethod = 'POST';
|
let httpMethod = 'POST';
|
||||||
if (mode === 'edit') {
|
if (mode === 'edit') {
|
||||||
httpMethod = 'PUT';
|
httpMethod = 'PUT';
|
||||||
|
|
|
@ -52,10 +52,14 @@ import TouchModule from 'diagram-js/lib/navigation/touch';
|
||||||
// @ts-expect-error TS(7016) FIXME
|
// @ts-expect-error TS(7016) FIXME
|
||||||
import ZoomScrollModule from 'diagram-js/lib/navigation/zoomscroll';
|
import ZoomScrollModule from 'diagram-js/lib/navigation/zoomscroll';
|
||||||
|
|
||||||
|
import { Can } from '@casl/react';
|
||||||
import HttpService from '../services/HttpService';
|
import HttpService from '../services/HttpService';
|
||||||
|
|
||||||
import ButtonWithConfirmation from './ButtonWithConfirmation';
|
import ButtonWithConfirmation from './ButtonWithConfirmation';
|
||||||
import { makeid } from '../helpers';
|
import { makeid } from '../helpers';
|
||||||
|
import { useUriListForPermissions } from '../hooks/UriListForPermissions';
|
||||||
|
import { PermissionsToCheck } from '../interfaces';
|
||||||
|
import { usePermissionFetcher } from '../hooks/PermissionService';
|
||||||
|
|
||||||
type OwnProps = {
|
type OwnProps = {
|
||||||
processModelId: string;
|
processModelId: string;
|
||||||
|
@ -107,6 +111,13 @@ export default function ReactDiagramEditor({
|
||||||
|
|
||||||
const alreadyImportedXmlRef = useRef(false);
|
const alreadyImportedXmlRef = useRef(false);
|
||||||
|
|
||||||
|
const { targetUris } = useUriListForPermissions();
|
||||||
|
const permissionRequestData: PermissionsToCheck = {
|
||||||
|
[targetUris.processModelShowPath]: ['PUT'],
|
||||||
|
[targetUris.processModelFileShowPath]: ['POST', 'GET', 'PUT', 'DELETE'],
|
||||||
|
};
|
||||||
|
const { ability } = usePermissionFetcher(permissionRequestData);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (diagramModelerState) {
|
if (diagramModelerState) {
|
||||||
return;
|
return;
|
||||||
|
@ -517,20 +528,40 @@ export default function ReactDiagramEditor({
|
||||||
if (diagramType !== 'readonly') {
|
if (diagramType !== 'readonly') {
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Button onClick={handleSave} variant="danger">
|
<Can
|
||||||
Save
|
I="PUT"
|
||||||
</Button>
|
a={targetUris.processModelFileShowPath}
|
||||||
{fileName && (
|
ability={ability}
|
||||||
<ButtonWithConfirmation
|
>
|
||||||
description={`Delete file ${fileName}?`}
|
<Button onClick={handleSave}>Save</Button>
|
||||||
onConfirmation={handleDelete}
|
</Can>
|
||||||
buttonLabel="Delete"
|
<Can
|
||||||
/>
|
I="DELETE"
|
||||||
)}
|
a={targetUris.processModelFileShowPath}
|
||||||
{onSetPrimaryFile && (
|
ability={ability}
|
||||||
<Button onClick={handleSetPrimaryFile}>Set as primary file</Button>
|
>
|
||||||
)}
|
{fileName && (
|
||||||
<Button onClick={downloadXmlFile}>Download xml</Button>
|
<ButtonWithConfirmation
|
||||||
|
description={`Delete file ${fileName}?`}
|
||||||
|
onConfirmation={handleDelete}
|
||||||
|
buttonLabel="Delete"
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</Can>
|
||||||
|
<Can I="PUT" a={targetUris.processModelShowPath} ability={ability}>
|
||||||
|
{onSetPrimaryFile && (
|
||||||
|
<Button onClick={handleSetPrimaryFile}>
|
||||||
|
Set as primary file
|
||||||
|
</Button>
|
||||||
|
)}
|
||||||
|
</Can>
|
||||||
|
<Can
|
||||||
|
I="GET"
|
||||||
|
a={targetUris.processModelFileShowPath}
|
||||||
|
ability={ability}
|
||||||
|
>
|
||||||
|
<Button onClick={downloadXmlFile}>Download xml</Button>
|
||||||
|
</Can>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import { createContext } from 'react';
|
import { createContext } from 'react';
|
||||||
import { AbilityBuilder, Ability } from '@casl/ability';
|
import { Ability } from '@casl/ability';
|
||||||
import { createContextualCan } from '@casl/react';
|
import { createContextualCan } from '@casl/react';
|
||||||
|
|
||||||
export const AbilityContext = createContext(new Ability());
|
export const AbilityContext = createContext(new Ability());
|
||||||
|
|
|
@ -12,19 +12,17 @@ export const usePermissionFetcher = (
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const processPermissionResult = (result: PermissionCheckResponseBody) => {
|
const processPermissionResult = (result: PermissionCheckResponseBody) => {
|
||||||
const { can, cannot, rules } = new AbilityBuilder(Ability);
|
const { can, cannot, rules } = new AbilityBuilder(Ability);
|
||||||
for (const [url, permissionVerbResults] of Object.entries(
|
Object.keys(result.results).forEach((url: string) => {
|
||||||
result.results
|
const permissionVerbResults = result.results[url];
|
||||||
)) {
|
Object.keys(permissionVerbResults).forEach((permissionVerb: string) => {
|
||||||
for (const [permissionVerb, hasPermission] of Object.entries(
|
const hasPermission = permissionVerbResults[permissionVerb];
|
||||||
permissionVerbResults
|
|
||||||
)) {
|
|
||||||
if (hasPermission) {
|
if (hasPermission) {
|
||||||
can(permissionVerb, url);
|
can(permissionVerb, url);
|
||||||
} else {
|
} else {
|
||||||
cannot(permissionVerb, url);
|
cannot(permissionVerb, url);
|
||||||
}
|
}
|
||||||
}
|
});
|
||||||
}
|
});
|
||||||
ability.update(rules);
|
ability.update(rules);
|
||||||
};
|
};
|
||||||
HttpService.makeCallToBackend({
|
HttpService.makeCallToBackend({
|
||||||
|
|
|
@ -5,8 +5,10 @@ export const useUriListForPermissions = () => {
|
||||||
const targetUris = {
|
const targetUris = {
|
||||||
processGroupListPath: `/v1.0/process-groups`,
|
processGroupListPath: `/v1.0/process-groups`,
|
||||||
processGroupShowPath: `/v1.0/process-groups/${params.process_group_id}`,
|
processGroupShowPath: `/v1.0/process-groups/${params.process_group_id}`,
|
||||||
processModelListPath: `/v1.0/process-models`,
|
processModelCreatePath: `/v1.0/process-models/${params.process_group_id}`,
|
||||||
processModelShowPath: `/v1.0/process-models/${params.process_model_id}`,
|
processModelShowPath: `/v1.0/process-models/${params.process_model_id}`,
|
||||||
|
processModelFileCreatePath: `/v1.0/process-models/${params.process_model_id}/files`,
|
||||||
|
processModelFileShowPath: `/v1.0/process-models/${params.process_model_id}/files/${params.file_name}`,
|
||||||
processInstanceListPath: `/v1.0/process-instances`,
|
processInstanceListPath: `/v1.0/process-instances`,
|
||||||
processInstanceActionPath: `/v1.0/process-models/${params.process_model_id}/process-instances`,
|
processInstanceActionPath: `/v1.0/process-models/${params.process_model_id}/process-instances`,
|
||||||
};
|
};
|
||||||
|
|
|
@ -35,6 +35,8 @@ export default function ProcessGroupShow() {
|
||||||
const { targetUris } = useUriListForPermissions();
|
const { targetUris } = useUriListForPermissions();
|
||||||
const permissionRequestData: PermissionsToCheck = {
|
const permissionRequestData: PermissionsToCheck = {
|
||||||
[targetUris.processGroupListPath]: ['POST'],
|
[targetUris.processGroupListPath]: ['POST'],
|
||||||
|
[targetUris.processGroupShowPath]: ['PUT'],
|
||||||
|
[targetUris.processModelCreatePath]: ['POST'],
|
||||||
};
|
};
|
||||||
const { ability } = usePermissionFetcher(permissionRequestData);
|
const { ability } = usePermissionFetcher(permissionRequestData);
|
||||||
|
|
||||||
|
@ -159,23 +161,29 @@ export default function ProcessGroupShow() {
|
||||||
<Stack orientation="horizontal" gap={3}>
|
<Stack orientation="horizontal" gap={3}>
|
||||||
<Can I="POST" a={targetUris.processGroupListPath} ability={ability}>
|
<Can I="POST" a={targetUris.processGroupListPath} ability={ability}>
|
||||||
<Button
|
<Button
|
||||||
kind="secondary"
|
|
||||||
href={`/admin/process-groups/new?parentGroupId=${processGroup.id}`}
|
href={`/admin/process-groups/new?parentGroupId=${processGroup.id}`}
|
||||||
>
|
>
|
||||||
Add a process group
|
Add a process group
|
||||||
</Button>
|
</Button>
|
||||||
</Can>
|
</Can>
|
||||||
<Button
|
<Can
|
||||||
href={`/admin/process-models/${modifiedProcessGroupId}/new`}
|
I="POST"
|
||||||
|
a={targetUris.processModelCreatePath}
|
||||||
|
ability={ability}
|
||||||
>
|
>
|
||||||
Add a process model
|
<Button
|
||||||
</Button>
|
href={`/admin/process-models/${modifiedProcessGroupId}/new`}
|
||||||
<Button
|
>
|
||||||
href={`/admin/process-groups/${modifiedProcessGroupId}/edit`}
|
Add a process model
|
||||||
variant="secondary"
|
</Button>
|
||||||
>
|
</Can>
|
||||||
Edit process group
|
<Can I="PUT" a={targetUris.processGroupShowPath} ability={ability}>
|
||||||
</Button>
|
<Button
|
||||||
|
href={`/admin/process-groups/${modifiedProcessGroupId}/edit`}
|
||||||
|
>
|
||||||
|
Edit process group
|
||||||
|
</Button>
|
||||||
|
</Can>
|
||||||
</Stack>
|
</Stack>
|
||||||
<br />
|
<br />
|
||||||
<br />
|
<br />
|
||||||
|
|
|
@ -106,9 +106,10 @@ export default function ProcessModelShow() {
|
||||||
|
|
||||||
const { targetUris } = useUriListForPermissions();
|
const { targetUris } = useUriListForPermissions();
|
||||||
const permissionRequestData: PermissionsToCheck = {
|
const permissionRequestData: PermissionsToCheck = {
|
||||||
[targetUris.processModelShowPath]: ['GET', 'PUT'],
|
[targetUris.processModelShowPath]: ['PUT'],
|
||||||
[targetUris.processInstanceListPath]: ['GET'],
|
[targetUris.processInstanceListPath]: ['GET'],
|
||||||
[targetUris.processInstanceActionPath]: ['POST'],
|
[targetUris.processInstanceActionPath]: ['POST'],
|
||||||
|
[targetUris.processModelFileCreatePath]: ['POST', 'GET', 'DELETE'],
|
||||||
};
|
};
|
||||||
const { ability } = usePermissionFetcher(permissionRequestData);
|
const { ability } = usePermissionFetcher(permissionRequestData);
|
||||||
|
|
||||||
|
@ -263,50 +264,62 @@ export default function ProcessModelShow() {
|
||||||
) => {
|
) => {
|
||||||
const elements = [];
|
const elements = [];
|
||||||
elements.push(
|
elements.push(
|
||||||
<Button
|
<Can I="GET" a={targetUris.processModelFileCreatePath} ability={ability}>
|
||||||
kind="ghost"
|
<Button
|
||||||
renderIcon={Edit}
|
kind="ghost"
|
||||||
iconDescription="Edit File"
|
renderIcon={Edit}
|
||||||
hasIconOnly
|
iconDescription="Edit File"
|
||||||
size="lg"
|
hasIconOnly
|
||||||
data-qa={`edit-file-${processModelFile.name.replace('.', '-')}`}
|
size="lg"
|
||||||
onClick={() => navigateToFileEdit(processModelFile)}
|
data-qa={`edit-file-${processModelFile.name.replace('.', '-')}`}
|
||||||
/>
|
onClick={() => navigateToFileEdit(processModelFile)}
|
||||||
|
/>
|
||||||
|
</Can>
|
||||||
);
|
);
|
||||||
elements.push(
|
elements.push(
|
||||||
<Button
|
<Can I="GET" a={targetUris.processModelFileCreatePath} ability={ability}>
|
||||||
kind="ghost"
|
<Button
|
||||||
renderIcon={Download}
|
kind="ghost"
|
||||||
iconDescription="Download File"
|
renderIcon={Download}
|
||||||
hasIconOnly
|
iconDescription="Download File"
|
||||||
size="lg"
|
hasIconOnly
|
||||||
onClick={() => downloadFile(processModelFile.name)}
|
size="lg"
|
||||||
/>
|
onClick={() => downloadFile(processModelFile.name)}
|
||||||
|
/>
|
||||||
|
</Can>
|
||||||
);
|
);
|
||||||
|
|
||||||
elements.push(
|
elements.push(
|
||||||
<ButtonWithConfirmation
|
<Can
|
||||||
kind="ghost"
|
I="DELETE"
|
||||||
renderIcon={TrashCan}
|
a={targetUris.processModelFileCreatePath}
|
||||||
iconDescription="Delete File"
|
ability={ability}
|
||||||
hasIconOnly
|
>
|
||||||
description={`Delete file: ${processModelFile.name}`}
|
<ButtonWithConfirmation
|
||||||
onConfirmation={() => {
|
kind="ghost"
|
||||||
onDeleteFile(processModelFile.name);
|
renderIcon={TrashCan}
|
||||||
}}
|
iconDescription="Delete File"
|
||||||
confirmButtonLabel="Delete"
|
hasIconOnly
|
||||||
/>
|
description={`Delete file: ${processModelFile.name}`}
|
||||||
|
onConfirmation={() => {
|
||||||
|
onDeleteFile(processModelFile.name);
|
||||||
|
}}
|
||||||
|
confirmButtonLabel="Delete"
|
||||||
|
/>
|
||||||
|
</Can>
|
||||||
);
|
);
|
||||||
if (processModelFile.name.match(/\.bpmn$/) && !isPrimaryBpmnFile) {
|
if (processModelFile.name.match(/\.bpmn$/) && !isPrimaryBpmnFile) {
|
||||||
elements.push(
|
elements.push(
|
||||||
<Button
|
<Can I="PUT" a={targetUris.processModelShowPath} ability={ability}>
|
||||||
kind="ghost"
|
<Button
|
||||||
renderIcon={Favorite}
|
kind="ghost"
|
||||||
iconDescription="Set As Primary File"
|
renderIcon={Favorite}
|
||||||
hasIconOnly
|
iconDescription="Set As Primary File"
|
||||||
size="lg"
|
hasIconOnly
|
||||||
onClick={() => onSetPrimaryFile(processModelFile.name)}
|
size="lg"
|
||||||
/>
|
onClick={() => onSetPrimaryFile(processModelFile.name)}
|
||||||
|
/>
|
||||||
|
</Can>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
return elements;
|
return elements;
|
||||||
|
@ -337,7 +350,11 @@ export default function ProcessModelShow() {
|
||||||
let fileLink = null;
|
let fileLink = null;
|
||||||
const fileUrl = profileModelFileEditUrl(processModelFile);
|
const fileUrl = profileModelFileEditUrl(processModelFile);
|
||||||
if (fileUrl) {
|
if (fileUrl) {
|
||||||
fileLink = <Link to={fileUrl}>{processModelFile.name}</Link>;
|
if (ability.can('GET', targetUris.processModelFileCreatePath)) {
|
||||||
|
fileLink = <Link to={fileUrl}>{processModelFile.name}</Link>;
|
||||||
|
} else {
|
||||||
|
fileLink = <span>{processModelFile.name}</span>;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
constructedTag = (
|
constructedTag = (
|
||||||
<TableRow key={processModelFile.name}>
|
<TableRow key={processModelFile.name}>
|
||||||
|
@ -442,47 +459,53 @@ export default function ProcessModelShow() {
|
||||||
</Stack>
|
</Stack>
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
<ButtonSet>
|
<Can
|
||||||
<Button
|
I="POST"
|
||||||
renderIcon={Upload}
|
a={targetUris.processModelFileCreatePath}
|
||||||
data-qa="upload-file-button"
|
ability={ability}
|
||||||
onClick={() => setShowFileUploadModal(true)}
|
>
|
||||||
size="sm"
|
<ButtonSet>
|
||||||
kind=""
|
<Button
|
||||||
className="button-white-background"
|
renderIcon={Upload}
|
||||||
>
|
data-qa="upload-file-button"
|
||||||
Upload File
|
onClick={() => setShowFileUploadModal(true)}
|
||||||
</Button>
|
size="sm"
|
||||||
<Button
|
kind=""
|
||||||
renderIcon={Add}
|
className="button-white-background"
|
||||||
href={`/admin/process-models/${modifiedProcessModelId}/files?file_type=bpmn`}
|
>
|
||||||
size="sm"
|
Upload File
|
||||||
>
|
</Button>
|
||||||
New BPMN File
|
<Button
|
||||||
</Button>
|
renderIcon={Add}
|
||||||
<Button
|
href={`/admin/process-models/${modifiedProcessModelId}/files?file_type=bpmn`}
|
||||||
renderIcon={Add}
|
size="sm"
|
||||||
href={`/admin/process-models/${modifiedProcessModelId}/files?file_type=dmn`}
|
>
|
||||||
size="sm"
|
New BPMN File
|
||||||
>
|
</Button>
|
||||||
New DMN File
|
<Button
|
||||||
</Button>
|
renderIcon={Add}
|
||||||
<Button
|
href={`/admin/process-models/${modifiedProcessModelId}/files?file_type=dmn`}
|
||||||
renderIcon={Add}
|
size="sm"
|
||||||
href={`/admin/process-models/${modifiedProcessModelId}/form?file_ext=json`}
|
>
|
||||||
size="sm"
|
New DMN File
|
||||||
>
|
</Button>
|
||||||
New JSON File
|
<Button
|
||||||
</Button>
|
renderIcon={Add}
|
||||||
<Button
|
href={`/admin/process-models/${modifiedProcessModelId}/form?file_ext=json`}
|
||||||
renderIcon={Add}
|
size="sm"
|
||||||
href={`/admin/process-models/${modifiedProcessModelId}/form?file_ext=md`}
|
>
|
||||||
size="sm"
|
New JSON File
|
||||||
>
|
</Button>
|
||||||
New Markdown File
|
<Button
|
||||||
</Button>
|
renderIcon={Add}
|
||||||
</ButtonSet>
|
href={`/admin/process-models/${modifiedProcessModelId}/form?file_ext=md`}
|
||||||
<br />
|
size="sm"
|
||||||
|
>
|
||||||
|
New Markdown File
|
||||||
|
</Button>
|
||||||
|
</ButtonSet>
|
||||||
|
<br />
|
||||||
|
</Can>
|
||||||
{processModelFileList()}
|
{processModelFileList()}
|
||||||
</AccordionItem>
|
</AccordionItem>
|
||||||
</Accordion>
|
</Accordion>
|
||||||
|
|
Loading…
Reference in New Issue