mirror of https://github.com/buster-so/buster.git
Merge pull request #34 from buster-so/nate/cleanup-permissions-pages
Cleanup permission pages 📃
This commit is contained in:
commit
96dfae1b22
File diff suppressed because it is too large
Load Diff
|
@ -66,6 +66,7 @@
|
|||
"material-symbols": "^0.27.2",
|
||||
"monaco-sql-languages": "^0.12.2",
|
||||
"monaco-themes": "^0.4.4",
|
||||
"monaco-yaml": "^5.2.3",
|
||||
"next": "14.2.22",
|
||||
"next-themes": "^0.4.4",
|
||||
"next-transpile-modules": "^10.0.1",
|
||||
|
@ -119,6 +120,7 @@
|
|||
"eslint-config-next": "14.2.3",
|
||||
"eslint-config-prettier": "^9.1.0",
|
||||
"eslint-plugin-prettier": "^5.2.1",
|
||||
"monaco-editor-webpack-plugin": "^7.1.0",
|
||||
"postcss": "~8",
|
||||
"sass": "^1.83.1",
|
||||
"tailwindcss": "^3.4.17",
|
||||
|
|
|
@ -78,28 +78,14 @@ export const prefetchGetDatasetMetadata = async (
|
|||
|
||||
export const useCreateDataset = () => {
|
||||
const queryClient = useQueryClient();
|
||||
const mutationFn = useMemoizedFn(() => createDataset());
|
||||
const onSuccess = useMemoizedFn((newDataset: unknown) => {
|
||||
queryClient.setQueryData<BusterDatasetListItem[]>(['datasets', {}], (oldData) => {
|
||||
// const newListItem: BusterDatasetListItem = {
|
||||
// ...newDataset,
|
||||
// name: newDataset.name,
|
||||
// created_at: newDataset.created_at,
|
||||
// updated_at: newDataset.updated_at,
|
||||
// definition: newDataset.definition,
|
||||
// owner: '',
|
||||
// };
|
||||
return oldData;
|
||||
});
|
||||
});
|
||||
const onError = useMemoizedFn((error: any) => {
|
||||
console.error('Failed to create dataset:', error);
|
||||
|
||||
const onSuccess = useMemoizedFn(() => {
|
||||
queryClient.invalidateQueries({ queryKey: ['datasets', {}] });
|
||||
});
|
||||
|
||||
return useCreateReactMutation({
|
||||
mutationFn,
|
||||
onSuccess,
|
||||
onError
|
||||
mutationFn: createDataset,
|
||||
onSuccess
|
||||
});
|
||||
};
|
||||
|
||||
|
|
|
@ -30,8 +30,11 @@ export const getDatasetDataSample = async (datasetId: string): Promise<BusterDat
|
|||
.then((res) => res.data);
|
||||
};
|
||||
|
||||
export const createDataset = async (): Promise<BusterDataset> => {
|
||||
return await mainApi.post<BusterDataset>(`/datasets`).then((res) => res.data);
|
||||
export const createDataset = async (params: {
|
||||
name: string;
|
||||
data_source_id: string;
|
||||
}): Promise<BusterDataset> => {
|
||||
return await mainApi.post<BusterDataset>(`/datasets`, params).then((res) => res.data);
|
||||
};
|
||||
|
||||
export const deleteDataset = async (datasetId: string): Promise<void> => {
|
||||
|
|
|
@ -14,7 +14,7 @@ import { useDeployDataset } from '@/api/busterv2';
|
|||
|
||||
export const useDatasetPageContext = ({ datasetId }: { datasetId: string }) => {
|
||||
const segments = useSelectedLayoutSegment() as DatasetApps;
|
||||
const { mutate: onUpdateDataset } = useDeployDataset();
|
||||
const { mutate: onUpdateDataset, isPending: isDeployingDataset } = useDeployDataset();
|
||||
const { dataset, datasetData } = useIndividualDataset({ datasetId });
|
||||
const originalDatasetSQL = dataset?.data?.sql;
|
||||
const datasetYmlFile = dataset?.data?.yml_file;
|
||||
|
@ -27,7 +27,7 @@ export const useDatasetPageContext = ({ datasetId }: { datasetId: string }) => {
|
|||
const disablePublish = useMemo(() => {
|
||||
const originalSQL = datasetSQL || '';
|
||||
const originalYmlFile = datasetYmlFile || '';
|
||||
return !datasetId || !sql || originalSQL === sql || !ymlFile || originalYmlFile === ymlFile;
|
||||
return !datasetId || !sql || !ymlFile || (originalYmlFile === ymlFile && originalSQL === sql);
|
||||
}, [datasetSQL, sql, datasetId, datasetYmlFile, ymlFile]);
|
||||
|
||||
const isChangedSQL = useMemo(() => {
|
||||
|
@ -40,10 +40,11 @@ export const useDatasetPageContext = ({ datasetId }: { datasetId: string }) => {
|
|||
});
|
||||
|
||||
const onPublishDataset = useMemoizedFn(async () => {
|
||||
if (disablePublish || !sql || !ymlFile) return;
|
||||
onUpdateDataset({
|
||||
dataset_id: datasetId!,
|
||||
sql: sql!,
|
||||
yml: ymlFile!
|
||||
sql: sql,
|
||||
yml: ymlFile
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -69,7 +70,8 @@ export const useDatasetPageContext = ({ datasetId }: { datasetId: string }) => {
|
|||
dataset,
|
||||
disablePublish,
|
||||
isChangedSQL,
|
||||
datasetId
|
||||
datasetId,
|
||||
isDeployingDataset
|
||||
};
|
||||
};
|
||||
|
||||
|
|
|
@ -17,6 +17,7 @@ export const DatasetsIndividualHeader: React.FC<{}> = React.memo(({}) => {
|
|||
const selectedApp = useDatasetPageContextSelector((state) => state.selectedApp);
|
||||
const dataset = useDatasetPageContextSelector((state) => state.dataset);
|
||||
const onPublishDataset = useDatasetPageContextSelector((state) => state.onPublishDataset);
|
||||
const isDeployingDataset = useDatasetPageContextSelector((state) => state.isDeployingDataset);
|
||||
const resetDataset = useDatasetPageContextSelector((state) => state.resetDataset);
|
||||
const disablePublish = useDatasetPageContextSelector((state) => state.disablePublish);
|
||||
const isChangedSQL = useDatasetPageContextSelector((state) => state.isChangedSQL);
|
||||
|
@ -25,7 +26,6 @@ export const DatasetsIndividualHeader: React.FC<{}> = React.memo(({}) => {
|
|||
const datasetName = dataset?.data?.name;
|
||||
|
||||
const isAdmin = useUserConfigContextSelector((state) => state.isAdmin);
|
||||
const setOpenNewDatasetModal = useDatasetContextSelector((state) => state.setOpenNewDatasetModal);
|
||||
|
||||
const preventNavigation = !disablePublish;
|
||||
|
||||
|
@ -59,10 +59,14 @@ export const DatasetsIndividualHeader: React.FC<{}> = React.memo(({}) => {
|
|||
<Divider type="vertical" className="!h-4" />
|
||||
|
||||
<div className="flex items-center space-x-2">
|
||||
<Button type="text" onClick={onReset} disabled={!isChangedSQL}>
|
||||
<Button type="text" onClick={onReset} disabled={!isChangedSQL || isDeployingDataset}>
|
||||
Reset
|
||||
</Button>
|
||||
<Button type="primary" disabled={disablePublish} onClick={onPublishDataset}>
|
||||
<Button
|
||||
type="primary"
|
||||
disabled={disablePublish}
|
||||
onClick={onPublishDataset}
|
||||
loading={isDeployingDataset}>
|
||||
Publish
|
||||
</Button>
|
||||
</div>
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
import { BusterDataset } from '@/api/busterv2/datasets';
|
||||
import { AppCodeEditor } from '@/components/inputs/AppCodeEditor';
|
||||
import { createStyles } from 'antd-style';
|
||||
import React from 'react';
|
||||
|
@ -11,7 +10,12 @@ export const MetadataContainer: React.FC<{
|
|||
|
||||
return (
|
||||
<div className={cx(styles.container, 'flex h-full w-full flex-col overflow-hidden')}>
|
||||
<AppCodeEditor className="overflow-hidden" value={ymlFile} onChange={setYmlFile} />
|
||||
<AppCodeEditor
|
||||
language="yaml"
|
||||
className="overflow-hidden"
|
||||
value={ymlFile}
|
||||
onChange={setYmlFile}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
});
|
||||
|
|
|
@ -1,22 +1,12 @@
|
|||
import React, { useLayoutEffect, useMemo, useState } from 'react';
|
||||
import { Button, Select, SelectProps } from 'antd';
|
||||
import { Input, Select, SelectProps } from 'antd';
|
||||
import { useMemoizedFn, useMount } from 'ahooks';
|
||||
import { useDatasetContextSelector } from '@/context/Datasets';
|
||||
import { useDataSourceContextSelector } from '@/context/DataSources';
|
||||
import {
|
||||
BusterDatasetListItem,
|
||||
useCreateDataset,
|
||||
useGetDatasets,
|
||||
useUpdateDataset
|
||||
} from '@/api/busterv2/datasets';
|
||||
import { useCreateDataset } from '@/api/busterv2/datasets';
|
||||
import { useAppLayoutContextSelector } from '@/context/BusterAppLayout';
|
||||
import { BusterRoutes, createBusterRoute } from '@/routes';
|
||||
import { useRouter } from 'next/navigation';
|
||||
import { AppModal, Text } from '@/components';
|
||||
import { useAntToken } from '@/styles/useAntToken';
|
||||
import { BusterList, BusterListColumn, BusterListRow } from '@/components/list';
|
||||
import { formatDate } from '@/utils/date';
|
||||
import { timeout } from '@/utils';
|
||||
|
||||
const headerConfig = {
|
||||
title: 'Create a dataset',
|
||||
|
@ -35,21 +25,22 @@ export const NewDatasetModal: React.FC<{
|
|||
const forceInitDataSourceList = useDataSourceContextSelector(
|
||||
(state) => state.forceInitDataSourceList
|
||||
);
|
||||
const { mutateAsync: createDataset } = useCreateDataset();
|
||||
const [creatingDataset, setCreatingDataset] = React.useState(false);
|
||||
const { mutateAsync: createDataset, isPending: creatingDataset } = useCreateDataset();
|
||||
const [selectedDatasource, setSelectedDatasource] = React.useState<string | null>(
|
||||
datasourceId || null
|
||||
);
|
||||
const [datasetName, setDatasetName] = React.useState<string>('');
|
||||
|
||||
const disableSubmit = !selectedDatasource;
|
||||
const disableSubmit = !selectedDatasource || !datasetName;
|
||||
|
||||
const createNewDatasetPreflight = useMemoizedFn(async () => {
|
||||
if (creatingDataset || disableSubmit) return;
|
||||
setCreatingDataset(true);
|
||||
if (creatingDataset || disableSubmit || !selectedDatasource) return;
|
||||
|
||||
beforeCreate?.();
|
||||
|
||||
const res = await createDataset({
|
||||
data_source_id: selectedDatasource!
|
||||
data_source_id: selectedDatasource,
|
||||
name: datasetName
|
||||
});
|
||||
if (res.id) {
|
||||
onChangePage({
|
||||
|
@ -62,16 +53,13 @@ export const NewDatasetModal: React.FC<{
|
|||
afterCreate?.();
|
||||
}, 150);
|
||||
}
|
||||
setTimeout(() => {
|
||||
setCreatingDataset(false);
|
||||
}, 500);
|
||||
});
|
||||
|
||||
const onAddDataSourceClick = useMemoizedFn(() => {
|
||||
onClose();
|
||||
router.push(createBusterRoute({ route: BusterRoutes.SETTINGS_DATASOURCES_ADD }));
|
||||
setTimeout(() => {
|
||||
router.push(createBusterRoute({ route: BusterRoutes.SETTINGS_DATASOURCES_ADD }));
|
||||
}, 350);
|
||||
onClose();
|
||||
}, 450);
|
||||
});
|
||||
|
||||
useLayoutEffect(() => {
|
||||
|
@ -98,14 +86,18 @@ export const NewDatasetModal: React.FC<{
|
|||
return (
|
||||
<AppModal open={open} onClose={onClose} header={headerConfig} footer={footerConfig}>
|
||||
{open && (
|
||||
<SelectDataSourceDropdown
|
||||
setSelectedDatasource={setSelectedDatasource}
|
||||
selectedDatasource={selectedDatasource}
|
||||
/>
|
||||
)}
|
||||
<div className="mt-2 flex flex-col gap-3">
|
||||
<FormWrapper title="Dataset name">
|
||||
<DatasetNameInput setDatasetName={setDatasetName} datasetName={datasetName} />
|
||||
</FormWrapper>
|
||||
|
||||
{open && selectedDatasource && (
|
||||
<SelectFromExistingDataset selectedDatasource={selectedDatasource} />
|
||||
<FormWrapper title="Datasource">
|
||||
<SelectDataSourceDropdown
|
||||
setSelectedDatasource={setSelectedDatasource}
|
||||
selectedDatasource={selectedDatasource}
|
||||
/>
|
||||
</FormWrapper>
|
||||
</div>
|
||||
)}
|
||||
</AppModal>
|
||||
);
|
||||
|
@ -132,6 +124,10 @@ const SelectDataSourceDropdown: React.FC<{
|
|||
return selectOptions.find((option) => option.value === selectedDatasource);
|
||||
}, [selectOptions, selectedDatasource]);
|
||||
|
||||
const onSelect = useMemoizedFn((value: unknown) => {
|
||||
setSelectedDatasource(value as string);
|
||||
});
|
||||
|
||||
useMount(() => {
|
||||
initDataSourceList();
|
||||
router.prefetch(
|
||||
|
@ -149,115 +145,41 @@ const SelectDataSourceDropdown: React.FC<{
|
|||
value={selectedOption}
|
||||
placeholder="Select datasources that this term pertains to"
|
||||
popupMatchSelectWidth={true}
|
||||
autoFocus={true}
|
||||
onChange={(value) => {
|
||||
setSelectedDatasource(value as unknown as string);
|
||||
}}
|
||||
onChange={onSelect}
|
||||
/>
|
||||
);
|
||||
});
|
||||
SelectDataSourceDropdown.displayName = 'SelectDataSourceDropdown';
|
||||
|
||||
const SelectFromExistingDataset: React.FC<{
|
||||
selectedDatasource: string;
|
||||
}> = React.memo(({ selectedDatasource }) => {
|
||||
const token = useAntToken();
|
||||
const { data: importedDatasets, isFetched: isFetchedDatasets } = useGetDatasets({
|
||||
imported: true
|
||||
});
|
||||
const { mutateAsync: onUpdateDataset } = useUpdateDataset();
|
||||
|
||||
const onChangePage = useAppLayoutContextSelector((s) => s.onChangePage);
|
||||
|
||||
const [submittingId, setSubmittingId] = useState<string | null>(null);
|
||||
|
||||
const columns: BusterListColumn[] = useMemo(() => {
|
||||
return [
|
||||
{
|
||||
title: 'Name',
|
||||
dataIndex: 'name'
|
||||
},
|
||||
{
|
||||
title: 'Updated at',
|
||||
dataIndex: 'updated_at',
|
||||
render: (v) => formatDate({ date: v, format: 'lll' }),
|
||||
width: 130
|
||||
},
|
||||
{
|
||||
title: 'Actions',
|
||||
dataIndex: 'actions',
|
||||
width: 100,
|
||||
render: (_, record: BusterDatasetListItem) => (
|
||||
<div className="flex items-center justify-end">
|
||||
<Button
|
||||
loading={submittingId === record.id}
|
||||
type="default"
|
||||
onClick={() => onSelectDataset(record.id)}>
|
||||
Use dataset
|
||||
</Button>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
];
|
||||
}, [submittingId]);
|
||||
|
||||
const rows: BusterListRow[] = useMemo(() => {
|
||||
return importedDatasets.map((dataset) => ({
|
||||
id: dataset.id,
|
||||
data: dataset
|
||||
}));
|
||||
}, [importedDatasets]);
|
||||
|
||||
const onSelectDataset = useMemoizedFn(async (datasetId: string) => {
|
||||
setSubmittingId(datasetId);
|
||||
// try {
|
||||
// await onUpdateDataset({
|
||||
// id: datasetId,
|
||||
// name: 'test'
|
||||
// });
|
||||
// await timeout(500);
|
||||
// onChangePage({
|
||||
// route: BusterRoutes.APP_DATASETS_ID,
|
||||
// datasetId
|
||||
// });
|
||||
// } catch (error) {
|
||||
// setSubmittingId(null);
|
||||
// }
|
||||
});
|
||||
const DatasetNameInput: React.FC<{
|
||||
setDatasetName: (name: string) => void;
|
||||
datasetName: string;
|
||||
}> = React.memo(
|
||||
({ setDatasetName, datasetName }) => {
|
||||
return (
|
||||
<Input
|
||||
autoFocus
|
||||
defaultValue={datasetName}
|
||||
placeholder="Enter a name for your dataset"
|
||||
onChange={(e) => setDatasetName(e.target.value)}
|
||||
/>
|
||||
);
|
||||
},
|
||||
() => true
|
||||
);
|
||||
DatasetNameInput.displayName = 'DatasetNameInput';
|
||||
|
||||
const FormWrapper: React.FC<{
|
||||
title: string;
|
||||
children: React.ReactNode;
|
||||
}> = React.memo(({ title, children }) => {
|
||||
return (
|
||||
<div
|
||||
className="mt-3 flex h-[250px] w-full flex-col"
|
||||
style={{
|
||||
border: `0.5px solid ${token.colorBorder}`,
|
||||
borderRadius: token.borderRadius
|
||||
}}>
|
||||
<div
|
||||
className="flex"
|
||||
style={{
|
||||
padding: 12,
|
||||
background: token.controlItemBgActive,
|
||||
borderBottom: `0.5px solid ${token.colorBorder}`
|
||||
}}>
|
||||
<Text size="sm">Use an existing table or view as a dataset</Text>
|
||||
</div>
|
||||
<div className="h-full w-full">
|
||||
<BusterList
|
||||
columns={columns}
|
||||
rows={rows}
|
||||
showHeader={false}
|
||||
emptyState={
|
||||
!isFetchedDatasets ? (
|
||||
<div className="flex h-full w-full items-center justify-center">
|
||||
<Text>No datasets found</Text>
|
||||
</div>
|
||||
) : (
|
||||
<></>
|
||||
)
|
||||
}
|
||||
/>
|
||||
<div className="grid grid-cols-[minmax(150px,auto)_1fr] gap-4">
|
||||
<div>
|
||||
<Text>{title}</Text>
|
||||
</div>
|
||||
<div>{children}</div>
|
||||
</div>
|
||||
);
|
||||
});
|
||||
SelectFromExistingDataset.displayName = 'SelectFromExistingDataset';
|
||||
FormWrapper.displayName = 'FormWrapper';
|
||||
|
|
|
@ -12,6 +12,9 @@ import { createStyles } from 'antd-style';
|
|||
import { motion } from 'framer-motion';
|
||||
import { useMemoizedFn } from 'ahooks';
|
||||
|
||||
import './MonacoWebWorker';
|
||||
import { configureMonacoToUseYaml } from './yamlHelper';
|
||||
|
||||
//import GithubLightTheme from 'monaco-themes/themes/Github Light.json';
|
||||
//import NightOwnTheme from 'monaco-themes/themes/Night Owl.json';
|
||||
//https://github.com/brijeshb42/monaco-ace-tokenizer
|
||||
|
@ -120,8 +123,13 @@ export const AppCodeEditor = forwardRef<AppCodeEditorHandle, AppCodeEditorProps>
|
|||
(await import('./Github_light')).default,
|
||||
(await import('./Tomorrow-Night')).default
|
||||
]);
|
||||
monaco.editor.defineTheme('github-light', GithubLightTheme as any);
|
||||
monaco.editor.defineTheme('night-owl', NightOwlTheme as any);
|
||||
|
||||
if (language === 'yaml') {
|
||||
await configureMonacoToUseYaml(monaco);
|
||||
}
|
||||
|
||||
monaco.editor.defineTheme('github-light', GithubLightTheme);
|
||||
monaco.editor.defineTheme('night-owl', NightOwlTheme);
|
||||
editor.updateOptions({
|
||||
theme: useDarkMode ? 'night-owl' : 'github-light'
|
||||
});
|
||||
|
|
|
@ -1,9 +1,10 @@
|
|||
import tailwind from '../../../../tailwind.config';
|
||||
import type { editor } from 'monaco-editor';
|
||||
const colors = tailwind.theme.extend.colors;
|
||||
|
||||
const editorBackground = '#ffffff';
|
||||
|
||||
const theme = {
|
||||
const theme: editor.IStandaloneThemeData = {
|
||||
base: 'vs',
|
||||
inherit: true,
|
||||
rules: [
|
||||
|
@ -336,7 +337,14 @@ const theme = {
|
|||
foreground: '032f62',
|
||||
fontStyle: 'underline',
|
||||
token: 'string.other.link'
|
||||
}
|
||||
},
|
||||
{
|
||||
foreground: '24292e',
|
||||
token: 'string.yaml'
|
||||
},
|
||||
{ foreground: colors.buster.primary, token: 'type' },
|
||||
{ foreground: '24292e', token: 'keyword.yaml' }, //booleans
|
||||
{ foreground: 'b31d28', token: 'number.yaml' }
|
||||
],
|
||||
colors: {
|
||||
'editor.foreground': '#24292e',
|
||||
|
|
|
@ -0,0 +1,37 @@
|
|||
import { isServer } from '@tanstack/react-query';
|
||||
|
||||
if (!isServer && typeof window !== 'undefined') {
|
||||
window.MonacoEnvironment = {
|
||||
getWorker(moduleId, label) {
|
||||
switch (label) {
|
||||
case 'editorWorkerService':
|
||||
return new Worker(new URL('monaco-editor/esm/vs/editor/editor.worker', import.meta.url));
|
||||
case 'css':
|
||||
case 'less':
|
||||
case 'scss':
|
||||
return new Worker(
|
||||
new URL('monaco-editor/esm/vs/language/css/css.worker', import.meta.url)
|
||||
);
|
||||
case 'handlebars':
|
||||
case 'html':
|
||||
case 'razor':
|
||||
return new Worker(
|
||||
new URL('monaco-editor/esm/vs/language/html/html.worker', import.meta.url)
|
||||
);
|
||||
case 'json':
|
||||
return new Worker(
|
||||
new URL('monaco-editor/esm/vs/language/json/json.worker', import.meta.url)
|
||||
);
|
||||
case 'javascript':
|
||||
case 'typescript':
|
||||
return new Worker(
|
||||
new URL('monaco-editor/esm/vs/language/typescript/ts.worker', import.meta.url)
|
||||
);
|
||||
case 'yaml':
|
||||
return new Worker(new URL('monaco-yaml/yaml.worker', import.meta.url));
|
||||
default:
|
||||
throw new Error(`Unknown label ${label}`);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
|
@ -1,4 +1,6 @@
|
|||
const theme = {
|
||||
import type { editor } from 'monaco-editor';
|
||||
|
||||
const theme: editor.IStandaloneThemeData = {
|
||||
inherit: true,
|
||||
base: 'vs-dark',
|
||||
rules: [
|
||||
|
@ -339,6 +341,12 @@ const theme = {
|
|||
token: 'storage'
|
||||
}
|
||||
],
|
||||
colors: {
|
||||
'editor.foreground': '#DCDCAA',
|
||||
'editor.background': '#1E1E1E',
|
||||
'editorCursor.foreground': '#DCDCAA',
|
||||
'editorWhitespace.foreground': '#DCDCAA'
|
||||
},
|
||||
encodedTokensColors: []
|
||||
};
|
||||
|
||||
|
|
|
@ -0,0 +1,38 @@
|
|||
export const configureMonacoToUseYaml = async (monaco: typeof import('monaco-editor')) => {
|
||||
const { configureMonacoYaml } = await import('monaco-yaml');
|
||||
|
||||
configureMonacoYaml(monaco, {
|
||||
enableSchemaRequest: true,
|
||||
schemas: [
|
||||
{
|
||||
// If YAML file is opened matching this glob
|
||||
fileMatch: ['**/.prettierrc.*'],
|
||||
// Then this schema will be downloaded from the internet and used.
|
||||
uri: 'https://json.schemastore.org/prettierrc.json'
|
||||
},
|
||||
{
|
||||
// If YAML file is opened matching this glob
|
||||
fileMatch: ['**/person.yaml'],
|
||||
// The following schema will be applied
|
||||
schema: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
name: {
|
||||
type: 'string',
|
||||
description: 'The person’s display name'
|
||||
},
|
||||
age: {
|
||||
type: 'integer',
|
||||
description: 'How old is the person in years?'
|
||||
},
|
||||
occupation: {
|
||||
enum: ['Delivery person', 'Software engineer', 'Astronaut']
|
||||
}
|
||||
}
|
||||
},
|
||||
// And the URI will be linked to as the source.
|
||||
uri: 'https://github.com/remcohaszing/monaco-yaml#usage'
|
||||
}
|
||||
]
|
||||
});
|
||||
};
|
|
@ -16,7 +16,6 @@ export const BusterList: React.FC<BusterListProps> = ({
|
|||
onSelectChange,
|
||||
emptyState,
|
||||
showHeader = true,
|
||||
columnHeaderVariant,
|
||||
contextMenu,
|
||||
showSelectAll = true
|
||||
}) => {
|
||||
|
|
|
@ -15,7 +15,7 @@ export const BusterListRowComponentSelector = React.forwardRef<
|
|||
selectedRowKeys?: string[];
|
||||
rows: BusterListRow[];
|
||||
style?: React.CSSProperties;
|
||||
columnRowVariant: BusterListProps['columnRowVariant'];
|
||||
columnRowVariant?: BusterListProps['columnRowVariant'];
|
||||
}
|
||||
>(
|
||||
(
|
||||
|
|
Loading…
Reference in New Issue