Skip to content

Commit

Permalink
resources actions (#19)
Browse files Browse the repository at this point in the history
* delete resource button application

* added routes for deleted resources

* locales update

* locales update and redirection

* locales update and redirection

* init Deleted Detail container

* init Resources Deleted List container

* translations update

* locales update

* locales update for breadcrumbs and sidebar

* delete call params update

* layout update

* locales update

* Deleted resources sidebar item removal

* deletedResourcesList button in ResourcesListContainer

* adjustment of action buttons layout

* translations and Deleted Resources button in card header

* CHANGELOG.md update

* locales update

* translations update, obsolete code removal, button titles

* go back button init, translations update, datatable icon update

* submodule update

* locales update

* init retrive rerource prompt before the call

* locales update

* translations update

* comments, syntax update

* indentaion, comments, retrievePrompt renamed to confirmationPrompt

* isolating ButtonWithAuthz's resource to a variable

* isolating ButtonWithAuthz's resource to a variable

* rerouting path update, useEffect applied to condition where resource is falsy

* routes update

* routes update

* rendering condition update to prevent undefined

* link pathname update

* conditional rendering, console.log removal

* ButtonWithAuthz resource as a variable

* styling update - min height for .resource-detail-description

* inline styling removal

* locales update

* route update for resource deletion

* path update from /resources/deleted/ to /resources-deleted/

* whitespace removal

* naming unification

* naming unification

* grid area in resource detail container

* resoure update for delete button

* resoure update, improved code defence

* css grid application

* button with authz resource as a variable

* renaming container

* deleted resource detail container route update

* resource renaming

* .DS_Store removal

* resources renaming

* locales update

* create resource result check

* get deleted resoures params update

* button with authz instead of regular button in DeleteResourceButton

* get resources api call adjusment

* get data for deleted resources list call update

* obsolete code removal

* DeletedResourceDetailConatiner naming update

* obsolete code removal

* access resource update

* substituing regular buttons with ButtonWithAuthz

* locales udpate

* Button title update

* obsolete code removal - extra resource removal

* overengineered code removal - removal contentloader delay function

* resource update for DeletedResources routes in index.js

* naming update

* reosurce update

* routes resources update

---------

Co-authored-by: Petr Kavulok <petrkavulok@Petrs-MacBook-Pro.local>
  • Loading branch information
petrKavulok and Petr Kavulok authored May 26, 2023
1 parent 28a52a5 commit a262085
Show file tree
Hide file tree
Showing 11 changed files with 657 additions and 139 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@ Tested with Seacat Auth service [v23.13-beta](https://github.com/TeskaLabs/seaca

- ASAB WebUI submodule version bump [[1960466](https://github.com/TeskaLabs/asab-webui/commit/1960466a45d0c48ec279e703317ebf0a59fdcbda)] commit (INDIGO Sprint 230317, [!22](https://github.com/TeskaLabs/seacat-admin-webui/pull/22))

- Resources actions extended. Added posibility to rename, delete, hard-delete and retrieve resources (INDIGO Sprint 230217, [!19](https://github.com/TeskaLabs/seacat-admin-webui/pull/19))

### Refactoring

- Dropdown menu used to assign `tenants` nad `roles` to specific `Credentials` has been refactored to offer more data than the initial limit, upon clicking the 'More ...' button. (INDIGO Sprint 230203, [!14](https://github.com/TeskaLabs/seacat-admin-webui/pull/14))
Expand Down
44 changes: 38 additions & 6 deletions public/locales/cs/translation.json
Original file line number Diff line number Diff line change
Expand Up @@ -66,10 +66,12 @@
"Resources": "Zdroje",
"New resource": "Nový zdroj",
"Resource detail": "Detail zdroje",
"Deleted resources": "Odstraněné zdroje",
"Deleted resource detail": "Detail odstraněného zdroje",
"Roles": "Role",
"New roles": "Nové role",
"Role detail": "Detail role",
"Credentials": "Uživ. Identifikace",
"Credentials": "Uživatelské údaje",
"New credentials": "Nové uživ. údaje",
"Credentials detail": "Detail uživ. údajů",
"Reset password": "Obnovení hesla",
Expand Down Expand Up @@ -365,18 +367,48 @@
"Invalid format, resource cannot start with a underscore": "Nesprávný formát, zdroj nemůže začínat podtržítkem",
"Invalid format, only lower-case letters, numbers, dash and underscore are allowed": "Nesprávný formát, pouze malá písmena, číslice, pomlčka a podtržítko jsou povoleny",
"Only lower-case letters, numbers, dash and underscore are allowed": "Pouze malá písmena, číslice, pomlčka a podtržítko jsou povoleny",
"Something went wrong, failed to create resource": "Něco je špatně, nepodařilo se vytvořit zdroj"
"Failed to create resource": "Nepodařilo se vytvořit zdroj"
},
"ResourcesDetailContainer": {
"Resource": "Zdroj",
"Delete resource": "Odstranit zdroj",
"Resource updated successfully": "Zdroj byl úspěšně aktualizován",
"Something went wrong, can't fetch resource details": "Něco je špatně, nepodařilo se načíst zdroj",
"Something went wrong, failed to update resource": "Něco je špatně, aktualizace zdroje se nezdařila"
"Can't fetch resource details": "Nepodařilo se načíst zdroj",
"Failed to update resource": "Aktualizace zdroje se nezdařila",
"Failed to delete resource": "Odstranění zdroje se nezdařilo",
"Resource successfully deleted": "Zdroj byl úspěšně odstraněn",
"Do you really want to delete this resource": "Opravdu si přejete odstranit tento zdroj?"
},
"ResourcesListContainer": {
"Resources list": "Seznam zdrojů",
"Create resource": "Vytvořit zdroj",
"Something went wrong, failed to load resources": "Něco je špatně, nepodařilo se načíst zdroje"
"Delete resource": "Odstranit zdroj",
"Deleted resources": "Odstraněné zdroje",
"Failed to load resources": "Nepodařilo se načíst zdroje",
"Failed to delete the resource": "Nepodařilo se odstranit zdroj",
"Do you want to delete this resource": "Přejete si tento zdroj odstranit?",
"Resource successfully deleted": "Zdroj byl úspěšně odstraněn"
},
"ResourcesDeletedDetailContainer": {
"Resource": "Zdroj",
"Hard-delete": "Trvale odstranit",
"Retrieve": "Obnovit zdroj",
"Can't fetch resource details": "Nepodařilo se načíst zdroj",
"Failed to hard-delete this resource": "Nepodařilo se trvale odstranit tento zdroj",
"Failed to retrieve resource": "Obnova zdroje se nezdařila",
"Resource retrieved successfuly": "Obnova zdroje proběhla úspěšně",
"Resource was successfully hard-deleted": "Zdroj byl úspěšně trvale odstranit",
"Do you really want to hard-delete this resource": "Opravdu si přejete trvale odstranit zdroj?",
"Do you really want to retrieve this resource": "Opravdu si přejete obnovit zdroj?"
},
"ResourcesDeletedListContainer": {
"Back": "Zpět",
"Retrieve resource": "Obnovit zdroj",
"Resource retrieved successfuly": "Obnova zdroje proběhla úspěšně",
"Failed to load resources": "Nepodařilo se načíst zdroje",
"Failed to retrieve resource": "Obnova zdroje se nezdařila",
"Deleted resources": "Seznam odstraněných zdrojů",
"Do you really want to retrieve this resource": "Opravdu si přejete obnovit zdroj?"
},
"SessionListContainer": {
"Credentials": "Uživ. Identifikace",
Expand Down Expand Up @@ -508,7 +540,7 @@
"Sidebar": {
"About": "O Aplikaci",
"Auth": "Autorizace",
"Credentials": "Uživ. Identifikace",
"Credentials": "Uživatelé",
"Tenants": "Tenanti",
"Sessions": "Relace",
"Roles": "Role",
Expand Down
39 changes: 35 additions & 4 deletions public/locales/en/translation.json
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,8 @@
"Resources": "Resources",
"New resource": "New resource",
"Resource detail": "Resource detail",
"Deleted resources": "Deleted resources",
"Deleted resource detail": "Deleted resource detail",
"Roles": "Roles",
"New roles": "New roles",
"Role detail": "Role detail",
Expand Down Expand Up @@ -365,18 +367,47 @@
"Invalid format, resource cannot start with a underscore": "Invalid format, resource cannot start with a underscore",
"Invalid format, only letters, numbers, dash and underscore are allowed": "Invalid format, only letters, numbers, dash and underscore are allowed",
"Only lower-case letters, numbers, dash and underscore are allowed": "Only lower-case letters, numbers, dash and underscore are allowed",
"Something went wrong, failed to create resource": "Something went wrong, failed to create resource"
"Failed to create resource": "Failed to create resource"
},
"ResourcesDetailContainer": {
"Resource": "Resource",
"Delete resource": "Delete resource",
"Resource updated successfully": "Resource updated successfully",
"Something went wrong, can't fetch resource details": "Something went wrong, can't fetch resource details",
"Something went wrong, failed to update resource": "Something went wrong, failed to update resource"
"Can't fetch resource details": "Can't fetch resource details",
"Failed to update resource": "Failed to update resource",
"Failed to delete resource": "Failed to delete resource",
"Resource successfully deleted": "Resource successfully deleted",
"Do you really want to delete this resource": "Do you really want to delete this resource"
},
"ResourcesListContainer": {
"Resources list": "Resources list",
"Create resource": "Create resource",
"Something went wrong, failed to load resources": "Something went wrong, failed to load resources"
"Delete resource": "Delete resource",
"Deleted resources": "Deleted resources",
"Failed to load resources": "Failed to load resources",
"Failed to delete the resource": "Failed to delete the resource",
"Do you want to delete this resource": "Do you want to delete this resource?",
"Resource successfully deleted": "Resource successfully deleted"
},
"ResourcesDeletedDetailContainer": {
"Hard-delete": "Hard-delete",
"Retrieve": "Retrieve",
"Can't fetch resource details": "Can't fetch resource details",
"Failed to hard-delete this resource": "Failed to hard-delete this resource",
"Failed to retrieve resource": "Failed to retrieve resource",
"Resource retrieved successfuly": "Resource retrieved successfuly",
"Resource was successfully hard-deleted": "Resource was successfully hard-deleted",
"Do you really want to hard-delete this resource": "Do you really want to hard-delete this resource?",
"Do you really want to retrieve this resource": "Do you really want to retrieve this resource?"
},
"ResourcesDeletedListContainer": {
"Back": "Back",
"Retrieve resource": "Retrieve resource",
"Resource retrieved successfuly": "Resource retrieved successfuly",
"Failed to load resources": "Failed to load resources",
"Failed to retrieve resource": "Failed to retrieve resource",
"Deleted resources": "Deleted resources",
"Do you really want to retrieve this resource": "Do you really want to retrieve this resource?"
},
"SessionListContainer": {
"Credentials": "Credentials",
Expand Down
6 changes: 3 additions & 3 deletions src/modules/auth/credentials/CredentialsSessionCard.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ import { useTranslation } from 'react-i18next';
import { Link } from "react-router-dom";

import {
Row, Col,
Card, CardHeader, CardFooter, CardBody
Row, Col, CardHeader,
Card, CardFooter, CardBody
} from 'reactstrap';

import { ButtonWithAuthz } from 'asab-webui';
Expand Down Expand Up @@ -61,7 +61,7 @@ function CredentialsSessionCard(props) {
</CardBody>
<CardFooter>
<ButtonWithAuthz
title={t("CredentialsSessionCard|Terminate user sessions")}
title={t("CredentialsSessionCard|Log out")}
id={props.credentials_id}
color="danger"
outline
Expand Down
22 changes: 19 additions & 3 deletions src/modules/auth/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,11 @@ const RolesCreateContainer = lazy(() => componentLoader(() => import('./roles/Ro
const RolesListContainer = lazy(() => componentLoader(() => import('./roles/RolesListContainer')));
const RolesDetailContainer = lazy(() => componentLoader(() => import('./roles/RolesDetailContainer')));

const ResourcesListContainer =lazy(() => componentLoader(() => import('./resources/ResourcesListContainer')));
const ResourcesDetailContainer =lazy(() => componentLoader(() => import('./resources/ResourcesDetailContainer')));
const ResourcesCreateContainer =lazy(() => componentLoader(() => import('./resources/ResourcesCreateContainer')));
const ResourcesListContainer = lazy(() => componentLoader(() => import('./resources/ResourcesListContainer')));
const ResourcesDetailContainer = lazy(() => componentLoader(() => import('./resources/ResourcesDetailContainer')));
const ResourcesCreateContainer = lazy(() => componentLoader(() => import('./resources/ResourcesCreateContainer')));
const ResourcesDeletedListContainer = lazy(() => componentLoader(() => import('./resources/ResourcesDeletedListContainer')));;
const DeletedResourceDetailContainer = lazy(() => componentLoader(() => import('./resources/DeletedResourceDetailContainer')));;

const ClientListContainer = lazy(() => componentLoader(() => import('./clients/ClientListContainer')));
const ClientCreateContainer = lazy(() => componentLoader(() => import('./clients/ClientCreateContainer')));
Expand Down Expand Up @@ -54,6 +56,20 @@ export default class SeaCatAuthModule extends Module {
component: ResourcesCreateContainer,
resource: "seacat:resource:access"
});
app.Router.addRoute({
path: '/auth/resources-deleted',
exact: true,
name: 'Deleted resources',
component: ResourcesDeletedListContainer,
resource: 'authz:superuser'
});
app.Router.addRoute({
path: '/auth/resources-deleted/:resource_id',
exact: true,
name: 'Deleted resource detail',
component: DeletedResourceDetailContainer,
resource: 'authz:superuser'
});
app.Router.addRoute({
path: '/auth/resources/:resource_id',
exact: true,
Expand Down
162 changes: 162 additions & 0 deletions src/modules/auth/resources/DeletedResourceDetailContainer.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,162 @@
import React, { useState, useEffect } from 'react';
import { useSelector } from 'react-redux';
import { useTranslation } from 'react-i18next';

import {
Container, Row, Col, Card,
CardHeader, CardBody, Button,
CardFooter, ButtonGroup
} from 'reactstrap';

import { DateTime, ButtonWithAuthz } from 'asab-webui';

const DeletedResourceDetailContainer = (props) => {
const { t } = useTranslation();
const SeaCatAuthAPI = props.app.axiosCreate('seacat_auth');
const [resource, setResource] = useState(undefined);
const [editMode, setEditMode] = useState(false);
const { resource_id } = props.match.params;

const editResource = "authz:superuser";
const resources = useSelector(state => state.auth?.resources);

useEffect(() => {
getResourceDetail(resource_id);
}, []);

useEffect(() => {
if (!resource) return null;
}, [resource]);

const getResourceDetail = async (resourceId) => {
try {
let response = await SeaCatAuthAPI.get(`resource/${resourceId}`);
setResource(response.data);
} catch(e) {
console.error(e);
props.app.addAlert("warning", `${t("ResourcesDeletedDetailContainer|Can't fetch resource details")}. ${e?.response?.data?.message}`, 30);
}
}

// Set delete resource dialog
const confirmForm = (type) => {
var r = confirm(t(`ResourcesDeletedDetailContainer|Do you really want to ${type === "delete" ? 'hard-delete' : 'retrieve'} this resource`));
if (r == true) {
if (type === "delete") {
hardDelete();
} else {
retrieveResource();
}
}
}

// Retrieve the resource
const retrieveResource = async () => {
try {
let response = await SeaCatAuthAPI.post(`/resource/${resource_id}`, {});
if (response.data.result !== "OK") {
throw new Error(t("ResourcesDeletedDetailContainer|Failed to retrieve resource"));
}
props.app.addAlert("success", t("ResourcesDeletedDetailContainer|Resource retrieved successfuly"));
props.history.push("/auth/resources");
} catch(e) {
console.error(e);
props.app.addAlert("warning", `${t("ResourcesDeletedDetailContainer|Failed to retrieve resource")}. ${e?.response?.data?.message}`, 30);
}
}

// Hard-deletes selected resource. After this action, the resource cannot be retrieved anymore.
const hardDelete = async () => {
try {
let response = await SeaCatAuthAPI.delete(`/resource/${resource_id}`, { params: { hard_delete: true } });
if (response.data.result !== "OK") {
throw new Error(t("ResourcesDeletedDetailContainer|Failed to hard-delete this resource"));
}
props.app.addAlert("success", t("ResourcesDeletedDetailContainer|Resource was successfully hard-deleted"));
props.history.push("/auth/resources");
} catch(e) {
console.error(e);
props.app.addAlert("warning", `${t("ResourcesDeletedDetailContainer|Failed to hard-delete this resource")}. ${e?.response?.data?.message}`, 30);
}
}

return (
<Container className="resource-container">
<Card className='reosurce-detail-description'>
<CardHeader className="border-bottom">
<div className="card-header-title">
<i className="cil-lock-locked pr-2"></i>
{t("ResourcesDeletedDetailContainer|Resource")}
</div>
</CardHeader>

<CardBody>
<Row>
<Col md={3}>{t("Name")}</Col>
<Col>{resource?._id}</Col>
</Row>
<Row className="mt-3">
<Col md={3}>{t("Created at")}</Col>
<Col><DateTime value={resource?._c} /></Col>
</Row>
<Row>
<Col md={3}>{t("Modified at")}</Col>
<Col><DateTime value={resource?._m} /></Col>
</Row>
<Row className='mt-3'>
<Col sm={3}>{t("Description")}</Col>
<Col sm={6} className="resource-detail-description">{resource?.description}</Col>
</Row>
</CardBody>

<CardFooter>
{editMode ?
<>
<ButtonGroup>
<Button
color="outline-primary"
type="button"
title={t("Cancel")}
onClick={(e) => (setEditMode(false))}
>
{t("Cancel")}
</Button>
</ButtonGroup>
<div className="actions-right">
<Button
color="primary"
onClick={() => confirmForm("retrieve")}
title={t("ResourcesDeletedDetailContainer|Retrieve")}
>
{t("ResourcesDeletedDetailContainer|Retrieve")}
</Button>
<Button
color="danger"
type="button"
onClick={() => confirmForm("delete")}
title={t("ResourcesDeletedDetailContainer|Hard-delete")}
>
{t("ResourcesDeletedDetailContainer|Hard-delete")}
</Button>
</div>
</>
:
<ButtonWithAuthz
color="primary"
outline
type="button"
onClick={(e) => (e.preventDefault(), setEditMode(true))}
resources={resources}
resource={editResource}
title={t("Edit")}
>
{t("Edit")}
</ButtonWithAuthz>
}
</CardFooter>
</Card>
</Container>
);
}

export default DeletedResourceDetailContainer;
7 changes: 5 additions & 2 deletions src/modules/auth/resources/ResourcesCreateContainer.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,18 +36,21 @@ const ResourceCreateContainer = (props) => {
let body = {};
body["description"] = values.resource_description;
try {
let res = await SeaCatAuthAPI.post(`/resource/${values.resource_id}`,
let response = await SeaCatAuthAPI.post(`/resource/${values.resource_id}`,
JSON.stringify(body),
{
headers: {
'Content-Type': 'application/json'
}
});
if (response.data.result != "OK"){
throw new Error(t('ResourcesCreateContainer|Failed to create resource'));
}
props.app.addAlert("success", t("ResourcesCreateContainer|Resource created"));
props.history.push("/auth/resources");
} catch(e) {
console.error(e);
props.app.addAlert("warning", `${t("ResourcesCreateContainer|Something went wrong, failed to create resource")}. ${e?.response?.data?.message}`, 30);
props.app.addAlert("warning", `${t("ResourcesCreateContainer|Failed to create resource")}. ${e?.response?.data?.message}`, 30);
}
}

Expand Down
Loading

0 comments on commit a262085

Please sign in to comment.