chore: import upstream snapshot with attribution

This commit is contained in:
wehub-resource-sync
2026-07-13 12:08:39 +08:00
commit a0df89c693
5252 changed files with 523444 additions and 0 deletions
@@ -0,0 +1,61 @@
import { useCurrentStateAndParams } from '@uirouter/react';
import LaptopCode from '@/assets/ico/laptop-code.svg?c';
import { useEnvironmentId } from '@/react/hooks/useEnvironmentId';
import { useApplications } from '@/react/kubernetes/applications/queries/useApplications';
import { Datatable, TableSettingsMenu } from '@@/datatables';
import { TableSettingsMenuAutoRefresh } from '@@/datatables/TableSettingsMenuAutoRefresh';
import { useTableStateWithStorage } from '@@/datatables/useTableState';
import {
BasicTableSettings,
refreshableSettings,
RefreshableTableSettings,
} from '@@/datatables/types';
import { useColumns } from './columns';
interface TableSettings extends BasicTableSettings, RefreshableTableSettings {}
export function NodeApplicationsDatatable() {
const tableState = useTableStateWithStorage<TableSettings>(
'kube-node-apps',
'Name',
(set) => ({
...refreshableSettings(set),
})
);
const envId = useEnvironmentId();
const {
params: { nodeName },
} = useCurrentStateAndParams();
const applicationsQuery = useApplications(envId, {
nodeName,
refetchInterval: tableState.autoRefreshRate * 1000,
});
const applications = applicationsQuery.data ?? [];
const columns = useColumns();
return (
<Datatable
dataset={applications}
settingsManager={tableState}
columns={columns}
disableSelect
title="Applications running on this node"
titleIcon={LaptopCode}
isLoading={applicationsQuery.isLoading}
renderTableSettings={() => (
<TableSettingsMenu>
<TableSettingsMenuAutoRefresh
value={tableState.autoRefreshRate}
onChange={tableState.setAutoRefreshRate}
/>
</TableSettingsMenu>
)}
data-cy="node-applications-datatable"
/>
);
}
@@ -0,0 +1,5 @@
import { createColumnHelper } from '@tanstack/react-table';
import { Application } from '@/react/kubernetes/applications/ListView/ApplicationsDatatable/types';
export const helper = createColumnHelper<Application>();
@@ -0,0 +1,39 @@
import { CellContext } from '@tanstack/react-table';
import { isExternalApplication } from '@/react/kubernetes/applications/utils';
import { useIsSystemNamespace } from '@/react/kubernetes/namespaces/queries/useIsSystemNamespace';
import { Application } from '@/react/kubernetes/applications/ListView/ApplicationsDatatable/types';
import { Link } from '@@/Link';
import { SystemBadge } from '@@/Badge/SystemBadge';
import { ExternalBadge } from '@@/Badge/ExternalBadge';
import { helper } from './columns.helper';
export const name = helper.accessor('Name', {
header: 'Name',
cell: Cell,
});
function Cell({ row: { original: item } }: CellContext<Application, string>) {
const isSystem = useIsSystemNamespace(item.ResourcePool);
return (
<div className="flex items-center gap-2">
<Link
to="kubernetes.applications.application"
params={{ name: item.Name, namespace: item.ResourcePool }}
data-cy={`application-link-${item.Name}`}
>
{item.Name}
</Link>
{isSystem ? (
<SystemBadge className="ml-auto" />
) : (
isExternalApplication({ metadata: item.Metadata }) && (
<ExternalBadge className="ml-auto" />
)
)}
</div>
);
}
@@ -0,0 +1,82 @@
import _, { round } from 'lodash';
import { useMemo } from 'react';
import { truncate } from '@/portainer/filters/filters';
import { usePublicSettings } from '@/react/portainer/settings/queries';
import { bytesToReadableFormat } from '@/react/kubernetes/utils';
import { Link } from '@@/Link';
import { helper } from './columns.helper';
import { name } from './columns.name';
export function useColumns() {
const hideStacksQuery = usePublicSettings<boolean>({
select: (settings) =>
settings.GlobalDeploymentOptions.hideStacksFunctionality,
});
return useMemo(
() =>
_.compact([
name,
!hideStacksQuery.data &&
helper.accessor('StackName', {
header: 'Stack',
cell: ({ getValue }) => getValue() || '-',
}),
helper.accessor((item) => item.ResourcePool, {
header: 'Namespace',
cell: ({ getValue }) => {
const namespace = getValue();
return (
<Link
to="kubernetes.resourcePools.resourcePool"
params={{ id: namespace }}
data-cy={`namespace-link-${namespace}`}
>
{namespace}
</Link>
);
},
}),
helper.accessor('Image', {
header: 'Image',
cell: ({ row: { original: item } }) => {
const containersLength = item.Containers?.length || 0;
return (
<div title={item.Image}>
{truncate(item.Image, 64)}
{containersLength > 1 && <>+ {containersLength - 1}</>}
</div>
);
},
}),
helper.accessor((row) => row.Resource?.CpuRequest, {
header: 'CPU reservation',
cell: ({ getValue }) =>
typeof getValue() === 'number' ? round(getValue() || 0, 2) : '-',
}),
helper.accessor((row) => row.Resource?.CpuLimit, {
header: 'CPU Limit',
cell: ({ getValue }) =>
typeof getValue() === 'number' ? round(getValue() || 0, 2) : '-',
}),
helper.accessor((row) => row.Resource?.MemoryRequest, {
header: 'Memory reservation',
cell: ({ getValue }) =>
typeof getValue() === 'number'
? bytesToReadableFormat(getValue() || 0)
: '-',
}),
helper.accessor((row) => row.Resource?.MemoryLimit, {
header: 'Memory Limit',
cell: ({ getValue }) =>
typeof getValue() === 'number'
? bytesToReadableFormat(getValue() || 0)
: '-',
}),
]),
[hideStacksQuery.data]
);
}
@@ -0,0 +1,6 @@
import { KubernetesApplication } from '@/kubernetes/models/application/models';
export type NodeApplication = KubernetesApplication & {
CPU: number;
Memory: number;
};