Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
import { Classes, Tab, Tabs as BPTabs } from '@blueprintjs/core';
import styled from '@emotion/styled';
import { useStore } from '@tanstack/react-form';
import { withForm } from 'react-science/ui';

import { StyledDialogBody } from '../../../elements/StyledDialogBody.js';

import { ExportTab } from './tabs/export_tab.js';
import { ExternalApiTab } from './tabs/external_api_tab.js';
import { GeneralTab } from './tabs/general_tab.js';
import { ImportFiltersTab } from './tabs/import_filters_tab.js';
import { NucleiTab } from './tabs/nuclei_tab.js';
Expand Down Expand Up @@ -40,7 +42,13 @@ export const GeneralSettingsDialogBody = withForm({
props: {
height: undefined as number | undefined,
},
render: ({ height, form }) => {
render: function GeneralSettingsDialogBody({ height, form }) {
const isExperimentalEnabled = useStore(
form.store,
(state) =>
state.values.display.general?.experimentalFeatures?.display ?? false,
);

return (
<StyledDialogBody>
<Div height={height}>
Expand All @@ -67,6 +75,14 @@ export const GeneralSettingsDialogBody = withForm({
panel={<TitleBlockTab form={form} />}
/>

{isExperimentalEnabled && (
<Tab
id="external-apis"
title="External APIs"
panel={<ExternalApiTab form={form} />}
/>
)}

<Tab id="export" title="Export" panel={<ExportTab form={form} />} />
</Tabs>
</Div>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
import { Classes } from '@blueprintjs/core';
import { useField } from '@tanstack/react-form';
import { EXTERNAL_API_KEYS } from '@zakodium/nmrium-core';
import { useMemo } from 'react';
import { FaPlus, FaRegTrashAlt } from 'react-icons/fa';
import { Button, withForm } from 'react-science/ui';
import type { CellProps } from 'react-table';
import type { z } from 'zod';

import type { Column } from '../../../../elements/ReactTable/ReactTable.js';
import { Select2 } from '../../../../elements/Select2.js';
import { CellActions, CellInput, TableSettings } from '../ui/table.js';
import { TableSection } from '../ui/table_section.js';
import type { externalAPIValidation } from '../validation/external_apis_validation.js';
import { defaultGeneralSettingsFormValues } from '../validation.js';

type API = z.input<typeof externalAPIValidation>;
const emptyApi: API = { key: 'CT', serverLink: '', APIKey: '' };

const itemsAPI = EXTERNAL_API_KEYS.slice();

export const ExternalApiTab = withForm({
defaultValues: defaultGeneralSettingsFormValues,
render: function ExternalApiTab({ form }) {
const { Field } = form;
const field = useField({ form, name: 'externalAPIs', mode: 'array' });
const { name, state, pushValue, insertValue, removeValue } = field;

const columns = useMemo<Array<Column<API>>>(
() => [
{
Header: '#',
style: { minWidth: '2em', textAlign: 'center' },
accessor: (_, index) => index + 1,
},
{
Header: 'Service',
Cell: ({ row: { index } }: CellProps<API>) => (
<Field name={`${name}[${index}].key`}>
{(field) => (
<Select2
items={itemsAPI}
itemValueKey="key"
itemTextKey="description"
selectedItemValue={field.state.value}
onItemSelect={({ key }) => field.handleChange(key)}
intent={!field.state.meta.isValid ? 'danger' : 'none'}
fill
/>
)}
</Field>
),
},
{
Header: 'Server link',
Cell: ({ row: { index } }: CellProps<API>) => (
<Field name={`${name}[${index}].serverLink`}>
{(field) => (
<CellInput
name={field.name}
value={field.state.value}
onChange={field.handleChange}
onBlur={field.handleBlur}
intent={
!field.state.meta.isValid && field.state.meta.isDirty
? 'danger'
: 'none'
}
/>
)}
</Field>
),
},
{
Header: 'API key',
Cell: ({ row: { index } }: CellProps<API>) => (
<Field name={`${name}[${index}].APIKey`}>
{(field) => (
<CellInput
name={field.name}
value={field.state.value}
onChange={field.handleChange}
onBlur={field.handleBlur}
intent={
!field.state.meta.isValid && field.state.meta.isDirty
? 'danger'
: 'none'
}
/>
)}
</Field>
),
},
{
Header: '',
style: { width: '60px' },
id: 'add-button',
Cell: ({ row: { index } }: CellProps<API>) => {
return (
<CellActions>
<Button
size="small"
intent="success"
variant="minimal"
onClick={() => insertValue(index, emptyApi)}
>
<FaPlus className={Classes.ICON} />
</Button>
<Button
size="small"
intent="danger"
variant="minimal"
onClick={() => removeValue(index)}
>
<FaRegTrashAlt className={Classes.ICON} />
</Button>
</CellActions>
);
},
},
],
[Field, insertValue, name, removeValue],
);

function onAddField() {
pushValue(emptyApi, { dontRunListeners: true });
}

return (
<TableSection
title="External APIs"
actions={<Button onClick={onAddField}>Add an external API</Button>}
>
<TableSettings
data={state.value}
columns={columns}
emptyDataRowText="No external APIs"
/>
</TableSection>
);
},
});
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
import { Checkbox, Classes } from '@blueprintjs/core';
import type { CSSObject } from '@emotion/react';
import styled from '@emotion/styled';
import { Classes } from '@blueprintjs/core';
import { useStore } from '@tanstack/react-form';
import { useCallback, useMemo } from 'react';
import { FaPlus, FaRegTrashAlt } from 'react-icons/fa';
Expand All @@ -9,13 +7,14 @@ import type { CellProps } from 'react-table';
import type { z } from 'zod';

import { useChartData } from '../../../../context/ChartContext.js';
import { Input2 } from '../../../../elements/Input2.js';
import type {
BaseRowStyle,
Column,
} from '../../../../elements/ReactTable/ReactTable.js';
import ReactTable from '../../../../elements/ReactTable/ReactTable.js';
import type { Column } from '../../../../elements/ReactTable/ReactTable.js';
import { getSpectraObjectPaths } from '../../../../utility/getSpectraObjectPaths.js';
import {
CellActions,
CellCheckbox,
CellInput,
TableSettings,
} from '../ui/table.js';
import { TableSection } from '../ui/table_section.js';
import type { infoBlockFieldTabValidation } from '../validation/title_block_tab_validation.js';
import { defaultGeneralSettingsFormValues } from '../validation.js';
Expand Down Expand Up @@ -59,30 +58,6 @@ export const TitleBlockTab = withForm({
},
});

const tableStyle: CSSObject = {
'thead tr th': { zIndex: 1 },
td: { padding: 0 },
};
const rowStyle: BaseRowStyle = {
hover: { backgroundColor: '#f7f7f7' },
active: { backgroundColor: '#f5f5f5' },
};

const CellInput = styled(Input2)`
input {
background-color: transparent;
box-shadow: none;
}
`;
const CellCheckbox = styled(Checkbox)`
margin: 0;
`;
const Actions = styled.div`
display: flex;
justify-content: space-evenly;
gap: 0.25em;
`;

type Field = z.input<typeof infoBlockFieldTabValidation>;
const emptyField: Field = {
label: '',
Expand Down Expand Up @@ -190,7 +165,7 @@ const Fields = withFieldGroup({
id: 'add-button',
Cell: ({ row: { index } }: CellProps<Field>) => {
return (
<Actions>
<CellActions>
<Button
size="small"
intent="success"
Expand All @@ -207,7 +182,7 @@ const Fields = withFieldGroup({
>
<FaRegTrashAlt className={Classes.ICON} />
</Button>
</Actions>
</CellActions>
);
},
},
Expand All @@ -218,9 +193,7 @@ const Fields = withFieldGroup({
const fields = useStore(group.store, (state) => state.values.fields);

return (
<ReactTable
style={tableStyle}
rowStyle={rowStyle}
<TableSettings
data={fields}
columns={columns}
emptyDataRowText="No Fields"
Expand Down
37 changes: 37 additions & 0 deletions src/component/modal/setting/tanstack_general_settings/ui/table.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import { Checkbox } from '@blueprintjs/core';
import type { CSSObject } from '@emotion/react';
import styled from '@emotion/styled';
import type { ComponentProps } from 'react';

import { Input2 } from '../../../../elements/Input2.js';
import type { BaseRowStyle } from '../../../../elements/ReactTable/ReactTable.js';
import ReactTable from '../../../../elements/ReactTable/ReactTable.js';

const tableStyle: CSSObject = {
'thead tr th': { zIndex: 1 },
td: { padding: 0 },
};
const rowStyle: BaseRowStyle = {
hover: { backgroundColor: '#f7f7f7' },
active: { backgroundColor: '#f5f5f5' },
};
export const CellInput = styled(Input2)`
input {
background-color: transparent;
box-shadow: none;
}
`;
export const CellCheckbox = styled(Checkbox)`
margin: 0;
`;
export const CellActions = styled.div`
display: flex;
justify-content: space-evenly;
gap: 0.25em;
`;

export function TableSettings<T extends object>(
props: Omit<ComponentProps<typeof ReactTable<T>>, 'style' | 'rowStyle'>,
) {
return <ReactTable<T> {...props} style={tableStyle} rowStyle={rowStyle} />;
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { z } from 'zod';
import { workspaceDefaultProperties } from '../../../workspaces/workspaceDefaultProperties.js';

import { exportPreferencesValidation } from './validation/export_tab_validation.js';
import { externalAPIsValidation } from './validation/external_apis_validation.js';
import {
displayGeneralValidation,
generalValidation,
Expand Down Expand Up @@ -33,6 +34,7 @@ export const workspaceValidation = z.object({
nmrLoaders: nmrLoadersValidation,
export: exportPreferencesValidation,
infoBlock: infoBlockTabValidation,
externalAPIs: externalAPIsValidation,
});

// This object is used to define type not real values. Do not use it as values
Expand Down Expand Up @@ -68,4 +70,7 @@ export const defaultGeneralSettingsFormValues: z.input<
workspaceDefaultProperties.nmrLoaders,
),
export: exportPreferencesValidation.encode(workspaceDefaultProperties.export),
externalAPIs: externalAPIsValidation.encode(
workspaceDefaultProperties.externalAPIs,
),
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { EXTERNAL_API_KEYS } from '@zakodium/nmrium-core';
import { z } from 'zod';

export const externalAPIValidation = z.object({
key: z.enum(EXTERNAL_API_KEYS.map(({ key }) => key)),
serverLink: z.url(),
APIKey: z.string(),
});
export const externalAPIsValidation = z.array(externalAPIValidation);
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { z } from 'zod';

import { checkUniqueByKey } from '../utils/checkUniqueByKey.js';
import { checkUniqueByKey } from './check_unique_by_key.js';

export const nucleiValidation = z
.array(
Expand Down
Loading