Skip to content

Commit

Permalink
feat: complete database panel with filters
Browse files Browse the repository at this point in the history
close #1254
close #1255
close #1256
close #1257
  • Loading branch information
hamed-musallam committed Oct 6, 2021
1 parent 9826128 commit 1641d90
Show file tree
Hide file tree
Showing 8 changed files with 339 additions and 30 deletions.
27 changes: 27 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Expand Up @@ -93,6 +93,7 @@
"react-table": "7.6.0",
"react-transition-group": "^4.4.2",
"react-use": "^17.3.1",
"smart-array-filter": "^2.0.3",
"spectrum-generator": "^5.4.0",
"yup": "^0.32.9"
},
Expand Down
135 changes: 105 additions & 30 deletions src/component/panels/databasePanel/DatabasePanel.tsx
@@ -1,39 +1,56 @@
/** @jsxImportSource @emotion/react */
import { css } from '@emotion/react';
import { SvgNmrSum } from 'cheminfo-font';
import { useCallback, useState, useRef, memo } from 'react';
import { useAccordionContext } from 'analysis-ui-components';
import { DatabaseNMREntry } from 'nmr-processing/lib/databases/DatabaseNMREntry';
import { useCallback, useState, useRef, memo, useEffect, useMemo } from 'react';
import ReactCardFlip from 'react-card-flip';

// import { useChartData } from '../../context/ChartContext';
import ToolTip from '../../elements/ToolTip/ToolTip';
import {
initiateDatabase,
getDatabasesNames,
} from '../../../data/data1d/database';
import { useChartData } from '../../context/ChartContext';
import Input from '../../elements/Input';
import Select from '../../elements/Select';
import DefaultPanelHeader from '../header/DefaultPanelHeader';
import PreferencesHeader from '../header/PreferencesHeader';

import DatabasePreferences from './DatabasePreferences';
import DatabaseTable from './DatabaseTable';

const styles = css`
display: flex;
flex-direction: column;
height: 100%;
width: 100%;
.sum-button {
width: 22px;
height: 22px;
display: flex;
align-items: center;
justify-content: center;
.header {
height: 36px;
padding: 2px 0px;
}
.input-container {
width: 100%;
}
.search-input {
width: 100% !important;
border-radius: 5px;
border: 0.55px solid gray;
padding: 5px;
outline: none;
}
`;

export interface DatabaseInnerProps {
database: any;
nucleus: string;
}

