mirror of https://github.com/portainer/portainer
refactor(settings/auth): migrate ldap tables to react [EE-4712] (#10822)
parent
45be6c2b45
commit
ddb89f71b4
|
@ -6,11 +6,8 @@ import { InternalAuth } from '@/react/portainer/settings/AuthenticationView/Inte
|
||||||
import { r2a } from '@/react-tools/react2angular';
|
import { r2a } from '@/react-tools/react2angular';
|
||||||
import { withReactQuery } from '@/react-tools/withReactQuery';
|
import { withReactQuery } from '@/react-tools/withReactQuery';
|
||||||
import { withUIRouter } from '@/react-tools/withUIRouter';
|
import { withUIRouter } from '@/react-tools/withUIRouter';
|
||||||
import { ApplicationSettingsPanel } from '@/react/portainer/settings/SettingsView/ApplicationSettingsPanel';
|
import { LDAPUsersTable } from '@/react/portainer/settings/AuthenticationView/LDAPAuth/LDAPUsersTable';
|
||||||
import { KubeSettingsPanel } from '@/react/portainer/settings/SettingsView/KubeSettingsPanel';
|
import { LDAPGroupsTable } from '@/react/portainer/settings/AuthenticationView/LDAPAuth/LDAPGroupsTable';
|
||||||
import { HelmCertPanel } from '@/react/portainer/settings/SettingsView/HelmCertPanel';
|
|
||||||
import { HiddenContainersPanel } from '@/react/portainer/settings/SettingsView/HiddenContainersPanel/HiddenContainersPanel';
|
|
||||||
import { SSLSettingsPanelWrapper } from '@/react/portainer/settings/SettingsView/SSLSettingsPanel/SSLSettingsPanel';
|
|
||||||
|
|
||||||
export const settingsModule = angular
|
export const settingsModule = angular
|
||||||
.module('portainer.app.react.components.settings', [])
|
.module('portainer.app.react.components.settings', [])
|
||||||
|
@ -23,20 +20,5 @@ export const settingsModule = angular
|
||||||
'internalAuth',
|
'internalAuth',
|
||||||
r2a(InternalAuth, ['onSaveSettings', 'isLoading', 'value', 'onChange'])
|
r2a(InternalAuth, ['onSaveSettings', 'isLoading', 'value', 'onChange'])
|
||||||
)
|
)
|
||||||
.component(
|
.component('ldapUsersDatatable', r2a(LDAPUsersTable, ['dataset']))
|
||||||
'applicationSettingsPanel',
|
.component('ldapGroupsDatatable', r2a(LDAPGroupsTable, ['dataset'])).name;
|
||||||
r2a(withReactQuery(ApplicationSettingsPanel), ['onSuccess', 'settings'])
|
|
||||||
)
|
|
||||||
.component(
|
|
||||||
'sslSettingsPanel',
|
|
||||||
r2a(withReactQuery(SSLSettingsPanelWrapper), [])
|
|
||||||
)
|
|
||||||
.component('helmCertPanel', r2a(withReactQuery(HelmCertPanel), []))
|
|
||||||
.component(
|
|
||||||
'hiddenContainersPanel',
|
|
||||||
r2a(withUIRouter(withReactQuery(HiddenContainersPanel)), [])
|
|
||||||
)
|
|
||||||
.component(
|
|
||||||
'kubeSettingsPanel',
|
|
||||||
r2a(withUIRouter(withReactQuery(KubeSettingsPanel)), ['settings'])
|
|
||||||
).name;
|
|
||||||
|
|
|
@ -6,7 +6,6 @@ import { ldapSettingsCustom } from './ldap-settings-custom';
|
||||||
import { ldapSettingsOpenLdap } from './ldap-settings-openldap';
|
import { ldapSettingsOpenLdap } from './ldap-settings-openldap';
|
||||||
|
|
||||||
import { ldapConnectivityCheck } from './ldap-connectivity-check';
|
import { ldapConnectivityCheck } from './ldap-connectivity-check';
|
||||||
import { ldapGroupsDatatable } from './ldap-groups-datatable';
|
|
||||||
import { ldapGroupSearch } from './ldap-group-search';
|
import { ldapGroupSearch } from './ldap-group-search';
|
||||||
import { ldapGroupSearchItem } from './ldap-group-search-item';
|
import { ldapGroupSearchItem } from './ldap-group-search-item';
|
||||||
import { ldapUserSearch } from './ldap-user-search';
|
import { ldapUserSearch } from './ldap-user-search';
|
||||||
|
@ -18,7 +17,6 @@ import { ldapCustomAdminGroup } from './ldap-custom-admin-group';
|
||||||
import { ldapSettingsSecurity } from './ldap-settings-security';
|
import { ldapSettingsSecurity } from './ldap-settings-security';
|
||||||
import { ldapSettingsTestLogin } from './ldap-settings-test-login';
|
import { ldapSettingsTestLogin } from './ldap-settings-test-login';
|
||||||
import { ldapCustomUserSearch } from './ldap-custom-user-search';
|
import { ldapCustomUserSearch } from './ldap-custom-user-search';
|
||||||
import { ldapUsersDatatable } from './ldap-users-datatable';
|
|
||||||
import { LDAPService } from './ldap.service';
|
import { LDAPService } from './ldap.service';
|
||||||
import { LDAP } from './ldap.rest';
|
import { LDAP } from './ldap.rest';
|
||||||
|
|
||||||
|
@ -27,7 +25,6 @@ export default angular
|
||||||
.service('LDAPService', LDAPService)
|
.service('LDAPService', LDAPService)
|
||||||
.service('LDAP', LDAP)
|
.service('LDAP', LDAP)
|
||||||
.component('ldapConnectivityCheck', ldapConnectivityCheck)
|
.component('ldapConnectivityCheck', ldapConnectivityCheck)
|
||||||
.component('ldapGroupsDatatable', ldapGroupsDatatable)
|
|
||||||
.component('ldapSettings', ldapSettings)
|
.component('ldapSettings', ldapSettings)
|
||||||
.component('adSettings', adSettings)
|
.component('adSettings', adSettings)
|
||||||
.component('ldapGroupSearch', ldapGroupSearch)
|
.component('ldapGroupSearch', ldapGroupSearch)
|
||||||
|
@ -42,5 +39,4 @@ export default angular
|
||||||
.component('ldapSettingsOpenLdap', ldapSettingsOpenLdap)
|
.component('ldapSettingsOpenLdap', ldapSettingsOpenLdap)
|
||||||
.component('ldapSettingsSecurity', ldapSettingsSecurity)
|
.component('ldapSettingsSecurity', ldapSettingsSecurity)
|
||||||
.component('ldapSettingsTestLogin', ldapSettingsTestLogin)
|
.component('ldapSettingsTestLogin', ldapSettingsTestLogin)
|
||||||
.component('ldapCustomUserSearch', ldapCustomUserSearch)
|
.component('ldapCustomUserSearch', ldapCustomUserSearch).name;
|
||||||
.component('ldapUsersDatatable', ldapUsersDatatable).name;
|
|
||||||
|
|
|
@ -67,8 +67,4 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div ng-if="$ctrl.showTable">
|
<ldap-groups-datatable ng-if="$ctrl.showTable" dataset="$ctrl.groups"></ldap-groups-datatable>
|
||||||
<div class="form-group col-sm-12">
|
|
||||||
<ldap-groups-datatable dataset="$ctrl.groups" title-text="Groups" title-icon="users" table-key="ldapGroups"></ldap-groups-datatable>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
|
@ -56,8 +56,4 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div ng-if="$ctrl.showTable">
|
<ldap-users-datatable ng-if="$ctrl.showTable" dataset="$ctrl.users"></ldap-users-datatable>
|
||||||
<div class="form-group col-sm-12">
|
|
||||||
<ldap-users-datatable dataset="$ctrl.users" title-text="Users" title-icon="users" table-key="ldapUsers" order-by="" reverse-order=""></ldap-users-datatable>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
|
@ -25,8 +25,4 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div ng-if="$ctrl.showTable">
|
<ldap-groups-datatable ng-if="$ctrl.showTable" dataset="$ctrl.groups"></ldap-groups-datatable>
|
||||||
<div class="form-group col-sm-12">
|
|
||||||
<ldap-groups-datatable dataset="$ctrl.groups" title-text="Groups" title-icon="users" table-key="ldapGroups"></ldap-groups-datatable>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
|
@ -1,12 +0,0 @@
|
||||||
export const ldapGroupsDatatable = {
|
|
||||||
templateUrl: './ldap-groups-datatable.html',
|
|
||||||
controller: 'GenericDatatableController',
|
|
||||||
bindings: {
|
|
||||||
titleText: '@',
|
|
||||||
titleIcon: '@',
|
|
||||||
dataset: '<',
|
|
||||||
tableKey: '@',
|
|
||||||
orderBy: '@',
|
|
||||||
reverseOrder: '<',
|
|
||||||
},
|
|
||||||
};
|
|
|
@ -1,80 +0,0 @@
|
||||||
<div class="datatable">
|
|
||||||
<rd-widget>
|
|
||||||
<rd-widget-body classes="no-padding">
|
|
||||||
<div class="toolBar">
|
|
||||||
<div class="toolBarTitle vertical-center">
|
|
||||||
<pr-icon icon="$ctrl.titleIcon"></pr-icon>
|
|
||||||
{{ $ctrl.titleText }}
|
|
||||||
</div>
|
|
||||||
<div class="searchBar vertical-center">
|
|
||||||
<pr-icon icon="'search'"></pr-icon>
|
|
||||||
<input
|
|
||||||
type="text"
|
|
||||||
class="searchInput"
|
|
||||||
ng-model="$ctrl.state.textFilter"
|
|
||||||
ng-change="$ctrl.onTextFilterChange()"
|
|
||||||
placeholder="Search..."
|
|
||||||
auto-focus
|
|
||||||
ng-model-options="{ debounce: 300 }"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="table-responsive">
|
|
||||||
<table class="table-hover nowrap-cells table">
|
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
<th>
|
|
||||||
<table-column-header
|
|
||||||
col-title="'User Name'"
|
|
||||||
can-sort="true"
|
|
||||||
is-sorted="$ctrl.state.orderBy === 'Name'"
|
|
||||||
is-sorted-desc="$ctrl.state.orderBy === 'Name' && $ctrl.state.reverseOrder"
|
|
||||||
ng-click="$ctrl.changeOrderBy('Name')"
|
|
||||||
></table-column-header>
|
|
||||||
</th>
|
|
||||||
<th>
|
|
||||||
<table-column-header col-title="'Groups'" can-sort="false"></table-column-header>
|
|
||||||
</th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
<tr
|
|
||||||
dir-paginate="item in ($ctrl.state.filteredDataSet = ($ctrl.dataset | filter:$ctrl.state.textFilter | orderBy:$ctrl.state.orderBy:$ctrl.state.reverseOrder | itemsPerPage: $ctrl.state.paginatedItemLimit))"
|
|
||||||
ng-class="{ active: item.Checked }"
|
|
||||||
>
|
|
||||||
<td>
|
|
||||||
{{ item.Name }}
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
<p ng-repeat="group in item.Groups" style="margin: 0">{{ group }}</p>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr ng-if="!$ctrl.dataset">
|
|
||||||
<td colspan="3" class="text-muted text-center">Loading...</td>
|
|
||||||
</tr>
|
|
||||||
<tr ng-if="$ctrl.state.filteredDataSet.length === 0">
|
|
||||||
<td colspan="5" class="text-muted text-center">No groups found.</td>
|
|
||||||
</tr>
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
</div>
|
|
||||||
<div class="footer" ng-if="$ctrl.dataset">
|
|
||||||
<div class="paginationControls">
|
|
||||||
<form class="form-inline">
|
|
||||||
<span class="limitSelector">
|
|
||||||
<span style="margin-right: 5px"> Items per page </span>
|
|
||||||
<select class="form-control" ng-model="$ctrl.state.paginatedItemLimit" ng-change="$ctrl.changePaginationLimit()">
|
|
||||||
<option value="0">All</option>
|
|
||||||
<option value="10">10</option>
|
|
||||||
<option value="25">25</option>
|
|
||||||
<option value="50">50</option>
|
|
||||||
<option value="100">100</option>
|
|
||||||
</select>
|
|
||||||
</span>
|
|
||||||
<dir-pagination-controls max-size="5"></dir-pagination-controls>
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</rd-widget-body>
|
|
||||||
</rd-widget>
|
|
||||||
</div>
|
|
|
@ -32,8 +32,4 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div ng-if="$ctrl.showTable">
|
<ldap-users-datatable ng-if="$ctrl.showTable" dataset="$ctrl.users"></ldap-users-datatable>
|
||||||
<div class="form-group col-sm-12">
|
|
||||||
<ldap-users-datatable dataset="$ctrl.users" title-text="Users" title-icon="users" table-key="ldapUsers" order-by="" reverse-order=""></ldap-users-datatable>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
|
@ -1,12 +0,0 @@
|
||||||
export const ldapUsersDatatable = {
|
|
||||||
templateUrl: './ldap-users-datatable.html',
|
|
||||||
controller: 'GenericDatatableController',
|
|
||||||
bindings: {
|
|
||||||
titleText: '@',
|
|
||||||
titleIcon: '@',
|
|
||||||
dataset: '<',
|
|
||||||
tableKey: '@',
|
|
||||||
orderBy: '@',
|
|
||||||
reverseOrder: '<',
|
|
||||||
},
|
|
||||||
};
|
|
|
@ -1,74 +0,0 @@
|
||||||
<div class="datatable">
|
|
||||||
<rd-widget>
|
|
||||||
<rd-widget-body classes="no-padding">
|
|
||||||
<div class="toolBar">
|
|
||||||
<div class="toolBarTitle vertical-center">
|
|
||||||
<pr-icon icon="$ctrl.titleIcon"></pr-icon>
|
|
||||||
{{ $ctrl.titleText }}
|
|
||||||
</div>
|
|
||||||
<div class="searchBar vertical-center">
|
|
||||||
<pr-icon icon="'search'"></pr-icon>
|
|
||||||
<input
|
|
||||||
type="text"
|
|
||||||
class="searchInput"
|
|
||||||
ng-model="$ctrl.state.textFilter"
|
|
||||||
ng-change="$ctrl.onTextFilterChange()"
|
|
||||||
placeholder="Search..."
|
|
||||||
auto-focus
|
|
||||||
ng-model-options="{ debounce: 300 }"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="table-responsive">
|
|
||||||
<table class="table-hover nowrap-cells table">
|
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
<th>
|
|
||||||
<table-column-header
|
|
||||||
col-title="'Name'"
|
|
||||||
can-sort="true"
|
|
||||||
is-sorted="$ctrl.state.orderBy === 'Name'"
|
|
||||||
is-sorted-desc="$ctrl.state.orderBy === 'Name' && $ctrl.state.reverseOrder"
|
|
||||||
ng-click="$ctrl.changeOrderBy('Name')"
|
|
||||||
></table-column-header>
|
|
||||||
</th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
<tr
|
|
||||||
dir-paginate="item in ($ctrl.state.filteredDataSet = ($ctrl.dataset | filter:$ctrl.state.textFilter | orderBy:$ctrl.state.orderBy:$ctrl.state.reverseOrder | itemsPerPage: $ctrl.state.paginatedItemLimit)) track by $index"
|
|
||||||
ng-class="{ active: item.Checked }"
|
|
||||||
>
|
|
||||||
<td>
|
|
||||||
<a ui-sref="portainer.groups.group({id: item.Id})">{{ item }}</a>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr ng-if="!$ctrl.dataset">
|
|
||||||
<td colspan="3" class="text-muted text-center">Loading...</td>
|
|
||||||
</tr>
|
|
||||||
<tr ng-if="$ctrl.state.filteredDataSet.length === 0">
|
|
||||||
<td colspan="5" class="text-muted text-center">No users found.</td>
|
|
||||||
</tr>
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
</div>
|
|
||||||
<div class="footer" ng-if="$ctrl.dataset">
|
|
||||||
<div class="paginationControls">
|
|
||||||
<form class="form-inline">
|
|
||||||
<span class="limitSelector">
|
|
||||||
<span style="margin-right: 5px"> Items per page </span>
|
|
||||||
<select class="form-control" ng-model="$ctrl.state.paginatedItemLimit" ng-change="$ctrl.changePaginationLimit()">
|
|
||||||
<option value="0">All</option>
|
|
||||||
<option value="10">10</option>
|
|
||||||
<option value="25">25</option>
|
|
||||||
<option value="50">50</option>
|
|
||||||
<option value="100">100</option>
|
|
||||||
</select>
|
|
||||||
</span>
|
|
||||||
<dir-pagination-controls max-size="5"></dir-pagination-controls>
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</rd-widget-body>
|
|
||||||
</rd-widget>
|
|
||||||
</div>
|
|
|
@ -0,0 +1,49 @@
|
||||||
|
import { Users } from 'lucide-react';
|
||||||
|
import { createColumnHelper } from '@tanstack/react-table';
|
||||||
|
|
||||||
|
import { Datatable } from '@@/datatables';
|
||||||
|
import { useTableStateWithoutStorage } from '@@/datatables/useTableState';
|
||||||
|
|
||||||
|
const columns = getColumns();
|
||||||
|
|
||||||
|
interface Value {
|
||||||
|
Name: string;
|
||||||
|
Groups: string[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export function LDAPGroupsTable({ dataset }: { dataset?: Value[] }) {
|
||||||
|
const tableState = useTableStateWithoutStorage();
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Datatable
|
||||||
|
columns={columns}
|
||||||
|
dataset={dataset || []}
|
||||||
|
isLoading={!dataset}
|
||||||
|
title="Groups"
|
||||||
|
titleIcon={Users}
|
||||||
|
settingsManager={tableState}
|
||||||
|
emptyContentLabel="No groups found."
|
||||||
|
disableSelect
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function getColumns() {
|
||||||
|
const helper = createColumnHelper<Value>();
|
||||||
|
|
||||||
|
return [
|
||||||
|
helper.accessor('Name', {}),
|
||||||
|
helper.accessor((item) => item.Groups.join(','), {
|
||||||
|
header: 'Groups',
|
||||||
|
cell: ({ row: { original: item } }) => (
|
||||||
|
<>
|
||||||
|
{item.Groups.map((g) => (
|
||||||
|
<p className="m-0" key={g}>
|
||||||
|
{g}
|
||||||
|
</p>
|
||||||
|
))}
|
||||||
|
</>
|
||||||
|
),
|
||||||
|
}),
|
||||||
|
];
|
||||||
|
}
|
|
@ -0,0 +1,37 @@
|
||||||
|
import { Users } from 'lucide-react';
|
||||||
|
|
||||||
|
import { Datatable } from '@@/datatables';
|
||||||
|
import { useTableStateWithoutStorage } from '@@/datatables/useTableState';
|
||||||
|
|
||||||
|
const columns = getColumns();
|
||||||
|
|
||||||
|
interface Value {
|
||||||
|
value: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function LDAPUsersTable({ dataset }: { dataset?: string[] }) {
|
||||||
|
const tableState = useTableStateWithoutStorage();
|
||||||
|
const items = dataset?.map((value) => ({ value }));
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Datatable
|
||||||
|
columns={columns}
|
||||||
|
dataset={items || []}
|
||||||
|
isLoading={!items}
|
||||||
|
title="Users"
|
||||||
|
titleIcon={Users}
|
||||||
|
settingsManager={tableState}
|
||||||
|
emptyContentLabel="No users found."
|
||||||
|
disableSelect
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function getColumns() {
|
||||||
|
return [
|
||||||
|
{
|
||||||
|
header: 'Name',
|
||||||
|
accessorFn: ({ value }: Value) => value,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
}
|
Loading…
Reference in New Issue