This is an automated email from the ASF dual-hosted git repository.
riemer pushed a commit to branch dev
in repository https://gitbox.apache.org/repos/asf/streampipes.git
The following commit(s) were added to refs/heads/dev by this push:
new 3e45179647 feat: Add retention time configuration (#3763)
3e45179647 is described below
commit 3e45179647b40d2fe7d91180bd619780bb62eb57
Author: Jacqueline Höllig <[email protected]>
AuthorDate: Mon Sep 8 09:56:42 2025 +0200
feat: Add retention time configuration (#3763)
* init
* prettier and lint
* first draft UI
* first draft ui
* first UI drafr
* Basic Version of Data Model in Java
* Eliminated Stepper
* added action to ui
* added action to data model
* changes to swagger auth
* drafted api endpoint
* save instance wise scheduler
* first cron job draft
* Minor
* first running scheduling draft
* corrected settings cron job
* eliminated cron interval in frontend
* added elementID in configuration entry
* eliminated some enum issued
* first working draft
* retention working
* deleted comments
* added retention coloring
* cleanup
* Revert "init"
This reverts commit a76dd1dce2afc611e53750c0206f2444258489de.
* eliminated double lisences
* Update
streampipes-model/src/main/java/org/apache/streampipes/model/datalake/RetentionTimeConfig.java
eliminaated unnecessary line
Co-authored-by: Dominik Riemer <[email protected]>
* Update
streampipes-service-core/src/main/java/org/apache/streampipes/service/core/scheduler/DataLakeScheduler.java
changed naming of logger
Co-authored-by: Dominik Riemer <[email protected]>
* Update
streampipes-rest/src/main/java/org/apache/streampipes/rest/impl/datalake/DataLakeResource.java
deleted spacing
Co-authored-by: Dominik Riemer <[email protected]>
* Update
streampipes-service-core/src/main/java/org/apache/streampipes/service/core/scheduler/DataLakeScheduler.java
deleted empty line
Co-authored-by: Dominik Riemer <[email protected]>
* Update
ui/src/app/configuration/dialog/data-retention-dialog/model/retention-config.model.ts
Deleted Export
Co-authored-by: Dominik Riemer <[email protected]>
* Update
ui/src/app/configuration/dialog/data-retention-dialog/components/select-retention/select-retention-action/select-retention-action.component.ts
deleted comment
Co-authored-by: Dominik Riemer <[email protected]>
* Update
ui/src/app/configuration/dialog/data-retention-dialog/model/data-retention-config.model.ts
deleted comment
Co-authored-by: Dominik Riemer <[email protected]>
* new line in record DataRetentionConfig
* record new line
added correct email
* eliminated TODO comment
* deleted empty if
* fixed type error
* changed log to LOF
* added Header in DataLakeScheduler
* maven issues
* fixed maven formatting
---------
Co-authored-by: Jacqueline Höllig
<[email protected]>
Co-authored-by: Jacqueline Höllig <[email protected]>
Co-authored-by: Dominik Riemer <[email protected]>
---
.../model/datalake/DataLakeMeasure.java | 11 ++
.../model/datalake/DataRetentionConfig.java | 13 +-
.../model/datalake/RetentionAction.java | 13 +-
.../model/datalake/RetentionExportConfig.java | 10 +-
.../model/datalake/RetentionInterval.java | 14 +-
.../model/datalake/RetentionTimeConfig.java | 11 +-
.../impl/datalake/DataLakeMeasureResource.java | 1 +
.../rest/impl/datalake/DataLakeResource.java | 27 ++++
.../service/core/StreamPipesCoreApplication.java | 5 +-
.../service/core/scheduler/DataLakeScheduler.java | 75 +++++++++++
.../src/lib/apis/datalake-rest.service.ts | 16 +++
.../src/lib/model/gen/streampipes-model.ts | 47 ++++++-
ui/src/app/configuration/configuration.module.ts | 12 +-
.../datalake-configuration-entry.ts | 5 +
.../datalake-configuration.component.html | 39 ++++++
.../datalake-configuration.component.ts | 21 ++-
.../select-export/select-format.component.html | 20 +++
.../select-export/select-format.component.scss | 17 +++
.../select-export/select-format.component.ts | 56 ++++++++
.../select-data-retention.component.html | 33 +++++
.../select-data-retention.component.scss | 21 +++
.../select-data-retention.component.ts | 38 ++++++
.../select-retention/select-data.component.html | 31 +++++
.../select-retention/select-data.component.scss | 33 +++++
.../select-retention/select-data.component.ts | 41 ++++++
.../select-retention-action.component.html | 47 +++++++
.../select-retention-action.component.scss | 21 +++
.../select-retention-action.component.ts | 35 +++++
.../data-retention-dialog.component.html | 59 ++++++++
.../data-retention-dialog.component.scss | 75 +++++++++++
.../data-retention-dialog.component.ts | 84 ++++++++++++
.../model/data-retention-config.model.ts | 24 ++++
.../model/data-retention-dialog.model.ts | 28 ++++
.../model/retention-config.model.ts | 23 ++++
.../model/retention-export-config.model.ts | 40 ++++++
.../services/data-export.service.ts | 148 +++++++++++++++++++++
.../services/file-name.service.spec.ts | 118 ++++++++++++++++
.../services/file-name.service.ts | 59 ++++++++
38 files changed, 1332 insertions(+), 39 deletions(-)
diff --git
a/streampipes-model/src/main/java/org/apache/streampipes/model/datalake/DataLakeMeasure.java
b/streampipes-model/src/main/java/org/apache/streampipes/model/datalake/DataLakeMeasure.java
index 61895df80d..50eefd8da3 100644
---
a/streampipes-model/src/main/java/org/apache/streampipes/model/datalake/DataLakeMeasure.java
+++
b/streampipes-model/src/main/java/org/apache/streampipes/model/datalake/DataLakeMeasure.java
@@ -53,6 +53,8 @@ public class DataLakeMeasure implements Storable {
private DataLakeMeasureSchemaUpdateStrategy schemaUpdateStrategy =
DataLakeMeasureSchemaUpdateStrategy.UPDATE_SCHEMA;
+ private RetentionTimeConfig retentionTime;
+
public DataLakeMeasure() {
super();
}
@@ -139,6 +141,15 @@ public class DataLakeMeasure implements Storable {
this.schemaUpdateStrategy = schemaUpdateStrategy;
}
+
+ public void setRetentionTime(RetentionTimeConfig retentionTime) {
+ this.retentionTime = retentionTime;
+ }
+
+ public RetentionTimeConfig getRetentionTime() {
+ return retentionTime;
+ }
+
/**
* This can be used to get the name of the timestamp property without the
stream prefix
*
diff --git
a/ui/src/app/configuration/datalake-configuration/datalake-configuration-entry.ts
b/streampipes-model/src/main/java/org/apache/streampipes/model/datalake/DataRetentionConfig.java
similarity index 82%
copy from
ui/src/app/configuration/datalake-configuration/datalake-configuration-entry.ts
copy to
streampipes-model/src/main/java/org/apache/streampipes/model/datalake/DataRetentionConfig.java
index 4c8c9b71dc..8a920e52d8 100644
---
a/ui/src/app/configuration/datalake-configuration/datalake-configuration-entry.ts
+++
b/streampipes-model/src/main/java/org/apache/streampipes/model/datalake/DataRetentionConfig.java
@@ -15,11 +15,10 @@
* limitations under the License.
*
*/
-export class DataLakeConfigurationEntry {
- public name: string;
- public pipelines: string[] = [];
- public events = 0;
- public remove = true;
- constructor() {}
-}
+package org.apache.streampipes.model.datalake;
+
+public record DataRetentionConfig(
+ RetentionInterval interval,
+ int olderThanDays,
+ RetentionAction action) {}
\ No newline at end of file
diff --git
a/ui/src/app/configuration/datalake-configuration/datalake-configuration-entry.ts
b/streampipes-model/src/main/java/org/apache/streampipes/model/datalake/RetentionAction.java
similarity index 82%
copy from
ui/src/app/configuration/datalake-configuration/datalake-configuration-entry.ts
copy to
streampipes-model/src/main/java/org/apache/streampipes/model/datalake/RetentionAction.java
index 4c8c9b71dc..640b05622e 100644
---
a/ui/src/app/configuration/datalake-configuration/datalake-configuration-entry.ts
+++
b/streampipes-model/src/main/java/org/apache/streampipes/model/datalake/RetentionAction.java
@@ -15,11 +15,12 @@
* limitations under the License.
*
*/
-export class DataLakeConfigurationEntry {
- public name: string;
- public pipelines: string[] = [];
- public events = 0;
- public remove = true;
- constructor() {}
+
+package org.apache.streampipes.model.datalake;
+
+public enum RetentionAction {
+ DELETE,
+ SAVE,
+ SAVEDELETE
}
diff --git
a/ui/src/app/configuration/datalake-configuration/datalake-configuration-entry.ts
b/streampipes-model/src/main/java/org/apache/streampipes/model/datalake/RetentionExportConfig.java
similarity index 82%
copy from
ui/src/app/configuration/datalake-configuration/datalake-configuration-entry.ts
copy to
streampipes-model/src/main/java/org/apache/streampipes/model/datalake/RetentionExportConfig.java
index 4c8c9b71dc..340afd3e02 100644
---
a/ui/src/app/configuration/datalake-configuration/datalake-configuration-entry.ts
+++
b/streampipes-model/src/main/java/org/apache/streampipes/model/datalake/RetentionExportConfig.java
@@ -15,11 +15,7 @@
* limitations under the License.
*
*/
-export class DataLakeConfigurationEntry {
- public name: string;
- public pipelines: string[] = [];
- public events = 0;
- public remove = true;
- constructor() {}
-}
+package org.apache.streampipes.model.datalake;
+
+public record RetentionExportConfig() {}
diff --git
a/ui/src/app/configuration/datalake-configuration/datalake-configuration-entry.ts
b/streampipes-model/src/main/java/org/apache/streampipes/model/datalake/RetentionInterval.java
similarity index 82%
copy from
ui/src/app/configuration/datalake-configuration/datalake-configuration-entry.ts
copy to
streampipes-model/src/main/java/org/apache/streampipes/model/datalake/RetentionInterval.java
index 4c8c9b71dc..f951d6e92e 100644
---
a/ui/src/app/configuration/datalake-configuration/datalake-configuration-entry.ts
+++
b/streampipes-model/src/main/java/org/apache/streampipes/model/datalake/RetentionInterval.java
@@ -15,11 +15,11 @@
* limitations under the License.
*
*/
-export class DataLakeConfigurationEntry {
- public name: string;
- public pipelines: string[] = [];
- public events = 0;
- public remove = true;
- constructor() {}
-}
+package org.apache.streampipes.model.datalake;
+
+public enum RetentionInterval {
+ DAILY,
+ MONTHLY,
+ WEEKLY
+}
\ No newline at end of file
diff --git
a/ui/src/app/configuration/datalake-configuration/datalake-configuration-entry.ts
b/streampipes-model/src/main/java/org/apache/streampipes/model/datalake/RetentionTimeConfig.java
similarity index 82%
copy from
ui/src/app/configuration/datalake-configuration/datalake-configuration-entry.ts
copy to
streampipes-model/src/main/java/org/apache/streampipes/model/datalake/RetentionTimeConfig.java
index 4c8c9b71dc..0c9d11753a 100644
---
a/ui/src/app/configuration/datalake-configuration/datalake-configuration-entry.ts
+++
b/streampipes-model/src/main/java/org/apache/streampipes/model/datalake/RetentionTimeConfig.java
@@ -15,11 +15,8 @@
* limitations under the License.
*
*/
-export class DataLakeConfigurationEntry {
- public name: string;
- public pipelines: string[] = [];
- public events = 0;
- public remove = true;
- constructor() {}
-}
+package org.apache.streampipes.model.datalake;
+//, RetentionExportConfig exportConfig
+public record RetentionTimeConfig(
+ DataRetentionConfig dataRetentionConfig) {}
diff --git
a/streampipes-rest/src/main/java/org/apache/streampipes/rest/impl/datalake/DataLakeMeasureResource.java
b/streampipes-rest/src/main/java/org/apache/streampipes/rest/impl/datalake/DataLakeMeasureResource.java
index 8bef5a04f4..97a3a4f0ea 100644
---
a/streampipes-rest/src/main/java/org/apache/streampipes/rest/impl/datalake/DataLakeMeasureResource.java
+++
b/streampipes-rest/src/main/java/org/apache/streampipes/rest/impl/datalake/DataLakeMeasureResource.java
@@ -115,6 +115,7 @@ public class DataLakeMeasureResource extends
AbstractAuthGuardedRestResource {
return badRequest();
}
+
@DeleteMapping(path = "{id}", produces = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<?> deleteDataLakeMeasure(@PathVariable("id") String
elementId) {
try {
diff --git
a/streampipes-rest/src/main/java/org/apache/streampipes/rest/impl/datalake/DataLakeResource.java
b/streampipes-rest/src/main/java/org/apache/streampipes/rest/impl/datalake/DataLakeResource.java
index 296653909c..66ffa2a82d 100644
---
a/streampipes-rest/src/main/java/org/apache/streampipes/rest/impl/datalake/DataLakeResource.java
+++
b/streampipes-rest/src/main/java/org/apache/streampipes/rest/impl/datalake/DataLakeResource.java
@@ -25,6 +25,7 @@ import
org.apache.streampipes.dataexplorer.export.OutputFormat;
import org.apache.streampipes.dataexplorer.management.DataExplorerDispatcher;
import org.apache.streampipes.model.datalake.DataLakeMeasure;
import org.apache.streampipes.model.datalake.DataSeries;
+import org.apache.streampipes.model.datalake.RetentionTimeConfig;
import org.apache.streampipes.model.datalake.SpQueryResult;
import org.apache.streampipes.model.datalake.param.ProvidedRestQueryParams;
import org.apache.streampipes.model.message.Notifications;
@@ -400,6 +401,32 @@ public class DataLakeResource extends AbstractRestResource
{
return SUPPORTED_PARAMS.containsAll(providedParams.keySet());
}
+ @PostMapping(
+ path = "/{elementId}/cleanup",
+ produces = MediaType.APPLICATION_JSON_VALUE,
+ consumes = MediaType.APPLICATION_JSON_VALUE)
+ @Operation(summary = "Sets the retention mechanism for a certain
measurement", tags = {"Data Lake"},
+ responses = {
+ @ApiResponse(
+ responseCode = "400",
+ description = "Can't store the given data to this data lake"),
+ @ApiResponse(
+ responseCode = "200",
+ description = "Successfully stored data")})
+ public ResponseEntity<?> setDataLakeRetention(
+ @PathVariable String elementId,
+ @RequestBody RetentionTimeConfig retention){
+ var measure = this.dataExplorerSchemaManagement.getById(elementId);
+ measure.setRetentionTime(retention);
+ try {
+ this.dataExplorerSchemaManagement.updateMeasurement(measure);
+ } catch (IllegalArgumentException e) {
+ return badRequest(e.getMessage());
+ }
+
+ return ok();
+ }
+
private ProvidedRestQueryParams populate(String measurementId, Map<String,
String> rawParams) {
Map<String, String> queryParamMap = new HashMap<>();
rawParams.forEach((key, value) -> queryParamMap.put(key, String.join(",",
value)));
diff --git
a/streampipes-service-core/src/main/java/org/apache/streampipes/service/core/StreamPipesCoreApplication.java
b/streampipes-service-core/src/main/java/org/apache/streampipes/service/core/StreamPipesCoreApplication.java
index 635d98aed9..d3bc1a37db 100644
---
a/streampipes-service-core/src/main/java/org/apache/streampipes/service/core/StreamPipesCoreApplication.java
+++
b/streampipes-service-core/src/main/java/org/apache/streampipes/service/core/StreamPipesCoreApplication.java
@@ -56,6 +56,7 @@ import
org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
+import org.springframework.scheduling.annotation.EnableScheduling;
import jakarta.annotation.PostConstruct;
import jakarta.annotation.PreDestroy;
@@ -67,6 +68,7 @@ import java.util.concurrent.TimeUnit;
@Configuration
@EnableAutoConfiguration
+@EnableScheduling
@Import({
OpenApiConfiguration.class,
SpPermissionEvaluator.class,
@@ -77,7 +79,8 @@ import java.util.concurrent.TimeUnit;
})
@ComponentScan({
"org.apache.streampipes.rest.*",
- "org.apache.streampipes.service.core.oauth2"
+ "org.apache.streampipes.service.core.oauth2",
+ "org.apache.streampipes.service.core.scheduler"
})
public class StreamPipesCoreApplication extends StreamPipesServiceBase {
diff --git
a/streampipes-service-core/src/main/java/org/apache/streampipes/service/core/scheduler/DataLakeScheduler.java
b/streampipes-service-core/src/main/java/org/apache/streampipes/service/core/scheduler/DataLakeScheduler.java
new file mode 100644
index 0000000000..a351d9c416
--- /dev/null
+++
b/streampipes-service-core/src/main/java/org/apache/streampipes/service/core/scheduler/DataLakeScheduler.java
@@ -0,0 +1,75 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.streampipes.service.core.scheduler;
+
+import org.apache.streampipes.dataexplorer.api.IDataExplorerQueryManagement;
+import org.apache.streampipes.dataexplorer.api.IDataExplorerSchemaManagement;
+import org.apache.streampipes.dataexplorer.management.DataExplorerDispatcher;
+import org.apache.streampipes.model.datalake.DataLakeMeasure;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.scheduling.annotation.Scheduled;
+import org.springframework.stereotype.Component;
+
+import java.time.Instant;
+import java.time.temporal.ChronoUnit;
+import java.util.List;
+
+
+@Component
+public class DataLakeScheduler {
+
+ private static final Logger LOG =
LoggerFactory.getLogger(DataLakeScheduler.class);
+
+ private final IDataExplorerSchemaManagement dataExplorerSchemaManagement =
new DataExplorerDispatcher()
+ .getDataExplorerManager()
+ .getSchemaManagement();
+
+ private final IDataExplorerQueryManagement dataExplorerQueryManagement =
new DataExplorerDispatcher()
+ .getDataExplorerManager()
+ .getQueryManagement(this.dataExplorerSchemaManagement);
+
+ public void exportMeasurements() {
+ // Method body is empty; add functionality as needed
+ }
+
+ public void deleteMeasurements(DataLakeMeasure m) {
+ Instant now = Instant.now();
+ Instant daysAgo =
now.minus(m.getRetentionTime().dataRetentionConfig().olderThanDays(),
ChronoUnit.DAYS);
+
+ long endDate = daysAgo.toEpochMilli();
+ LOG.info("Current time in millis: " + now.toEpochMilli());
+ LOG.info("Current time in millis to delete: " + endDate);
+
+ this.dataExplorerQueryManagement.deleteData(m.getMeasureName(), null,
endDate);
+ }
+
+ @Scheduled(cron = "0 1 0 * * 6") // CronJob Scheduled every Saturday (5)
00:01
+ public void cleanupMeasurements() {
+ List<DataLakeMeasure> allMeasurements =
this.dataExplorerSchemaManagement.getAllMeasurements();
+ LOG.info("GET ALL Measurements");
+ for (DataLakeMeasure m : allMeasurements) {
+ if (m.getRetentionTime() != null) {
+ LOG.info("Start delete Measurement " + m.getMeasureName());
+ deleteMeasurements(m);
+ LOG.info("Measurements " + m.getMeasureName() + " successfully
deleted");
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git
a/ui/projects/streampipes/platform-services/src/lib/apis/datalake-rest.service.ts
b/ui/projects/streampipes/platform-services/src/lib/apis/datalake-rest.service.ts
index 9b865257cd..f95c0584b6 100644
---
a/ui/projects/streampipes/platform-services/src/lib/apis/datalake-rest.service.ts
+++
b/ui/projects/streampipes/platform-services/src/lib/apis/datalake-rest.service.ts
@@ -22,6 +22,7 @@ import {
HttpContext,
HttpParams,
HttpRequest,
+ HttpHeaders,
} from '@angular/common/http';
import { Observable, of } from 'rxjs';
import { DataLakeMeasure, SpQueryResult } from
'../model/gen/streampipes-model';
@@ -153,6 +154,21 @@ export class DatalakeRestService {
return this.buildDownloadRequest(index, qp);
}
+ cleanup(index: string, config: any) {
+ console.log('cleanup');
+ console.log(config);
+
+ const url = `${this.dataLakeUrl}/${index}/cleanup`;
+
+ const request = new HttpRequest('POST', url, config, {
+ headers: new HttpHeaders({ 'Content-Type': 'application/json' }),
// optional if already handled globally
+ });
+
+ console.log(request);
+
+ return this.http.request(request);
+ }
+
buildDownloadRequest(index: string, queryParams: any) {
const url = this.dataLakeUrl + '/measurements/' + index + '/download';
const request = new HttpRequest('GET', url, {
diff --git
a/ui/projects/streampipes/platform-services/src/lib/model/gen/streampipes-model.ts
b/ui/projects/streampipes/platform-services/src/lib/model/gen/streampipes-model.ts
index 7c6b3efd8f..b8c3b053f8 100644
---
a/ui/projects/streampipes/platform-services/src/lib/model/gen/streampipes-model.ts
+++
b/ui/projects/streampipes/platform-services/src/lib/model/gen/streampipes-model.ts
@@ -21,7 +21,6 @@
/* eslint-disable */
// @ts-nocheck
// Generated using typescript-generator version 3.2.1263 on 2025-08-27
21:55:36.
-
export class NamedStreamPipesEntity implements Storable {
'@class':
| 'org.apache.streampipes.model.SpDataStream'
@@ -1243,6 +1242,7 @@ export class DataLakeMeasure implements Storable {
'pipelineId': string;
'pipelineIsRunning': boolean;
'pipelineName': string;
+ 'retentionTime': RetentionTimeConfig;
'rev': string;
'schemaUpdateStrategy': DataLakeMeasureSchemaUpdateStrategy;
'schemaVersion': string;
@@ -1263,6 +1263,9 @@ export class DataLakeMeasure implements Storable {
instance.pipelineId = data.pipelineId;
instance.pipelineIsRunning = data.pipelineIsRunning;
instance.pipelineName = data.pipelineName;
+ instance.retentionTime = RetentionTimeConfig.fromData(
+ data.retentionTime,
+ );
instance.rev = data.rev;
instance.schemaUpdateStrategy = data.schemaUpdateStrategy;
instance.schemaVersion = data.schemaVersion;
@@ -1371,6 +1374,26 @@ export class DataProcessorType {
}
}
+export class DataRetentionConfig {
+ action: RetentionAction;
+ interval: RetentionInterval;
+ olderThanDays: number;
+
+ static fromData(
+ data: DataRetentionConfig,
+ target?: DataRetentionConfig,
+ ): DataRetentionConfig {
+ if (!data) {
+ return data;
+ }
+ const instance = target || new DataRetentionConfig();
+ instance.action = data.action;
+ instance.interval = data.interval;
+ instance.olderThanDays = data.olderThanDays;
+ return instance;
+ }
+}
+
export class DataSeries {
headers: string[];
rows: any[][];
@@ -3295,6 +3318,24 @@ export class ResourceMetadata {
}
}
+export class RetentionTimeConfig {
+ dataRetentionConfig: DataRetentionConfig;
+
+ static fromData(
+ data: RetentionTimeConfig,
+ target?: RetentionTimeConfig,
+ ): RetentionTimeConfig {
+ if (!data) {
+ return data;
+ }
+ const instance = target || new RetentionTimeConfig();
+ instance.dataRetentionConfig = DataRetentionConfig.fromData(
+ data.dataRetentionConfig,
+ );
+ return instance;
+ }
+}
+
export class RuntimeOptionsRequest {
'@class':
| 'org.apache.streampipes.model.runtime.RuntimeOptionsRequest'
@@ -4200,6 +4241,10 @@ export type PropertyScope =
| 'MEASUREMENT_PROPERTY'
| 'NONE';
+export type RetentionAction = 'DELETE' | 'SAVE' | 'SAVEDELETE';
+
+export type RetentionInterval = 'DAILY' | 'MONTHLY' | 'WEEKLY';
+
export type SelectionStaticPropertyUnion =
| AnyStaticProperty
| OneOfStaticProperty;
diff --git a/ui/src/app/configuration/configuration.module.ts
b/ui/src/app/configuration/configuration.module.ts
index 9b1bfd1cff..ce72c85a36 100644
--- a/ui/src/app/configuration/configuration.module.ts
+++ b/ui/src/app/configuration/configuration.module.ts
@@ -105,7 +105,11 @@ import { CertificateDetailsDialogComponent } from
'./dialog/certificate-details/
import { AlternateIdConfigurationComponent } from
'./security-configuration/alternate-id-configuration/alternate-id-configuration.component';
import { UserAcknowledgmentComponent } from
'./general-configuration/user-acknowledgement/user-acknowledgment.component';
import { QuillEditorComponent } from 'ngx-quill';
-
+import { MatStepperModule } from '@angular/material/stepper';
+import { DataRetentionDialogComponent } from
'./dialog/data-retention-dialog/data-retention-dialog.component';
+import { SelectDataComponent } from
'./dialog/data-retention-dialog/components/select-retention/select-data.component';
+import { SelectDataRetentionComponent } from
'./dialog/data-retention-dialog/components/select-retention/select-data-retention/select-data-retention.component';
+import { SelectRetentionActionComponent } from
'./dialog/data-retention-dialog/components/select-retention/select-retention-action/select-retention-action.component';
@NgModule({
imports: [
CommonModule,
@@ -204,6 +208,7 @@ import { QuillEditorComponent } from 'ngx-quill';
MatSort,
MatListModule,
MatDialogModule,
+ MatStepperModule,
TranslateModule.forChild({}),
QuillEditorComponent,
],
@@ -253,7 +258,7 @@ import { QuillEditorComponent } from 'ngx-quill';
SpMessagingBrokerConfigComponent,
SpRegisteredExtensionsServiceComponent,
SpExtensionsServiceConfigurationComponent,
-
+ DataRetentionDialogComponent,
SpExtensionsInstallationComponent,
SpExtensionsInstallationDialogComponent,
EndpointItemComponent,
@@ -265,6 +270,9 @@ import { QuillEditorComponent } from 'ngx-quill';
CertificateDetailsDialogComponent,
AlternateIdConfigurationComponent,
UserAcknowledgmentComponent,
+ SelectDataComponent,
+ SelectDataRetentionComponent,
+ SelectRetentionActionComponent,
],
providers: [
OrderByPipe,
diff --git
a/ui/src/app/configuration/datalake-configuration/datalake-configuration-entry.ts
b/ui/src/app/configuration/datalake-configuration/datalake-configuration-entry.ts
index 4c8c9b71dc..545d12a72d 100644
---
a/ui/src/app/configuration/datalake-configuration/datalake-configuration-entry.ts
+++
b/ui/src/app/configuration/datalake-configuration/datalake-configuration-entry.ts
@@ -1,3 +1,6 @@
+import { RetentionTimeConfig } from '@streampipes/platform-services';
+import { RetentionConfig } from
'../dialog/data-retention-dialog/model/retention-config.model';
+
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
@@ -20,6 +23,8 @@ export class DataLakeConfigurationEntry {
public pipelines: string[] = [];
public events = 0;
public remove = true;
+ public elementId: string;
+ public retention: RetentionTimeConfig;
constructor() {}
}
diff --git
a/ui/src/app/configuration/datalake-configuration/datalake-configuration.component.html
b/ui/src/app/configuration/datalake-configuration/datalake-configuration.component.html
index 5044fd3091..ee6a7afaac 100644
---
a/ui/src/app/configuration/datalake-configuration/datalake-configuration.component.html
+++
b/ui/src/app/configuration/datalake-configuration/datalake-configuration.component.html
@@ -202,6 +202,45 @@
</td>
</ng-container>
+ <ng-container matColumnDef="retention">
+ <th mat-header-cell *matHeaderCellDef>
+ Retention Rate
+ </th>
+ <td mat-cell *matCellDef="let configurationEntry">
+ <div fxLayout="row">
+ <span
+ fxFlex
+ fxFlexOrder="3"
+ fxLayout="row"
+ fxLayoutAlign="start center"
+ >
+ <button
+ color="accent"
+ mat-icon-button
+ matTooltip="Set retention rate"
+ data-cy="datalake-retention-btn"
+ matTooltipPosition="above"
+ (click)="
+ openRetentionDialog(
+
configurationEntry.elementId
+ )
+ "
+ >
+ <i
+ class="material-icons"
+ [ngStyle]="{
+ color:
configurationEntry?.retention
+ ? 'green'
+ : 'red'
+ }"
+ >history</i
+ >
+ </button>
+ </span>
+ </div>
+ </td>
+ </ng-container>
+
<tr
mat-header-row
*matHeaderRowDef="displayedColumns"
diff --git
a/ui/src/app/configuration/datalake-configuration/datalake-configuration.component.ts
b/ui/src/app/configuration/datalake-configuration/datalake-configuration.component.ts
index d73bf0b44c..389e24ca17 100644
---
a/ui/src/app/configuration/datalake-configuration/datalake-configuration.component.ts
+++
b/ui/src/app/configuration/datalake-configuration/datalake-configuration.component.ts
@@ -36,7 +36,7 @@ import {
import { DeleteDatalakeIndexComponent } from
'../dialog/delete-datalake-index/delete-datalake-index-dialog.component';
import { SpConfigurationTabsService } from '../configuration-tabs.service';
import { SpConfigurationRoutes } from '../configuration.routes';
-
+import { DataRetentionDialogComponent } from
'../dialog/data-retention-dialog/data-retention-dialog.component';
@Component({
selector: 'sp-datalake-configuration',
templateUrl: './datalake-configuration.component.html',
@@ -60,6 +60,7 @@ export class DatalakeConfigurationComponent implements OnInit
{
'download',
'truncate',
'remove',
+ 'retention',
];
pageSize = 15;
@@ -94,8 +95,12 @@ export class DatalakeConfigurationComponent implements
OnInit {
.subscribe(inUseMeasurements => {
allMeasurements.forEach(measurement => {
const entry = new DataLakeConfigurationEntry();
+ entry.elementId = measurement.elementId;
entry.name = measurement.measureName;
entry.events = -1;
+ if (measurement?.retentionTime != null) {
+ entry.retention = measurement.retentionTime;
+ }
inUseMeasurements.forEach(inUseMeasurement => {
if (
inUseMeasurement.measureName ===
@@ -176,6 +181,20 @@ export class DatalakeConfigurationComponent implements
OnInit {
});
}
+ openRetentionDialog(measurementId: string) {
+ this.dialogService.open(DataRetentionDialogComponent, {
+ panelType: PanelType.SLIDE_IN_PANEL,
+ title: 'Set Data Retention',
+ width: '50vw',
+ data: {
+ dataRetentionDialogModel: {
+ measureName: measurementId,
+ },
+ measurementIndex: measurementId,
+ },
+ });
+ }
+
onPageChange(event: any) {
this.pageIndex = event.pageIndex;
this.receiveMeasurementSizes(this.pageIndex);
diff --git
a/ui/src/app/configuration/dialog/data-retention-dialog/components/select-export/select-format.component.html
b/ui/src/app/configuration/dialog/data-retention-dialog/components/select-export/select-format.component.html
new file mode 100644
index 0000000000..e2b580dc08
--- /dev/null
+++
b/ui/src/app/configuration/dialog/data-retention-dialog/components/select-export/select-format.component.html
@@ -0,0 +1,20 @@
+<!--
+ ~ Licensed to the Apache Software Foundation (ASF) under one or more
+ ~ contributor license agreements. See the NOTICE file distributed with
+ ~ this work for additional information regarding copyright ownership.
+ ~ The ASF licenses this file to You under the Apache License, Version 2.0
+ ~ (the "License"); you may not use this file except in compliance with
+ ~ the License. You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ ~
+ -->
+
+<ng-template matStepLabel>{{ 'Set Backup Options' | translate }}</ng-template>
+<div>BACKUP Steps</div>
diff --git
a/ui/src/app/configuration/dialog/data-retention-dialog/components/select-export/select-format.component.scss
b/ui/src/app/configuration/dialog/data-retention-dialog/components/select-export/select-format.component.scss
new file mode 100644
index 0000000000..2b53bbd279
--- /dev/null
+++
b/ui/src/app/configuration/dialog/data-retention-dialog/components/select-export/select-format.component.scss
@@ -0,0 +1,17 @@
+/*!
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
diff --git
a/ui/src/app/configuration/dialog/data-retention-dialog/components/select-export/select-format.component.ts
b/ui/src/app/configuration/dialog/data-retention-dialog/components/select-export/select-format.component.ts
new file mode 100644
index 0000000000..a743572742
--- /dev/null
+++
b/ui/src/app/configuration/dialog/data-retention-dialog/components/select-export/select-format.component.ts
@@ -0,0 +1,56 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+import { Component, inject, Input, OnInit } from '@angular/core';
+import { FormatExportConfig } from '../../model/format-export-config.model';
+import { FileMetadata, FilesService } from '@streampipes/platform-services';
+import { CurrentUserService } from '../../../../services/current-user.service';
+
+@Component({
+ selector: 'sp-select-format',
+ templateUrl: './select-format.component.html',
+ styleUrls: [
+ './select-format.component.scss',
+ '../../data-download-dialog.component.scss',
+ ],
+ standalone: false,
+})
+export class SelectFormatComponent implements OnInit {
+ @Input() formatExportConfig: FormatExportConfig;
+
+ hasReadFilePrivilege = false;
+ excelTemplates: FileMetadata[] = [];
+
+ private fileService = inject(FilesService);
+ private currentUserService = inject(CurrentUserService);
+
+ constructor() {}
+
+ ngOnInit() {
+ this.hasReadFilePrivilege = this.currentUserService.hasRole(
+ 'PRIVILEGE_READ_FILES',
+ );
+ if (this.hasReadFilePrivilege) {
+ this.fileService
+ .getFileMetadata(['xlsx'])
+ .subscribe(excelTemplates => {
+ this.excelTemplates = excelTemplates;
+ });
+ }
+ }
+}
diff --git
a/ui/src/app/configuration/dialog/data-retention-dialog/components/select-retention/select-data-retention/select-data-retention.component.html
b/ui/src/app/configuration/dialog/data-retention-dialog/components/select-retention/select-data-retention/select-data-retention.component.html
new file mode 100644
index 0000000000..6107805927
--- /dev/null
+++
b/ui/src/app/configuration/dialog/data-retention-dialog/components/select-retention/select-data-retention/select-data-retention.component.html
@@ -0,0 +1,33 @@
+<!--
+ ~ Licensed to the Apache Software Foundation (ASF) under one or more
+ ~ contributor license agreements. See the NOTICE file distributed with
+ ~ this work for additional information regarding copyright ownership.
+ ~ The ASF licenses this file to You under the Apache License, Version 2.0
+ ~ (the "License"); you may not use this file except in compliance with
+ ~ the License. You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ ~
+ -->
+
+<sp-configuration-box [title]="'Data Retention Intervals' | translate">
+ <div>
+ <mat-form-field appearance="fill">
+ <mat-label>Everything older than </mat-label>
+ <input
+ matInput
+ type="number"
+ [(ngModel)]="dataRetentionConfig.olderThanDays"
+ min="1"
+ step="1"
+ />
+ <span matSuffix>days</span>
+ </mat-form-field>
+ </div>
+</sp-configuration-box>
diff --git
a/ui/src/app/configuration/dialog/data-retention-dialog/components/select-retention/select-data-retention/select-data-retention.component.scss
b/ui/src/app/configuration/dialog/data-retention-dialog/components/select-retention/select-data-retention/select-data-retention.component.scss
new file mode 100644
index 0000000000..9f7a0894d7
--- /dev/null
+++
b/ui/src/app/configuration/dialog/data-retention-dialog/components/select-retention/select-data-retention/select-data-retention.component.scss
@@ -0,0 +1,21 @@
+/*!
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+.ml-35 {
+ margin-left: 35px;
+}
diff --git
a/ui/src/app/configuration/dialog/data-retention-dialog/components/select-retention/select-data-retention/select-data-retention.component.ts
b/ui/src/app/configuration/dialog/data-retention-dialog/components/select-retention/select-data-retention/select-data-retention.component.ts
new file mode 100644
index 0000000000..2f3fc07055
--- /dev/null
+++
b/ui/src/app/configuration/dialog/data-retention-dialog/components/select-retention/select-data-retention/select-data-retention.component.ts
@@ -0,0 +1,38 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+import { Component, Input, OnInit } from '@angular/core';
+import {
+ DataExplorerDataConfig,
+ DateRange,
+} from '@streampipes/platform-services';
+import { DataRetentionConfig } from
'../../../model/data-retention-config.model';
+
+@Component({
+ selector: 'sp-select-data-retention',
+ templateUrl: './select-data-retention.component.html',
+ styleUrls: [
+ './select-data-retention.component.scss',
+ // '../select-data.component.scss',
+ ],
+ standalone: false,
+})
+export class SelectDataRetentionComponent {
+ @Input() dataExplorerDataConfig: DataExplorerDataConfig;
+ @Input() dataRetentionConfig: DataRetentionConfig;
+}
diff --git
a/ui/src/app/configuration/dialog/data-retention-dialog/components/select-retention/select-data.component.html
b/ui/src/app/configuration/dialog/data-retention-dialog/components/select-retention/select-data.component.html
new file mode 100644
index 0000000000..d18a46abb6
--- /dev/null
+++
b/ui/src/app/configuration/dialog/data-retention-dialog/components/select-retention/select-data.component.html
@@ -0,0 +1,31 @@
+<!--
+ ~ Licensed to the Apache Software Foundation (ASF) under one or more
+ ~ contributor license agreements. See the NOTICE file distributed with
+ ~ this work for additional information regarding copyright ownership.
+ ~ The ASF licenses this file to You under the Apache License, Version 2.0
+ ~ (the "License"); you may not use this file except in compliance with
+ ~ the License. You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ ~
+ -->
+
+<div class="mt-10">
+ <sp-select-data-retention
+ [dataExplorerDataConfig]="dataExplorerDataConfig"
+ [dataRetentionConfig]="dataRetentionConfig"
+ >
+ </sp-select-data-retention>
+
+ <sp-select-retention-action
+ [dataExplorerDataConfig]="dataExplorerDataConfig"
+ [dataRetentionConfig]="dataRetentionConfig"
+ >
+ </sp-select-retention-action>
+</div>
diff --git
a/ui/src/app/configuration/dialog/data-retention-dialog/components/select-retention/select-data.component.scss
b/ui/src/app/configuration/dialog/data-retention-dialog/components/select-retention/select-data.component.scss
new file mode 100644
index 0000000000..952aff0e3e
--- /dev/null
+++
b/ui/src/app/configuration/dialog/data-retention-dialog/components/select-retention/select-data.component.scss
@@ -0,0 +1,33 @@
+/*!
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+.sp-radio-group {
+ display: flex;
+ flex-direction: column;
+ margin: 15px 0;
+}
+
+.sp-radio-button {
+ margin: 5px;
+ width: 100%;
+}
+
+.form-field-date {
+ top: -10px;
+ width: 300px;
+}
diff --git
a/ui/src/app/configuration/dialog/data-retention-dialog/components/select-retention/select-data.component.ts
b/ui/src/app/configuration/dialog/data-retention-dialog/components/select-retention/select-data.component.ts
new file mode 100644
index 0000000000..6c0743e361
--- /dev/null
+++
b/ui/src/app/configuration/dialog/data-retention-dialog/components/select-retention/select-data.component.ts
@@ -0,0 +1,41 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+import { Component, Input } from '@angular/core';
+
+import { DataRetentionConfig } from '../../model/data-retention-config.model';
+import { DataExplorerDataConfig } from '@streampipes/platform-services';
+
+@Component({
+ selector: 'sp-select-data',
+ templateUrl: './select-data.component.html',
+ styleUrls: ['./select-data.component.scss'],
+ standalone: false,
+})
+export class SelectDataComponent {
+ /**
+ * Contains the measurement and date range for a selected data widget
+ * This value is not required
+ */
+ @Input() dataExplorerDataConfig: DataExplorerDataConfig;
+
+ /**
+ * Represents the user configurations for the download
+ */
+ @Input() dataRetentionConfig: DataRetentionConfig;
+}
diff --git
a/ui/src/app/configuration/dialog/data-retention-dialog/components/select-retention/select-retention-action/select-retention-action.component.html
b/ui/src/app/configuration/dialog/data-retention-dialog/components/select-retention/select-retention-action/select-retention-action.component.html
new file mode 100644
index 0000000000..75a1af8b1e
--- /dev/null
+++
b/ui/src/app/configuration/dialog/data-retention-dialog/components/select-retention/select-retention-action/select-retention-action.component.html
@@ -0,0 +1,47 @@
+<!--
+ ~ Licensed to the Apache Software Foundation (ASF) under one or more
+ ~ contributor license agreements. See the NOTICE file distributed with
+ ~ this work for additional information regarding copyright ownership.
+ ~ The ASF licenses this file to You under the Apache License, Version 2.0
+ ~ (the "License"); you may not use this file except in compliance with
+ ~ the License. You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ ~
+ -->
+
+<sp-configuration-box [title]="'Data Retention Action' | translate">
+ <mat-form-field appearance="fill" class="sp-select-field">
+ <mat-label>{{ 'Select Action' | translate }}</mat-label>
+ <mat-select
+ [(ngModel)]="dataRetentionConfig.action"
+ data-cy="retention-action-select"
+ >
+ <mat-option value="DELETE" data-cy="action-configuration-delete">
+ {{ 'delete' | translate }}
+ </mat-option>
+
+ <mat-option
+ value="SAVE"
+ disabled
+ data-cy="retention-configuration-save"
+ >
+ {{ 'save' | translate }}
+ </mat-option>
+
+ <mat-option
+ value="SAVEDELETE"
+ disabled
+ data-cy="retention-configuration-save-delete"
+ >
+ {{ 'save and delete' | translate }}
+ </mat-option>
+ </mat-select>
+ </mat-form-field>
+</sp-configuration-box>
diff --git
a/ui/src/app/configuration/dialog/data-retention-dialog/components/select-retention/select-retention-action/select-retention-action.component.scss
b/ui/src/app/configuration/dialog/data-retention-dialog/components/select-retention/select-retention-action/select-retention-action.component.scss
new file mode 100644
index 0000000000..9f7a0894d7
--- /dev/null
+++
b/ui/src/app/configuration/dialog/data-retention-dialog/components/select-retention/select-retention-action/select-retention-action.component.scss
@@ -0,0 +1,21 @@
+/*!
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+.ml-35 {
+ margin-left: 35px;
+}
diff --git
a/ui/src/app/configuration/dialog/data-retention-dialog/components/select-retention/select-retention-action/select-retention-action.component.ts
b/ui/src/app/configuration/dialog/data-retention-dialog/components/select-retention/select-retention-action/select-retention-action.component.ts
new file mode 100644
index 0000000000..30a7041aa3
--- /dev/null
+++
b/ui/src/app/configuration/dialog/data-retention-dialog/components/select-retention/select-retention-action/select-retention-action.component.ts
@@ -0,0 +1,35 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+import { Component, Input, OnInit } from '@angular/core';
+import {
+ DataExplorerDataConfig,
+ DateRange,
+} from '@streampipes/platform-services';
+import { DataRetentionConfig } from
'../../../model/data-retention-config.model';
+
+@Component({
+ selector: 'sp-select-retention-action',
+ templateUrl: './select-retention-action.component.html',
+ styleUrls: ['./select-retention-action.component.scss'],
+ standalone: false,
+})
+export class SelectRetentionActionComponent {
+ @Input() dataExplorerDataConfig: DataExplorerDataConfig;
+ @Input() dataRetentionConfig: DataRetentionConfig;
+}
diff --git
a/ui/src/app/configuration/dialog/data-retention-dialog/data-retention-dialog.component.html
b/ui/src/app/configuration/dialog/data-retention-dialog/data-retention-dialog.component.html
new file mode 100644
index 0000000000..d61cdf86db
--- /dev/null
+++
b/ui/src/app/configuration/dialog/data-retention-dialog/data-retention-dialog.component.html
@@ -0,0 +1,59 @@
+<!--
+ ~ Licensed to the Apache Software Foundation (ASF) under one or more
+ ~ contributor license agreements. See the NOTICE file distributed with
+ ~ this work for additional information regarding copyright ownership.
+ ~ The ASF licenses this file to You under the Apache License, Version 2.0
+ ~ (the "License"); you may not use this file except in compliance with
+ ~ the License. You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ ~
+ -->
+
+<div class="sp-dialog-container">
+ <div class="sp-dialog-content p-15">
+ <div fxFlex="100">
+ <!-- Stepper removed, content displayed directly -->
+ <div
+ class="retention-step-content"
+ *ngIf="retentionConfig?.dataRetentionConfig"
+ >
+ <sp-select-data
+ [dataExplorerDataConfig]="
+ dataRetentionDialogModel.dataExplorerDataConfig
+ "
+ [dataRetentionConfig]="retentionConfig.dataRetentionConfig"
+ >
+ </sp-select-data>
+ </div>
+ </div>
+ </div>
+
+ <div class="sp-dialog-actions actions-align-right">
+ <button
+ mat-button
+ mat-raised-button
+ class="mat-basic"
+ style="margin-right: 10px"
+ (click)="exitDialog()"
+ >
+ {{ 'Close' | translate }}
+ </button>
+
+ <button
+ mat-button
+ mat-raised-button
+ color="accent"
+ data-cy="download-configuration-download-btn"
+ (click)="setCleanUp()"
+ >
+ {{ 'Start Sync' | translate }}
+ </button>
+ </div>
+</div>
diff --git
a/ui/src/app/configuration/dialog/data-retention-dialog/data-retention-dialog.component.scss
b/ui/src/app/configuration/dialog/data-retention-dialog/data-retention-dialog.component.scss
new file mode 100644
index 0000000000..db27d964b7
--- /dev/null
+++
b/ui/src/app/configuration/dialog/data-retention-dialog/data-retention-dialog.component.scss
@@ -0,0 +1,75 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+.sp-radio-group {
+ display: flex;
+ flex-direction: column;
+ margin: 15px 0;
+}
+.sp-radio-button {
+ margin: 5px;
+ width: 100%;
+}
+
+mat-toolbar {
+ background: #39b54a;
+ color: white;
+}
+
+mat-dialog-content {
+ padding: 24px;
+ -webkit-box-ordinal-group: 2;
+ -webkit-order: 1;
+ order: 1;
+ -webkit-box-orient: vertical;
+ -webkit-box-direction: normal;
+ -webkit-flex-direction: column;
+ flex-direction: column;
+ overflow: auto;
+ -webkit-overflow-scrolling: touch;
+}
+
+.mat-dialog-content {
+ width: 100%;
+ height: 74%;
+ margin: 0;
+}
+
+.mat-dialog-actions {
+ margin-bottom: 0px;
+ padding-right: 10px;
+}
+
+.ml-35 {
+ margin-left: 35px;
+}
+
+.mt-35 {
+ margin-top: 35px;
+}
+
+.event-color {
+ color: #e0e0e0;
+}
+
+.icon-check {
+ font-size: 100px;
+ height: 100px;
+ width: 100px;
+ color: #b3b3b3;
+}
diff --git
a/ui/src/app/configuration/dialog/data-retention-dialog/data-retention-dialog.component.ts
b/ui/src/app/configuration/dialog/data-retention-dialog/data-retention-dialog.component.ts
new file mode 100644
index 0000000000..f3a56621fb
--- /dev/null
+++
b/ui/src/app/configuration/dialog/data-retention-dialog/data-retention-dialog.component.ts
@@ -0,0 +1,84 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+import { Component, Input, OnInit, ViewChild } from '@angular/core';
+import { DialogRef } from '@streampipes/shared-ui';
+import { DataRetentionDialogModel } from './model/data-retention-dialog.model';
+import {
+ DatalakeRestService,
+ RetentionTimeConfig,
+} from '@streampipes/platform-services';
+
+@Component({
+ selector: 'sp-data-retention-dialog',
+ templateUrl: 'data-retention-dialog.component.html',
+ styleUrls: ['./data-retention-dialog.component.scss'],
+ standalone: false,
+})
+export class DataRetentionDialogComponent implements OnInit {
+ @Input() dataRetentionDialogModel: DataRetentionDialogModel;
+
+ @Input()
+ retentionConfig: RetentionTimeConfig;
+
+ @Input()
+ measurementIndex: string;
+
+ constructor(
+ public dialogRef: DialogRef<DataRetentionDialogComponent>,
+ private datalakeRestService: DatalakeRestService,
+ ) {}
+
+ ngOnInit() {
+ this.datalakeRestService
+ .getMeasurement(this.measurementIndex)
+ .subscribe({
+ next: measure => {
+ if (measure.retentionTime != null) {
+ this.retentionConfig ??= measure.retentionTime;
+ } else {
+ this.retentionConfig ??= RetentionTimeConfig.fromData({
+ dataRetentionConfig: {
+ olderThanDays: 30,
+ interval: 'DAILY',
+ },
+ } as RetentionTimeConfig);
+ }
+ },
+ error: err => {
+ console.error('Error loading measurement:', err);
+ },
+ });
+ }
+
+ exitDialog() {
+ this.dialogRef.close();
+ }
+
+ close(refreshDataLakeIndex: boolean) {
+ this.dialogRef.close(refreshDataLakeIndex);
+ }
+
+ setCleanUp() {
+ this.datalakeRestService
+ .cleanup(this.measurementIndex, this.retentionConfig)
+ .subscribe(data => {
+ this.close(true);
+ });
+ }
+}
diff --git
a/ui/src/app/configuration/dialog/data-retention-dialog/model/data-retention-config.model.ts
b/ui/src/app/configuration/dialog/data-retention-dialog/model/data-retention-config.model.ts
new file mode 100644
index 0000000000..50b81045e6
--- /dev/null
+++
b/ui/src/app/configuration/dialog/data-retention-dialog/model/data-retention-config.model.ts
@@ -0,0 +1,24 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+export interface DataRetentionConfig {
+ olderThanDays: number;
+ interval?: 'DAILY' | 'MONTHLY';
+ measurement?: string;
+ action?: 'delete' | 'save' | 'save and delete';
+}
diff --git
a/ui/src/app/configuration/dialog/data-retention-dialog/model/data-retention-dialog.model.ts
b/ui/src/app/configuration/dialog/data-retention-dialog/model/data-retention-dialog.model.ts
new file mode 100644
index 0000000000..ac44f2ee84
--- /dev/null
+++
b/ui/src/app/configuration/dialog/data-retention-dialog/model/data-retention-dialog.model.ts
@@ -0,0 +1,28 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+import {
+ DataExplorerDataConfig,
+ DateRange,
+} from '@streampipes/platform-services';
+
+export interface DataRetentionDialogModel {
+ measureName?: string;
+
+ dataExplorerDateRange?: DateRange;
+ dataExplorerDataConfig?: DataExplorerDataConfig;
+}
diff --git
a/ui/src/app/configuration/dialog/data-retention-dialog/model/retention-config.model.ts
b/ui/src/app/configuration/dialog/data-retention-dialog/model/retention-config.model.ts
new file mode 100644
index 0000000000..edff55138d
--- /dev/null
+++
b/ui/src/app/configuration/dialog/data-retention-dialog/model/retention-config.model.ts
@@ -0,0 +1,23 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+import { DataRetentionConfig } from './data-retention-config.model';
+
+export interface RetentionConfig {
+ dataRetentionConfig: DataRetentionConfig;
+ //exportConfig: {};
+}
diff --git
a/ui/src/app/configuration/dialog/data-retention-dialog/model/retention-export-config.model.ts
b/ui/src/app/configuration/dialog/data-retention-dialog/model/retention-export-config.model.ts
new file mode 100644
index 0000000000..aeafbf5a35
--- /dev/null
+++
b/ui/src/app/configuration/dialog/data-retention-dialog/model/retention-export-config.model.ts
@@ -0,0 +1,40 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+export type FormatExportConfig =
+ | JsonFormatExportConfig
+ | CsvFormatExportConfig
+ | ExcelFormatConfig;
+
+export interface JsonFormatExportConfig {
+ format: 'json';
+}
+
+export interface CsvFormatExportConfig {
+ format: 'csv';
+ delimiter: 'comma' | 'semicolon';
+ headerColumnName: 'key' | 'label';
+}
+
+export interface ExcelFormatConfig {
+ format: 'xlsx';
+ templateId: string;
+ startRow: number;
+ useTemplate: boolean;
+ headerColumnName: 'key' | 'label';
+}
diff --git
a/ui/src/app/configuration/dialog/data-retention-dialog/services/data-export.service.ts
b/ui/src/app/configuration/dialog/data-retention-dialog/services/data-export.service.ts
new file mode 100644
index 0000000000..a014ed97f9
--- /dev/null
+++
b/ui/src/app/configuration/dialog/data-retention-dialog/services/data-export.service.ts
@@ -0,0 +1,148 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+import { EventEmitter, Injectable } from '@angular/core';
+import { ExportConfig } from '../model/export-config.model';
+import {
+ DatalakeQueryParameters,
+ DatalakeRestService,
+ DataViewQueryGeneratorService,
+} from '@streampipes/platform-services';
+import { HttpEventType } from '@angular/common/http';
+import { DataDownloadDialogModel } from '../model/data-download-dialog.model';
+import { DownloadProgress } from '../model/download-progress.model';
+import { FileNameService } from './file-name.service';
+
+@Injectable({
+ providedIn: 'root',
+})
+export class DataExportService {
+ public updateDownloadProgress: EventEmitter<DownloadProgress> =
+ new EventEmitter();
+
+ constructor(
+ public dataLakeRestService: DatalakeRestService,
+ public dataViewQueryGeneratorService: DataViewQueryGeneratorService,
+ public fileNameService: FileNameService,
+ ) {}
+
+ public downloadData(
+ exportConfig: ExportConfig,
+ dataDownloadDialogModel: DataDownloadDialogModel,
+ ) {
+ let downloadRequest;
+
+ if (
+ exportConfig.dataExportConfig.dataRangeConfiguration === 'visible'
+ ) {
+ downloadRequest = this.dataLakeRestService.downloadQueriedData(
+ exportConfig.dataExportConfig.measurement,
+ exportConfig.formatExportConfig,
+ exportConfig.dataExportConfig.missingValueBehaviour,
+ this.generateQueryRequest(
+ exportConfig,
+ dataDownloadDialogModel,
+ ),
+ );
+ } else {
+ // case for 'all' and 'customInverval'
+ let startTime,
+ endTime = undefined;
+ if (
+ exportConfig.dataExportConfig.dataRangeConfiguration ===
+ 'customInterval'
+ ) {
+ startTime =
+
exportConfig.dataExportConfig.dateRange.startDate.getTime();
+ endTime =
+ exportConfig.dataExportConfig.dateRange.endDate.getTime();
+ }
+ downloadRequest = this.dataLakeRestService.downloadRawData(
+ exportConfig.dataExportConfig.measurement,
+ exportConfig.formatExportConfig,
+ exportConfig.dataExportConfig.missingValueBehaviour,
+ startTime,
+ endTime,
+ );
+ }
+
+ downloadRequest.subscribe(event => {
+ let downloadProgress: DownloadProgress;
+ // progress
+ if (event.type === HttpEventType.DownloadProgress) {
+ downloadProgress = {
+ downloadedMBs: event.loaded / 1024 / 1014,
+ finished: false,
+ };
+ this.updateDownloadProgress.emit(downloadProgress);
+ }
+
+ // finished
+ if (event.type === HttpEventType.Response) {
+ this.createFile(event.body, exportConfig);
+ downloadProgress = {
+ downloadedMBs: event.loaded / 1024 / 1014,
+ finished: true,
+ };
+ this.updateDownloadProgress.emit(downloadProgress);
+ }
+ });
+ }
+
+ private generateQueryRequest(
+ exportConfig: ExportConfig,
+ dataDownloadDialogModel: DataDownloadDialogModel,
+ selectedQueryIndex: number = 0,
+ ): DatalakeQueryParameters {
+ return this.dataViewQueryGeneratorService.generateQuery(
+ exportConfig.dataExportConfig.dateRange.startDate.getTime(),
+ exportConfig.dataExportConfig.dateRange.endDate.getTime(),
+ dataDownloadDialogModel.dataExplorerDataConfig.sourceConfigs[
+ selectedQueryIndex
+ ],
+ false,
+ );
+ }
+
+ /**
+ * The code in this method can be updated. Currently, it uses a native
approach to download a file.
+ * At other places we use the fileSaver library
(https://www.npmjs.com/package/file-saver) to download files.
+ * However, this library only supports files up to 2GB.
+ * There are other alternatives like StreamSaver.js
(https://github.com/jimmywarting/StreamSaver.js).
+ * But then we probably should replace the fileSaver library with
StreamSaver to only have one dependency.
+ * In the documentation it is also stated that an alternative approach is
under development.
+ * It is probably also worth in looking into this one.
+ */
+ private createFile(data, exportConfig: ExportConfig) {
+ const a = document.createElement('a');
+ document.body.appendChild(a);
+ a.style.display = 'display: none';
+
+ const name = this.fileNameService.generateName(
+ exportConfig,
+ new Date(),
+ );
+ const blob = new Blob([data]);
+
+ const url = window.URL.createObjectURL(blob);
+ a.href = url;
+ a.download = name;
+ a.click();
+ window.URL.revokeObjectURL(url);
+ }
+}
diff --git
a/ui/src/app/configuration/dialog/data-retention-dialog/services/file-name.service.spec.ts
b/ui/src/app/configuration/dialog/data-retention-dialog/services/file-name.service.spec.ts
new file mode 100644
index 0000000000..deef6c48ed
--- /dev/null
+++
b/ui/src/app/configuration/dialog/data-retention-dialog/services/file-name.service.spec.ts
@@ -0,0 +1,118 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+import { ExportConfig } from '../model/export-config.model';
+import { DateRange } from '@streampipes/platform-services';
+import { FileNameService } from './file-name.service';
+
+describe('FileNameService', () => {
+ const service = new FileNameService();
+
+ // Testing data
+ const defaultExportDate = new Date(2022, 11, 11, 3);
+ const defaultStartDate = new Date(2022, 11, 2, 3);
+ const defaultEndDate = new Date(2022, 11, 6, 3);
+ const defaultDateRange = new DateRange(defaultStartDate, defaultEndDate);
+ let defaultExportConfig: ExportConfig;
+
+ const expectedBaseName = '2022-12-11_measurement_';
+
+ beforeEach(() => {
+ defaultExportConfig = {
+ dataExportConfig: {
+ dataRangeConfiguration: 'all',
+ missingValueBehaviour: 'ignore',
+ measurement: 'measurement',
+ },
+ formatExportConfig: {
+ format: 'csv',
+ delimiter: 'comma',
+ },
+ };
+ });
+
+ it('Name for all data csv', () => {
+ const result = service.generateName(
+ defaultExportConfig,
+ defaultExportDate,
+ );
+ expect(result).toBe(`${expectedBaseName}all.csv`);
+ });
+
+ it('Name for all data json', () => {
+ defaultExportConfig.formatExportConfig.format = 'json';
+ const result = service.generateName(
+ defaultExportConfig,
+ defaultExportDate,
+ );
+ expect(result).toBe(`${expectedBaseName}all.json`);
+ });
+
+ it('Name for custom interval csv', () => {
+ defaultExportConfig.dataExportConfig.dataRangeConfiguration =
+ 'customInterval';
+ defaultExportConfig.dataExportConfig.dateRange = defaultDateRange;
+
+ const result = service.generateName(
+ defaultExportConfig,
+ defaultExportDate,
+ );
+ expect(result).toBe(
+ `${expectedBaseName}customInterval_2022-12-02_2022-12-06.csv`,
+ );
+ });
+
+ it('Name for custom visible json', () => {
+ defaultExportConfig.formatExportConfig.format = 'json';
+ defaultExportConfig.dataExportConfig.dataRangeConfiguration =
'visible';
+ defaultExportConfig.dataExportConfig.dateRange = defaultDateRange;
+
+ const result = service.generateName(
+ defaultExportConfig,
+ defaultExportDate,
+ );
+ expect(result).toBe(
+ `${expectedBaseName}visible_2022-12-02_2022-12-06.json`,
+ );
+ });
+
+ it('Name when missing start date range', () => {
+ defaultExportConfig.dataExportConfig.dataRangeConfiguration =
'visible';
+ defaultExportConfig.dataExportConfig.dateRange = new DateRange();
+ defaultExportConfig.dataExportConfig.dateRange.endDate =
defaultEndDate;
+
+ const result = service.generateName(
+ defaultExportConfig,
+ defaultExportDate,
+ );
+ expect(result).toBe(`${expectedBaseName}visible_2022-12-06.csv`);
+ });
+
+ it('Name when missing end date range', () => {
+ defaultExportConfig.dataExportConfig.dataRangeConfiguration =
'visible';
+ defaultExportConfig.dataExportConfig.dateRange = new DateRange();
+ defaultExportConfig.dataExportConfig.dateRange.startDate =
+ defaultStartDate;
+
+ const result = service.generateName(
+ defaultExportConfig,
+ defaultExportDate,
+ );
+ expect(result).toBe(`${expectedBaseName}visible_2022-12-02.csv`);
+ });
+});
diff --git
a/ui/src/app/configuration/dialog/data-retention-dialog/services/file-name.service.ts
b/ui/src/app/configuration/dialog/data-retention-dialog/services/file-name.service.ts
new file mode 100644
index 0000000000..66d8fe5b60
--- /dev/null
+++
b/ui/src/app/configuration/dialog/data-retention-dialog/services/file-name.service.ts
@@ -0,0 +1,59 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+import { Injectable } from '@angular/core';
+import { ExportConfig } from '../model/export-config.model';
+
+@Injectable({
+ providedIn: 'root',
+})
+export class FileNameService {
+ public generateName(exportConfig: ExportConfig, exportDate: Date): string {
+ const baseName = `${this.getDateString(exportDate)}_${
+ exportConfig.dataExportConfig.measurement
+ }_`;
+ const dataRangeOption =
+ exportConfig.dataExportConfig.dataRangeConfiguration;
+ let dateRange = '';
+ const fileExtension = `.${exportConfig.formatExportConfig.format}`;
+
+ if (
+ exportConfig.dataExportConfig.dateRange !== undefined &&
+ (dataRangeOption === 'customInterval' ||
+ dataRangeOption === 'visible')
+ ) {
+ if (exportConfig.dataExportConfig.dateRange.startDate) {
+ dateRange += `_${this.getDateString(
+ exportConfig.dataExportConfig.dateRange.startDate,
+ )}`;
+ }
+
+ if (exportConfig.dataExportConfig.dateRange.endDate) {
+ dateRange += `_${this.getDateString(
+ exportConfig.dataExportConfig.dateRange.endDate,
+ )}`;
+ }
+ }
+
+ return baseName + dataRangeOption + dateRange + fileExtension;
+ }
+
+ public getDateString(date: Date): string {
+ return date.toISOString().split('T')[0];
+ }
+}