Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: search results list values #488

Merged
merged 10 commits into from
Dec 10, 2023
Original file line number Diff line number Diff line change
@@ -1,10 +1,7 @@
.layers-result-custom-tooltip {
position: absolute;
height: 30px;
border: 1px solid cornflowerblue;
/* overflow: hidden; */
pointer-events: none;
transition: opacity 1s;
border-radius: 8px;
}

.layers-result-custom-tooltip.ag-tooltip-hiding {
Expand All @@ -16,6 +13,7 @@
white-space: nowrap;
}

.layers-result-custom-tooltip p:first-of-type {
.layers-result-custom-tooltip span {
font-weight: bold;
padding: 0 4px;
}
Original file line number Diff line number Diff line change
@@ -1,15 +1,22 @@
import React, { forwardRef, useImperativeHandle, useState } from 'react';
import { forwardRef, useImperativeHandle, useState } from 'react';
import { FormattedMessage } from 'react-intl';
import { get } from 'lodash';
import { ITooltipParams } from 'ag-grid-community';
import { Typography } from '@map-colonies/react-core';
import { LayerRecordTypes } from '../../../../discrete-layer/components/layer-details/entity-types-keys';
import { DateGranularityType, FieldConfigModelType } from '../../../../discrete-layer/models';
import { ILayerImage } from '../../../../discrete-layer/models/layerImage';
import { dateFormatter } from '../../../helpers/formatters';

import './name.tooltip-renderer.css';

export default forwardRef((props: ITooltipParams, ref) => {
// eslint-disable-next-line
const [data, setData] = useState<ILayerImage>(props.api.getDisplayedRowAtIndex(props.rowIndex).data);
const color = get(props, 'color', 'white') as string;

const [data] = useState<ILayerImage>(props.api.getDisplayedRowAtIndex(props.rowIndex).data);
const [layerRecordTypename] = useState<LayerRecordTypes>(data.__typename);
const [color] = useState<string>(get(props, 'color', 'white'));
const [infoTooltipMap] = useState<Map<LayerRecordTypes, FieldConfigModelType[]>>(get(props, 'infoTooltipMap'));
const [fields] = useState<FieldConfigModelType[]>(infoTooltipMap.get(layerRecordTypename) as FieldConfigModelType[]);

useImperativeHandle(ref, () => {
return {
// eslint-disable-next-line
Expand All @@ -20,19 +27,20 @@ export default forwardRef((props: ITooltipParams, ref) => {
});

return (
<div
className="layers-result-custom-tooltip"
style={{ backgroundColor: color}}
>
<p>
<span>{data.productName}</span>
</p>
{/* <p>
<span>Country: </span> {data.country}
</p>
<p>
<span>Total: </span> {data.total}
</p> */}
<div className="layers-result-custom-tooltip" style={{ backgroundColor: color }}>
<>
{
fields.map((field: FieldConfigModelType, index: number) => {
const value = `${get(data, field.fieldName as string)}`;
return (
<Typography tag="p" key={`${field}${index}`}>
<Typography tag="span"><FormattedMessage id={`${field.label}`} />: </Typography>
<bdi>{field.dateGranularity ? dateFormatter(value, field.dateGranularity === DateGranularityType.DATE_AND_TIME) : value}</bdi>
</Typography>
);
})
}
</>
</div>
);
});
1 change: 1 addition & 0 deletions src/common/i18n/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,7 @@
"filters.ingestion-date.unified.label": "Version Date",

"results.fields.name.label": "Name",
"results.fields.ingestion-date.label": "Version Date",
"results.fields.update-date.label": "Updated in catalog",
"results.fields.order.label": "Order",
"results.fields.resolution.label": "Resolution",
Expand Down
1 change: 1 addition & 0 deletions src/common/i18n/he.json
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,7 @@
"filters.ingestion-date.unified.label": "תאריך גירסה",

"results.fields.name.label": "שם",
"results.fields.ingestion-date.label": "תאריך גירסה",
"results.fields.update-date.label": "עדכון פרטים",
"results.fields.order.label": "סדר",
"results.fields.resolution.label": "רזולוציה",
Expand Down
15 changes: 15 additions & 0 deletions src/discrete-layer/components/layer-details/entity-types-keys.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,3 +46,18 @@ export const FieldConfigModelKeys: FieldConfigModelArray = Object.keys(FieldConf
export type LayerMetadataMixedUnionKeys = KeysOfUnion<LayerMetadataMixedUnion>;

export type LayerRecordTypes = "Layer3DRecord" | "LayerRasterRecord" | "BestRecord" | "LayerDemRecord" | "VectorBestRecord" | "QuantizedMeshBestRecord";

let tempLayerRecordTypesObject:
| {
[key in LayerRecordTypes]: undefined;
}
| undefined = {
Layer3DRecord: undefined,
LayerRasterRecord: undefined,
BestRecord: undefined,
LayerDemRecord: undefined,
VectorBestRecord: undefined,
QuantizedMeshBestRecord: undefined,
};

export const LayerRecordTypesKeys = Object.keys(tempLayerRecordTypesObject);
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ import {
Layer3DRecordModelKeys,
LayerDemRecordModelKeys,
LayerRasterRecordModelKeys,
LayerRecordTypes,
} from './entity-types-keys';
import { LayersDetailsComponent } from './layer-details';
import { IRecordFieldInfo } from './layer-details.field-info';
Expand Down Expand Up @@ -74,7 +75,7 @@ interface EntityDialogProps {

const setDefaultValues = (record: Record<string, unknown>, descriptors: EntityDescriptorModelType[]): void => {
getFlatEntityDescriptors(
record['__typename'] as "Layer3DRecord" | "LayerRasterRecord" | "BestRecord" | "LayerDemRecord" | "VectorBestRecord" | "QuantizedMeshBestRecord",
record['__typename'] as LayerRecordTypes,
descriptors
).filter(
field => field.default
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ import { IngestionFields } from './ingestion-fields';
import {
removeEmptyObjFields,
transformFormFieldsToEntity,
extractUpdateRelatedFieldNames,
extractDescriptorRelatedFieldNames,
getFlatEntityDescriptors,
transformEntityToFormFields,
} from './utils';
Expand Down Expand Up @@ -190,7 +190,7 @@ const InnerForm = (
setIsSelectedFiles(!!ingestionFields.fileNames);

// Check update related fields in metadata obj
const updateFields = extractUpdateRelatedFieldNames(metadata.recordModel, getFlatEntityDescriptors(layerRecord.__typename, entityDescriptors));
const updateFields = extractDescriptorRelatedFieldNames('updateRules', getFlatEntityDescriptors(layerRecord.__typename, entityDescriptors));

for (const [key, val] of Object.entries(metadata.recordModel)) {
if (val === null || (updateFields.includes(key) && mode === Mode.UPDATE)) {
Expand Down
32 changes: 22 additions & 10 deletions src/discrete-layer/components/layer-details/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,13 +33,15 @@ import {
Layer3DRecordModelArray,
LayerDemRecordModelArray,
VectorBestRecordModelArray,
QuantizedMeshBestRecordModelArray
QuantizedMeshBestRecordModelArray,
LayerRecordTypes,
LayerRecordTypesKeys
} from './entity-types-keys';

const JSON_INDENTATION = 4;

export const getEntityDescriptors = (
layerRecordTypename: "Layer3DRecord" | "LayerRasterRecord" | "BestRecord" | "LayerDemRecord" | "VectorBestRecord" | "QuantizedMeshBestRecord",
layerRecordTypename: LayerRecordTypes,
entityDescriptors: EntityDescriptorModelType[]
): IRecordCategoryFieldsInfo[] => {
let entityDesc;
Expand Down Expand Up @@ -67,19 +69,29 @@ export const getEntityDescriptors = (
};

export const getFlatEntityDescriptors = (
layerRecordTypename: "Layer3DRecord" | "LayerRasterRecord" | "BestRecord" | "LayerDemRecord" | "VectorBestRecord" | "QuantizedMeshBestRecord",
layerRecordTypename: LayerRecordTypes,
entityDescriptors: EntityDescriptorModelType[]
): FieldConfigModelType[] => {
const descriptors = getEntityDescriptors(layerRecordTypename, entityDescriptors);
const flat: FieldConfigModelType[] = [];
let flat: FieldConfigModelType[] = [];
descriptors.forEach((category: CategoryConfigModelType) => {
category.fields?.forEach((field: FieldConfigModelType) => {
flat.push(field);
});
flat = [ ...flat, ...(category.fields ?? []) ];
});
return flat;
};

export const getFieldNamesByEntityDescriptorMap = (
descriptor: keyof FieldConfigModelType,
entityDescriptors: EntityDescriptorModelType[]
): Map<LayerRecordTypes, string[]> => {
const fieldNamesMap = new Map();
LayerRecordTypesKeys.forEach((layerRecordTypename: string) => {
const fieldNames = extractDescriptorRelatedFieldNames(descriptor, getFlatEntityDescriptors(layerRecordTypename as LayerRecordTypes, entityDescriptors));
fieldNamesMap.set(layerRecordTypename, fieldNames);
});
return fieldNamesMap;
};

export const getBasicType = (fieldName: FieldInfoName, typename: string, lookupTable?: string): string => {
let recordModel;
if (lookupTable != null && lookupTable !== 'zoomlevelresolutions') return 'LookupTableType';
Expand Down Expand Up @@ -252,9 +264,9 @@ export const getPartialRecord = (inputValues: Partial<ILayerImage>, descriptors:
return partialRecordData;
};

export const extractUpdateRelatedFieldNames = (record: ILayerImage, descriptors: FieldConfigModelType[]): string[] => {
const updateRulesFields = descriptors.filter((descriptor) => descriptor.updateRules !== null);
return updateRulesFields.map(field => field.fieldName) as string[];
export const extractDescriptorRelatedFieldNames = (descriptorName: keyof FieldConfigModelType, descriptors: FieldConfigModelType[]): string[] => {
const fields = descriptors.filter((descriptor) => descriptor[descriptorName]);
return fields.map(field => field.fieldName) as string[];
};

// eslint-disable-next-line @typescript-eslint/no-explicit-any
Expand Down
65 changes: 36 additions & 29 deletions src/discrete-layer/components/layers-results/layers-results.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import React, { useEffect, useMemo, useRef, useState } from 'react';
import { useIntl } from 'react-intl';
import { ChangeDetectionStrategyType } from 'ag-grid-react';
import { ColDef, RowDataChangedEvent, ValueGetterParams } from 'ag-grid-community';
import { observer } from 'mobx-react-lite';
import { isObject, isEmpty } from 'lodash';
import { Box } from '@map-colonies/react-components';
Expand All @@ -22,18 +23,20 @@ import { ProductTypeRenderer } from '../../../common/components/grid/cell-render
import { StyledByDataRenderer } from '../../../common/components/grid/cell-renderer/styled-by-data.cell-renderer';
import { HeaderFootprintRenderer } from '../../../common/components/grid/header-renderer/footprint.header-renderer';
import CustomTooltip from '../../../common/components/grid/tooltip-renderer/name.tooltip-renderer';
import { Error } from '../../../common/components/tree/statuses/error';
import { Loading } from '../../../common/components/tree/statuses/loading';
import CONFIG from '../../../common/config';
import { dateFormatter } from '../../../common/helpers/formatters';
import { usePrevious } from '../../../common/hooks/previous.hook';
import { EntityDescriptorModelType } from '../../models';
import { IDispatchAction } from '../../models/actionDispatcherStore';
import { ILayerImage } from '../../models/layerImage';
import { useStore } from '../../models/RootStore';
import { TabViews } from '../../views/tab-views';
import { LayerRecordTypes } from '../layer-details/entity-types-keys';
import { getFieldNamesByEntityDescriptorMap } from '../layer-details/utils';

import './layers-results.css';
import { ColDef, RowDataChangedEvent } from 'ag-grid-community';
import { Loading } from '../../../common/components/tree/statuses/loading';
import { Error } from '../../../common/components/tree/statuses/error';

const PAGINATION = true;
const PAGE_SIZE = 10;
Expand Down Expand Up @@ -200,18 +203,22 @@ export const LayersResultsComponent: React.FC<LayersResultsComponentProps> = obs
field: 'productName',
cellRenderer: 'styledByDataRenderer',
suppressMovable: true,
tooltipComponent: 'customTooltip',
tooltipField: 'productName',
tooltipComponentParams: { color: '#ececec' }
tooltipComponent: 'customTooltip',
tooltipComponentParams: { color: '#ececec', infoTooltipMap: store.discreteLayersStore.entityTooltipFields }
},
{
headerName: intl.formatMessage({
id: 'results.fields.update-date.label',
id: 'results.fields.ingestion-date.label',
}),
minWidth: 140,
flex: 1,
field: 'updateDate',
field: 'ingestionDate',
suppressMovable: true,
valueGetter: (params: ValueGetterParams): string => {
const { data } = params;
return data.ingestionDate !== undefined && data.ingestionDate !== null ? data.ingestionDate : data.insertDate;
},
valueFormatter: (params: GridValueFormatterParams): string => dateFormatter(params.value)
},
{
Expand Down Expand Up @@ -286,15 +293,15 @@ export const LayersResultsComponent: React.FC<LayersResultsComponentProps> = obs
onRowDataUpdated(event: RowDataChangedEvent) {
const rowToUpdate: GridRowNode | undefined | null = event.api.getRowNode(store.discreteLayersStore.selectedLayer?.id as string);

// Find the pinned column to update as well.
// Find the pinned column to update as well
const pinnedColId = (event.api.getColumnDefs().find(colDef => (colDef as ColDef).pinned) as ColDef).colId as string;

event.api.refreshCells({
force: true,
suppressFlash: true,
columns:['productName', '__typename', 'updateDate', pinnedColId],
rowNodes: !isEmpty(rowToUpdate) ? [rowToUpdate] : undefined
});
event.api.refreshCells({
force: true,
suppressFlash: true,
columns:['productName', '__typename', 'updateDate', pinnedColId],
rowNodes: !isEmpty(rowToUpdate) ? [rowToUpdate] : undefined
});
},
};

Expand All @@ -306,23 +313,23 @@ export const LayersResultsComponent: React.FC<LayersResultsComponentProps> = obs

useEffect(() => {
gridApi?.setColumnDefs(colDef);
},[store.userStore.user]);
}, [store.userStore.user]);

return (
<Box id='layerResults'>
{props.searchError ? <Error
className="errorMessage"
message={props.searchError.response?.errors[0].message}
details={
props.searchError.response?.errors[0].extensions?.exception?.config?.url
}
/> :
<GridComponent
gridOptions={gridOptions}
rowData={getRowData()}
style={props.style}
isLoading={props.searchLoading}
/>
<Box id="layerResults">
{
props.searchError ?
<Error
className="errorMessage"
message={props.searchError.response?.errors[0].message}
details={props.searchError.response?.errors[0].extensions?.exception?.config?.url}
/> :
<GridComponent
gridOptions={gridOptions}
rowData={getRowData()}
style={props.style}
isLoading={props.searchLoading}
/>
}
</Box>
);
Expand Down
4 changes: 3 additions & 1 deletion src/discrete-layer/models/FieldConfigModel.base.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ export const FieldConfigModelBase = withTypedRefs<Refs>()(ModelBase
isManuallyEditable: types.union(types.undefined, types.null, types.boolean),
isFilterable: types.union(types.undefined, types.null, types.late((): any => FilterableFieldConfigModel)),
isBriefField: types.union(types.undefined, types.null, types.late((): any => BriefFieldConfigModel)),
isInfoTooltip: types.union(types.undefined, types.null, types.boolean),
isSortable: types.union(types.undefined, types.null, types.boolean),
isRequired: types.union(types.undefined, types.null, types.boolean),
isAutoGenerated: types.union(types.undefined, types.null, types.boolean),
Expand Down Expand Up @@ -80,6 +81,7 @@ export class FieldConfigModelSelector extends QueryBuilder {
get label() { return this.__attr(`label`) }
get fullWidth() { return this.__attr(`fullWidth`) }
get isManuallyEditable() { return this.__attr(`isManuallyEditable`) }
get isInfoTooltip() { return this.__attr(`isInfoTooltip`) }
get isSortable() { return this.__attr(`isSortable`) }
get isRequired() { return this.__attr(`isRequired`) }
get isAutoGenerated() { return this.__attr(`isAutoGenerated`) }
Expand All @@ -106,4 +108,4 @@ export function selectFromFieldConfig() {
return new FieldConfigModelSelector()
}

export const fieldConfigModelPrimitives = selectFromFieldConfig().fieldName.queryableName.fullWidth.isManuallyEditable.isSortable.isRequired.isAutoGenerated.isLifecycleEnvolved.isCopyable.isDisabled.rows.infoMsgCode.default.dateGranularity.autocomplete(autocompletionModelPrimitives).validation(validationConfigModelPrimitives).isFilterable(filterableFieldConfigModelPrimitives).isBriefField(briefFieldConfigModelPrimitives).lookupTable.lookupExcludeFields.dependentField(dependentFieldModelPrimitives).lookupTableBinding(lookupTableBindingModelPrimitives)
export const fieldConfigModelPrimitives = selectFromFieldConfig().fieldName.queryableName.fullWidth.isManuallyEditable.isInfoTooltip.isSortable.isRequired.isAutoGenerated.isLifecycleEnvolved.isCopyable.isDisabled.rows.infoMsgCode.default.dateGranularity.autocomplete(autocompletionModelPrimitives).validation(validationConfigModelPrimitives).isFilterable(filterableFieldConfigModelPrimitives).isBriefField(briefFieldConfigModelPrimitives).lookupTable.lookupExcludeFields.dependentField(dependentFieldModelPrimitives).lookupTableBinding(lookupTableBindingModelPrimitives)
Loading
Loading