1
0
Fork 0
mirror of https://github.com/portainer/portainer.git synced 2025-08-05 05:45:22 +02:00

refactor(ui): move react components to react codebase [EE-3354] (#8258)

* refactor(ui): move react components to react codebase [EE-3354]

* refactor(app): move bocx selector options

* refactor(react): spearate portainer components

* fix(app): fix imports
This commit is contained in:
Chaim Lev-Ari 2023-02-28 17:32:29 +02:00 committed by GitHub
parent f9a09301a8
commit b98c71f1ab
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
66 changed files with 312 additions and 294 deletions

View file

@ -1,8 +1,3 @@
// theme icons
import automode from '@/assets/ico/theme/auto.svg?c';
import darkmode from '@/assets/ico/theme/darkmode.svg?c';
import lightmode from '@/assets/ico/theme/lightmode.svg?c';
import highcontrastmode from '@/assets/ico/theme/highcontrastmode.svg?c';
// general icons
import heartbeatup from '@/assets/ico/heartbeat-up.svg?c';
import heartbeatdown from '@/assets/ico/heartbeat-down.svg?c';
@ -47,10 +42,6 @@ const placeholder = Placeholder;
export const SvgIcons = {
heartbeatup,
heartbeatdown,
automode,
darkmode,
lightmode,
highcontrastmode,
dataflow,
dockericon,
git,

View file

@ -0,0 +1,27 @@
import { Share2, Sliders } from 'lucide-react';
import { BoxSelectorOption } from '@@/BoxSelector';
export function getOptions(
hasNetworks: boolean
): ReadonlyArray<BoxSelectorOption<string>> {
return [
{
id: 'network_config',
icon: Sliders,
iconType: 'badge',
label: 'Configuration',
description: 'I want to configure a network before deploying it',
value: 'local',
},
{
id: 'network_deploy',
icon: Share2,
iconType: 'badge',
label: 'Creation',
description: 'I want to create a network from a configuration',
value: 'swarm',
disabled: () => !hasNetworks,
},
] as const;
}

View file

@ -3,7 +3,7 @@ import { useMutation, useQueryClient } from 'react-query';
import { EnvironmentId } from '@/react/portainer/environments/types';
import axios, { parseAxiosError } from '@/portainer/services/axios';
import { promiseSequence } from '@/portainer/helpers/promise-utils';
import { useIntegratedLicenseInfo } from '@/portainer/license-management/use-license.service';
import { useIntegratedLicenseInfo } from '@/react/portainer/licenses/use-license.service';
export function useAssociateDeviceMutation() {
const queryClient = useQueryClient();

View file

@ -0,0 +1,22 @@
import { List, Tag } from 'lucide-react';
import { BoxSelectorOption } from '@@/BoxSelector';
export const groupTypeOptions: ReadonlyArray<BoxSelectorOption<boolean>> = [
{
id: 'static-group',
value: false,
label: 'Static',
description: 'Manually select Edge environments',
icon: List,
iconType: 'badge',
},
{
id: 'dynamic-group',
value: true,
label: 'Dynamic',
description: 'Automatically associate environments via tags',
icon: Tag,
iconType: 'badge',
},
] as const;

View file

@ -0,0 +1,23 @@
import { Tag } from 'lucide-react';
import { BoxSelectorOption } from '@@/BoxSelector';
export const tagOptions: ReadonlyArray<BoxSelectorOption<boolean>> = [
{
id: 'or-selector',
value: true,
label: 'Partial Match',
description:
'Associate any environment matching at least one of the selected tags',
icon: Tag,
iconType: 'badge',
},
{
id: 'and-selector',
value: false,
label: 'Full Match',
description: 'Associate any environment matching all of the selected tags',
icon: Tag,
iconType: 'badge',
},
];

View file

@ -0,0 +1,22 @@
import { Calendar, Edit } from 'lucide-react';
import { BoxSelectorOption } from '@@/BoxSelector';
export const cronMethodOptions: ReadonlyArray<BoxSelectorOption<string>> = [
{
id: 'config_basic',
value: 'basic',
icon: Calendar,
iconType: 'badge',
label: 'Basic configuration',
description: 'Select date from calendar',
},
{
id: 'config_advanced',
value: 'advanced',
icon: Edit,
iconType: 'badge',
label: 'Advanced configuration',
description: 'Write your own cron rule',
},
] as const;

View file

@ -0,0 +1,30 @@
import { AlignJustify, Sliders } from 'lucide-react';
import { KubernetesApplicationPlacementTypes } from '@/kubernetes/models/application/models';
import { BoxSelectorOption } from '@@/BoxSelector';
export const placementOptions: ReadonlyArray<BoxSelectorOption<number>> = [
{
id: 'placement_hard',
value: KubernetesApplicationPlacementTypes.MANDATORY,
icon: Sliders,
iconType: 'badge',
label: 'Mandatory',
description: (
<>
Schedule this application <b>ONLY</b> on nodes that match <b>ALL</b>{' '}
Rules
</>
),
},
{
id: 'placement_soft',
value: KubernetesApplicationPlacementTypes.PREFERRED,
icon: AlignJustify,
iconType: 'badge',
label: 'Preferred',
description:
'Schedule this application on nodes that match the rules if possible',
},
] as const;

View file

@ -4,7 +4,7 @@ import { EnvironmentId } from '@/react/portainer/environments/types';
export async function getIsRBACEnabled(environmentId: EnvironmentId) {
try {
const { data } = await axios.get(
const { data } = await axios.get<boolean>(
`kubernetes/${environmentId}/rbac_enabled`
);
return data;

View file

@ -0,0 +1,23 @@
import { KubernetesConfigurationKinds } from 'Kubernetes/models/configuration/models';
import { FileCode, Lock } from 'lucide-react';
import { BoxSelectorOption } from '@@/BoxSelector';
export const typeOptions: ReadonlyArray<BoxSelectorOption<number>> = [
{
id: 'type_basic',
value: KubernetesConfigurationKinds.CONFIGMAP,
icon: FileCode,
iconType: 'badge',
label: 'ConfigMap',
description: 'This configuration holds non-sensitive information',
},
{
id: 'type_secret',
value: KubernetesConfigurationKinds.SECRET,
icon: Lock,
iconType: 'badge',
label: 'Secret',
description: 'This configuration holds sensitive information',
},
] as const;

View file

@ -1,6 +1,7 @@
import { server, rest } from '@/setup-tests/server';
import { renderWithQueryClient } from '@/react-tools/test-utils';
import { LicenseType } from '@/portainer/license-management/types';
import { LicenseType } from '../licenses/types';
import { LicenseNodePanel } from './LicenseNodePanel';

View file

@ -1,10 +1,9 @@
import { LicenseType } from '@/portainer/license-management/types';
import { useLicenseInfo } from '@/portainer/license-management/use-license.service';
import { TextTip } from '@@/Tip/TextTip';
import { InformationPanel } from '@@/InformationPanel';
import { useNodesCount } from '../system/useNodesCount';
import { useLicenseInfo } from '../licenses/use-license.service';
import { LicenseType } from '../licenses/types';
export function LicenseNodePanel() {
const nodesValid = useNodesValid();

View file

@ -0,0 +1,34 @@
import { Eye, Moon, Sun, RefreshCw } from 'lucide-react';
import { BadgeIcon } from '@@/BadgeIcon';
export const options = [
{
id: 'light',
icon: <BadgeIcon icon={Sun} />,
label: 'Light Theme',
description: 'Default color mode',
value: 'light',
},
{
id: 'dark',
icon: <BadgeIcon icon={Moon} />,
label: 'Dark Theme',
description: 'Dark color mode',
value: 'dark',
},
{
id: 'highcontrast',
icon: <BadgeIcon icon={Eye} />,
label: 'High Contrast',
description: 'High contrast color mode',
value: 'highcontrast',
},
{
id: 'auto',
icon: <BadgeIcon icon={RefreshCw} />,
label: 'Auto',
description: 'Sync with system theme',
value: 'auto',
},
];

View file

@ -0,0 +1,155 @@
import { useMutation, useQuery, useQueryClient } from 'react-query';
import axios, { parseAxiosError } from '@/portainer/services/axios';
import { success as notifySuccess } from '@/portainer/services/notifications';
import {
CreateGitCredentialPayload,
GitCredential,
UpdateGitCredentialPayload,
} from './types';
export async function createGitCredential(
gitCredential: CreateGitCredentialPayload
) {
try {
await axios.post(buildGitUrl(gitCredential.userId), gitCredential);
} catch (e) {
throw parseAxiosError(e as Error, 'Unable to create git credential');
}
}
export async function getGitCredentials(userId: number) {
try {
const { data } = await axios.get<GitCredential[]>(buildGitUrl(userId));
return data;
} catch (e) {
throw parseAxiosError(e as Error, 'Unable to get git credentials');
}
}
export async function getGitCredential(userId: number, id: number) {
try {
const { data } = await axios.get<GitCredential>(buildGitUrl(userId, id));
return data;
} catch (e) {
throw parseAxiosError(e as Error, 'Unable to get git credential');
}
}
export async function deleteGitCredential(credential: GitCredential) {
try {
await axios.delete<GitCredential[]>(
buildGitUrl(credential.userId, credential.id)
);
} catch (e) {
throw parseAxiosError(e as Error, 'Unable to delete git credential');
}
}
export async function updateGitCredential(
credential: Partial<UpdateGitCredentialPayload>,
userId: number,
id: number
) {
try {
const { data } = await axios.put(buildGitUrl(userId, id), credential);
return data;
} catch (e) {
throw parseAxiosError(e as Error, 'Unable to update credential');
}
}
export function useUpdateGitCredentialMutation() {
const queryClient = useQueryClient();
return useMutation(
({
credential,
userId,
id,
}: {
credential: UpdateGitCredentialPayload;
userId: number;
id: number;
}) => updateGitCredential(credential, userId, id),
{
onSuccess: (_, data) => {
notifySuccess(
'Git credential updated successfully',
data.credential.name
);
return queryClient.invalidateQueries(['gitcredentials']);
},
meta: {
error: {
title: 'Failure',
message: 'Unable to update credential',
},
},
}
);
}
export function useDeleteGitCredentialMutation() {
const queryClient = useQueryClient();
return useMutation(deleteGitCredential, {
onSuccess: (_, credential) => {
notifySuccess('Git Credential deleted successfully', credential.name);
return queryClient.invalidateQueries(['gitcredentials']);
},
meta: {
error: {
title: 'Failure',
message: 'Unable to delete git credential',
},
},
});
}
export function useGitCredentials(userId: number) {
return useQuery('gitcredentials', () => getGitCredentials(userId), {
staleTime: 20,
meta: {
error: {
title: 'Failure',
message: 'Unable to retrieve git credentials',
},
},
});
}
export function useGitCredential(userId: number, id: number) {
return useQuery(['gitcredentials', id], () => getGitCredential(userId, id), {
meta: {
error: {
title: 'Failure',
message: 'Unable to retrieve git credential',
},
},
});
}
export function useCreateGitCredentialMutation() {
const queryClient = useQueryClient();
return useMutation(createGitCredential, {
onSuccess: (_, payload) => {
notifySuccess('Credentials created successfully', payload.name);
return queryClient.invalidateQueries(['gitcredentials']);
},
meta: {
error: {
title: 'Failure',
message: 'Unable to create credential',
},
},
});
}
function buildGitUrl(userId: number, credentialId?: number) {
return credentialId
? `/users/${userId}/gitcredentials/${credentialId}`
: `/users/${userId}/gitcredentials`;
}

View file

@ -0,0 +1,35 @@
import {
PaginationTableSettings,
SortableTableSettings,
} from '@@/datatables/types';
export interface GitCredentialTableSettings
extends SortableTableSettings,
PaginationTableSettings {}
export interface GitCredentialFormValues {
name: string;
username?: string;
password: string;
}
export interface CreateGitCredentialPayload {
userId: number;
name: string;
username?: string;
password: string;
}
export interface UpdateGitCredentialPayload {
name: string;
username?: string;
password: string;
}
export type GitCredential = {
id: number;
userId: number;
name: string;
username: string;
creationDate: number;
};

View file

@ -0,0 +1,38 @@
import { Shield } from 'lucide-react';
import { BoxSelectorOption } from '@@/BoxSelector';
export const tlsOptions: ReadonlyArray<BoxSelectorOption<string>> = [
{
id: 'tls_client_ca',
value: 'tls_client_ca',
icon: Shield,
iconType: 'badge',
label: 'TLS with server and client verification',
description: 'Use client certificates and server verification',
},
{
id: 'tls_client_noca',
value: 'tls_client_noca',
icon: Shield,
iconType: 'badge',
label: 'TLS with client verification only',
description: 'Use client certificates without server verification',
},
{
id: 'tls_ca',
value: 'tls_ca',
icon: Shield,
iconType: 'badge',
label: 'TLS with server verification only',
description: 'Only verify the server certificate',
},
{
id: 'tls_only',
value: 'tls_only',
icon: Shield,
iconType: 'badge',
label: 'TLS only',
description: 'No server/client verification',
},
] as const;

View file

@ -0,0 +1,15 @@
.canvas-container {
display: contents;
}
.kvm-maximized {
position: fixed;
background: white;
bottom: 0;
top: 0;
left: 0;
width: 100vw;
z-index: 1000;
max-height: 100% !important;
overflow-y: scroll;
}

View file

@ -0,0 +1,24 @@
import { KVM } from '@open-amt-cloud-toolkit/ui-toolkit-react/reactjs/src/kvm.bundle';
import './KVMControl.css';
export interface KVMControlProps {
deviceId: string;
server: string;
token: string;
}
export function KVMControl({ deviceId, server, token }: KVMControlProps) {
if (!deviceId || !server || !token) return <div>Loading...</div>;
return (
<KVM
deviceId={deviceId}
mpsServer={`https://${server}/mps/ws/relay`}
authToken={token}
mouseDebounceTime="200"
canvasHeight="100%"
canvasWidth="100%"
/>
);
}

View file

@ -0,0 +1 @@
export { KVMControl } from './KVMControl';

View file

@ -3,7 +3,7 @@ import { boolean, number, object, SchemaOf, string } from 'yup';
import { GitAuthModel } from '@/react/portainer/gitops/types';
import { useDebounce } from '@/react/hooks/useDebounce';
import { GitCredential } from '@/portainer/views/account/git-credential/types';
import { GitCredential } from '@/react/portainer/account/git-credentials/types';
import { SwitchField } from '@@/form-components/SwitchField';
import { Input } from '@@/form-components/Input';

View file

@ -1,5 +1,5 @@
import { useGitCredentials } from '@/portainer/views/account/git-credential/gitCredential.service';
import { GitCredential } from '@/portainer/views/account/git-credential/types';
import { GitCredential } from '@/react/portainer/account/git-credentials/types';
import { useGitCredentials } from '@/react/portainer/account/git-credentials/git-credentials.service';
import { useUser } from '@/react/hooks/useUser';
import { FormControl } from '@@/form-components/FormControl';

View file

@ -3,7 +3,7 @@ import { Form, Formik } from 'formik';
import { rest } from 'msw';
import { withUserProvider } from '@/react/test-utils/withUserProvider';
import { GitCredential } from '@/portainer/views/account/git-credential/types';
import { GitCredential } from '@/react/portainer/account/git-credentials/types';
import { GitForm, buildGitValidationSchema } from './GitForm';
import { GitFormModel } from './types';

View file

@ -5,12 +5,13 @@ import { ComposePathField } from '@/react/portainer/gitops/ComposePathField';
import { RefField } from '@/react/portainer/gitops/RefField';
import { GitFormUrlField } from '@/react/portainer/gitops/GitFormUrlField';
import { GitFormModel } from '@/react/portainer/gitops/types';
import { GitCredential } from '@/portainer/views/account/git-credential/types';
import { TimeWindowDisplay } from '@/react/portainer/gitops/TimeWindowDisplay';
import { FormSection } from '@@/form-components/FormSection';
import { TimeWindowDisplay } from '@@/TimeWindowDisplay';
import { validateForm } from '@@/form-components/validate-form';
import { GitCredential } from '../account/git-credentials/types';
import { AdditionalFileField } from './AdditionalFilesField';
import { gitAuthValidation, AuthFieldset } from './AuthFieldset';
import { AutoUpdateFieldset } from './AutoUpdateFieldset';

View file

@ -5,7 +5,7 @@ import { useCurrentEnvironment } from '@/react/hooks/useCurrentEnvironment';
import { TextTip } from '@@/Tip/TextTip';
import { withEdition } from '../portainer/feature-flags/withEdition';
import { withEdition } from '../feature-flags/withEdition';
const TimeWindowDisplayWrapper = withEdition(TimeWindowDisplay, 'BE');

View file

@ -0,0 +1,23 @@
import { Download, Upload } from 'lucide-react';
import { FeatureId } from '@/react/portainer/feature-flags/enums';
import { BoxSelectorOption } from '@@/BoxSelector';
export const restoreOptions: ReadonlyArray<BoxSelectorOption<string>> = [
{
id: 'restore_file',
value: 'file',
icon: Upload,
iconType: 'badge',
label: 'Upload backup file',
},
{
id: 'restore_s3',
value: 's3',
icon: Download,
iconType: 'badge',
label: 'Retrieve from S3',
feature: FeatureId.S3_RESTORE,
},
] as const;

View file

@ -0,0 +1,43 @@
import { server, rest } from '@/setup-tests/server';
import { getLicenses } from './license.service';
import type { License } from './types';
describe('getLicenses', () => {
it('on success should return the server body', async () => {
const catchFn = jest.fn();
const thenFn = jest.fn();
const data: License[] = [];
server.use(
rest.get('/api/licenses', (req, res, ctx) => res(ctx.json(data)))
);
const promise = getLicenses();
await promise.then(thenFn).catch(catchFn);
expect(catchFn).not.toHaveBeenCalled();
expect(thenFn).toHaveBeenCalledWith(data);
});
it('on failure should return the server message', async () => {
const catchFn = jest.fn();
const thenFn = jest.fn();
const message = 'message';
const details = 'details';
server.use(
rest.get('/api/licenses', (req, res, ctx) =>
res(ctx.status(400), ctx.json({ message, details }))
)
);
const promise = getLicenses();
await promise.then(thenFn, catchFn);
expect(catchFn).toHaveBeenCalledWith(new Error(message));
expect(thenFn).not.toHaveBeenCalled();
});
});

View file

@ -0,0 +1,128 @@
import _ from 'lodash';
import { AxiosError } from 'axios';
import axios from '@/portainer/services/axios';
import { License, LicenseInfo } from './types';
type Listener = (info: LicenseInfo) => void;
interface Store {
data?: LicenseInfo;
lastLoaded?: number;
invalidated: boolean;
listeners: Listener[];
}
const store: Store = {
listeners: [],
invalidated: true,
};
export async function getLicenses() {
try {
const { data } = await axios.get<License[]>(buildUrl());
return data;
} catch (e) {
const axiosError = e as AxiosError;
throw new Error(axiosError.response?.data.message);
}
}
interface AttachResponse {
licenses: License[];
failedKeys: Record<string, string>;
}
export async function attachLicense(licenseKeys: string[]) {
try {
const { data } = await axios.post<AttachResponse>(buildUrl(), {
licenseKeys,
});
if (Object.keys(data.failedKeys).length === licenseKeys.length) {
return data;
}
store.invalidated = true;
getLicenseInfo();
return data;
} catch (e) {
const axiosError = e as AxiosError;
if (axiosError.response?.status === 401) {
throw new Error(
'Your session has expired, please refresh the browser and log in again.'
);
}
throw new Error(axiosError.response?.data.message);
}
}
interface RemoveResponse {
failedKeys: Record<string, string>;
}
export async function removeLicense(licenseKeys: string[]) {
try {
const { data } = await axios.post<RemoveResponse>(buildUrl('remove'), {
licenseKeys,
});
if (Object.keys(data.failedKeys).length === licenseKeys.length) {
return data;
}
store.invalidated = true;
getLicenseInfo();
return data;
} catch (e) {
const axiosError = e as AxiosError;
throw new Error(axiosError.response?.data.message);
}
}
export function resetState() {
store.invalidated = true;
store.data = undefined;
}
export async function getLicenseInfo() {
try {
if (
store.data &&
!store.invalidated &&
store.lastLoaded &&
Math.abs(store.lastLoaded - Date.now()) < 1000 * 30
) {
return store.data;
}
const { data: info } = await axios.get<LicenseInfo>(buildUrl('info'));
store.data = info;
store.lastLoaded = Date.now();
store.invalidated = false;
store.listeners.forEach((listener) => listener(info));
return info;
} catch (e) {
const axiosError = e as AxiosError;
throw new Error(axiosError.response?.data.message);
}
}
export function subscribe(listener: Listener) {
store.listeners.push(listener);
}
export function unsubscribe(listener: Listener) {
_.remove<Listener>(store.listeners, listener);
}
function buildUrl(action = '') {
let url = 'licenses';
if (action) {
url += `/${action}`;
}
return url;
}

View file

@ -0,0 +1,45 @@
// matches https://github.com/portainer/liblicense/blob/master/liblicense.go#L66-L74
export enum Edition {
CE = 1,
BE,
EE,
}
// matches https://github.com/portainer/liblicense/blob/master/liblicense.go#L60-L64
export enum LicenseType {
Trial = 1,
Subscription,
}
// matches https://github.com/portainer/liblicense/blob/master/liblicense.go#L35-L50
export interface License {
id: string;
company: string;
created: number;
email: string;
expiresAfter: number;
licenseKey: string;
nodes: number;
productEdition: Edition;
revoked: boolean;
revokedAt: number;
type: LicenseType;
version: number;
reference: string;
expiresAt: number;
}
// matches https://github.com/portainer/portainer-ee/blob/c4575bf528583fe1682267db4ee40a11a905f611/api/portainer.go#L588-L597
export interface LicenseInfo {
productEdition: Edition;
company: string;
email: string;
createdAt: number;
expiresAt: number;
nodes: number;
type: LicenseType;
valid: boolean;
enforcedAt: number;
enforced: boolean;
}

View file

@ -0,0 +1,37 @@
import { useQuery } from 'react-query';
import { error as notifyError } from '@/portainer/services/notifications';
import { useNodesCount } from '@/react/portainer/system/useNodesCount';
import { getLicenseInfo } from './license.service';
import { LicenseInfo, LicenseType } from './types';
export function useLicenseInfo() {
const { isLoading, data: info } = useQuery<LicenseInfo, Error>(
'licenseInfo',
() => getLicenseInfo(),
{
onError(error) {
notifyError('Failure', error as Error, 'Failed to get license info');
},
}
);
return { isLoading, info };
}
export function useIntegratedLicenseInfo() {
const { isLoading: isLoadingNodes, data: nodesCount = 0 } = useNodesCount();
const { isLoading: isLoadingLicense, info } = useLicenseInfo();
if (
isLoadingLicense ||
isLoadingNodes ||
!info ||
info.type === LicenseType.Trial
) {
return null;
}
return { licenseInfo: info as LicenseInfo, usedNodes: nodesCount };
}

View file

@ -0,0 +1,62 @@
import { Edit } from 'lucide-react';
import Docker from '@/assets/ico/vendor/docker.svg?c';
import Ecr from '@/assets/ico/vendor/ecr.svg?c';
import Quay from '@/assets/ico/vendor/quay.svg?c';
import Proget from '@/assets/ico/vendor/proget.svg?c';
import Azure from '@/assets/ico/vendor/azure.svg?c';
import Gitlab from '@/assets/ico/vendor/gitlab.svg?c';
import { BadgeIcon } from '@@/BadgeIcon';
export const options = [
{
id: 'registry_dockerhub',
icon: Docker,
label: 'DockerHub',
description: 'DockerHub authenticated account',
value: '6',
},
{
id: 'registry_aws_ecr',
icon: Ecr,
label: 'AWS ECR',
description: 'Amazon elastic container registry',
value: '7',
},
{
id: 'registry_quay',
icon: Quay,
label: 'Quay.io',
description: 'Quay container registry',
value: '1',
},
{
id: 'registry_proget',
icon: Proget,
label: 'ProGet',
description: 'ProGet container registry',
value: '5',
},
{
id: 'registry_azure',
icon: Azure,
label: 'Azure',
description: 'Azure container registry',
value: '2',
},
{
id: 'registry_gitlab',
icon: Gitlab,
label: 'GitLab',
description: 'GitLab container registry',
value: '4',
},
{
id: 'registry_custom',
icon: <BadgeIcon icon={Edit} />,
label: 'Custom registry',
description: 'Define your own registry',
value: '3',
},
];

View file

@ -0,0 +1,40 @@
import { ArrowDownCircle } from 'lucide-react';
import { FeatureId } from '@/react/portainer/feature-flags/enums';
import Microsoft from '@/assets/ico/vendor/microsoft.svg?c';
import Ldap from '@/assets/ico/ldap.svg?c';
import OAuth from '@/assets/ico/oauth.svg?c';
import { BadgeIcon } from '@@/BadgeIcon';
export const options = [
{
id: 'auth_internal',
icon: <BadgeIcon icon={ArrowDownCircle} />,
label: 'Internal',
description: 'Internal authentication mechanism',
value: 1,
},
{
id: 'auth_ldap',
icon: Ldap,
label: 'LDAP',
description: 'LDAP authentication',
value: 2,
},
{
id: 'auth_ad',
icon: Microsoft,
label: 'Microsoft Active Directory',
description: 'AD authentication',
value: 4,
feature: FeatureId.HIDE_INTERNAL_AUTH,
},
{
id: 'auth_oauth',
icon: OAuth,
label: 'OAuth',
description: 'OAuth authentication',
value: 3,
},
];

View file

@ -0,0 +1,28 @@
import { Edit } from 'lucide-react';
import { FeatureId } from '@/react/portainer/feature-flags/enums';
import Openldap from '@/assets/ico/vendor/openldap.svg?c';
import { BadgeIcon } from '@@/BadgeIcon';
const SERVER_TYPES = {
CUSTOM: 0,
OPEN_LDAP: 1,
AD: 2,
};
export const options = [
{
id: 'ldap_custom',
icon: <BadgeIcon icon={Edit} />,
label: 'Custom',
value: SERVER_TYPES.CUSTOM,
},
{
id: 'ldap_openldap',
icon: Openldap,
label: 'OpenLDAP',
value: SERVER_TYPES.OPEN_LDAP,
feature: FeatureId.EXTERNAL_AUTH_LDAP,
},
];

View file

@ -0,0 +1,42 @@
import { Edit } from 'lucide-react';
import { FeatureId } from '@/react/portainer/feature-flags/enums';
import Microsoft from '@/assets/ico/vendor/microsoft.svg?c';
import Google from '@/assets/ico/vendor/google.svg?c';
import Github from '@/assets/ico/vendor/github.svg?c';
import { BadgeIcon } from '@@/BadgeIcon';
export const options = [
{
id: 'microsoft',
icon: Microsoft,
label: 'Microsoft',
description: 'Microsoft OAuth provider',
value: 'microsoft',
feature: FeatureId.HIDE_INTERNAL_AUTH,
},
{
id: 'google',
icon: Google,
label: 'Google',
description: 'Google OAuth provider',
value: 'google',
feature: FeatureId.HIDE_INTERNAL_AUTH,
},
{
id: 'github',
icon: Github,
label: 'Github',
description: 'Github OAuth provider',
value: 'github',
feature: FeatureId.HIDE_INTERNAL_AUTH,
},
{
id: 'custom',
icon: <BadgeIcon icon={Edit} />,
label: 'Custom',
description: 'Custom OAuth provider',
value: 'custom',
},
];

View file

@ -0,0 +1,22 @@
import { DownloadCloud, UploadCloud } from 'lucide-react';
import { FeatureId } from '@/react/portainer/feature-flags/enums';
import { BadgeIcon } from '@@/BadgeIcon';
export const options = [
{
id: 'backup_file',
icon: <BadgeIcon icon={DownloadCloud} />,
label: 'Download backup file',
value: 'file',
},
{
id: 'backup_s3',
icon: <BadgeIcon icon={UploadCloud} />,
label: 'Store in S3',
description: 'Define a cron schedule',
value: 's3',
feature: FeatureId.S3_BACKUP_SETTING,
},
];