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];
+    }
+}

Reply via email to