+ );
+};
+
+export default PoliciesDetailPage;
diff --git a/openmetadata-ui/src/main/resources/ui/src/pages/PoliciesPage/PoliciesListPage/PoliciesList.less b/openmetadata-ui/src/main/resources/ui/src/pages/PoliciesPage/PoliciesListPage/PoliciesList.less
new file mode 100644
index 00000000000..3c46bf82c4e
--- /dev/null
+++ b/openmetadata-ui/src/main/resources/ui/src/pages/PoliciesPage/PoliciesListPage/PoliciesList.less
@@ -0,0 +1,35 @@
+/*
+ * Copyright 2022 Collate
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+.policies-list-container {
+ .ant-btn {
+ border-radius: 4px;
+ }
+}
+
+.policies-list-table {
+ .ant-table-thead > tr > th {
+ font-weight: bold;
+ background: #fff;
+ }
+
+ .ant-table-row .ant-table-cell:first-child,
+ .ant-table-thead .ant-table-cell:first-child {
+ padding-left: 16px;
+ }
+
+ table {
+ border: 1px solid #dde3ea;
+ box-shadow: 1px 1px 3px 0px rgba(0, 0, 0, 0.12);
+ }
+}
diff --git a/openmetadata-ui/src/main/resources/ui/src/pages/PoliciesPage/PoliciesListPage/PoliciesList.tsx b/openmetadata-ui/src/main/resources/ui/src/pages/PoliciesPage/PoliciesListPage/PoliciesList.tsx
new file mode 100644
index 00000000000..7ca4d355df0
--- /dev/null
+++ b/openmetadata-ui/src/main/resources/ui/src/pages/PoliciesPage/PoliciesListPage/PoliciesList.tsx
@@ -0,0 +1,100 @@
+/*
+ * Copyright 2021 Collate
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import { Space, Table } from 'antd';
+import { ColumnsType } from 'antd/lib/table';
+import { uniqueId } from 'lodash';
+import React, { FC, useMemo } from 'react';
+import { Link } from 'react-router-dom';
+import RichTextEditorPreviewer from '../../../components/common/rich-text-editor/RichTextEditorPreviewer';
+import { Policy } from '../../../generated/entity/policies/policy';
+import { getEntityName } from '../../../utils/CommonUtils';
+import {
+ getPolicyWithFqnPath,
+ getRoleWithFqnPath,
+} from '../../../utils/RouterUtils';
+import SVGIcons, { Icons } from '../../../utils/SvgUtils';
+
+interface PolicyListProps {
+ policies: Policy[];
+}
+
+const PoliciesList: FC = ({ policies }) => {
+ const columns: ColumnsType = useMemo(() => {
+ return [
+ {
+ title: 'Name',
+ dataIndex: 'name',
+ width: '200px',
+ key: 'name',
+ render: (_, record) => (
+
+ {getEntityName(record)}
+
+ ),
+ },
+ {
+ title: 'Description',
+ dataIndex: 'description',
+ key: 'description',
+ render: (_, record) => (
+
+ ),
+ },
+ {
+ title: 'Roles',
+ dataIndex: 'roles',
+ width: '200px',
+ key: 'roles',
+ render: (_, record) => {
+ return record.roles?.length ? (
+
+ {record.roles.map((role) => (
+
+ {getEntityName(role)}
+
+ ))}
+
+ ) : (
+ '-- '
+ );
+ },
+ },
+ {
+ title: 'Actions',
+ dataIndex: 'actions',
+ width: '80px',
+ key: 'actions',
+ render: () => {
+ return ;
+ },
+ },
+ ];
+ }, []);
+
+ return (
+
+ );
+};
+
+export default PoliciesList;
diff --git a/openmetadata-ui/src/main/resources/ui/src/pages/PoliciesPage/PoliciesListPage/PoliciesListPage.tsx b/openmetadata-ui/src/main/resources/ui/src/pages/PoliciesPage/PoliciesListPage/PoliciesListPage.tsx
new file mode 100644
index 00000000000..c998e2b9ad2
--- /dev/null
+++ b/openmetadata-ui/src/main/resources/ui/src/pages/PoliciesPage/PoliciesListPage/PoliciesListPage.tsx
@@ -0,0 +1,66 @@
+/*
+ * Copyright 2021 Collate
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import { Button, Col, Row, Space } from 'antd';
+import { AxiosError } from 'axios';
+import React, { useEffect, useState } from 'react';
+import { getPolicies } from '../../../axiosAPIs/rolesAPIV1';
+import Loader from '../../../components/Loader/Loader';
+import { Policy } from '../../../generated/entity/policies/policy';
+import { Paging } from '../../../generated/type/paging';
+import { showErrorToast } from '../../../utils/ToastUtils';
+import PoliciesList from './PoliciesList';
+import './PoliciesList.less';
+
+const PoliciesListPage = () => {
+ const [policies, setPolicies] = useState([]);
+ const [isLoading, setIsLoading] = useState(false);
+
+ const fetchPolicies = async (paging?: Paging) => {
+ setIsLoading(true);
+ try {
+ const data = await getPolicies(
+ 'owner,location,roles,teams',
+ paging?.after,
+ paging?.before
+ );
+
+ setPolicies(data.data || []);
+ } catch (error) {
+ showErrorToast(error as AxiosError);
+ } finally {
+ setIsLoading(false);
+ }
+ };
+
+ useEffect(() => {
+ fetchPolicies();
+ }, []);
+
+ return isLoading ? (
+
+ ) : (
+
+
+
+
+
+
+
+
+
+
+ );
+};
+
+export default PoliciesListPage;
diff --git a/openmetadata-ui/src/main/resources/ui/src/pages/RolesPage/AddRolePage/AddRolePage.tsx b/openmetadata-ui/src/main/resources/ui/src/pages/RolesPage/AddRolePage/AddRolePage.tsx
new file mode 100644
index 00000000000..2d675f3e9b7
--- /dev/null
+++ b/openmetadata-ui/src/main/resources/ui/src/pages/RolesPage/AddRolePage/AddRolePage.tsx
@@ -0,0 +1,167 @@
+/*
+ * Copyright 2021 Collate
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import { Button, Card, Col, Form, Input, Row, Select, Space } from 'antd';
+import { AxiosError } from 'axios';
+import React, { useEffect, useState } from 'react';
+import { useHistory } from 'react-router-dom';
+import { addRole, getPolicies } from '../../../axiosAPIs/rolesAPIV1';
+import RichTextEditor from '../../../components/common/rich-text-editor/RichTextEditor';
+import TitleBreadcrumb from '../../../components/common/title-breadcrumb/title-breadcrumb.component';
+import {
+ GlobalSettingOptions,
+ GlobalSettingsMenuCategory,
+} from '../../../constants/globalSettings.constants';
+import { Policy } from '../../../generated/entity/policies/policy';
+import { getRoleWithFqnPath, getSettingPath } from '../../../utils/RouterUtils';
+import { showErrorToast } from '../../../utils/ToastUtils';
+const { Option } = Select;
+const breadcrumb = [
+ {
+ name: 'Roles',
+ url: getSettingPath(
+ GlobalSettingsMenuCategory.ACCESS,
+ GlobalSettingOptions.ROLES
+ ),
+ },
+ {
+ name: 'Add New Role',
+ url: '',
+ },
+];
+
+const AddRolePage = () => {
+ const history = useHistory();
+ const [policies, setPolicies] = useState([]);
+ const [name, setName] = useState('');
+ const [description, setDescription] = useState('');
+ const [selectedPolicies, setSelectedPolicies] = useState([]);
+
+ const fetchPolicies = async () => {
+ try {
+ const data = await getPolicies('owner,location,roles,teams');
+
+ setPolicies(data.data || []);
+ } catch (error) {
+ showErrorToast(error as AxiosError);
+ }
+ };
+
+ const handleCancel = () => {
+ history.push(
+ getSettingPath(
+ GlobalSettingsMenuCategory.ACCESS,
+ GlobalSettingOptions.ROLES
+ )
+ );
+ };
+
+ const handleSumbit = async () => {
+ const data = {
+ name,
+ description,
+ policies: selectedPolicies.map((policy) => ({
+ id: policy,
+ type: 'policy',
+ })),
+ };
+
+ try {
+ const dataResponse = await addRole(data);
+ if (dataResponse) {
+ history.push(getRoleWithFqnPath(dataResponse.fullyQualifiedName || ''));
+ }
+ } catch (error) {
+ showErrorToast(error as AxiosError);
+ }
+ };
+
+ useEffect(() => {
+ fetchPolicies();
+ }, []);
+
+ return (
+
+
+
+
+
+
+
+ setName(e.target.value)}
+ />
+
+
+ setDescription(value)}
+ />
+
+
+
+
+
+
+
+
+
+
+
+
+
+ );
+};
+
+export default AddRolePage;
diff --git a/openmetadata-ui/src/main/resources/ui/src/pages/RolesPage/RolesDetailPage/RolesDetail.less b/openmetadata-ui/src/main/resources/ui/src/pages/RolesPage/RolesDetailPage/RolesDetail.less
new file mode 100644
index 00000000000..227a3a7e04a
--- /dev/null
+++ b/openmetadata-ui/src/main/resources/ui/src/pages/RolesPage/RolesDetailPage/RolesDetail.less
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2022 Collate
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+.roles-detail {
+ .policies-list-table {
+ .ant-table-thead > tr > th {
+ font-weight: bold;
+ background: #fff;
+ }
+
+ .ant-table-row .ant-table-cell:first-child,
+ .ant-table-thead .ant-table-cell:first-child {
+ padding-left: 16px;
+ }
+
+ table {
+ border: 1px solid #dde3ea;
+ box-shadow: 1px 1px 3px 0px rgba(0, 0, 0, 0.12);
+ }
+ }
+}
diff --git a/openmetadata-ui/src/main/resources/ui/src/pages/RolesPage/RolesDetailPage/RolesDetailPage.tsx b/openmetadata-ui/src/main/resources/ui/src/pages/RolesPage/RolesDetailPage/RolesDetailPage.tsx
new file mode 100644
index 00000000000..68a6bd88443
--- /dev/null
+++ b/openmetadata-ui/src/main/resources/ui/src/pages/RolesPage/RolesDetailPage/RolesDetailPage.tsx
@@ -0,0 +1,177 @@
+/*
+ * Copyright 2021 Collate
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import { Card, Col, Empty, Row, Table, Tabs } from 'antd';
+import { ColumnsType } from 'antd/lib/table';
+import { AxiosError } from 'axios';
+import { isEmpty, uniqueId } from 'lodash';
+import { EntityReference } from 'Models';
+import React, { useEffect, useMemo, useState } from 'react';
+import { Link, useParams } from 'react-router-dom';
+import { getRoleByName } from '../../../axiosAPIs/rolesAPIV1';
+import Description from '../../../components/common/description/Description';
+import RichTextEditorPreviewer from '../../../components/common/rich-text-editor/RichTextEditorPreviewer';
+import TitleBreadcrumb from '../../../components/common/title-breadcrumb/title-breadcrumb.component';
+import Loader from '../../../components/Loader/Loader';
+import {
+ GlobalSettingOptions,
+ GlobalSettingsMenuCategory,
+} from '../../../constants/globalSettings.constants';
+import { Role } from '../../../generated/entity/teams/role';
+import { getEntityName } from '../../../utils/CommonUtils';
+import {
+ getPolicyWithFqnPath,
+ getSettingPath,
+} from '../../../utils/RouterUtils';
+import { showErrorToast } from '../../../utils/ToastUtils';
+import './RolesDetail.less';
+
+const { TabPane } = Tabs;
+
+const PoliciesList = ({ policies }: { policies: EntityReference[] }) => {
+ const columns: ColumnsType = useMemo(() => {
+ return [
+ {
+ title: 'Name',
+ dataIndex: 'name',
+ width: '200px',
+ key: 'name',
+ render: (_, record) => (
+
+ {getEntityName(record)}
+
+ ),
+ },
+ {
+ title: 'Description',
+ dataIndex: 'description',
+ key: 'description',
+ render: (_, record) => (
+
+ ),
+ },
+ ];
+ }, []);
+
+ return (
+