// eslint-disable-next-line @typescript-eslint/no-unused-vars
function DatabasePanelInner({ database }: DatabaseInnerProps) {
// const dispatch = useDispatch();
function DatabasePanelInner({ nucleus }: DatabaseInnerProps) {
const [isFlipped, setFlipStatus] = useState(false);
const [data, setData] = useState<DatabaseNMREntry[]>([]);
const settingRef = useRef<any>();
const searchKeywords = useRef<[string, string]>(['', '']);
const databaseInstance = useRef(initiateDatabase('solvent', nucleus));
const { item } = useAccordionContext('Database');

const settingsPanelHandler = useCallback(() => {
setFlipStatus(!isFlipped);
Expand All @@ -47,19 +64,83 @@ function DatabasePanelInner({ database }: DatabaseInnerProps) {
setFlipStatus(false);
}, []);

const databaseList = useMemo(() => {
return getDatabasesNames().map(({ id, name }) => ({
key: id,
value: id,
label: name,
}));
}, []);

const solventsList = useMemo(() => {
let result: any = [];
const solvents = databaseInstance.current.getSolvents();
result = solvents.map((key) => {
return {
key,
label: key,
value: key,
};
}, []);
result.unshift({ key: '-1', label: 'All', value: '-1' });
return result;
}, []);

useEffect(() => {
if (item?.isOpen) {
const result = databaseInstance.current.search(searchKeywords.current);
setTimeout(() => {
setData(result);
});
}
}, [item?.isOpen]);

const handleSearch = useCallback((input) => {
if (typeof input === 'string' || input === -1) {
searchKeywords.current[0] = input === -1 ? '' : input;
} else {
searchKeywords.current[1] = input.target.value;
}
const result = databaseInstance.current.search(searchKeywords.current);
setData(result);
}, []);

const handleChangeDatabase = useCallback(
(databaseKey) => {
databaseInstance.current = initiateDatabase(databaseKey, nucleus);
const result = databaseInstance.current.search();
searchKeywords.current = ['', ''];
setData(result);
},
[nucleus],
);

return (
<div css={styles}>
{!isFlipped && (
<DefaultPanelHeader
showSettingButton
onSettingClick={settingsPanelHandler}
canDelete={false}
className="header"
>
<ToolTip title="test" popupPlacement="right">
<button className="test-button" type="button" onClick={() => null}>
<SvgNmrSum />
</button>
</ToolTip>
<Select
style={{ flex: 2 }}
data={databaseList}
onChange={handleChangeDatabase}
/>
<Select
style={{ flex: 1 }}
data={solventsList}
onChange={handleSearch}
/>
<Input
style={{ container: { flex: 3 } }}
className="search-input"
debounceTime={500}
placeholder="Search for parameter..."
onChange={handleSearch}
/>
</DefaultPanelHeader>
)}
{isFlipped && (
Expand All @@ -75,7 +156,7 @@ function DatabasePanelInner({ database }: DatabaseInnerProps) {
containerStyle={{ overflow: 'hidden', height: '100%' }}
>
<div style={{ overflow: 'auto', height: '100%', display: 'block' }}>
<p>Database Panel</p>
<DatabaseTable data={data} />
</div>
<DatabasePreferences ref={settingRef} />
</ReactCardFlip>
Expand All @@ -86,14 +167,8 @@ function DatabasePanelInner({ database }: DatabaseInnerProps) {

const MemoizedDatabasePanel = memo(DatabasePanelInner);

export default function DatabasePanel() {
// const { database = {} } = useChartData();

return (
<MemoizedDatabasePanel
{...{
database: {},
}}
/>
);
export default function PeaksPanel() {
const { activeTab } = useChartData();
if (!activeTab) return <div />;
return <MemoizedDatabasePanel nucleus={activeTab} />;
}
10 changes: 10 additions & 0 deletions src/component/panels/databasePanel/DatabaseTable/NamesRenderer.tsx
@@ -0,0 +1,10 @@
import { CSSProperties } from 'react';

const style: CSSProperties = {
whiteSpace: 'pre-line',
textOverflow: 'ellipsis',
};

export default function NamesRenderer(props: { names: string[] }) {
return <p style={style}>{props.names.join('\n')}</p>;
}
@@ -0,0 +1,20 @@
import { CSSProperties } from 'react';

import { DataBaseRange } from '../../../../data/data1d/database';

const style: CSSProperties = {
whiteSpace: 'pre-line',
textOverflow: 'ellipsis',
};

export function RangesRenderer(props: { ranges: DataBaseRange[] }) {
return (
<p style={style}>
{props.ranges
.map((range) => {
return range.signals.map((signal) => signal.delta).join(',');
})
.join('\n')}
</p>
);
}
75 changes: 75 additions & 0 deletions src/component/panels/databasePanel/DatabaseTable/index.tsx
@@ -0,0 +1,75 @@
import { useMemo, memo } from 'react';

import { usePreferences } from '../../../context/PreferencesContext';
import ReactTable from '../../../elements/ReactTable/ReactTable';
import setCustomColumn from '../../../elements/ReactTable/setCustomColumn';
import { getValue } from '../../../utility/LocalStorage';
import NoTableData from '../../extra/placeholder/NoTableData';
import { databaseDefaultValues } from '../../extra/preferences/defaultValues';

import NamesRenderer from './NamesRenderer';
import { RangesRenderer } from './RangesRenderer';

interface DatabaseTableProps {
data: any;
}

function DatabaseTable({ data }: DatabaseTableProps) {
const preferences = usePreferences();
const initialColumns = useMemo(
() => [
{
index: 1,
Header: '#',
width: '1%',
minWidth: '24px',
Cell: ({ row }) => row.index + 1,
},
],
[],
);

const tableColumns = useMemo(() => {
const databasePreferences = getValue(
preferences,
'formatting.panels.database',
databaseDefaultValues,
);

let cols = [...initialColumns];

if (databasePreferences.showNames) {
setCustomColumn(cols, {
index: 2,
columnLabel: 'names',
accessor: (row) => row.names[0],
Cell: ({ row }) => <NamesRenderer names={row?.original.names} />,
});
}

if (databasePreferences.showRanges) {
setCustomColumn(cols, {
index: 3,
columnLabel: 'ranges',
Cell: ({ row }) => <RangesRenderer ranges={row?.original.ranges} />,
});
}

if (databasePreferences.showSolvent) {
setCustomColumn(cols, {
index: 4,
columnLabel: 'solvent',
Cell: ({ row }) => <RangesRenderer ranges={row?.original.solvent} />,
});
}
return cols.sort((object1, object2) => object1.index - object2.index);
}, [initialColumns, preferences]);

return data && data.length > 0 ? (
<ReactTable data={data} columns={tableColumns} />
) : (
<NoTableData />
);
}

export default memo(DatabaseTable);

0 comments on commit 1641d90

Please sign in to comment.