@cobaltcore-dev/aurora 0.18.0 → 0.19.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/client/App.d.ts +12 -0
- package/dist/client/{BucketToastNotifications-D2Cq2VrV.mjs → BucketToastNotifications-BGd2wVmh.mjs} +2 -2
- package/dist/client/{BucketToastNotifications-D2Cq2VrV.mjs.map → BucketToastNotifications-BGd2wVmh.mjs.map} +1 -1
- package/dist/client/DeletePcaModal-BU6kbKsw.mjs +80 -0
- package/dist/client/DeletePcaModal-BU6kbKsw.mjs.map +1 -0
- package/dist/client/DetailsInfo-BUyuYpJj.mjs +52 -0
- package/dist/client/DetailsInfo-BUyuYpJj.mjs.map +1 -0
- package/dist/client/{FloatingIpActionModals-sJlSFIsK.mjs → FloatingIpActionModals-DAtZoYGS.mjs} +22 -22
- package/dist/client/{FloatingIpActionModals-sJlSFIsK.mjs.map → FloatingIpActionModals-DAtZoYGS.mjs.map} +1 -1
- package/dist/client/{ImageToastNotifications-CISH3c_d.mjs → ImageToastNotifications-BhjU1bfT.mjs} +7 -7
- package/dist/client/{ImageToastNotifications-CISH3c_d.mjs.map → ImageToastNotifications-BhjU1bfT.mjs.map} +1 -1
- package/dist/client/{_flavorId-Cx5tf2KQ.mjs → _flavorId-BQY7YhNx.mjs} +2 -2
- package/dist/client/{_flavorId-Cx5tf2KQ.mjs.map → _flavorId-BQY7YhNx.mjs.map} +1 -1
- package/dist/client/{_flavorId-C6RJfhh8.mjs → _flavorId-sS1sg_DZ.mjs} +3 -3
- package/dist/client/{_flavorId-C6RJfhh8.mjs.map → _flavorId-sS1sg_DZ.mjs.map} +1 -1
- package/dist/client/{_floatingIpId-C4Sa8tMa.mjs → _floatingIpId-BHZGh8U8.mjs} +2 -2
- package/dist/client/{_floatingIpId-C4Sa8tMa.mjs.map → _floatingIpId-BHZGh8U8.mjs.map} +1 -1
- package/dist/client/{_floatingIpId-CAUBZ5WD2.mjs → _floatingIpId-CR3aD38l2.mjs} +5 -5
- package/dist/client/{_floatingIpId-CAUBZ5WD2.mjs.map → _floatingIpId-CR3aD38l2.mjs.map} +1 -1
- package/dist/client/{_imageId-DpXNAIbD.mjs → _imageId-Cf-Xdksv.mjs} +3 -3
- package/dist/client/{_imageId-DpXNAIbD.mjs.map → _imageId-Cf-Xdksv.mjs.map} +1 -1
- package/dist/client/_pcaId-B7j0sXnY.mjs +545 -0
- package/dist/client/_pcaId-B7j0sXnY.mjs.map +1 -0
- package/dist/client/{_projectId-fEA6fnFQ.mjs → _projectId-Cq9JnhRj.mjs} +3 -3
- package/dist/client/{_projectId-fEA6fnFQ.mjs.map → _projectId-Cq9JnhRj.mjs.map} +1 -1
- package/dist/client/{_projectId-w-tZz0FI.mjs → _projectId-D8FHe0gr.mjs} +2 -2
- package/dist/client/{_projectId-w-tZz0FI.mjs.map → _projectId-D8FHe0gr.mjs.map} +1 -1
- package/dist/client/{_projectId-qvINx3Dx.mjs → _projectId-Ig3QqYzt.mjs} +2 -2
- package/dist/client/{_projectId-qvINx3Dx.mjs.map → _projectId-Ig3QqYzt.mjs.map} +1 -1
- package/dist/client/{_projectId-BOaPmCuz.mjs → _projectId-b4NGeECR.mjs} +3 -3
- package/dist/client/{_projectId-BOaPmCuz.mjs.map → _projectId-b4NGeECR.mjs.map} +1 -1
- package/dist/client/{_securityGroupId-B6_lD8ry.mjs → _securityGroupId-BVSsCus9.mjs} +2 -2
- package/dist/client/{_securityGroupId-B6_lD8ry.mjs.map → _securityGroupId-BVSsCus9.mjs.map} +1 -1
- package/dist/client/{_securityGroupId-D9FHSkNU.mjs → _securityGroupId-gwV4eB0s.mjs} +16 -16
- package/dist/client/{_securityGroupId-D9FHSkNU.mjs.map → _securityGroupId-gwV4eB0s.mjs.map} +1 -1
- package/dist/client/{_storageType-ZFnIALny.mjs → _storageType-CH2khFcZ.mjs} +2 -2
- package/dist/client/{_storageType-ZFnIALny.mjs.map → _storageType-CH2khFcZ.mjs.map} +1 -1
- package/dist/client/{_storageType-MgntkZb6.mjs → _storageType-D-1H6SX1.mjs} +856 -856
- package/dist/client/{_storageType-MgntkZb6.mjs.map → _storageType-D-1H6SX1.mjs.map} +1 -1
- package/dist/client/analytics/setupRouterAnalytics.d.ts +20 -0
- package/dist/client/assets/__mocks__/svgMock.d.ts +3 -0
- package/dist/client/build-DgeVmENN.mjs.map +1 -1
- package/dist/client/components/Auth/SessionExpirationTimer.d.ts +4 -0
- package/dist/client/components/ClipboardText.d.ts +10 -0
- package/dist/client/components/ContentHeader/ContentHeader.d.ts +10 -0
- package/dist/client/components/Error/RouteError.d.ts +9 -0
- package/dist/client/components/Error/StatusError.d.ts +11 -0
- package/dist/client/components/JsonEditor.d.ts +39 -0
- package/dist/client/components/ListToolbar/FiltersInput.d.ts +6 -0
- package/dist/client/components/ListToolbar/SelectedFilters.d.ts +24 -0
- package/dist/client/components/ListToolbar/SortInput.d.ts +11 -0
- package/dist/client/components/ListToolbar/index.d.ts +26 -0
- package/dist/client/components/ListToolbar/types.d.ts +116 -0
- package/dist/client/components/ProjectView/ProjectInfoBox.d.ts +12 -0
- package/dist/client/components/Slot.d.ts +7 -0
- package/dist/client/components/navigation/LanguageSelect.d.ts +3 -0
- package/dist/client/components/navigation/MainNavigation.d.ts +10 -0
- package/dist/client/components/navigation/UserMenu.d.ts +1 -0
- package/dist/client/components/navigation/types.d.ts +4 -0
- package/dist/client/{floatingips-DOGKGGkC.mjs → floatingips-DyBEotB8.mjs} +10 -10
- package/dist/client/{floatingips-DOGKGGkC.mjs.map → floatingips-DyBEotB8.mjs.map} +1 -1
- package/dist/client/hooks/index.d.ts +15 -0
- package/dist/client/hooks/useDomainId.d.ts +21 -0
- package/dist/client/hooks/useModalTracking.d.ts +33 -0
- package/dist/client/hooks/useProjectId.d.ts +22 -0
- package/dist/client/hooks-iGiEkLTp.mjs +12 -0
- package/dist/client/hooks-iGiEkLTp.mjs.map +1 -0
- package/dist/client/{images-B1wqMKYw.mjs → images-BklbSacK.mjs} +2 -2
- package/dist/client/{images-B1wqMKYw.mjs.map → images-BklbSacK.mjs.map} +1 -1
- package/dist/client/{images-D5UsQi8i.mjs → images-C3voJ3B1.mjs} +259 -259
- package/dist/client/{images-D5UsQi8i.mjs.map → images-C3voJ3B1.mjs.map} +1 -1
- package/dist/client/index.d.ts +2 -0
- package/dist/client/index.js +337 -344
- package/dist/client/index.js.map +1 -1
- package/dist/client/md-CyCflQee.mjs.map +1 -1
- package/dist/client/{objects-DpgXMFrG.mjs → objects-B3Z8h4RU.mjs} +2 -2
- package/dist/client/{objects-DpgXMFrG.mjs.map → objects-B3Z8h4RU.mjs.map} +1 -1
- package/dist/client/{objects-Deo1Ic1A.mjs → objects-CGOfO00N.mjs} +499 -475
- package/dist/client/objects-CGOfO00N.mjs.map +1 -0
- package/dist/client/{pca-DztTIs18.mjs → pca-72YR_Pk0.mjs} +3 -3
- package/dist/client/pca-72YR_Pk0.mjs.map +1 -0
- package/dist/client/pca-CsBx_IDO.mjs +251 -0
- package/dist/client/pca-CsBx_IDO.mjs.map +1 -0
- package/dist/client/pcaAccess-Br4kVjLQ.mjs +9 -0
- package/dist/client/pcaAccess-Br4kVjLQ.mjs.map +1 -0
- package/dist/client/router.d.ts +7 -0
- package/dist/client/{securitygroups-BRtHaTLm.mjs → securitygroups-8vRbXmBL.mjs} +3 -3
- package/dist/client/{securitygroups-BRtHaTLm.mjs.map → securitygroups-8vRbXmBL.mjs.map} +1 -1
- package/dist/client/store/AuthProvider.d.ts +23 -0
- package/dist/client/trpcClient-BxcNKnhv.mjs +65 -0
- package/dist/client/trpcClient-BxcNKnhv.mjs.map +1 -0
- package/dist/client/trpcClient.d.ts +56 -49
- package/dist/client/utils/buildFilterParams.d.ts +5 -0
- package/dist/client/utils/cn.d.ts +27 -0
- package/dist/client/utils/formatBytes.d.ts +40 -0
- package/dist/client/utils/formatFloatingIpStatus.d.ts +6 -0
- package/dist/client/utils/languageDetection.d.ts +11 -0
- package/dist/client/utils/trpcErrors.d.ts +13 -0
- package/dist/client/utils/useErrorTranslation.d.ts +4 -0
- package/dist/client/utils/useListWithFiltering.d.ts +84 -0
- package/dist/client/utils/useModal.d.ts +3 -0
- package/dist/server/index.d.ts +51 -49
- package/dist/server/index.js +53 -23
- package/package.json +4 -2
- package/dist/client/_pcaId-DY9GPV7t.mjs +0 -479
- package/dist/client/_pcaId-DY9GPV7t.mjs.map +0 -1
- package/dist/client/_pcaId-ldtkXsbp.mjs +0 -36
- package/dist/client/_pcaId-ldtkXsbp.mjs.map +0 -1
- package/dist/client/constants-COPE2ktv.mjs +0 -153
- package/dist/client/constants-COPE2ktv.mjs.map +0 -1
- package/dist/client/hooks-DvdvErNv.mjs +0 -2
- package/dist/client/objects-Deo1Ic1A.mjs.map +0 -1
- package/dist/client/pca-B7WldCGw.mjs +0 -202
- package/dist/client/pca-B7WldCGw.mjs.map +0 -1
- package/dist/client/pca-DztTIs18.mjs.map +0 -1
- package/dist/client/pcaAccess-BYUY700H.mjs +0 -9
- package/dist/client/pcaAccess-BYUY700H.mjs.map +0 -1
- package/dist/client/trpcClient-Dy_MP_Pv.mjs +0 -57
- package/dist/client/trpcClient-Dy_MP_Pv.mjs.map +0 -1
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { default as React } from 'react';
|
|
2
|
+
export interface ClipboardTextProps extends React.HTMLAttributes<HTMLDivElement> {
|
|
3
|
+
tooltipContent?: string;
|
|
4
|
+
text: string;
|
|
5
|
+
className?: string;
|
|
6
|
+
truncateAt?: number;
|
|
7
|
+
showTooltip?: boolean;
|
|
8
|
+
}
|
|
9
|
+
declare const ClipboardText: React.FC<ClipboardTextProps>;
|
|
10
|
+
export default ClipboardText;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { ReactNode } from 'react';
|
|
2
|
+
interface ContentHeaderProps {
|
|
3
|
+
title: string;
|
|
4
|
+
projectId: string;
|
|
5
|
+
description?: string | null;
|
|
6
|
+
actions?: ReactNode;
|
|
7
|
+
badges?: ReactNode;
|
|
8
|
+
}
|
|
9
|
+
export declare function ContentHeader({ title, projectId, description, actions, badges }: ContentHeaderProps): import("react/jsx-runtime").JSX.Element;
|
|
10
|
+
export {};
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
interface RouteErrorProps {
|
|
2
|
+
error: unknown;
|
|
3
|
+
title?: string;
|
|
4
|
+
helpText?: string;
|
|
5
|
+
/** Explicitly pass a safe error message to display. Use this when you want to show specific error details. */
|
|
6
|
+
safeErrorMessage?: string;
|
|
7
|
+
}
|
|
8
|
+
export declare function RouteError({ error, title, helpText, safeErrorMessage }: RouteErrorProps): import("react/jsx-runtime").JSX.Element;
|
|
9
|
+
export {};
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
interface StatusErrorProps {
|
|
2
|
+
message: string;
|
|
3
|
+
statusCode?: number;
|
|
4
|
+
onHomeClick?: () => void;
|
|
5
|
+
onBackClick?: () => void;
|
|
6
|
+
title: string;
|
|
7
|
+
showHeader?: boolean;
|
|
8
|
+
reset?: () => void;
|
|
9
|
+
}
|
|
10
|
+
export declare function StatusError({ message, statusCode, onHomeClick, onBackClick, title, reset }: StatusErrorProps): import("react/jsx-runtime").JSX.Element;
|
|
11
|
+
export {};
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
export interface JsonEditorProps {
|
|
2
|
+
/** Current JSON string value */
|
|
3
|
+
value: string;
|
|
4
|
+
/** Callback when value changes */
|
|
5
|
+
onChange: (value: string) => void;
|
|
6
|
+
/** Callback when editor loses focus */
|
|
7
|
+
onBlur?: () => void;
|
|
8
|
+
/** Whether the editor is disabled */
|
|
9
|
+
disabled?: boolean;
|
|
10
|
+
/** Placeholder text when empty */
|
|
11
|
+
placeholder?: string;
|
|
12
|
+
/** Error message to display (also shows error border) */
|
|
13
|
+
error?: string | null;
|
|
14
|
+
/** Additional CSS class names (use height classes like h-96 to set fixed height) */
|
|
15
|
+
className?: string;
|
|
16
|
+
/** HTML id attribute */
|
|
17
|
+
id?: string;
|
|
18
|
+
/** HTML name attribute */
|
|
19
|
+
name?: string;
|
|
20
|
+
/** Number of spaces for indentation (default: 2) */
|
|
21
|
+
indentSize?: number;
|
|
22
|
+
/** Whether to show line numbers (default: true) */
|
|
23
|
+
showLineNumbers?: boolean;
|
|
24
|
+
/** Test ID for testing */
|
|
25
|
+
"data-testid"?: string;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* A simple JSON editor component with line numbers and smart indentation.
|
|
29
|
+
*
|
|
30
|
+
* Features:
|
|
31
|
+
* - Line numbers
|
|
32
|
+
* - Tab key inserts spaces
|
|
33
|
+
* - Enter key auto-indents based on context
|
|
34
|
+
* - Closing braces/brackets auto-dedent
|
|
35
|
+
* - Error state styling
|
|
36
|
+
* - Accessible and keyboard-friendly
|
|
37
|
+
*/
|
|
38
|
+
export declare const JsonEditor: ({ value, onChange, onBlur, disabled, placeholder, error, className, id, name, indentSize, showLineNumbers, "data-testid": testId, }: JsonEditorProps) => import("react/jsx-runtime").JSX.Element;
|
|
39
|
+
export default JsonEditor;
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { Filter, SelectedFilter } from './types';
|
|
2
|
+
export type FiltersInputProps = {
|
|
3
|
+
filters: Filter[];
|
|
4
|
+
onChange: (filter: SelectedFilter) => void;
|
|
5
|
+
};
|
|
6
|
+
export declare const FiltersInput: ({ filters, onChange }: FiltersInputProps) => import("react/jsx-runtime").JSX.Element;
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { SelectedFilter } from './types';
|
|
2
|
+
export type SelectedFiltersProps = {
|
|
3
|
+
/**
|
|
4
|
+
* Array of currently active filters to be displayed as closeable pills.
|
|
5
|
+
*/
|
|
6
|
+
selectedFilters: SelectedFilter[];
|
|
7
|
+
/**
|
|
8
|
+
* Callback function invoked when a user removes an individual filter pill.
|
|
9
|
+
*/
|
|
10
|
+
onDelete: (filter: SelectedFilter) => void;
|
|
11
|
+
/**
|
|
12
|
+
* Callback function invoked when the "Clear all" button is clicked.
|
|
13
|
+
*/
|
|
14
|
+
onClear: () => void;
|
|
15
|
+
};
|
|
16
|
+
/**
|
|
17
|
+
* SelectedFilters Component
|
|
18
|
+
*
|
|
19
|
+
* Displays currently active filters as closeable pill components with individual
|
|
20
|
+
* remove buttons and an optional "Clear all" button (shown when 2+ filters are active).
|
|
21
|
+
*
|
|
22
|
+
* The pills are arranged in a flexible, wrapping layout that adapts to available space.
|
|
23
|
+
*/
|
|
24
|
+
export declare const SelectedFilters: ({ selectedFilters, onDelete, onClear }: SelectedFiltersProps) => import("react/jsx-runtime").JSX.Element;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { default as React } from 'react';
|
|
2
|
+
import { SortOption } from './types';
|
|
3
|
+
export interface SortInputProps {
|
|
4
|
+
sortBy?: string | number | string[];
|
|
5
|
+
onSortByChange: (param?: string | number | string[]) => void;
|
|
6
|
+
sortDirection: "asc" | "desc";
|
|
7
|
+
onSortDirectionChange: (direction: "asc" | "desc") => void;
|
|
8
|
+
options: SortOption[];
|
|
9
|
+
selectClassName?: string;
|
|
10
|
+
}
|
|
11
|
+
export declare const SortInput: React.FC<SortInputProps>;
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { ReactNode } from 'react';
|
|
2
|
+
import { SearchInputProps } from '@cloudoperators/juno-ui-components';
|
|
3
|
+
import { FilterSettings, SortSettings } from './types';
|
|
4
|
+
export type ListToolbarProps = {
|
|
5
|
+
filterSettings?: FilterSettings;
|
|
6
|
+
onFilter?: (filterSettings: FilterSettings) => void;
|
|
7
|
+
sortSettings?: SortSettings;
|
|
8
|
+
onSort?: (sortSettings: SortSettings) => void;
|
|
9
|
+
searchTerm?: string;
|
|
10
|
+
onSearch?: (searchTerm: string) => void;
|
|
11
|
+
searchInputProps?: Omit<SearchInputProps, "value" | "onSearch" | "onClear" | "onInput">;
|
|
12
|
+
actions?: ReactNode;
|
|
13
|
+
tabs?: {
|
|
14
|
+
items: Array<{
|
|
15
|
+
label: string;
|
|
16
|
+
value: string;
|
|
17
|
+
}>;
|
|
18
|
+
activeItem: string;
|
|
19
|
+
onActiveItemChange: (value: ReactNode) => void;
|
|
20
|
+
};
|
|
21
|
+
totalCount?: number;
|
|
22
|
+
itemName?: string;
|
|
23
|
+
filteredCount?: number;
|
|
24
|
+
lastUpdated?: Date | string;
|
|
25
|
+
};
|
|
26
|
+
export declare const ListToolbar: ({ filterSettings, onFilter, sortSettings, onSort, searchTerm, onSearch, searchInputProps, actions, tabs, totalCount, filteredCount, itemName, lastUpdated, }: ListToolbarProps) => import("react/jsx-runtime").JSX.Element;
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Represents a single selected filter value in the active filter list
|
|
3
|
+
* Used to track which filters are currently applied to the data
|
|
4
|
+
*/
|
|
5
|
+
export type SelectedFilter = {
|
|
6
|
+
/** The filter name/key this selection belongs to (e.g., "status", "visibility") */
|
|
7
|
+
name: string;
|
|
8
|
+
/** The selected value for this filter (e.g., "active", "public") */
|
|
9
|
+
value: string;
|
|
10
|
+
/**
|
|
11
|
+
* Whether this filter is temporarily disabled without removing it
|
|
12
|
+
* Useful for "show/hide" functionality in the UI
|
|
13
|
+
* @default false
|
|
14
|
+
*/
|
|
15
|
+
inactive?: boolean;
|
|
16
|
+
};
|
|
17
|
+
/**
|
|
18
|
+
* Defines a filterable field and its available options
|
|
19
|
+
* Represents a single filter category that users can apply to narrow down results
|
|
20
|
+
*/
|
|
21
|
+
export type Filter = {
|
|
22
|
+
/**
|
|
23
|
+
* Human-readable name shown in the UI
|
|
24
|
+
* @example "Status", "Visibility", "Disk Format"
|
|
25
|
+
*/
|
|
26
|
+
displayName: string;
|
|
27
|
+
/**
|
|
28
|
+
* The actual parameter name used in API requests
|
|
29
|
+
* @example "status", "visibility", "disk_format"
|
|
30
|
+
*/
|
|
31
|
+
filterName: string;
|
|
32
|
+
/**
|
|
33
|
+
* Array of available values users can select for this filter
|
|
34
|
+
* @example ["active", "queued", "saving"] for status filter
|
|
35
|
+
*/
|
|
36
|
+
values: string[];
|
|
37
|
+
/**
|
|
38
|
+
* Whether this filter supports selecting multiple values using the 'in' operator
|
|
39
|
+
*
|
|
40
|
+
* For OpenStack Glance API:
|
|
41
|
+
* - Supports 'in': name, status, id, container_format, disk_format
|
|
42
|
+
* - Does NOT support 'in': visibility, protected, owner, tags, dates
|
|
43
|
+
*
|
|
44
|
+
* When true, multiple selections will be combined as: `filterName=in:value1,value2,value3`
|
|
45
|
+
* When false, only single value is allowed: `filterName=value`
|
|
46
|
+
*
|
|
47
|
+
* @default false
|
|
48
|
+
* @example
|
|
49
|
+
* // supportsMultiValue: true
|
|
50
|
+
* status=in:active,queued,saving
|
|
51
|
+
*
|
|
52
|
+
* // supportsMultiValue: false
|
|
53
|
+
* visibility=public
|
|
54
|
+
*/
|
|
55
|
+
supportsMultiValue?: boolean;
|
|
56
|
+
};
|
|
57
|
+
/**
|
|
58
|
+
* Complete filter configuration including available filters and current selections
|
|
59
|
+
* Represents the entire filtering state for a list view
|
|
60
|
+
*/
|
|
61
|
+
export type FilterSettings = {
|
|
62
|
+
/**
|
|
63
|
+
* Currently applied filters by the user
|
|
64
|
+
* If undefined or empty, no filters are active
|
|
65
|
+
*/
|
|
66
|
+
selectedFilters?: SelectedFilter[];
|
|
67
|
+
/**
|
|
68
|
+
* Available filter definitions that users can choose from
|
|
69
|
+
* These define what filters are available in the UI
|
|
70
|
+
*/
|
|
71
|
+
filters: Filter[];
|
|
72
|
+
};
|
|
73
|
+
/**
|
|
74
|
+
* Represents a single option in the sort dropdown
|
|
75
|
+
* Defines a field that data can be sorted by
|
|
76
|
+
*/
|
|
77
|
+
export type SortOption = {
|
|
78
|
+
/**
|
|
79
|
+
* The actual field name to sort by (used in API requests)
|
|
80
|
+
* @example "created_at", "name", "size", "status"
|
|
81
|
+
*/
|
|
82
|
+
value: string;
|
|
83
|
+
/**
|
|
84
|
+
* Human-readable label shown in the UI
|
|
85
|
+
* @example "Created At", "Name", "Size", "Status"
|
|
86
|
+
*/
|
|
87
|
+
label: string;
|
|
88
|
+
};
|
|
89
|
+
/**
|
|
90
|
+
* Complete sorting configuration including available options and current sort state
|
|
91
|
+
* Represents the entire sorting state for a list view
|
|
92
|
+
*/
|
|
93
|
+
export type SortSettings = {
|
|
94
|
+
/**
|
|
95
|
+
* Array of available fields that can be used for sorting
|
|
96
|
+
* These options are displayed in the sort dropdown
|
|
97
|
+
*/
|
|
98
|
+
options: SortOption[];
|
|
99
|
+
/**
|
|
100
|
+
* Currently selected sort field
|
|
101
|
+
* Can be a string (single field), number (field index), or array (multiple fields)
|
|
102
|
+
*
|
|
103
|
+
* For OpenStack Glance API, typically a string representing the field name
|
|
104
|
+
* @example "created_at", "name", "size"
|
|
105
|
+
*/
|
|
106
|
+
sortBy?: string | number | string[];
|
|
107
|
+
/**
|
|
108
|
+
* Current sort direction
|
|
109
|
+
*
|
|
110
|
+
* - "asc": Ascending order (A-Z, 0-9, oldest to newest)
|
|
111
|
+
* - "desc": Descending order (Z-A, 9-0, newest to oldest)
|
|
112
|
+
*
|
|
113
|
+
* @default "desc" (typically for created_at to show newest first)
|
|
114
|
+
*/
|
|
115
|
+
sortDirection?: "asc" | "desc";
|
|
116
|
+
};
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
interface ProjectInfoBoxProps {
|
|
2
|
+
projectInfo: {
|
|
3
|
+
id: string;
|
|
4
|
+
name: string;
|
|
5
|
+
description?: string;
|
|
6
|
+
domain?: {
|
|
7
|
+
name?: string;
|
|
8
|
+
};
|
|
9
|
+
};
|
|
10
|
+
}
|
|
11
|
+
export declare function ProjectInfoBox({ projectInfo }: ProjectInfoBoxProps): import("react/jsx-runtime").JSX.Element;
|
|
12
|
+
export {};
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { FC } from 'react';
|
|
2
|
+
import { SlotProps } from '../AuroraApp';
|
|
3
|
+
export declare function Slot({ component: Component, useShadowDOM, currentService, }: {
|
|
4
|
+
component: FC<SlotProps>;
|
|
5
|
+
useShadowDOM?: boolean;
|
|
6
|
+
currentService?: string;
|
|
7
|
+
}): import("react/jsx-runtime").JSX.Element | null;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { NavigationItem } from './types';
|
|
2
|
+
import { Slots } from '../../AuroraApp';
|
|
3
|
+
interface NavigationProps {
|
|
4
|
+
items: NavigationItem[];
|
|
5
|
+
handleThemeToggle?: (theme: string) => void;
|
|
6
|
+
appName?: string;
|
|
7
|
+
slots?: Slots;
|
|
8
|
+
}
|
|
9
|
+
export declare function MainNavigation({ items, handleThemeToggle, appName, slots }: NavigationProps): import("react/jsx-runtime").JSX.Element;
|
|
10
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function UserMenu(): import("react/jsx-runtime").JSX.Element;
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { A as e, B as t, E as n, G as r, H as i, K as a, P as o, R as s, U as c, Y as l, at as u, dt as d, et as f, m as p, o as m, r as h, rt as g, tt as _, y as v } from "./build-DgeVmENN.mjs";
|
|
2
|
-
import { r as y } from "./trpcClient-
|
|
3
|
-
import { t as b } from "./
|
|
4
|
-
import
|
|
5
|
-
import "./
|
|
6
|
-
import { t as S } from "./FloatingIpActionModals-
|
|
2
|
+
import { r as y } from "./trpcClient-BxcNKnhv.mjs";
|
|
3
|
+
import { t as b } from "./useProjectId-DBc5lpoU.mjs";
|
|
4
|
+
import "./hooks-iGiEkLTp.mjs";
|
|
5
|
+
import { t as x } from "./useModal-DCs1OJh7.mjs";
|
|
6
|
+
import { t as S } from "./FloatingIpActionModals-DAtZoYGS.mjs";
|
|
7
7
|
import { n as C, t as w } from "./useListWithFiltering-BuhE81I6.mjs";
|
|
8
8
|
import { t as T } from "./buildFilterParams-DoZzMKX9.mjs";
|
|
9
9
|
import { m as E, r as D, s as O } from "./md-CyCflQee.mjs";
|
|
@@ -47,7 +47,7 @@ var z = {
|
|
|
47
47
|
I._({ id: "Nu4oKW" }),
|
|
48
48
|
""
|
|
49
49
|
], V = ({ floatingIp: t }) => {
|
|
50
|
-
let { i18n: i, _: a } = P(), o = M(), s =
|
|
50
|
+
let { i18n: i, _: a } = P(), o = M(), s = b(), c = () => {
|
|
51
51
|
o({
|
|
52
52
|
to: "/projects/$projectId/network/floatingips/$floatingIpId",
|
|
53
53
|
params: {
|
|
@@ -130,7 +130,7 @@ var z = {
|
|
|
130
130
|
children: [/*#__PURE__*/ A(n, { children: f.map((e) => /*#__PURE__*/ A(s, { children: e }, e)) }), e.map((e) => /*#__PURE__*/ A(V, { floatingIp: e }, e.id))]
|
|
131
131
|
});
|
|
132
132
|
}, U = /^(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}$/, W = /^(([0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}|(([0-9a-fA-F]{1,4}:){1,7}:)|(([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4})|(([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2})|(([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3})|(([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4})|(([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5})|([0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6}))|(:((:[0-9a-fA-F]{1,4}){1,7}|:))|(::([fF]{4}(:0{1,4})?:)?((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|(([0-9a-fA-F]{1,4}:){1,4}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})))$/, G = (e) => U.test(e) || W.test(e), K = /^([a-zA-Z0-9]([a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?\.)*[a-zA-Z0-9]([a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?$/, q = ({ open: e, onClose: n }) => {
|
|
133
|
-
let { i18n: r, _: o } = P(), s =
|
|
133
|
+
let { i18n: r, _: o } = P(), s = b(), l = y.useUtils(), { isPending: u, ...g } = y.network.floatingIp.create.useMutation({ onSettled: () => l.network.floatingIp.list.invalidate() }), { data: _ = [], isLoading: v, error: x } = y.network.floatingIp.listExternalNetworks.useQuery({ project_id: s }), { data: S = [], isLoading: C, error: w } = y.network.floatingIp.listDnsDomains.useQuery({ project_id: s }), { data: T = [], isLoading: E, error: D } = y.network.floatingIp.listAvailablePorts.useQuery({ project_id: s }), O = L({
|
|
134
134
|
defaultValues: {
|
|
135
135
|
floating_network_id: "",
|
|
136
136
|
dns_domain: "",
|
|
@@ -164,7 +164,7 @@ var z = {
|
|
|
164
164
|
}
|
|
165
165
|
}), k = () => {
|
|
166
166
|
u || (O.reset(), g.reset(), n());
|
|
167
|
-
}, M = R(O.store, (e) => e.values.port_id), I = R(O.store, (e) => e.values.floating_network_id), z = T.find((e) => e.id === M)?.fixed_ips ?? [], B = (
|
|
167
|
+
}, M = R(O.store, (e) => e.values.port_id), I = R(O.store, (e) => e.values.floating_network_id), z = T.find((e) => e.id === M)?.fixed_ips ?? [], B = (x?.message || w?.message || D?.message) ?? g.error?.message ?? null;
|
|
168
168
|
return /*#__PURE__*/ j(h, {
|
|
169
169
|
open: e,
|
|
170
170
|
size: "large",
|
|
@@ -339,7 +339,7 @@ var z = {
|
|
|
339
339
|
]
|
|
340
340
|
});
|
|
341
341
|
}, J = "fixed_ip_address", Y = "asc", X = () => {
|
|
342
|
-
let { i18n: e, _: t } = P(), n =
|
|
342
|
+
let { i18n: e, _: t } = P(), n = b(), [r, i] = x(!1), { searchTerm: a, handleSearchChange: o, sortSettings: s, handleSortChange: c, filterSettings: l, handleFilterChange: u } = w({
|
|
343
343
|
defaultSortKey: J,
|
|
344
344
|
defaultSortDir: Y,
|
|
345
345
|
sortOptions: [
|
|
@@ -431,4 +431,4 @@ function Z() {
|
|
|
431
431
|
//#endregion
|
|
432
432
|
export { Z as component };
|
|
433
433
|
|
|
434
|
-
//# sourceMappingURL=floatingips-
|
|
434
|
+
//# sourceMappingURL=floatingips-DyBEotB8.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"floatingips-DOGKGGkC.mjs","names":["MdError","MdRemoveCircle","MdCheckCircle","STATUS_CONFIG","ACTIVE","text","icon","size","color","fill","DOWN","ERROR","TABLE_COLUMNS","t","useNavigate","DataGridCell","DataGridRow","PopupMenu","PopupMenuItem","PopupMenuOptions","STATUS_CONFIG","FloatingIpActionModals","useProjectId","FloatingIpTableRow","floatingIp","useLingui","navigate","projectId","navigateToDetailsPage","to","params","floatingIpId","id","data-testid","onClick","div","className","status","icon","text","floating_ip_address","fixed_ip_address","floating_network_id","description","e","stopPropagation","toggleEditModal","toggleAttachModal","toggleDetachModal","toggleReleaseModal","label","t","DataGrid","DataGridHeadCell","DataGridRow","DataGridCell","ContentHeading","Stack","Spinner","FloatingIpTableRow","TABLE_COLUMNS","FloatingIpListContainer","floatingIps","isLoading","isError","error","useLingui","columns","className","distribution","alignment","direction","variant","size","message","t","length","data-testid","colSpan","p","map","label","ip","floatingIp","id","z","useForm","useStore","Modal","Form","FormSection","Spinner","Message","Textarea","TextInput","Select","SelectOption","trpcReact","useProjectId","ipv4Regex","ipv6Regex","isValidIpAddress","value","test","dnsNameRegex","AllocateFloatingIpModal","open","onClose","useLingui","projectId","utils","useUtils","isPending","createFloatingIpMutation","network","floatingIp","create","useMutation","onSettled","list","invalidate","data","externalNetworks","isLoading","isExternalNetworksLoading","error","externalNetworksError","listExternalNetworks","useQuery","project_id","dnsDomains","isDnsDomainsLoading","dnsDomainsError","listDnsDomains","availablePorts","isPortsLoading","portsError","listAvailablePorts","formSchema","object","floating_network_id","string","dns_domain","dns_name","trim","max","t","refine","message","description","floating_ip_address","port_id","fixed_ip_address","form","defaultValues","validators","onSubmit","mutateAsync","tenant_id","handleClose","reset","currentPortId","store","state","values","currentFloatingNetworkId","selectedPort","find","port","id","portFixedIps","fixed_ips","formErrorMessage","size","title","onCancel","cancelButtonLabel","confirmButtonLabel","onConfirm","handleSubmit","disableConfirmButton","dismissible","variant","className","div","span","e","preventDefault","Field","name","children","field","onChange","handleChange","label","helptext","placeholder","disabled","required","loading","map","onBlur","handleBlur","target","errortext","meta","errors","join","portId","p","ips","setFieldValue","length","ip_address","Button","ListToolbar","trpcReact","buildFilterParams","useListWithFiltering","useModal","useProjectId","FloatingIpListContainer","AllocateFloatingIpModal","DEFAULT_SORT_KEY","DEFAULT_SORT_DIR","FloatingIpsList","useLingui","projectId","allocateModalOpen","toggleAllocateModal","searchTerm","handleSearchChange","sortSettings","handleSortChange","filterSettings","handleFilterChange","defaultSortKey","defaultSortDir","sortOptions","label","t","value","filters","displayName","filterName","values","supportsMultiValue","data","floatingIps","isLoading","isError","error","network","floatingIp","list","useQuery","project_id","sort_key","sortBy","sort_dir","sortDirection","div","className","onSearch","onSort","onFilter","actions","variant","onClick","open","onClose","useLingui","FloatingIpsList","ContentHeading","Route","RouteComponent","t","component"],"sources":["../../src/client/routes/_auth/projects/$projectId/network/floatingips/-components/-table/constants.tsx","../../src/client/routes/_auth/projects/$projectId/network/floatingips/-components/-table/FloatingIpTableRow.tsx","../../src/client/routes/_auth/projects/$projectId/network/floatingips/-components/-table/FloatingIpListContainer.tsx","../../src/client/routes/_auth/projects/$projectId/network/floatingips/-components/-modals/AllocateFloatingIpModal.tsx","../../src/client/routes/_auth/projects/$projectId/network/floatingips/-components/FloatingIpsList.tsx","../../src/client/routes/_auth/projects/$projectId/network/floatingips/index.tsx?tsr-split=component"],"sourcesContent":["import { MdError, MdRemoveCircle, MdCheckCircle } from \"react-icons/md\"\nimport { t } from \"@lingui/core/macro\"\nimport { FloatingIpStatus } from \"@/server/Network/types/floatingIp\"\n\ntype FloatingIpStatusDisplay = {\n text: string\n icon: React.ReactNode\n}\n\nexport const STATUS_CONFIG: Record<FloatingIpStatus, FloatingIpStatusDisplay> = {\n ACTIVE: {\n text: \"Active\",\n icon: <MdCheckCircle size={18} color=\"white\" fill=\"#4FB81C\" />,\n },\n DOWN: {\n text: \"Down\",\n icon: <MdRemoveCircle size={18} color=\"white\" fill=\"#969696\" />,\n },\n ERROR: {\n text: \"Error\",\n icon: <MdError size={18} color=\"white\" fill=\"#C70000\" />,\n },\n} as const\n\nexport const TABLE_COLUMNS = () =>\n [\n t`Status`,\n t`Floating IP Address`,\n t`Fixed IP Address`,\n t`Subnet`,\n t`Description`,\n \"\", // empty column for item-actions with context menu containing \"Preview\", \"Edit Description\", \"Attach\", \"Detach\" and \"Release\"\n ] as const\n","import { useNavigate } from \"@tanstack/react-router\"\nimport { useLingui } from \"@lingui/react/macro\"\nimport {\n DataGridCell,\n DataGridRow,\n PopupMenu,\n PopupMenuItem,\n PopupMenuOptions,\n} from \"@cloudoperators/juno-ui-components\"\nimport { FloatingIp } from \"@/server/Network/types/floatingIp\"\nimport { STATUS_CONFIG } from \"./constants\"\nimport { FloatingIpActionModals } from \"../-modals/FloatingIpActionModals\"\nimport { useProjectId } from \"@/client/hooks\"\n\ninterface FloatingIpTableRowProps {\n floatingIp: FloatingIp\n}\n\nexport const FloatingIpTableRow = ({ floatingIp }: FloatingIpTableRowProps) => {\n const { t } = useLingui()\n const navigate = useNavigate()\n const projectId = useProjectId()\n\n const navigateToDetailsPage = () => {\n navigate({\n to: \"/projects/$projectId/network/floatingips/$floatingIpId\",\n params: { projectId, floatingIpId: floatingIp.id },\n })\n }\n\n return (\n <DataGridRow key={floatingIp.id} data-testid={`floating-ip-row-${floatingIp.id}`} onClick={navigateToDetailsPage}>\n <DataGridCell>\n <div className=\"flex items-center gap-2\">\n {STATUS_CONFIG[floatingIp.status].icon}\n {STATUS_CONFIG[floatingIp.status].text}\n </div>\n </DataGridCell>\n <DataGridCell>{floatingIp.floating_ip_address}</DataGridCell>\n <DataGridCell>{floatingIp.fixed_ip_address || \"—\"}</DataGridCell>\n <DataGridCell>{floatingIp.floating_network_id}</DataGridCell>\n <DataGridCell>{floatingIp.description || \"—\"}</DataGridCell>\n <DataGridCell onClick={(e) => e.stopPropagation()} className=\"items-end pr-0\">\n <FloatingIpActionModals floatingIp={floatingIp}>\n {({ toggleEditModal, toggleAttachModal, toggleDetachModal, toggleReleaseModal }) => (\n <PopupMenu>\n <PopupMenuOptions>\n <PopupMenuItem label={t`Preview`} onClick={navigateToDetailsPage} />\n <PopupMenuItem label={t`Edit Description`} onClick={toggleEditModal} />\n <PopupMenuItem label={t`Attach`} onClick={toggleAttachModal} />\n <PopupMenuItem label={t`Detach`} onClick={toggleDetachModal} />\n <PopupMenuItem label={t`Release`} onClick={toggleReleaseModal} />\n </PopupMenuOptions>\n </PopupMenu>\n )}\n </FloatingIpActionModals>\n </DataGridCell>\n </DataGridRow>\n )\n}\n","import { Trans, useLingui } from \"@lingui/react/macro\"\nimport {\n DataGrid,\n DataGridHeadCell,\n DataGridRow,\n DataGridCell,\n ContentHeading,\n Stack,\n Spinner,\n} from \"@cloudoperators/juno-ui-components\"\nimport { FloatingIp } from \"@/server/Network/types/floatingIp\"\nimport { FloatingIpTableRow } from \"./FloatingIpTableRow\"\nimport { TABLE_COLUMNS } from \"./constants\"\n\ninterface FloatingIpListContainerProps {\n floatingIps: FloatingIp[]\n isLoading: boolean\n isError: boolean\n error: { message?: string } | null\n}\n\nexport const FloatingIpListContainer = ({ floatingIps, isLoading, isError, error }: FloatingIpListContainerProps) => {\n const { t } = useLingui()\n const columns = TABLE_COLUMNS()\n\n if (isLoading) {\n return (\n <Stack className=\"py-8\" distribution=\"center\" alignment=\"center\" direction=\"vertical\">\n <Spinner variant=\"primary\" size=\"large\" className=\"mb-2\" />\n <Trans>Loading...</Trans>\n </Stack>\n )\n }\n\n if (isError) {\n return (\n <Stack className=\"py-8\" distribution=\"center\" alignment=\"center\" direction=\"vertical\">\n {error?.message ?? t`Failed to load Floating IPs`}\n </Stack>\n )\n }\n\n if (floatingIps.length === 0) {\n return (\n <DataGrid columns={columns.length} className=\"floating-ips\" data-testid=\"no-floating-ips\">\n <DataGridRow>\n <DataGridCell colSpan={columns.length}>\n <ContentHeading>\n <Trans>No Floating IPs found</Trans>\n </ContentHeading>\n <p>\n <Trans>\n There are no Floating IPs available for this project. Floating IPs allow you to map public IP addresses\n to instances.\n </Trans>\n </p>\n </DataGridCell>\n </DataGridRow>\n </DataGrid>\n )\n }\n\n return (\n <DataGrid columns={columns.length}>\n <DataGridRow>\n {columns.map((label) => (\n <DataGridHeadCell key={label}>{label}</DataGridHeadCell>\n ))}\n </DataGridRow>\n {floatingIps.map((ip) => (\n <FloatingIpTableRow key={ip.id} floatingIp={ip} />\n ))}\n </DataGrid>\n )\n}\n","import { z } from \"zod\"\nimport { useForm, useStore } from \"@tanstack/react-form\"\nimport { Trans, useLingui } from \"@lingui/react/macro\"\nimport {\n Modal,\n Form,\n FormSection,\n Spinner,\n Message,\n Textarea,\n TextInput,\n Select,\n SelectOption,\n} from \"@cloudoperators/juno-ui-components\"\nimport { trpcReact } from \"@/client/trpcClient\"\nimport { useProjectId } from \"@/client/hooks\"\n\nexport interface AllocateFloatingIpModalProps {\n open: boolean\n onClose: () => void\n}\n\nconst ipv4Regex = /^(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3}$/\nconst ipv6Regex =\n /^(([0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}|(([0-9a-fA-F]{1,4}:){1,7}:)|(([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4})|(([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2})|(([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3})|(([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4})|(([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5})|([0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6}))|(:((:[0-9a-fA-F]{1,4}){1,7}|:))|(::([fF]{4}(:0{1,4})?:)?((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3}))|(([0-9a-fA-F]{1,4}:){1,4}:((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3})))$/\nconst isValidIpAddress = (value: string) => ipv4Regex.test(value) || ipv6Regex.test(value)\nconst dnsNameRegex = /^([a-zA-Z0-9]([a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?\\.)*[a-zA-Z0-9]([a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?$/\n\nexport const AllocateFloatingIpModal = ({ open, onClose }: AllocateFloatingIpModalProps) => {\n const { t } = useLingui()\n const projectId = useProjectId()\n const utils = trpcReact.useUtils()\n\n const { isPending, ...createFloatingIpMutation } = trpcReact.network.floatingIp.create.useMutation({\n onSettled: () => utils.network.floatingIp.list.invalidate(),\n })\n\n const {\n data: externalNetworks = [],\n isLoading: isExternalNetworksLoading,\n error: externalNetworksError,\n } = trpcReact.network.floatingIp.listExternalNetworks.useQuery({ project_id: projectId })\n\n const {\n data: dnsDomains = [],\n isLoading: isDnsDomainsLoading,\n error: dnsDomainsError,\n } = trpcReact.network.floatingIp.listDnsDomains.useQuery({ project_id: projectId })\n\n const {\n data: availablePorts = [],\n isLoading: isPortsLoading,\n error: portsError,\n } = trpcReact.network.floatingIp.listAvailablePorts.useQuery({ project_id: projectId })\n\n const formSchema = z.object({\n floating_network_id: z.string(),\n dns_domain: z.string(),\n dns_name: z\n .string()\n .trim()\n .max(63, t`DNS name must be at most 63 characters.`)\n .refine((value) => value === \"\" || dnsNameRegex.test(value), {\n message: t`Must be a valid PQDN or FQDN (alphanumeric and hyphens only, cannot start or end with hyphen).`,\n }),\n description: z\n .string()\n .trim()\n .max(255, t`Description must be at most 255 characters.`),\n floating_ip_address: z\n .string()\n .trim()\n .refine((value) => value === \"\" || isValidIpAddress(value), {\n message: t`Must be a valid IPv4 or IPv6 address (for example: 172.24.4.228 or 2001:db8::1).`,\n }),\n port_id: z.string(),\n fixed_ip_address: z.string(),\n })\n\n const form = useForm({\n defaultValues: {\n floating_network_id: \"\",\n dns_domain: \"\",\n dns_name: \"\",\n description: \"\",\n floating_ip_address: \"\",\n port_id: \"\",\n fixed_ip_address: \"\",\n },\n validators: {\n onSubmit: formSchema,\n },\n onSubmit: async ({ value }) => {\n if (isPending) return\n\n await createFloatingIpMutation.mutateAsync({\n project_id: projectId,\n tenant_id: projectId,\n floating_network_id: value.floating_network_id,\n ...(value.dns_domain && { dns_domain: value.dns_domain }),\n ...(value.dns_name && { dns_name: value.dns_name }),\n ...(value.description && { description: value.description }),\n ...(value.floating_ip_address && { floating_ip_address: value.floating_ip_address }),\n ...(value.port_id && { port_id: value.port_id }),\n ...(value.fixed_ip_address && { fixed_ip_address: value.fixed_ip_address }),\n })\n handleClose()\n },\n })\n\n const handleClose = () => {\n if (isPending) return\n\n form.reset()\n createFloatingIpMutation.reset()\n onClose()\n }\n\n const currentPortId = useStore(form.store, (state) => state.values.port_id)\n const currentFloatingNetworkId = useStore(form.store, (state) => state.values.floating_network_id)\n const selectedPort = availablePorts.find((port) => port.id === currentPortId)\n const portFixedIps = selectedPort?.fixed_ips ?? []\n\n const formErrorMessage =\n (externalNetworksError?.message || dnsDomainsError?.message || portsError?.message) ??\n createFloatingIpMutation.error?.message ??\n null\n\n return (\n <Modal\n open={open}\n size=\"large\"\n title={t`Allocate Floating IP`}\n onCancel={handleClose}\n cancelButtonLabel={t`Cancel`}\n confirmButtonLabel={t`Allocate`}\n onConfirm={form.handleSubmit}\n disableConfirmButton={isPending || !currentFloatingNetworkId}\n >\n {formErrorMessage && (\n <Message dismissible={false} variant=\"error\" className=\"mb-4\">\n {formErrorMessage}\n </Message>\n )}\n\n {isPending && (\n <div className=\"mb-4 flex items-center justify-center gap-2\">\n <Spinner variant=\"primary\" />\n <span className=\"text-theme-high text-sm\">\n <Trans>Allocating Floating IP...</Trans>\n </span>\n </div>\n )}\n\n {!isPending && (\n <Form\n className=\"mb-0\"\n id=\"allocate-floating-ip-form\"\n onSubmit={(e) => {\n e.preventDefault()\n form.handleSubmit()\n }}\n >\n <FormSection className=\"mb-4\">\n <form.Field\n name=\"floating_network_id\"\n children={(field) => (\n <Select\n id={field.name}\n name={field.name}\n value={field.state.value}\n onChange={(value) => field.handleChange(typeof value === \"string\" ? value : \"\")}\n label={t`External Network`}\n helptext={t`The ID of the network associated with the floating IP.`}\n placeholder={t`Select an external network`}\n disabled={isPending || isExternalNetworksLoading}\n required\n loading={isExternalNetworksLoading}\n >\n {externalNetworks.map(({ id, name }) => (\n <SelectOption key={id} value={id} label={name ? `${name} (${id})` : id} />\n ))}\n </Select>\n )}\n />\n </FormSection>\n <FormSection className=\"mb-4\">\n <form.Field\n name=\"dns_domain\"\n children={(field) => (\n <Select\n id={field.name}\n name={field.name}\n value={field.state.value}\n onChange={(value) => field.handleChange(typeof value === \"string\" ? value : \"\")}\n label={t`DNS Domain`}\n helptext={t`Select a DNS domain.`}\n disabled={isPending || isDnsDomainsLoading}\n loading={isDnsDomainsLoading}\n >\n {dnsDomains.map(({ id, name }) => (\n <SelectOption key={id} value={name} label={name} />\n ))}\n </Select>\n )}\n />\n </FormSection>\n <FormSection className=\"mb-4\">\n <form.Field\n name=\"dns_name\"\n children={(field) => (\n <TextInput\n id={field.name}\n name={field.name}\n value={field.state.value}\n onBlur={field.handleBlur}\n onChange={(e) => field.handleChange(e.target.value)}\n label={t`DNS Name`}\n placeholder={t`Enter DNS name`}\n helptext={t`Enter a valid PQDN or FQDN (max 63 characters) to associate with the floating IP. A and PTR records are created automatically.`}\n errortext={field.state.meta.errors.map((e) => e?.message).join(\", \")}\n disabled={isPending}\n />\n )}\n />\n </FormSection>\n <FormSection className=\"mb-4\">\n <form.Field\n name=\"description\"\n children={(field) => (\n <Textarea\n id={field.name}\n name={field.name}\n value={field.state.value}\n onBlur={field.handleBlur}\n onChange={(e) => field.handleChange(e.target.value)}\n placeholder={t`Description`}\n errortext={field.state.meta.errors.map((e) => e?.message).join(\", \")}\n disabled={isPending}\n />\n )}\n />\n </FormSection>\n <FormSection className=\"mb-4\">\n <form.Field\n name=\"floating_ip_address\"\n children={(field) => (\n <TextInput\n id={field.name}\n name={field.name}\n value={field.state.value}\n onBlur={field.handleBlur}\n onChange={(e) => field.handleChange(e.target.value)}\n label={t`Floating IP Address`}\n placeholder={t`Enter a floating IP`}\n helptext={t`Enter a floating IP or leave blank to auto-assign one`}\n errortext={field.state.meta.errors.map((e) => e?.message).join(\", \")}\n disabled={isPending}\n />\n )}\n />\n </FormSection>\n <FormSection className=\"mb-4\">\n <form.Field\n name=\"port_id\"\n children={(field) => (\n <Select\n id={field.name}\n name={field.name}\n value={field.state.value}\n onChange={(value) => {\n const portId = typeof value === \"string\" ? value : \"\"\n field.handleChange(portId)\n const port = availablePorts.find((p) => p.id === portId)\n const ips = port?.fixed_ips ?? []\n form.setFieldValue(\"fixed_ip_address\", ips.length === 1 ? ips[0].ip_address : \"\")\n }}\n label={t`Port ID`}\n placeholder={t`Select port to associate`}\n errortext={field.state.meta.errors.map((e) => e?.message).join(\", \")}\n disabled={isPending || isPortsLoading}\n loading={isPortsLoading}\n >\n {availablePorts.map((port) => (\n <SelectOption\n key={port.id}\n value={port.id}\n label={port.name ? `${port.name} (${port.id})` : port.id}\n />\n ))}\n </Select>\n )}\n />\n </FormSection>\n <FormSection>\n <form.Field\n name=\"fixed_ip_address\"\n children={(field) => (\n <Select\n id={field.name}\n name={field.name}\n value={field.state.value}\n onBlur={field.handleBlur}\n onChange={(value) => field.handleChange(typeof value === \"string\" ? value : \"\")}\n label={t`Fixed IP Address`}\n placeholder={t`Select a fixed IP address`}\n helptext={t`Associates on the selected port. If the port has multiple IPs, select the desired fixed IP address.`}\n errortext={field.state.meta.errors.map((e) => e?.message).join(\", \")}\n disabled={isPending || portFixedIps.length === 0}\n >\n {portFixedIps.map(({ ip_address }) => (\n <SelectOption key={ip_address} value={ip_address} label={ip_address} />\n ))}\n </Select>\n )}\n />\n </FormSection>\n </Form>\n )}\n </Modal>\n )\n}\n","import { useLingui } from \"@lingui/react/macro\"\nimport { Button } from \"@cloudoperators/juno-ui-components\"\nimport { FloatingIpQueryParameters } from \"@/server/Network/types/floatingIp\"\nimport { ListToolbar } from \"@/client/components/ListToolbar\"\nimport { trpcReact } from \"@/client/trpcClient\"\nimport { buildFilterParams } from \"@/client/utils/buildFilterParams\"\nimport { useListWithFiltering } from \"@/client/utils/useListWithFiltering\"\nimport { useModal } from \"@/client/utils/useModal\"\nimport { useProjectId } from \"@/client/hooks\"\nimport { FloatingIpListContainer } from \"./-table/FloatingIpListContainer\"\nimport { AllocateFloatingIpModal } from \"./-modals/AllocateFloatingIpModal\"\n\nconst DEFAULT_SORT_KEY = \"fixed_ip_address\"\nconst DEFAULT_SORT_DIR = \"asc\"\nexport type FloatingIpsSortKey = NonNullable<FloatingIpQueryParameters[\"sort_key\"]>\n\nexport const FloatingIpsList = () => {\n const { t } = useLingui()\n const projectId = useProjectId()\n const [allocateModalOpen, toggleAllocateModal] = useModal(false)\n\n const { searchTerm, handleSearchChange, sortSettings, handleSortChange, filterSettings, handleFilterChange } =\n useListWithFiltering<FloatingIpsSortKey>({\n defaultSortKey: DEFAULT_SORT_KEY,\n defaultSortDir: DEFAULT_SORT_DIR,\n sortOptions: [\n { label: t`Fixed IP Address`, value: \"fixed_ip_address\" },\n { label: t`Floating IP Address`, value: \"floating_ip_address\" },\n { label: t`Floating Network ID`, value: \"floating_network_id\" },\n { label: t`ID`, value: \"id\" },\n { label: t`Router ID`, value: \"router_id\" },\n { label: t`Status`, value: \"status\" },\n // Tenant_id was kept for backward compatibility in case the deprecated tenant ID was used to sort instead of the project ID.\n { label: t`Tenant ID`, value: \"tenant_id\" },\n { label: t`Project ID`, value: \"project_id\" },\n ],\n filterSettings: {\n filters: [\n {\n displayName: t`Status`,\n filterName: \"status\",\n values: [\"ACTIVE\", \"DOWN\", \"ERROR\"],\n supportsMultiValue: false,\n },\n ],\n },\n })\n\n const {\n data: floatingIps = [],\n isLoading,\n isError,\n error,\n } = trpcReact.network.floatingIp.list.useQuery({\n project_id: projectId,\n sort_key: sortSettings.sortBy,\n sort_dir: sortSettings.sortDirection,\n ...buildFilterParams(filterSettings),\n ...(searchTerm ? { searchTerm } : {}),\n })\n\n return (\n <div className=\"relative\">\n <ListToolbar\n searchTerm={searchTerm}\n onSearch={handleSearchChange}\n sortSettings={sortSettings}\n onSort={handleSortChange}\n filterSettings={filterSettings}\n onFilter={handleFilterChange}\n actions={<Button variant=\"primary\" label={t`Allocate Floating IP`} onClick={toggleAllocateModal} />}\n />\n\n <FloatingIpListContainer floatingIps={floatingIps} isLoading={isLoading} isError={isError} error={error} />\n\n {allocateModalOpen && <AllocateFloatingIpModal open={allocateModalOpen} onClose={toggleAllocateModal} />}\n </div>\n )\n}\n","import { createFileRoute } from \"@tanstack/react-router\"\nimport { t } from \"@lingui/core/macro\"\nimport { useLingui } from \"@lingui/react/macro\"\nimport { FloatingIpsList } from \"./-components/FloatingIpsList\"\nimport type { RouteInfo } from \"@/client/routes/routeInfo\"\nimport { ContentHeading } from \"@cloudoperators/juno-ui-components\"\n\nexport const Route = createFileRoute(\"/_auth/projects/$projectId/network/floatingips/\")({\n staticData: {\n section: \"network\",\n service: \"floatingips\",\n analytics: {\n name: \"network.floatingips.list\",\n },\n sectionCrumb: { labelKey: \"Network\" },\n crumb: { labelKey: \"Floating IPs\" },\n } satisfies RouteInfo,\n head: () => ({ meta: [{ title: t`Floating IPs` }] }),\n component: RouteComponent,\n})\n\nfunction RouteComponent() {\n const { t } = useLingui()\n return (\n <>\n <ContentHeading>{t`Floating IPs`}</ContentHeading>\n <FloatingIpsList />\n </>\n )\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"floatingips-DyBEotB8.mjs","names":["MdError","MdRemoveCircle","MdCheckCircle","STATUS_CONFIG","ACTIVE","text","icon","size","color","fill","DOWN","ERROR","TABLE_COLUMNS","t","useNavigate","DataGridCell","DataGridRow","PopupMenu","PopupMenuItem","PopupMenuOptions","STATUS_CONFIG","FloatingIpActionModals","useProjectId","FloatingIpTableRow","floatingIp","useLingui","navigate","projectId","navigateToDetailsPage","to","params","floatingIpId","id","data-testid","onClick","div","className","status","icon","text","floating_ip_address","fixed_ip_address","floating_network_id","description","e","stopPropagation","toggleEditModal","toggleAttachModal","toggleDetachModal","toggleReleaseModal","label","t","DataGrid","DataGridHeadCell","DataGridRow","DataGridCell","ContentHeading","Stack","Spinner","FloatingIpTableRow","TABLE_COLUMNS","FloatingIpListContainer","floatingIps","isLoading","isError","error","useLingui","columns","className","distribution","alignment","direction","variant","size","message","t","length","data-testid","colSpan","p","map","label","ip","floatingIp","id","z","useForm","useStore","Modal","Form","FormSection","Spinner","Message","Textarea","TextInput","Select","SelectOption","trpcReact","useProjectId","ipv4Regex","ipv6Regex","isValidIpAddress","value","test","dnsNameRegex","AllocateFloatingIpModal","open","onClose","useLingui","projectId","utils","useUtils","isPending","createFloatingIpMutation","network","floatingIp","create","useMutation","onSettled","list","invalidate","data","externalNetworks","isLoading","isExternalNetworksLoading","error","externalNetworksError","listExternalNetworks","useQuery","project_id","dnsDomains","isDnsDomainsLoading","dnsDomainsError","listDnsDomains","availablePorts","isPortsLoading","portsError","listAvailablePorts","formSchema","object","floating_network_id","string","dns_domain","dns_name","trim","max","t","refine","message","description","floating_ip_address","port_id","fixed_ip_address","form","defaultValues","validators","onSubmit","mutateAsync","tenant_id","handleClose","reset","currentPortId","store","state","values","currentFloatingNetworkId","selectedPort","find","port","id","portFixedIps","fixed_ips","formErrorMessage","size","title","onCancel","cancelButtonLabel","confirmButtonLabel","onConfirm","handleSubmit","disableConfirmButton","dismissible","variant","className","div","span","e","preventDefault","Field","name","children","field","onChange","handleChange","label","helptext","placeholder","disabled","required","loading","map","onBlur","handleBlur","target","errortext","meta","errors","join","portId","p","ips","setFieldValue","length","ip_address","Button","ListToolbar","trpcReact","buildFilterParams","useListWithFiltering","useModal","useProjectId","FloatingIpListContainer","AllocateFloatingIpModal","DEFAULT_SORT_KEY","DEFAULT_SORT_DIR","FloatingIpsList","useLingui","projectId","allocateModalOpen","toggleAllocateModal","searchTerm","handleSearchChange","sortSettings","handleSortChange","filterSettings","handleFilterChange","defaultSortKey","defaultSortDir","sortOptions","label","t","value","filters","displayName","filterName","values","supportsMultiValue","data","floatingIps","isLoading","isError","error","network","floatingIp","list","useQuery","project_id","sort_key","sortBy","sort_dir","sortDirection","div","className","onSearch","onSort","onFilter","actions","variant","onClick","open","onClose","useLingui","FloatingIpsList","ContentHeading","Route","RouteComponent","t","component"],"sources":["../../src/client/routes/_auth/projects/$projectId/network/floatingips/-components/-table/constants.tsx","../../src/client/routes/_auth/projects/$projectId/network/floatingips/-components/-table/FloatingIpTableRow.tsx","../../src/client/routes/_auth/projects/$projectId/network/floatingips/-components/-table/FloatingIpListContainer.tsx","../../src/client/routes/_auth/projects/$projectId/network/floatingips/-components/-modals/AllocateFloatingIpModal.tsx","../../src/client/routes/_auth/projects/$projectId/network/floatingips/-components/FloatingIpsList.tsx","../../src/client/routes/_auth/projects/$projectId/network/floatingips/index.tsx?tsr-split=component"],"sourcesContent":["import { MdError, MdRemoveCircle, MdCheckCircle } from \"react-icons/md\"\nimport { t } from \"@lingui/core/macro\"\nimport { FloatingIpStatus } from \"@/server/Network/types/floatingIp\"\n\ntype FloatingIpStatusDisplay = {\n text: string\n icon: React.ReactNode\n}\n\nexport const STATUS_CONFIG: Record<FloatingIpStatus, FloatingIpStatusDisplay> = {\n ACTIVE: {\n text: \"Active\",\n icon: <MdCheckCircle size={18} color=\"white\" fill=\"#4FB81C\" />,\n },\n DOWN: {\n text: \"Down\",\n icon: <MdRemoveCircle size={18} color=\"white\" fill=\"#969696\" />,\n },\n ERROR: {\n text: \"Error\",\n icon: <MdError size={18} color=\"white\" fill=\"#C70000\" />,\n },\n} as const\n\nexport const TABLE_COLUMNS = () =>\n [\n t`Status`,\n t`Floating IP Address`,\n t`Fixed IP Address`,\n t`Subnet`,\n t`Description`,\n \"\", // empty column for item-actions with context menu containing \"Preview\", \"Edit Description\", \"Attach\", \"Detach\" and \"Release\"\n ] as const\n","import { useNavigate } from \"@tanstack/react-router\"\nimport { useLingui } from \"@lingui/react/macro\"\nimport {\n DataGridCell,\n DataGridRow,\n PopupMenu,\n PopupMenuItem,\n PopupMenuOptions,\n} from \"@cloudoperators/juno-ui-components\"\nimport { FloatingIp } from \"@/server/Network/types/floatingIp\"\nimport { STATUS_CONFIG } from \"./constants\"\nimport { FloatingIpActionModals } from \"../-modals/FloatingIpActionModals\"\nimport { useProjectId } from \"@/client/hooks\"\n\ninterface FloatingIpTableRowProps {\n floatingIp: FloatingIp\n}\n\nexport const FloatingIpTableRow = ({ floatingIp }: FloatingIpTableRowProps) => {\n const { t } = useLingui()\n const navigate = useNavigate()\n const projectId = useProjectId()\n\n const navigateToDetailsPage = () => {\n navigate({\n to: \"/projects/$projectId/network/floatingips/$floatingIpId\",\n params: { projectId, floatingIpId: floatingIp.id },\n })\n }\n\n return (\n <DataGridRow key={floatingIp.id} data-testid={`floating-ip-row-${floatingIp.id}`} onClick={navigateToDetailsPage}>\n <DataGridCell>\n <div className=\"flex items-center gap-2\">\n {STATUS_CONFIG[floatingIp.status].icon}\n {STATUS_CONFIG[floatingIp.status].text}\n </div>\n </DataGridCell>\n <DataGridCell>{floatingIp.floating_ip_address}</DataGridCell>\n <DataGridCell>{floatingIp.fixed_ip_address || \"—\"}</DataGridCell>\n <DataGridCell>{floatingIp.floating_network_id}</DataGridCell>\n <DataGridCell>{floatingIp.description || \"—\"}</DataGridCell>\n <DataGridCell onClick={(e) => e.stopPropagation()} className=\"items-end pr-0\">\n <FloatingIpActionModals floatingIp={floatingIp}>\n {({ toggleEditModal, toggleAttachModal, toggleDetachModal, toggleReleaseModal }) => (\n <PopupMenu>\n <PopupMenuOptions>\n <PopupMenuItem label={t`Preview`} onClick={navigateToDetailsPage} />\n <PopupMenuItem label={t`Edit Description`} onClick={toggleEditModal} />\n <PopupMenuItem label={t`Attach`} onClick={toggleAttachModal} />\n <PopupMenuItem label={t`Detach`} onClick={toggleDetachModal} />\n <PopupMenuItem label={t`Release`} onClick={toggleReleaseModal} />\n </PopupMenuOptions>\n </PopupMenu>\n )}\n </FloatingIpActionModals>\n </DataGridCell>\n </DataGridRow>\n )\n}\n","import { Trans, useLingui } from \"@lingui/react/macro\"\nimport {\n DataGrid,\n DataGridHeadCell,\n DataGridRow,\n DataGridCell,\n ContentHeading,\n Stack,\n Spinner,\n} from \"@cloudoperators/juno-ui-components\"\nimport { FloatingIp } from \"@/server/Network/types/floatingIp\"\nimport { FloatingIpTableRow } from \"./FloatingIpTableRow\"\nimport { TABLE_COLUMNS } from \"./constants\"\n\ninterface FloatingIpListContainerProps {\n floatingIps: FloatingIp[]\n isLoading: boolean\n isError: boolean\n error: { message?: string } | null\n}\n\nexport const FloatingIpListContainer = ({ floatingIps, isLoading, isError, error }: FloatingIpListContainerProps) => {\n const { t } = useLingui()\n const columns = TABLE_COLUMNS()\n\n if (isLoading) {\n return (\n <Stack className=\"py-8\" distribution=\"center\" alignment=\"center\" direction=\"vertical\">\n <Spinner variant=\"primary\" size=\"large\" className=\"mb-2\" />\n <Trans>Loading...</Trans>\n </Stack>\n )\n }\n\n if (isError) {\n return (\n <Stack className=\"py-8\" distribution=\"center\" alignment=\"center\" direction=\"vertical\">\n {error?.message ?? t`Failed to load Floating IPs`}\n </Stack>\n )\n }\n\n if (floatingIps.length === 0) {\n return (\n <DataGrid columns={columns.length} className=\"floating-ips\" data-testid=\"no-floating-ips\">\n <DataGridRow>\n <DataGridCell colSpan={columns.length}>\n <ContentHeading>\n <Trans>No Floating IPs found</Trans>\n </ContentHeading>\n <p>\n <Trans>\n There are no Floating IPs available for this project. Floating IPs allow you to map public IP addresses\n to instances.\n </Trans>\n </p>\n </DataGridCell>\n </DataGridRow>\n </DataGrid>\n )\n }\n\n return (\n <DataGrid columns={columns.length}>\n <DataGridRow>\n {columns.map((label) => (\n <DataGridHeadCell key={label}>{label}</DataGridHeadCell>\n ))}\n </DataGridRow>\n {floatingIps.map((ip) => (\n <FloatingIpTableRow key={ip.id} floatingIp={ip} />\n ))}\n </DataGrid>\n )\n}\n","import { z } from \"zod\"\nimport { useForm, useStore } from \"@tanstack/react-form\"\nimport { Trans, useLingui } from \"@lingui/react/macro\"\nimport {\n Modal,\n Form,\n FormSection,\n Spinner,\n Message,\n Textarea,\n TextInput,\n Select,\n SelectOption,\n} from \"@cloudoperators/juno-ui-components\"\nimport { trpcReact } from \"@/client/trpcClient\"\nimport { useProjectId } from \"@/client/hooks\"\n\nexport interface AllocateFloatingIpModalProps {\n open: boolean\n onClose: () => void\n}\n\nconst ipv4Regex = /^(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3}$/\nconst ipv6Regex =\n /^(([0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}|(([0-9a-fA-F]{1,4}:){1,7}:)|(([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4})|(([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2})|(([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3})|(([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4})|(([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5})|([0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6}))|(:((:[0-9a-fA-F]{1,4}){1,7}|:))|(::([fF]{4}(:0{1,4})?:)?((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3}))|(([0-9a-fA-F]{1,4}:){1,4}:((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3})))$/\nconst isValidIpAddress = (value: string) => ipv4Regex.test(value) || ipv6Regex.test(value)\nconst dnsNameRegex = /^([a-zA-Z0-9]([a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?\\.)*[a-zA-Z0-9]([a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?$/\n\nexport const AllocateFloatingIpModal = ({ open, onClose }: AllocateFloatingIpModalProps) => {\n const { t } = useLingui()\n const projectId = useProjectId()\n const utils = trpcReact.useUtils()\n\n const { isPending, ...createFloatingIpMutation } = trpcReact.network.floatingIp.create.useMutation({\n onSettled: () => utils.network.floatingIp.list.invalidate(),\n })\n\n const {\n data: externalNetworks = [],\n isLoading: isExternalNetworksLoading,\n error: externalNetworksError,\n } = trpcReact.network.floatingIp.listExternalNetworks.useQuery({ project_id: projectId })\n\n const {\n data: dnsDomains = [],\n isLoading: isDnsDomainsLoading,\n error: dnsDomainsError,\n } = trpcReact.network.floatingIp.listDnsDomains.useQuery({ project_id: projectId })\n\n const {\n data: availablePorts = [],\n isLoading: isPortsLoading,\n error: portsError,\n } = trpcReact.network.floatingIp.listAvailablePorts.useQuery({ project_id: projectId })\n\n const formSchema = z.object({\n floating_network_id: z.string(),\n dns_domain: z.string(),\n dns_name: z\n .string()\n .trim()\n .max(63, t`DNS name must be at most 63 characters.`)\n .refine((value) => value === \"\" || dnsNameRegex.test(value), {\n message: t`Must be a valid PQDN or FQDN (alphanumeric and hyphens only, cannot start or end with hyphen).`,\n }),\n description: z\n .string()\n .trim()\n .max(255, t`Description must be at most 255 characters.`),\n floating_ip_address: z\n .string()\n .trim()\n .refine((value) => value === \"\" || isValidIpAddress(value), {\n message: t`Must be a valid IPv4 or IPv6 address (for example: 172.24.4.228 or 2001:db8::1).`,\n }),\n port_id: z.string(),\n fixed_ip_address: z.string(),\n })\n\n const form = useForm({\n defaultValues: {\n floating_network_id: \"\",\n dns_domain: \"\",\n dns_name: \"\",\n description: \"\",\n floating_ip_address: \"\",\n port_id: \"\",\n fixed_ip_address: \"\",\n },\n validators: {\n onSubmit: formSchema,\n },\n onSubmit: async ({ value }) => {\n if (isPending) return\n\n await createFloatingIpMutation.mutateAsync({\n project_id: projectId,\n tenant_id: projectId,\n floating_network_id: value.floating_network_id,\n ...(value.dns_domain && { dns_domain: value.dns_domain }),\n ...(value.dns_name && { dns_name: value.dns_name }),\n ...(value.description && { description: value.description }),\n ...(value.floating_ip_address && { floating_ip_address: value.floating_ip_address }),\n ...(value.port_id && { port_id: value.port_id }),\n ...(value.fixed_ip_address && { fixed_ip_address: value.fixed_ip_address }),\n })\n handleClose()\n },\n })\n\n const handleClose = () => {\n if (isPending) return\n\n form.reset()\n createFloatingIpMutation.reset()\n onClose()\n }\n\n const currentPortId = useStore(form.store, (state) => state.values.port_id)\n const currentFloatingNetworkId = useStore(form.store, (state) => state.values.floating_network_id)\n const selectedPort = availablePorts.find((port) => port.id === currentPortId)\n const portFixedIps = selectedPort?.fixed_ips ?? []\n\n const formErrorMessage =\n (externalNetworksError?.message || dnsDomainsError?.message || portsError?.message) ??\n createFloatingIpMutation.error?.message ??\n null\n\n return (\n <Modal\n open={open}\n size=\"large\"\n title={t`Allocate Floating IP`}\n onCancel={handleClose}\n cancelButtonLabel={t`Cancel`}\n confirmButtonLabel={t`Allocate`}\n onConfirm={form.handleSubmit}\n disableConfirmButton={isPending || !currentFloatingNetworkId}\n >\n {formErrorMessage && (\n <Message dismissible={false} variant=\"error\" className=\"mb-4\">\n {formErrorMessage}\n </Message>\n )}\n\n {isPending && (\n <div className=\"mb-4 flex items-center justify-center gap-2\">\n <Spinner variant=\"primary\" />\n <span className=\"text-theme-high text-sm\">\n <Trans>Allocating Floating IP...</Trans>\n </span>\n </div>\n )}\n\n {!isPending && (\n <Form\n className=\"mb-0\"\n id=\"allocate-floating-ip-form\"\n onSubmit={(e) => {\n e.preventDefault()\n form.handleSubmit()\n }}\n >\n <FormSection className=\"mb-4\">\n <form.Field\n name=\"floating_network_id\"\n children={(field) => (\n <Select\n id={field.name}\n name={field.name}\n value={field.state.value}\n onChange={(value) => field.handleChange(typeof value === \"string\" ? value : \"\")}\n label={t`External Network`}\n helptext={t`The ID of the network associated with the floating IP.`}\n placeholder={t`Select an external network`}\n disabled={isPending || isExternalNetworksLoading}\n required\n loading={isExternalNetworksLoading}\n >\n {externalNetworks.map(({ id, name }) => (\n <SelectOption key={id} value={id} label={name ? `${name} (${id})` : id} />\n ))}\n </Select>\n )}\n />\n </FormSection>\n <FormSection className=\"mb-4\">\n <form.Field\n name=\"dns_domain\"\n children={(field) => (\n <Select\n id={field.name}\n name={field.name}\n value={field.state.value}\n onChange={(value) => field.handleChange(typeof value === \"string\" ? value : \"\")}\n label={t`DNS Domain`}\n helptext={t`Select a DNS domain.`}\n disabled={isPending || isDnsDomainsLoading}\n loading={isDnsDomainsLoading}\n >\n {dnsDomains.map(({ id, name }) => (\n <SelectOption key={id} value={name} label={name} />\n ))}\n </Select>\n )}\n />\n </FormSection>\n <FormSection className=\"mb-4\">\n <form.Field\n name=\"dns_name\"\n children={(field) => (\n <TextInput\n id={field.name}\n name={field.name}\n value={field.state.value}\n onBlur={field.handleBlur}\n onChange={(e) => field.handleChange(e.target.value)}\n label={t`DNS Name`}\n placeholder={t`Enter DNS name`}\n helptext={t`Enter a valid PQDN or FQDN (max 63 characters) to associate with the floating IP. A and PTR records are created automatically.`}\n errortext={field.state.meta.errors.map((e) => e?.message).join(\", \")}\n disabled={isPending}\n />\n )}\n />\n </FormSection>\n <FormSection className=\"mb-4\">\n <form.Field\n name=\"description\"\n children={(field) => (\n <Textarea\n id={field.name}\n name={field.name}\n value={field.state.value}\n onBlur={field.handleBlur}\n onChange={(e) => field.handleChange(e.target.value)}\n placeholder={t`Description`}\n errortext={field.state.meta.errors.map((e) => e?.message).join(\", \")}\n disabled={isPending}\n />\n )}\n />\n </FormSection>\n <FormSection className=\"mb-4\">\n <form.Field\n name=\"floating_ip_address\"\n children={(field) => (\n <TextInput\n id={field.name}\n name={field.name}\n value={field.state.value}\n onBlur={field.handleBlur}\n onChange={(e) => field.handleChange(e.target.value)}\n label={t`Floating IP Address`}\n placeholder={t`Enter a floating IP`}\n helptext={t`Enter a floating IP or leave blank to auto-assign one`}\n errortext={field.state.meta.errors.map((e) => e?.message).join(\", \")}\n disabled={isPending}\n />\n )}\n />\n </FormSection>\n <FormSection className=\"mb-4\">\n <form.Field\n name=\"port_id\"\n children={(field) => (\n <Select\n id={field.name}\n name={field.name}\n value={field.state.value}\n onChange={(value) => {\n const portId = typeof value === \"string\" ? value : \"\"\n field.handleChange(portId)\n const port = availablePorts.find((p) => p.id === portId)\n const ips = port?.fixed_ips ?? []\n form.setFieldValue(\"fixed_ip_address\", ips.length === 1 ? ips[0].ip_address : \"\")\n }}\n label={t`Port ID`}\n placeholder={t`Select port to associate`}\n errortext={field.state.meta.errors.map((e) => e?.message).join(\", \")}\n disabled={isPending || isPortsLoading}\n loading={isPortsLoading}\n >\n {availablePorts.map((port) => (\n <SelectOption\n key={port.id}\n value={port.id}\n label={port.name ? `${port.name} (${port.id})` : port.id}\n />\n ))}\n </Select>\n )}\n />\n </FormSection>\n <FormSection>\n <form.Field\n name=\"fixed_ip_address\"\n children={(field) => (\n <Select\n id={field.name}\n name={field.name}\n value={field.state.value}\n onBlur={field.handleBlur}\n onChange={(value) => field.handleChange(typeof value === \"string\" ? value : \"\")}\n label={t`Fixed IP Address`}\n placeholder={t`Select a fixed IP address`}\n helptext={t`Associates on the selected port. If the port has multiple IPs, select the desired fixed IP address.`}\n errortext={field.state.meta.errors.map((e) => e?.message).join(\", \")}\n disabled={isPending || portFixedIps.length === 0}\n >\n {portFixedIps.map(({ ip_address }) => (\n <SelectOption key={ip_address} value={ip_address} label={ip_address} />\n ))}\n </Select>\n )}\n />\n </FormSection>\n </Form>\n )}\n </Modal>\n )\n}\n","import { useLingui } from \"@lingui/react/macro\"\nimport { Button } from \"@cloudoperators/juno-ui-components\"\nimport { FloatingIpQueryParameters } from \"@/server/Network/types/floatingIp\"\nimport { ListToolbar } from \"@/client/components/ListToolbar\"\nimport { trpcReact } from \"@/client/trpcClient\"\nimport { buildFilterParams } from \"@/client/utils/buildFilterParams\"\nimport { useListWithFiltering } from \"@/client/utils/useListWithFiltering\"\nimport { useModal } from \"@/client/utils/useModal\"\nimport { useProjectId } from \"@/client/hooks\"\nimport { FloatingIpListContainer } from \"./-table/FloatingIpListContainer\"\nimport { AllocateFloatingIpModal } from \"./-modals/AllocateFloatingIpModal\"\n\nconst DEFAULT_SORT_KEY = \"fixed_ip_address\"\nconst DEFAULT_SORT_DIR = \"asc\"\nexport type FloatingIpsSortKey = NonNullable<FloatingIpQueryParameters[\"sort_key\"]>\n\nexport const FloatingIpsList = () => {\n const { t } = useLingui()\n const projectId = useProjectId()\n const [allocateModalOpen, toggleAllocateModal] = useModal(false)\n\n const { searchTerm, handleSearchChange, sortSettings, handleSortChange, filterSettings, handleFilterChange } =\n useListWithFiltering<FloatingIpsSortKey>({\n defaultSortKey: DEFAULT_SORT_KEY,\n defaultSortDir: DEFAULT_SORT_DIR,\n sortOptions: [\n { label: t`Fixed IP Address`, value: \"fixed_ip_address\" },\n { label: t`Floating IP Address`, value: \"floating_ip_address\" },\n { label: t`Floating Network ID`, value: \"floating_network_id\" },\n { label: t`ID`, value: \"id\" },\n { label: t`Router ID`, value: \"router_id\" },\n { label: t`Status`, value: \"status\" },\n // Tenant_id was kept for backward compatibility in case the deprecated tenant ID was used to sort instead of the project ID.\n { label: t`Tenant ID`, value: \"tenant_id\" },\n { label: t`Project ID`, value: \"project_id\" },\n ],\n filterSettings: {\n filters: [\n {\n displayName: t`Status`,\n filterName: \"status\",\n values: [\"ACTIVE\", \"DOWN\", \"ERROR\"],\n supportsMultiValue: false,\n },\n ],\n },\n })\n\n const {\n data: floatingIps = [],\n isLoading,\n isError,\n error,\n } = trpcReact.network.floatingIp.list.useQuery({\n project_id: projectId,\n sort_key: sortSettings.sortBy,\n sort_dir: sortSettings.sortDirection,\n ...buildFilterParams(filterSettings),\n ...(searchTerm ? { searchTerm } : {}),\n })\n\n return (\n <div className=\"relative\">\n <ListToolbar\n searchTerm={searchTerm}\n onSearch={handleSearchChange}\n sortSettings={sortSettings}\n onSort={handleSortChange}\n filterSettings={filterSettings}\n onFilter={handleFilterChange}\n actions={<Button variant=\"primary\" label={t`Allocate Floating IP`} onClick={toggleAllocateModal} />}\n />\n\n <FloatingIpListContainer floatingIps={floatingIps} isLoading={isLoading} isError={isError} error={error} />\n\n {allocateModalOpen && <AllocateFloatingIpModal open={allocateModalOpen} onClose={toggleAllocateModal} />}\n </div>\n )\n}\n","import { createFileRoute } from \"@tanstack/react-router\"\nimport { t } from \"@lingui/core/macro\"\nimport { useLingui } from \"@lingui/react/macro\"\nimport { FloatingIpsList } from \"./-components/FloatingIpsList\"\nimport type { RouteInfo } from \"@/client/routes/routeInfo\"\nimport { ContentHeading } from \"@cloudoperators/juno-ui-components\"\n\nexport const Route = createFileRoute(\"/_auth/projects/$projectId/network/floatingips/\")({\n staticData: {\n section: \"network\",\n service: \"floatingips\",\n analytics: {\n name: \"network.floatingips.list\",\n },\n sectionCrumb: { labelKey: \"Network\" },\n crumb: { labelKey: \"Floating IPs\" },\n } satisfies RouteInfo,\n head: () => ({ meta: [{ title: t`Floating IPs` }] }),\n component: RouteComponent,\n})\n\nfunction RouteComponent() {\n const { t } = useLingui()\n return (\n <>\n <ContentHeading>{t`Floating IPs`}</ContentHeading>\n <FloatingIpsList />\n </>\n )\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* URL-based context hooks
|
|
3
|
+
*
|
|
4
|
+
* These hooks extract scope information (projectId, domainId) directly from URL params.
|
|
5
|
+
* This follows the principle "URL is the source of truth".
|
|
6
|
+
*
|
|
7
|
+
* Benefits:
|
|
8
|
+
* - Centralized URL param extraction (single point of change during route refactoring)
|
|
9
|
+
* - Type-safe access to route params
|
|
10
|
+
* - Runtime validation with clear error messages
|
|
11
|
+
* - No prop drilling needed
|
|
12
|
+
* - Easy to test and mock
|
|
13
|
+
*/
|
|
14
|
+
export { useProjectId } from './useProjectId';
|
|
15
|
+
export { useDomainId } from './useDomainId';
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Get the current user's domain ID from the authentication context.
|
|
3
|
+
*
|
|
4
|
+
* This hook provides access to the domain ID of the currently authenticated user.
|
|
5
|
+
* The domain ID is obtained from the user's session, not from URL parameters.
|
|
6
|
+
*
|
|
7
|
+
* @throws {Error} If user is not authenticated or domain ID is not available
|
|
8
|
+
* @returns {string} The current domain ID from the user's session
|
|
9
|
+
*
|
|
10
|
+
* @example
|
|
11
|
+
* ```tsx
|
|
12
|
+
* function UsersList() {
|
|
13
|
+
* const domainId = useDomainId()
|
|
14
|
+
*
|
|
15
|
+
* const { data } = trpc.identity.users.list.useQuery({
|
|
16
|
+
* domain_id: domainId
|
|
17
|
+
* })
|
|
18
|
+
* }
|
|
19
|
+
* ```
|
|
20
|
+
*/
|
|
21
|
+
export declare function useDomainId(): string;
|