Skip to content

Commit

Permalink
feat(admin-ui): Display the modified fields in the audit log modal fo…
Browse files Browse the repository at this point in the history
…r sub-items within the auth server. (#1969)

* fix: removable select value

* feat: update search on scope form

* feat: Add audit logs in ODIC Clients

* fix: reslove sonar qube issues

* fix: resolve code smells issues

* fix: collapsable detail in Audit-logs
  • Loading branch information
mjatin-dev authored Jan 29, 2025
1 parent 1ba639f commit f0d0c32
Show file tree
Hide file tree
Showing 20 changed files with 1,492 additions and 646 deletions.
19 changes: 18 additions & 1 deletion admin-ui/app/routes/Apps/Gluu/GluuAutoCompleteWithAdd.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import GluuLabel from '../Gluu/GluuLabel'
import GluuTooltip from './GluuTooltip'
import { useTranslation } from 'react-i18next'
import { ThemeContext } from 'Context/theme/themeContext'
import PropTypes from "prop-types";

function GluuAutoCompleteWithAdd({
label,
Expand All @@ -16,6 +17,7 @@ function GluuAutoCompleteWithAdd({
formik = undefined,
placeholder,
doc_category,
handler=null
}) {
const [items, setItems] = useState(value)
const [opts, setOpts] = useState(options)
Expand All @@ -29,7 +31,10 @@ function GluuAutoCompleteWithAdd({
if (validator(newItem)) {
setItems((currItems) => [...currItems, newItem])
setOpts((currOpts) => [...currOpts, newItem])
formik.setFieldValue(name, items)
formik.setFieldValue(name, items);
if (handler) {
handler(name, items)
}
}
}

Expand Down Expand Up @@ -85,4 +90,16 @@ function GluuAutoCompleteWithAdd({
)
}

GluuAutoCompleteWithAdd.propTypes = {
label: PropTypes.string,
name: PropTypes.string,
value: PropTypes.array,
options: PropTypes.array,
validator: PropTypes.func,
inputId: PropTypes.string,
formik: PropTypes.object,
placeholder: PropTypes.string,
doc_category: PropTypes.string,
handler: PropTypes.func
}
export default GluuAutoCompleteWithAdd
272 changes: 172 additions & 100 deletions admin-ui/app/routes/Apps/Gluu/GluuCommitDialog.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React, { useState, useEffect, useContext } from 'react'
import React, { useState, useEffect, useContext } from "react";
import {
FormGroup,
Col,
Expand All @@ -9,15 +9,20 @@ import {
ModalHeader,
ModalBody,
ModalFooter,
} from 'reactstrap'
import { useTranslation } from 'react-i18next'
import { ThemeContext } from 'Context/theme/themeContext'
import PropTypes from 'prop-types'
import { useSelector } from 'react-redux'
import useWebhookDialogAction from 'Utils/hooks/useWebhookDialogAction'
import { hasPermission, WEBHOOK_READ } from 'Utils/PermChecker'
Collapse,
Card,
CardBody,
} from "reactstrap";
import { useTranslation } from "react-i18next";
import { ThemeContext } from "Context/theme/themeContext";
import PropTypes from "prop-types";
import KeyboardArrowDownIcon from "@mui/icons-material/KeyboardArrowDown";
import KeyboardArrowUpIcon from "@mui/icons-material/KeyboardArrowUp";
import { useSelector } from "react-redux";
import useWebhookDialogAction from "Utils/hooks/useWebhookDialogAction";
import { hasPermission, WEBHOOK_READ } from "Utils/PermChecker";

const USER_MESSAGE = 'user_action_message'
const USER_MESSAGE = "user_action_message";

const GluuCommitDialog = ({
handler,
Expand All @@ -30,144 +35,211 @@ const GluuCommitDialog = ({
inputType,
feature,
}) => {
const permissions = useSelector((state) => state.authReducer.permissions)
const { t } = useTranslation()
const theme = useContext(ThemeContext)
const selectedTheme = theme.state.theme
const [active, setActive] = useState(false)
const [userMessage, setUserMessage] = useState('')
const permissions = useSelector((state) => state.authReducer.permissions);
const { t } = useTranslation();
const theme = useContext(ThemeContext);
const selectedTheme = theme.state.theme;
const [active, setActive] = useState(false);
const [isOpen, setIsOpen] = useState(null);
const [userMessage, setUserMessage] = useState("");
const { loadingWebhooks, webhookModal } = useSelector(
(state) => state.webhookReducer
)

);
const { webhookTriggerModal, onCloseModal } = useWebhookDialogAction({
feature,
modal,
})
});

useEffect(() => {
if (userMessage.length >= 10) {
setActive(true)
setActive(true);
} else {
setActive(false)
setActive(false);
}
}, [userMessage])
}, [userMessage]);

function handleAccept() {
if (formik) {
formik.setFieldValue('action_message', userMessage)
formik.setFieldValue("action_message", userMessage);
}
onAccept(userMessage)
setUserMessage('')
onAccept(userMessage);
setUserMessage("");
}
const closeModal = () => {
handler()
setUserMessage('')
onCloseModal()
}
handler();
setUserMessage("");
onCloseModal();
};

if (!modal) {
return <></>
return <></>;
}

const renderBadges = (values) => {
return (
<div className="d-flex flex-column gap-1 align-items-start">
{values.map((data, index) => (
<Badge
color={`primary-${selectedTheme} `}
style={{ width: "fit-content" }}
key={String(data)}
>
{JSON.stringify(data)}
</Badge>
))}
</div>
);
};
return (
<>
{(webhookModal || loadingWebhooks) && hasPermission(permissions, WEBHOOK_READ) ? (
{(webhookModal || loadingWebhooks) &&
hasPermission(permissions, WEBHOOK_READ) ? (
<>{webhookTriggerModal({ closeModal })}</>
) : (
<Modal
isOpen={modal}
size={'lg'}
size={"lg"}
toggle={closeModal}
className='modal-outline-primary'
className="modal-outline-primary"
>
<ModalHeader toggle={closeModal}>
<i
onClick={closeModal}
onKeyDown={() => {}}
style={{ color: 'green' }}
className='fa fa-2x fa-info fa-fw modal-icon mb-3'
role='img'
aria-hidden='true'
style={{ color: "green" }}
className="fa fa-2x fa-info fa-fw modal-icon mb-3"
role="img"
aria-hidden="true"
></i>
{!label || label === ''
? t('messages.action_commit_question')
{!label || label === ""
? t("messages.action_commit_question")
: label}
</ModalHeader>
<ModalBody>
{operations && <FormGroup row>List of changes</FormGroup>}
{operations &&
operations.map((item, key) => (
<FormGroup row key={key}>
<Col sm={1}>Set</Col>
<Col sm={5} style={{ overflow: 'auto' }}>
<Badge color={`primary-${selectedTheme}`}>
{item.path}
</Badge>
</Col>
<Col sm={1}>to</Col>
<Col sm={5} style={{ overflow: 'auto' }}>
{Array.isArray(item.value) ? (
<>
{item.value.map((data, index) => (
<Badge
color={`primary-${selectedTheme}`}
key={String(data)}
>
{String(data)}
</Badge>
))}
</>
) : (
<div
style={{
overflow: "auto",
maxHeight: "300px",
height: "auto",
marginBottom: "10px",
overflowX: "hidden",
}}
>
{operations?.length ? (
<FormGroup row>
<h1
style={{
fontSize: "1.2rem",
fontWeight: "bold",
margin: 0,
color: "black !important",
}}
>
List of changes
</h1>
</FormGroup>
) : null}
{operations &&
operations.map((item, key) => (
<FormGroup row key={key}>
<Col sm={1} style={{ fontWeight: "bold" }}>
Set
</Col>
<Col
sm={5}
style={{
overflow: "auto",
width: 300,
paddingBottom: 10,
}}
>
<Badge color={`primary-${selectedTheme}`}>
{String(item.value)}
{item.path}
</Badge>
)}
</Col>
</FormGroup>
))}
<FormGroup row>
<Col sm={12}>
<Input
id={USER_MESSAGE}
type={inputType ? inputType : 'textarea'}
name={USER_MESSAGE}
onChange={(e) => setUserMessage(e.target.value)}
placeholder={
!placeholderLabel || placeholderLabel === ''
? t('placeholders.action_commit_message')
: placeholderLabel
}
value={userMessage}
/>
{userMessage.length < 10 && (
<span className='text-danger'>
{10 - userMessage.length}{' '}
{userMessage.length ? ' more' : ''} characters required
</span>
)}
</Col>
</FormGroup>
</Col>
<Col sm={1} style={{ fontWeight: "bold" }}>
to
</Col>
<Col sm={5} style={{ overflow: "auto" }}>
{Array.isArray(item.value) ? (
<div className="d-flex flex-column gap-1 align-items-start">
{isOpen === key ? (
<Collapse isOpen={isOpen === key}>
{renderBadges(item.value)}
</Collapse>
) : (
renderBadges(item.value.slice(0, 2))
)}
{item.value.length > 2 && (
<Button
color="link"
onClick={() =>
setIsOpen(isOpen !== key ? key : null)
}
size="sm"
>
{isOpen === key ? "Show Less" : "Show More"}
{isOpen === key ? (
<KeyboardArrowUpIcon />
) : (
<KeyboardArrowDownIcon />
)}
</Button>
)}
</div>
) : (
<Badge color={`primary-${selectedTheme}`}>
{String(item.value)}
</Badge>
)}
</Col>
</FormGroup>
))}
</div>
<div>
<FormGroup row>
<Col sm={12}>
<Input
id={USER_MESSAGE}
type={inputType || "textarea"}
name={USER_MESSAGE}
onChange={(e) => setUserMessage(e.target.value)}
placeholder={
!placeholderLabel || placeholderLabel === ""
? t("placeholders.action_commit_message")
: placeholderLabel
}
rows="4"
value={userMessage}
/>
{userMessage.length < 10 && (
<span className="text-danger">
{10 - userMessage.length}{" "}
{userMessage.length ? " more" : ""} characters required
</span>
)}
</Col>
</FormGroup>
</div>
</ModalBody>
<ModalFooter>
{active && (
<Button color={`primary-${selectedTheme}`} onClick={handleAccept}>
<i className='fa fa-check-circle me-2'></i>
{t('actions.accept')}
<i className="fa fa-check-circle me-2"></i>
{t("actions.accept")}
</Button>
)}{' '}
)}{" "}
<Button onClick={closeModal}>
<i className='fa fa-remove me-2'></i>
{t('actions.no')}
<i className="fa fa-remove me-2"></i>
{t("actions.no")}
</Button>
</ModalFooter>
</Modal>
)}
</>
)
}
);
};

export default GluuCommitDialog
export default GluuCommitDialog;
GluuCommitDialog.propTypes = {
feature: PropTypes.string,
operations: PropTypes.any,
Expand All @@ -177,5 +249,5 @@ GluuCommitDialog.propTypes = {
placeholderLabel: PropTypes.string,
inputType: PropTypes.string,
label: PropTypes.string,
formik: PropTypes.object
}
formik: PropTypes.object,
};
3 changes: 3 additions & 0 deletions admin-ui/app/routes/Apps/Gluu/GluuToogle.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@ function GluuToogle({ name, formik, value, handler, disabled }) {
setChecked(event.target.checked)
if (formik !== undefined) {
formik.handleChange(event)
if(handler) {
handler(event)
}
} else {
handler(event)
}
Expand Down
Loading

0 comments on commit f0d0c32

Please sign in to comment.