From 2d3a2e4498f6fd4c8447b54e3597deddecb2b867 Mon Sep 17 00:00:00 2001 From: Roberto Fontanarosa Date: Fri, 13 Mar 2026 16:45:19 +0100 Subject: [PATCH 1/3] Add integrations map to Job proto and model --- proto/src/ground/v1beta1/job.proto | 9 +++++++++ web/src/app/converters/proto-model-converter.ts | 5 ++++- web/src/app/converters/survey-data-converter.ts | 3 ++- web/src/app/models/job.model.ts | 9 +++++++-- 4 files changed, 22 insertions(+), 4 deletions(-) diff --git a/proto/src/ground/v1beta1/job.proto b/proto/src/ground/v1beta1/job.proto index ee0e12f47..6046d7614 100644 --- a/proto/src/ground/v1beta1/job.proto +++ b/proto/src/ground/v1beta1/job.proto @@ -40,8 +40,17 @@ message Job { // One or more data collection tasks to be carried out by the user in order // to collect and submit data. repeated Task tasks = 5; + + // Integrations enabled for this job, keyed by integration ID. + // The presence of an entry indicates the integration is active. + // The value holds integration-specific configuration (reserved for future use). + map integrations = 6; } +// Configuration for a single integration associated with a job. +// Currently empty; will be extended with integration-specific fields. +message Integration {} + // A style used when rendering geometries and other UI elements associated // with this job. message Style { diff --git a/web/src/app/converters/proto-model-converter.ts b/web/src/app/converters/proto-model-converter.ts index 1098f9cef..df3f3b115 100644 --- a/web/src/app/converters/proto-model-converter.ts +++ b/web/src/app/converters/proto-model-converter.ts @@ -138,7 +138,7 @@ export function surveyToDocument( * Returns the proto representation of a Job model object. */ export function jobToDocument(job: Job): DocumentData { - const { id, index, name, color, tasks } = job; + const { id, index, name, color, tasks, integrations } = job; return toDocumentData( new Pb.Job({ @@ -149,6 +149,9 @@ export function jobToDocument(job: Job): DocumentData { tasks: (tasks?.toList() ?? List()) .map((task: Task) => toTaskMessage(task)) .toArray(), + integrations: Object.fromEntries( + integrations.entrySeq().map(([k]) => [k, new Pb.Integration()]) + ), }) ); } diff --git a/web/src/app/converters/survey-data-converter.ts b/web/src/app/converters/survey-data-converter.ts index a96921610..3b40559db 100644 --- a/web/src/app/converters/survey-data-converter.ts +++ b/web/src/app/converters/survey-data-converter.ts @@ -125,7 +125,8 @@ function jobPbToModel(pb: Pb.IJob): Job { ), pb.tasks!.find(task => task.level === DataCollectionLevel.LOI_METADATA) ? DataCollectionStrategy.MIXED - : DataCollectionStrategy.PREDEFINED + : DataCollectionStrategy.PREDEFINED, + Map(Object.keys(pb.integrations ?? {}).map(id => [id, {} as const])) ); } diff --git a/web/src/app/models/job.model.ts b/web/src/app/models/job.model.ts index bc2612c4a..e034b8d7c 100644 --- a/web/src/app/models/job.model.ts +++ b/web/src/app/models/job.model.ts @@ -14,7 +14,7 @@ * limitations under the License. */ -import { List, OrderedMap } from 'immutable'; +import { List, Map, OrderedMap } from 'immutable'; import { Copiable } from './copiable'; import { Task } from './task/task.model'; @@ -24,6 +24,10 @@ export enum DataCollectionStrategy { MIXED = 'MIXED', } +// Configuration for a single integration associated with a job. +// Currently empty; will be extended with integration-specific fields. +export type Integration = Record; + export class Job extends Copiable { constructor( readonly id: string, @@ -31,7 +35,8 @@ export class Job extends Copiable { readonly color?: string, readonly name?: string, readonly tasks?: OrderedMap, - readonly strategy?: DataCollectionStrategy + readonly strategy?: DataCollectionStrategy, + readonly integrations: Map = Map() ) { super(); From 724b4db603dc13a758c580b8ec3c028cb614eac1 Mon Sep 17 00:00:00 2001 From: Roberto Fontanarosa Date: Fri, 20 Mar 2026 15:30:52 +0100 Subject: [PATCH 2/3] used repeated instead of map for integrations --- proto/src/ground/v1beta1/job.proto | 12 ++++++------ web/src/app/converters/proto-model-converter.ts | 7 ++++--- web/src/app/converters/survey-data-converter.ts | 2 +- web/src/app/models/job.model.ts | 5 +++-- 4 files changed, 14 insertions(+), 12 deletions(-) diff --git a/proto/src/ground/v1beta1/job.proto b/proto/src/ground/v1beta1/job.proto index 6046d7614..a44b229b7 100644 --- a/proto/src/ground/v1beta1/job.proto +++ b/proto/src/ground/v1beta1/job.proto @@ -41,15 +41,15 @@ message Job { // to collect and submit data. repeated Task tasks = 5; - // Integrations enabled for this job, keyed by integration ID. - // The presence of an entry indicates the integration is active. - // The value holds integration-specific configuration (reserved for future use). - map integrations = 6; + // Zero or more integrations enabled for this job. + repeated Integration integrations = 6; } // Configuration for a single integration associated with a job. -// Currently empty; will be extended with integration-specific fields. -message Integration {} +message Integration { + // Required. The system-defined unique identifier of this integration. + string id = 1; +} // A style used when rendering geometries and other UI elements associated // with this job. diff --git a/web/src/app/converters/proto-model-converter.ts b/web/src/app/converters/proto-model-converter.ts index df3f3b115..2574168bd 100644 --- a/web/src/app/converters/proto-model-converter.ts +++ b/web/src/app/converters/proto-model-converter.ts @@ -149,9 +149,10 @@ export function jobToDocument(job: Job): DocumentData { tasks: (tasks?.toList() ?? List()) .map((task: Task) => toTaskMessage(task)) .toArray(), - integrations: Object.fromEntries( - integrations.entrySeq().map(([k]) => [k, new Pb.Integration()]) - ), + integrations: integrations + .valueSeq() + .map(i => new Pb.Integration({ id: i.id })) + .toArray(), }) ); } diff --git a/web/src/app/converters/survey-data-converter.ts b/web/src/app/converters/survey-data-converter.ts index 3b40559db..e8460d0b1 100644 --- a/web/src/app/converters/survey-data-converter.ts +++ b/web/src/app/converters/survey-data-converter.ts @@ -126,7 +126,7 @@ function jobPbToModel(pb: Pb.IJob): Job { pb.tasks!.find(task => task.level === DataCollectionLevel.LOI_METADATA) ? DataCollectionStrategy.MIXED : DataCollectionStrategy.PREDEFINED, - Map(Object.keys(pb.integrations ?? {}).map(id => [id, {} as const])) + Map((pb.integrations ?? []).map(i => [i.id!, {id: i.id!}])) ); } diff --git a/web/src/app/models/job.model.ts b/web/src/app/models/job.model.ts index e034b8d7c..fad971356 100644 --- a/web/src/app/models/job.model.ts +++ b/web/src/app/models/job.model.ts @@ -25,8 +25,9 @@ export enum DataCollectionStrategy { } // Configuration for a single integration associated with a job. -// Currently empty; will be extended with integration-specific fields. -export type Integration = Record; +export interface Integration { + id: string; +} export class Job extends Copiable { constructor( From 5fe8bb440cc20bb21d65d5ebde23899984edaa1f Mon Sep 17 00:00:00 2001 From: Roberto Fontanarosa Date: Fri, 20 Mar 2026 17:44:16 +0100 Subject: [PATCH 3/3] renamed integrations into enabledIntegrations --- proto/src/ground/v1beta1/job.proto | 2 +- web/src/app/converters/proto-model-converter.ts | 4 ++-- web/src/app/converters/survey-data-converter.ts | 2 +- web/src/app/models/job.model.ts | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/proto/src/ground/v1beta1/job.proto b/proto/src/ground/v1beta1/job.proto index a44b229b7..9a1f04b75 100644 --- a/proto/src/ground/v1beta1/job.proto +++ b/proto/src/ground/v1beta1/job.proto @@ -42,7 +42,7 @@ message Job { repeated Task tasks = 5; // Zero or more integrations enabled for this job. - repeated Integration integrations = 6; + repeated Integration enabled_integrations = 6; } // Configuration for a single integration associated with a job. diff --git a/web/src/app/converters/proto-model-converter.ts b/web/src/app/converters/proto-model-converter.ts index 2574168bd..974776eab 100644 --- a/web/src/app/converters/proto-model-converter.ts +++ b/web/src/app/converters/proto-model-converter.ts @@ -138,7 +138,7 @@ export function surveyToDocument( * Returns the proto representation of a Job model object. */ export function jobToDocument(job: Job): DocumentData { - const { id, index, name, color, tasks, integrations } = job; + const { id, index, name, color, tasks, enabledIntegrations } = job; return toDocumentData( new Pb.Job({ @@ -149,7 +149,7 @@ export function jobToDocument(job: Job): DocumentData { tasks: (tasks?.toList() ?? List()) .map((task: Task) => toTaskMessage(task)) .toArray(), - integrations: integrations + enabledIntegrations: enabledIntegrations .valueSeq() .map(i => new Pb.Integration({ id: i.id })) .toArray(), diff --git a/web/src/app/converters/survey-data-converter.ts b/web/src/app/converters/survey-data-converter.ts index e8460d0b1..16d6d57d3 100644 --- a/web/src/app/converters/survey-data-converter.ts +++ b/web/src/app/converters/survey-data-converter.ts @@ -126,7 +126,7 @@ function jobPbToModel(pb: Pb.IJob): Job { pb.tasks!.find(task => task.level === DataCollectionLevel.LOI_METADATA) ? DataCollectionStrategy.MIXED : DataCollectionStrategy.PREDEFINED, - Map((pb.integrations ?? []).map(i => [i.id!, {id: i.id!}])) + Map((pb.enabledIntegrations ?? []).map(i => [i.id!, {id: i.id!}])) ); } diff --git a/web/src/app/models/job.model.ts b/web/src/app/models/job.model.ts index fad971356..6c203bba6 100644 --- a/web/src/app/models/job.model.ts +++ b/web/src/app/models/job.model.ts @@ -37,7 +37,7 @@ export class Job extends Copiable { readonly name?: string, readonly tasks?: OrderedMap, readonly strategy?: DataCollectionStrategy, - readonly integrations: Map = Map() + readonly enabledIntegrations: Map = Map() ) { super();