mirror of https://github.com/portainer/portainer
fix(ui): scroll issue [EE-6667] (#11084)
* Fix scroll issue * fix minorissue * address review comments * add commentpull/11092/head
parent
43e56bf1c0
commit
671b22b5d6
|
@ -17,6 +17,7 @@
|
||||||
html {
|
html {
|
||||||
font-size: 16px;
|
font-size: 16px;
|
||||||
overflow-y: scroll;
|
overflow-y: scroll;
|
||||||
|
scroll-behavior: smooth;
|
||||||
}
|
}
|
||||||
|
|
||||||
html[theme='dark'],
|
html[theme='dark'],
|
||||||
|
|
|
@ -25,7 +25,7 @@ export const settingsModule = angular
|
||||||
)
|
)
|
||||||
.component(
|
.component(
|
||||||
'applicationSettingsPanel',
|
'applicationSettingsPanel',
|
||||||
r2a(withReactQuery(ApplicationSettingsPanel), ['onSuccess'])
|
r2a(withReactQuery(ApplicationSettingsPanel), ['onSuccess', 'settings'])
|
||||||
)
|
)
|
||||||
.component(
|
.component(
|
||||||
'sslSettingsPanel',
|
'sslSettingsPanel',
|
||||||
|
@ -38,5 +38,5 @@ export const settingsModule = angular
|
||||||
)
|
)
|
||||||
.component(
|
.component(
|
||||||
'kubeSettingsPanel',
|
'kubeSettingsPanel',
|
||||||
r2a(withUIRouter(withReactQuery(KubeSettingsPanel)), [])
|
r2a(withUIRouter(withReactQuery(KubeSettingsPanel)), ['settings'])
|
||||||
).name;
|
).name;
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { useMemo } from 'react';
|
import { useMemo, useEffect } from 'react';
|
||||||
|
|
||||||
import { useCurrentUser } from '@/react/hooks/useUser';
|
import { useCurrentUser } from '@/react/hooks/useUser';
|
||||||
import helm from '@/assets/ico/vendor/helm.svg?c';
|
import helm from '@/assets/ico/vendor/helm.svg?c';
|
||||||
|
@ -41,6 +41,19 @@ export function HelmRepositoryDatatable() {
|
||||||
helmReposQuery.data?.UserRepositories,
|
helmReposQuery.data?.UserRepositories,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
// window.location.hash will get everything after the hashbang
|
||||||
|
// the regex will match the the content after each hash
|
||||||
|
const timeout = setTimeout(() => {
|
||||||
|
const regEx = /#!.*#(.*)/;
|
||||||
|
const match = window.location.hash.match(regEx);
|
||||||
|
if (match && match[1]) {
|
||||||
|
document.getElementById(match[1])?.scrollIntoView();
|
||||||
|
}
|
||||||
|
}, 1000);
|
||||||
|
return () => clearTimeout(timeout);
|
||||||
|
}, []);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Datatable
|
<Datatable
|
||||||
getRowId={(row) => String(row.Id)}
|
getRowId={(row) => String(row.Id)}
|
||||||
|
@ -48,8 +61,9 @@ export function HelmRepositoryDatatable() {
|
||||||
description={<HelmDatatableDescription />}
|
description={<HelmDatatableDescription />}
|
||||||
settingsManager={tableState}
|
settingsManager={tableState}
|
||||||
columns={columns}
|
columns={columns}
|
||||||
title="Helm Repositories"
|
title="Helm repositories"
|
||||||
titleIcon={helm}
|
titleIcon={helm}
|
||||||
|
titleId="helm-repositories"
|
||||||
renderTableActions={(selectedRows) => (
|
renderTableActions={(selectedRows) => (
|
||||||
<HelmRepositoryDatatableActions selectedItems={selectedRows} />
|
<HelmRepositoryDatatableActions selectedItems={selectedRows} />
|
||||||
)}
|
)}
|
||||||
|
|
|
@ -36,7 +36,7 @@ export function HelmRepositoryDatatableActions({ selectedItems }: Props) {
|
||||||
data-cy="credentials-addButton"
|
data-cy="credentials-addButton"
|
||||||
icon={Plus}
|
icon={Plus}
|
||||||
>
|
>
|
||||||
Add Helm Repository
|
Add Helm repository
|
||||||
</Button>
|
</Button>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
|
|
@ -2,10 +2,7 @@ import { Settings as SettingsIcon } from 'lucide-react';
|
||||||
import { Field, Form, Formik, useFormikContext } from 'formik';
|
import { Field, Form, Formik, useFormikContext } from 'formik';
|
||||||
|
|
||||||
import { EdgeCheckinIntervalField } from '@/react/edge/components/EdgeCheckInIntervalField';
|
import { EdgeCheckinIntervalField } from '@/react/edge/components/EdgeCheckInIntervalField';
|
||||||
import {
|
import { useUpdateSettingsMutation } from '@/react/portainer/settings/queries';
|
||||||
useSettings,
|
|
||||||
useUpdateSettingsMutation,
|
|
||||||
} from '@/react/portainer/settings/queries';
|
|
||||||
import { notifySuccess } from '@/portainer/services/notifications';
|
import { notifySuccess } from '@/portainer/services/notifications';
|
||||||
|
|
||||||
import { Widget } from '@@/Widget';
|
import { Widget } from '@@/Widget';
|
||||||
|
@ -24,17 +21,13 @@ import { EnableTelemetryField } from './EnableTelemetryField';
|
||||||
|
|
||||||
export function ApplicationSettingsPanel({
|
export function ApplicationSettingsPanel({
|
||||||
onSuccess,
|
onSuccess,
|
||||||
|
settings,
|
||||||
}: {
|
}: {
|
||||||
onSuccess(settings: Settings): void;
|
onSuccess(settings: Settings): void;
|
||||||
|
settings: Settings;
|
||||||
}) {
|
}) {
|
||||||
const settingsQuery = useSettings();
|
|
||||||
const mutation = useUpdateSettingsMutation();
|
const mutation = useUpdateSettingsMutation();
|
||||||
|
|
||||||
if (!settingsQuery.data) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
const settings = settingsQuery.data;
|
|
||||||
const initialValues: Values = {
|
const initialValues: Values = {
|
||||||
edgeAgentCheckinInterval: settings.EdgeAgentCheckinInterval,
|
edgeAgentCheckinInterval: settings.EdgeAgentCheckinInterval,
|
||||||
enableTelemetry: settings.EnableTelemetry,
|
enableTelemetry: settings.EnableTelemetry,
|
||||||
|
|
|
@ -8,7 +8,8 @@ import { useEnvironmentId } from '@/react/hooks/useEnvironmentId';
|
||||||
import { LoadingButton } from '@@/buttons';
|
import { LoadingButton } from '@@/buttons';
|
||||||
import { Widget } from '@@/Widget';
|
import { Widget } from '@@/Widget';
|
||||||
|
|
||||||
import { useSettings, useUpdateSettingsMutation } from '../../queries';
|
import { useUpdateSettingsMutation } from '../../queries';
|
||||||
|
import { Settings } from '../../types';
|
||||||
|
|
||||||
import { HelmSection } from './HelmSection';
|
import { HelmSection } from './HelmSection';
|
||||||
import { KubeConfigSection } from './KubeConfigSection';
|
import { KubeConfigSection } from './KubeConfigSection';
|
||||||
|
@ -16,19 +17,14 @@ import { FormValues } from './types';
|
||||||
import { DeploymentOptionsSection } from './DeploymentOptionsSection';
|
import { DeploymentOptionsSection } from './DeploymentOptionsSection';
|
||||||
import { validation } from './validation';
|
import { validation } from './validation';
|
||||||
|
|
||||||
export function KubeSettingsPanel() {
|
export function KubeSettingsPanel({ settings }: { settings: Settings }) {
|
||||||
const settingsQuery = useSettings();
|
|
||||||
const queryClient = useQueryClient();
|
const queryClient = useQueryClient();
|
||||||
const environmentId = useEnvironmentId(false);
|
const environmentId = useEnvironmentId(false);
|
||||||
const mutation = useUpdateSettingsMutation();
|
const mutation = useUpdateSettingsMutation();
|
||||||
|
|
||||||
if (!settingsQuery.data) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
const initialValues: FormValues = {
|
const initialValues: FormValues = {
|
||||||
helmRepositoryUrl: settingsQuery.data.HelmRepositoryURL || '',
|
helmRepositoryUrl: settings.HelmRepositoryURL || '',
|
||||||
kubeconfigExpiry: settingsQuery.data.KubeconfigExpiry || '0',
|
kubeconfigExpiry: settings.KubeconfigExpiry || '0',
|
||||||
globalDeploymentOptions: {
|
globalDeploymentOptions: {
|
||||||
...{
|
...{
|
||||||
requireNoteOnApplications: false,
|
requireNoteOnApplications: false,
|
||||||
|
@ -39,7 +35,7 @@ export function KubeSettingsPanel() {
|
||||||
perEnvOverride: false,
|
perEnvOverride: false,
|
||||||
hideStacksFunctionality: false,
|
hideStacksFunctionality: false,
|
||||||
},
|
},
|
||||||
...settingsQuery.data.GlobalDeploymentOptions,
|
...settings.GlobalDeploymentOptions,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1,9 +1,11 @@
|
||||||
|
import { useEffect } from 'react';
|
||||||
import angular from 'angular';
|
import angular from 'angular';
|
||||||
|
|
||||||
import { StateManager } from '@/portainer/services/types';
|
import { StateManager } from '@/portainer/services/types';
|
||||||
|
|
||||||
import { PageHeader } from '@@/PageHeader';
|
import { PageHeader } from '@@/PageHeader';
|
||||||
|
|
||||||
|
import { useSettings } from '../queries';
|
||||||
import { Settings } from '../types';
|
import { Settings } from '../types';
|
||||||
import { isBE } from '../../feature-flags/feature-flags.service';
|
import { isBE } from '../../feature-flags/feature-flags.service';
|
||||||
|
|
||||||
|
@ -16,14 +18,33 @@ import { SSLSettingsPanelWrapper } from './SSLSettingsPanel/SSLSettingsPanel';
|
||||||
import { ExperimentalFeatures } from './ExperimentalFeatures';
|
import { ExperimentalFeatures } from './ExperimentalFeatures';
|
||||||
|
|
||||||
export function SettingsView() {
|
export function SettingsView() {
|
||||||
|
const settingsQuery = useSettings();
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (settingsQuery.data) {
|
||||||
|
const regEx = /#!.*#(.*)/;
|
||||||
|
const match = window.location.hash.match(regEx);
|
||||||
|
if (match && match[1]) {
|
||||||
|
document.getElementById(match[1])?.scrollIntoView();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, [settingsQuery.data]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<PageHeader title="Settings" breadcrumbs="Settings" reload />
|
<PageHeader title="Settings" breadcrumbs="Settings" reload />
|
||||||
|
|
||||||
<div className="mx-4 space-y-4">
|
<div className="mx-4 space-y-4">
|
||||||
<ApplicationSettingsPanel onSuccess={handleSuccess} />
|
{settingsQuery.data && (
|
||||||
|
<>
|
||||||
|
<ApplicationSettingsPanel
|
||||||
|
onSuccess={handleSuccess}
|
||||||
|
settings={settingsQuery.data}
|
||||||
|
/>
|
||||||
|
|
||||||
<KubeSettingsPanel />
|
<KubeSettingsPanel settings={settingsQuery.data} />
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
|
||||||
<HelmCertPanel />
|
<HelmCertPanel />
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue