From 9f732a288381a07784475d8c9a8dbb490f8fbe5d Mon Sep 17 00:00:00 2001 From: Eddy Babetto Date: Fri, 12 Jul 2024 16:12:20 +0200 Subject: [PATCH] Remove ExplicitTimestamp from server owned interface Explicit timestamp is added and removed from modals and interface, depending on the selected owner, and checked at settings change Signed-off-by: Eddy Babetto --- src/astarte-client/models/Interface/index.ts | 4 +- src/components/InterfaceEditor.tsx | 154 ++++++++++++++----- src/components/MappingEditor.tsx | 39 +++-- 3 files changed, 140 insertions(+), 57 deletions(-) diff --git a/src/astarte-client/models/Interface/index.ts b/src/astarte-client/models/Interface/index.ts index 9f2c462d..23fe5528 100644 --- a/src/astarte-client/models/Interface/index.ts +++ b/src/astarte-client/models/Interface/index.ts @@ -212,7 +212,9 @@ class AstarteInterface { validatedObj.type === 'datastream' ? new AstarteMapping({ ...mapping, - explicitTimestamp: mapping.explicitTimestamp || false, + ...(validatedObj.ownership === 'device' && { + explicitTimestamp: mapping.explicitTimestamp || false, + }), reliability: mapping.reliability || 'unreliable', retention: mapping.retention || 'discard', expiry: mapping.expiry || 0, diff --git a/src/components/InterfaceEditor.tsx b/src/components/InterfaceEditor.tsx index e2e6cec7..1832c675 100644 --- a/src/components/InterfaceEditor.tsx +++ b/src/components/InterfaceEditor.tsx @@ -155,8 +155,13 @@ const MappingRow = ({ className, mapping, onEdit, onDelete }: MappingRowProps) = const getDefaultMapping = (params: { interfaceType: AstarteInterface['type']; interfaceAggregation: AstarteInterface['aggregation']; + interfaceOwner: AstarteInterface['ownership']; }): AstarteMapping => { - if (params.interfaceType === 'datastream' && params.interfaceAggregation === 'individual') { + if ( + params.interfaceType === 'datastream' && + params.interfaceAggregation === 'individual' && + params.interfaceOwner == 'device' + ) { return { endpoint: '', type: 'double', @@ -170,6 +175,7 @@ const getDefaultMapping = (params: { }; interface MappingModalProps { + interfaceOwner: AstarteInterface['ownership']; interfaceType: AstarteInterface['type']; interfaceAggregation?: AstarteInterface['aggregation']; mapping?: AstarteMapping; @@ -178,6 +184,7 @@ interface MappingModalProps { } const MappingModal = ({ + interfaceOwner, interfaceType, interfaceAggregation = 'individual', mapping, @@ -185,7 +192,7 @@ const MappingModal = ({ onConfirm, }: MappingModalProps): React.ReactElement => { const [mappingDraft, setMappingDraft] = useState( - mapping || getDefaultMapping({ interfaceType, interfaceAggregation }), + mapping || getDefaultMapping({ interfaceType, interfaceAggregation, interfaceOwner }), ); const handleChange = useCallback((newMapping: AstarteMapping) => { @@ -201,6 +208,7 @@ const MappingModal = ({ { + (params: { + type: AstarteInterface['type']; + aggregation: AstarteInterface['aggregation']; + ownership: AstarteInterface['ownership']; + }) => { setInterfaceDraft((draft) => { - const mappings = draft.mappings.map((mapping) => - _.omit(mapping, [ + const mappings = draft.mappings.map((mapping) => { + return _.omit(mapping, [ 'allowUnset', 'reliability', 'retention', 'expiry', 'databaseRetentionPolicy', 'databaseRetentionTtl', - 'explicitTimestamp', - ]), - ); + ]); + }); return { ...draft, mappings }; }); + if (params.type === 'datastream' && params.aggregation === 'object') { - setDatastreamOptions(defaultDatastreamOptions); + setDatastreamOptions({ + ...defaultDatastreamOptions, + explicitTimestamp: params.ownership === 'device', + }); } else { - setDatastreamOptions({}); + setDatastreamOptions({ explicitTimestamp: params.ownership === 'device' }); } }, [], @@ -467,33 +482,91 @@ export default ({ const { value } = e.currentTarget; const type = value as AstarteInterface['type']; const aggregation = type === 'datastream' ? 'individual' : undefined; - clearMappingsOptions({ type, aggregation }); - setInterfaceDraft((draft) => ({ ...draft, type, aggregation })); + + clearMappingsOptions({ type, aggregation, ownership: interfaceDraft.ownership }); + setInterfaceDraft((draft) => { + const mappings = draft.mappings.map((mapping) => { + if (type === 'properties') { + return _.omit(mapping, ['explicitTimestamp']) as AstarteMapping; + } else { + return { + ...mapping, + explicitTimestamp: interfaceDraft.ownership === 'device', + } as AstarteMapping; + } + }); + + return { + ...draft, + mappings, + type, + aggregation, + }; + }); }, - [clearMappingsOptions], + [clearMappingsOptions, interfaceDraft], ); const handleInterfaceAggregationChange = useCallback( (e: React.ChangeEvent) => { const { value } = e.currentTarget; const aggregation = value as AstarteInterface['aggregation']; - clearMappingsOptions({ type: 'datastream', aggregation }); - setInterfaceDraft((draft) => ({ - ...draft, + + setInterfaceDraft((draft) => { + const mappings: AstarteMapping[] = draft.mappings.map((mapping) => { + return { + ...mapping, + explicitTimestamp: draft.ownership === 'device', + } as AstarteMapping; + }); + + return { + ...draft, + mappings, + aggregation, + }; + }); + + clearMappingsOptions({ + type: 'datastream', aggregation, - })); + ownership: interfaceDraft.ownership, + }); }, - [clearMappingsOptions], + [clearMappingsOptions, interfaceDraft], ); - const handleInterfaceOwnershipChange = useCallback((e: React.ChangeEvent) => { - const { value } = e.currentTarget; - const ownership = value as AstarteInterface['ownership']; - setInterfaceDraft((draft) => ({ - ...draft, - ownership, - })); - }, []); + const handleInterfaceOwnershipChange = useCallback( + (e: React.ChangeEvent) => { + const { value } = e.currentTarget; + const ownership = value as AstarteInterface['ownership']; + + setInterfaceDraft((draft) => { + const mappings: AstarteMapping[] = draft.mappings.map((mapping) => { + if (interfaceDraft.type === 'properties') { + return _.omit(mapping, ['explicitTimestamp']) as AstarteMapping; + } else { + return { + ...mapping, + explicitTimestamp: ownership === 'device', + } as AstarteMapping; + } + }); + + return { + ...draft, + mappings, + ownership, + }; + }); + clearMappingsOptions({ + type: interfaceDraft.type, + aggregation: interfaceDraft.aggregation, + ownership: ownership, + }); + }, + [clearMappingsOptions, interfaceDraft], + ); const handleInterfaceDescriptionChange = useCallback((e: React.ChangeEvent) => { const { value } = e.target; @@ -860,19 +933,21 @@ export default ({ - - - Timestamp - - - + {interfaceDraft.ownership === 'device' && ( + + + Timestamp + + + + )} )} {interfaceDraft.type === 'datastream' && interfaceDraft.aggregation === 'object' && ( @@ -1043,6 +1118,7 @@ export default ({ )} {isMappingModalVisible && ( + - - Timestamp - ) => { - const explicitTimestamp = !!e.target.checked; - onChange({ ...mapping, explicitTimestamp: explicitTimestamp || undefined }); - }} - isInvalid={mappingValidationErrors.explicitTimestamp != null} - /> - - {mappingValidationErrors.explicitTimestamp} - - + {isDevice && ( + + Timestamp + ) => { + const explicitTimestamp = !!e.target.checked; + onChange({ ...mapping, explicitTimestamp: explicitTimestamp || undefined }); + }} + isInvalid={mappingValidationErrors.explicitTimestamp != null} + /> + + {mappingValidationErrors.explicitTimestamp} + + + )} )}