Skip to content

Commit

Permalink
Merge branch 'main' into krancour/role-mgmt-fixes
Browse files Browse the repository at this point in the history
  • Loading branch information
krancour authored May 1, 2024
2 parents 930296f + c6d0a6d commit cde3a98
Show file tree
Hide file tree
Showing 10 changed files with 215 additions and 88 deletions.
78 changes: 74 additions & 4 deletions ui/src/features/common/code-editor/yaml-editor-lazy.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import Editor, { loader } from '@monaco-editor/react';
import { Typography } from 'antd';
import { Checkbox, Flex, Spin, Typography } from 'antd';
import type { JSONSchema4 } from 'json-schema';
import * as monaco from 'monaco-editor';
import { configureMonacoYaml } from 'monaco-yaml';
import React, { FC, useEffect, useRef } from 'react';
import yaml from 'yaml';

import styles from './yaml-editor.module.less';

Expand All @@ -18,16 +19,64 @@ export interface YamlEditorProps {
height?: string;
schema?: JSONSchema4;
placeholder?: string;
isLoading?: boolean;
isHideManagedFieldsDisplayed?: boolean;
label?: string;
}

const YamlEditor: FC<YamlEditorProps> = (props) => {
const editorRef = useRef<monaco.editor.IStandaloneCodeEditor | null>(null);
const { value, disabled, onChange, className, width, height, schema, placeholder } = props;
const {
value,
disabled,
onChange,
className,
width,
height,
schema,
placeholder,
isLoading,
isHideManagedFieldsDisplayed,
label
} = props;
const [hideManagedFields, setHideManagedFields] = React.useState(!!isHideManagedFieldsDisplayed);
const [managedFieldsValue, setManagedFieldsValue] = React.useState<object | null>(null);

const handleOnChange = (value: string | undefined) => {
onChange?.(value);
const handleOnChange = (newValue: string | undefined) => {
onChange?.(newValue);
};

React.useEffect(() => {
try {
const data = yaml.parse(value);

// Hide managedFields
if (hideManagedFields && data?.metadata?.managedFields) {
setManagedFieldsValue(data?.metadata?.managedFields);
delete data.metadata.managedFields;

onChange?.(yaml.stringify(data));
}

// Restore managedFields
if (!hideManagedFields && managedFieldsValue) {
onChange?.(
yaml.stringify({
...data,
metadata: {
...(typeof data.metadata === 'object' ? data.metadata : {}),
managedFields: managedFieldsValue
}
})
);

setManagedFieldsValue(null);
}
} catch (err) {
// ignore
}
}, [hideManagedFields, value]);

useEffect(() => {
configureMonacoYaml(monaco, {
enableSchemaRequest: true,
Expand All @@ -50,8 +99,29 @@ const YamlEditor: FC<YamlEditorProps> = (props) => {
editorRef.current = editor;
};

if (isLoading) {
return (
<Spin tip='Loading' size='small'>
<div className='content py-8' />
</Spin>
);
}

return (
<>
<Flex justify='space-between' className={isHideManagedFieldsDisplayed || label ? 'my-1' : ''}>
<div>{label}</div>
{isHideManagedFieldsDisplayed && (
<label>
<Checkbox
className='mr-2'
checked={hideManagedFields}
onChange={(e) => setHideManagedFields(e.target.checked)}
/>
Hide Managed Fields
</label>
)}
</Flex>
<div
style={{ border: '1px solid #d9d9d9', height, overflow: 'hidden' }}
className={className}
Expand Down
2 changes: 1 addition & 1 deletion ui/src/features/common/manifest-preview.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,5 +15,5 @@ export const ManifestPreview = ({ object }: { object: Stage | Freight }) => {
return v;
});

return <YamlEditor value={encodedObject} height='100%' disabled />;
return <YamlEditor value={encodedObject} height='100%' disabled isHideManagedFieldsDisplayed />;
};
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { useMutation, useQuery } from '@connectrpc/connect-query';
import { faEye, faPlus, faTrash } from '@fortawesome/free-solid-svg-icons';
import { faPencil, faPlus, faTrash } from '@fortawesome/free-solid-svg-icons';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { Button, Table } from 'antd';
import { format } from 'date-fns';
Expand All @@ -14,14 +14,14 @@ import {
} from '@ui/gen/service/v1alpha1/service-KargoService_connectquery';

import { CreateAnalysisTemplateModal } from './create-analysis-template-modal';
import { PreviewAnalysisTemplateModal } from './preview-analysis-template-modal';
import { EditAnalysisTemplateModal } from './edit-analysis-template-modal';

export const AnalysisTemplatesList = () => {
const { name } = useParams();
const confirm = useConfirmModal();

const { data, refetch } = useQuery(listAnalysisTemplates, { project: name });
const { show: showPreview } = useModal();
const { data, isLoading, refetch } = useQuery(listAnalysisTemplates, { project: name });
const { show: showEdit } = useModal();
const { show: showCreate } = useModal((p) => (
<CreateAnalysisTemplateModal {...p} namespace={name || ''} />
));
Expand All @@ -35,6 +35,7 @@ export const AnalysisTemplatesList = () => {
dataSource={data?.analysisTemplates}
pagination={{ hideOnSinglePage: true }}
rowKey={(i) => i.metadata?.name || ''}
loading={isLoading}
>
<Table.Column<AnalysisTemplate>
title='Creation Date'
Expand Down Expand Up @@ -62,12 +63,19 @@ export const AnalysisTemplatesList = () => {
render={(_, template) => (
<div className='flex gap-2 justify-end'>
<Button
icon={<FontAwesomeIcon icon={faEye} />}
icon={<FontAwesomeIcon icon={faPencil} />}
className='mr-2 ml-auto'
onClick={() => {
showPreview((p) => <PreviewAnalysisTemplateModal {...p} template={template} />);
showEdit((p) => (
<EditAnalysisTemplateModal
{...p}
templateName={template.metadata?.name || ''}
projectName={name || ''}
/>
));
}}
>
Preview
Edit
</Button>
<Button
icon={<FontAwesomeIcon icon={faTrash} />}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
import { createConnectQueryKey, useMutation, useQuery } from '@connectrpc/connect-query';
import { useQueryClient } from '@tanstack/react-query';
import { Modal } from 'antd';
import { useForm } from 'react-hook-form';

import YamlEditor from '@ui/features/common/code-editor/yaml-editor-lazy';
import { FieldContainer } from '@ui/features/common/form/field-container';
import { ModalProps } from '@ui/features/common/modal/use-modal';
import {
getAnalysisTemplate,
listAnalysisTemplates,
updateResource
} from '@ui/gen/service/v1alpha1/service-KargoService_connectquery';
import { RawFormat } from '@ui/gen/service/v1alpha1/service_pb';
import { decodeRawData } from '@ui/utils/decode-raw-data';

import { getAnalysisTemplateYAMLExample } from './utils/analysis-template-example';

type Props = ModalProps & {
templateName: string;
projectName: string;
};

export const EditAnalysisTemplateModal = ({ visible, hide, templateName, projectName }: Props) => {
const queryClient = useQueryClient();

const { mutateAsync, isPending } = useMutation(updateResource, {
onSuccess: () => hide()
});

const { data: templateResponse, isLoading } = useQuery(getAnalysisTemplate, {
project: projectName,
name: templateName,
format: RawFormat.YAML
});

const { control, handleSubmit } = useForm({
values: {
value: decodeRawData(templateResponse)
}
});

const onSubmit = handleSubmit(async (data) => {
const textEncoder = new TextEncoder();

await mutateAsync(
{
manifest: textEncoder.encode(data.value)
},
{
onSuccess: () =>
queryClient.invalidateQueries({ queryKey: createConnectQueryKey(listAnalysisTemplates) })
}
);
});

return (
<Modal
open={visible}
onCancel={hide}
title='Edit Analysis Template'
okText='Update'
onOk={onSubmit}
okButtonProps={{ loading: isPending }}
width={700}
>
<FieldContainer name='value' control={control}>
{({ field: { value, onChange } }) => (
<YamlEditor
value={value}
onChange={(e) => onChange(e || '')}
height='500px'
placeholder={getAnalysisTemplateYAMLExample(projectName)}
isLoading={isLoading}
isHideManagedFieldsDisplayed
label='Spec'
/>
)}
</FieldContainer>
</Modal>
);
};

This file was deleted.

3 changes: 2 additions & 1 deletion ui/src/features/project/credentials/credentials-list.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ export const CredentialsList = () => {
const { show: showCreate } = useModal();
const confirm = useConfirmModal();

const { data, refetch } = useQuery(listCredentials, { project: name });
const { data, isLoading, refetch } = useQuery(listCredentials, { project: name });
const { mutate } = useMutation(deleteCredentials, {
onSuccess: () => {
refetch();
Expand All @@ -40,6 +40,7 @@ export const CredentialsList = () => {
key={data?.credentials?.length}
dataSource={data?.credentials || []}
rowKey={(record) => record?.metadata?.name || ''}
loading={isLoading}
columns={[
{
title: 'Name',
Expand Down
21 changes: 10 additions & 11 deletions ui/src/features/stage/analysis-run-modal.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,12 @@
import { useQuery } from '@connectrpc/connect-query';
import { Button, Modal } from 'antd';
import { useParams } from 'react-router-dom';
import yaml from 'yaml';

import YamlEditor from '@ui/features/common/code-editor/yaml-editor-lazy';
import { ModalProps } from '@ui/features/common/modal/use-modal';
import { getAnalysisRun } from '@ui/gen/service/v1alpha1/service-KargoService_connectquery';
import { RawFormat } from "@ui/gen/service/v1alpha1/service_pb";

import { LoadingState } from '../common';
import { RawFormat } from '@ui/gen/service/v1alpha1/service_pb';
import { decodeRawData } from '@ui/utils/decode-raw-data';

type Props = ModalProps & {
name: string;
Expand All @@ -19,9 +17,8 @@ export const AnalysisRunModal = ({ visible, hide, name }: Props) => {
const { data, isLoading } = useQuery(getAnalysisRun, {
namespace: projectName,
name,
format: RawFormat.YAML,
format: RawFormat.YAML
});
const manifest = new TextDecoder().decode(data?.result?.value ?? new Uint8Array());

return (
<Modal
Expand All @@ -35,11 +32,13 @@ export const AnalysisRunModal = ({ visible, hide, name }: Props) => {
}
width={700}
>
{isLoading ? (
<LoadingState />
) : (
<YamlEditor value={manifest} height='500px' disabled />
)}
<YamlEditor
value={decodeRawData(data)}
height='500px'
isLoading={isLoading}
disabled
isHideManagedFieldsDisplayed
/>
</Modal>
);
};
Loading

0 comments on commit cde3a98

Please sign in to comment.