This is an automated email from the ASF dual-hosted git repository.
dominikriemer 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 578aad7e9f feat: Improve loading time of overview tables (#4551)
578aad7e9f is described below
commit 578aad7e9f4d32e82686ee0fe3bee4608581e630
Author: Dominik Riemer <[email protected]>
AuthorDate: Sat Jun 13 09:17:19 2026 +0200
feat: Improve loading time of overview tables (#4551)
---
.../AssetSummaryDto.java} | 11 +-
.../adapter/AdapterSummaryDto.java} | 18 +-
.../model/dashboard/DashboardSummaryDto.java | 4 +-
.../ChartSummaryDto.java} | 14 +-
.../DatasetSummaryDto.java} | 16 +-
.../management/AdapterResourceManager.java | 33 ++++
.../resource/management/AssetResourceManager.java | 62 ++++++
.../management/DataExplorerResourceManager.java | 34 +++-
.../DataExplorerWidgetResourceManager.java | 61 +++++-
.../management/DataLakeMeasureResourceManager.java | 158 ++++++++++++++++
.../resource/management/SpResourceManager.java | 8 +
.../rest/impl/AssetManagementResource.java | 13 ++
.../rest/impl/connect/AdapterResource.java | 13 ++
.../impl/datalake/DataLakeMeasureResource.java | 13 ++
.../rest/impl/datalake/DataLakeWidgetResource.java | 24 ++-
.../src/lib/apis/adapter.service.ts | 35 +++-
.../src/lib/apis/asset-management.service.ts | 10 +
.../src/lib/apis/chart.service.ts | 16 +-
.../src/lib/apis/datalake-rest.service.ts | 10 +
.../lib/model/resource/resource-summary.model.ts | 45 ++++-
.../asset-overview/asset-overview.component.ts | 19 +-
.../chart-overview-table.component.html | 74 ++++----
.../chart-overview-table.component.ts | 207 ++++++++++++++-------
.../existing-adapters.component.ts | 115 +++++++-----
.../delete-adapter-dialog.component.ts | 8 +-
.../all-adapter-actions-dialog.component.ts | 13 +-
ui/src/app/connect/filter/adapter-filter.pipe.ts | 13 +-
.../dashboard-overview-table.component.html | 4 +-
.../dashboard-overview-table.component.ts | 140 +++++++-------
.../datalake-configuration-entry.ts | 8 +-
.../datalake-configuration.component.html | 40 ++--
.../datalake-configuration.component.ts | 144 +++++++-------
32 files changed, 976 insertions(+), 407 deletions(-)
diff --git
a/streampipes-model/src/main/java/org/apache/streampipes/model/dashboard/DashboardSummaryDto.java
b/streampipes-model/src/main/java/org/apache/streampipes/model/assets/AssetSummaryDto.java
similarity index 71%
copy from
streampipes-model/src/main/java/org/apache/streampipes/model/dashboard/DashboardSummaryDto.java
copy to
streampipes-model/src/main/java/org/apache/streampipes/model/assets/AssetSummaryDto.java
index cd1c04fcd7..26bbde8471 100644
---
a/streampipes-model/src/main/java/org/apache/streampipes/model/dashboard/DashboardSummaryDto.java
+++
b/streampipes-model/src/main/java/org/apache/streampipes/model/assets/AssetSummaryDto.java
@@ -16,11 +16,10 @@
*
*/
-package org.apache.streampipes.model.dashboard;
+package org.apache.streampipes.model.assets;
-public record DashboardSummaryDto(String elementId,
- String name,
- String description,
- long createdAtEpochMs,
- long lastModifiedEpochMs) {
+public record AssetSummaryDto(String elementId,
+ String assetName,
+ String assetDescription,
+ boolean removable) {
}
diff --git
a/streampipes-model/src/main/java/org/apache/streampipes/model/dashboard/DashboardSummaryDto.java
b/streampipes-model/src/main/java/org/apache/streampipes/model/connect/adapter/AdapterSummaryDto.java
similarity index 59%
copy from
streampipes-model/src/main/java/org/apache/streampipes/model/dashboard/DashboardSummaryDto.java
copy to
streampipes-model/src/main/java/org/apache/streampipes/model/connect/adapter/AdapterSummaryDto.java
index cd1c04fcd7..8158dd9636 100644
---
a/streampipes-model/src/main/java/org/apache/streampipes/model/dashboard/DashboardSummaryDto.java
+++
b/streampipes-model/src/main/java/org/apache/streampipes/model/connect/adapter/AdapterSummaryDto.java
@@ -16,11 +16,17 @@
*
*/
-package org.apache.streampipes.model.dashboard;
+package org.apache.streampipes.model.connect.adapter;
-public record DashboardSummaryDto(String elementId,
- String name,
- String description,
- long createdAtEpochMs,
- long lastModifiedEpochMs) {
+import java.util.List;
+
+public record AdapterSummaryDto(String elementId,
+ String correspondingDataStreamElementId,
+ String name,
+ String description,
+ boolean running,
+ long createdAt,
+ String appId,
+ List<String> includedAssets,
+ String icon) {
}
diff --git
a/streampipes-model/src/main/java/org/apache/streampipes/model/dashboard/DashboardSummaryDto.java
b/streampipes-model/src/main/java/org/apache/streampipes/model/dashboard/DashboardSummaryDto.java
index cd1c04fcd7..fad916fce9 100644
---
a/streampipes-model/src/main/java/org/apache/streampipes/model/dashboard/DashboardSummaryDto.java
+++
b/streampipes-model/src/main/java/org/apache/streampipes/model/dashboard/DashboardSummaryDto.java
@@ -21,6 +21,6 @@ package org.apache.streampipes.model.dashboard;
public record DashboardSummaryDto(String elementId,
String name,
String description,
- long createdAtEpochMs,
- long lastModifiedEpochMs) {
+ Long createdAtEpochMs,
+ Long lastModifiedEpochMs) {
}
diff --git
a/streampipes-model/src/main/java/org/apache/streampipes/model/dashboard/DashboardSummaryDto.java
b/streampipes-model/src/main/java/org/apache/streampipes/model/datalake/ChartSummaryDto.java
similarity index 65%
copy from
streampipes-model/src/main/java/org/apache/streampipes/model/dashboard/DashboardSummaryDto.java
copy to
streampipes-model/src/main/java/org/apache/streampipes/model/datalake/ChartSummaryDto.java
index cd1c04fcd7..eb6f6035a5 100644
---
a/streampipes-model/src/main/java/org/apache/streampipes/model/dashboard/DashboardSummaryDto.java
+++
b/streampipes-model/src/main/java/org/apache/streampipes/model/datalake/ChartSummaryDto.java
@@ -16,11 +16,13 @@
*
*/
-package org.apache.streampipes.model.dashboard;
+package org.apache.streampipes.model.datalake;
-public record DashboardSummaryDto(String elementId,
- String name,
- String description,
- long createdAtEpochMs,
- long lastModifiedEpochMs) {
+public record ChartSummaryDto(String elementId,
+ String name,
+ Long createdAtEpochMs,
+ Long lastModifiedEpochMs,
+ String widgetType,
+ boolean multiSourceChart,
+ DataExplorerWidgetHealthStatus healthStatus) {
}
diff --git
a/streampipes-model/src/main/java/org/apache/streampipes/model/dashboard/DashboardSummaryDto.java
b/streampipes-model/src/main/java/org/apache/streampipes/model/datalake/DatasetSummaryDto.java
similarity index 63%
copy from
streampipes-model/src/main/java/org/apache/streampipes/model/dashboard/DashboardSummaryDto.java
copy to
streampipes-model/src/main/java/org/apache/streampipes/model/datalake/DatasetSummaryDto.java
index cd1c04fcd7..565d25fdfb 100644
---
a/streampipes-model/src/main/java/org/apache/streampipes/model/dashboard/DashboardSummaryDto.java
+++
b/streampipes-model/src/main/java/org/apache/streampipes/model/datalake/DatasetSummaryDto.java
@@ -16,11 +16,15 @@
*
*/
-package org.apache.streampipes.model.dashboard;
+package org.apache.streampipes.model.datalake;
-public record DashboardSummaryDto(String elementId,
- String name,
- String description,
- long createdAtEpochMs,
- long lastModifiedEpochMs) {
+import java.util.List;
+
+public record DatasetSummaryDto(String elementId,
+ String measureName,
+ boolean retentionConfigured,
+ String lastExport,
+ Boolean lastRetentionStatus,
+ List<String> pipelines,
+ boolean removable) {
}
diff --git
a/streampipes-resource-management/src/main/java/org/apache/streampipes/resource/management/AdapterResourceManager.java
b/streampipes-resource-management/src/main/java/org/apache/streampipes/resource/management/AdapterResourceManager.java
index 3e981cb9c3..f3ba00fc39 100644
---
a/streampipes-resource-management/src/main/java/org/apache/streampipes/resource/management/AdapterResourceManager.java
+++
b/streampipes-resource-management/src/main/java/org/apache/streampipes/resource/management/AdapterResourceManager.java
@@ -19,26 +19,53 @@ package org.apache.streampipes.resource.management;
import org.apache.streampipes.commons.exceptions.connect.AdapterException;
import org.apache.streampipes.model.connect.adapter.AdapterDescription;
+import org.apache.streampipes.model.connect.adapter.AdapterSummaryDto;
+import org.apache.streampipes.model.resource.ResourceSummaryDto;
import org.apache.streampipes.model.util.Cloner;
+import
org.apache.streampipes.resource.management.permission.SpPermissionEvaluator;
import org.apache.streampipes.resource.management.secret.SecretProvider;
import org.apache.streampipes.storage.api.connect.IAdapterStorage;
import org.apache.streampipes.storage.api.system.ICertificateStorage;
import org.apache.streampipes.storage.management.StorageDispatcher;
+import org.springframework.security.core.Authentication;
+
public class AdapterResourceManager extends
AbstractResourceManager<IAdapterStorage> {
private final ICertificateStorage certificateStorage;
+ private final SpPermissionEvaluator permissionEvaluator;
public AdapterResourceManager(IAdapterStorage adapterStorage,
ICertificateStorage certificateStorage) {
super(adapterStorage);
this.certificateStorage = certificateStorage;
+ this.permissionEvaluator = new SpPermissionEvaluator();
}
public AdapterResourceManager() {
super(StorageDispatcher.INSTANCE.getNoSqlStore()
.getAdapterInstanceStorage());
this.certificateStorage =
StorageDispatcher.INSTANCE.getNoSqlStore().getCertificateStorage();
+ this.permissionEvaluator = new SpPermissionEvaluator();
+ }
+
+ public ResourceSummaryDto<AdapterSummaryDto> getSummary(Authentication auth)
{
+ var adapters = db.findAll().stream()
+ .filter(adapter -> canReadAdapter(auth, adapter))
+ .map(adapter -> new AdapterSummaryDto(
+ adapter.getElementId(),
+ adapter.getCorrespondingDataStreamElementId(),
+ adapter.getName(),
+ adapter.getDescription(),
+ adapter.isRunning(),
+ adapter.getCreatedAt(),
+ adapter.getAppId(),
+ adapter.getIncludedAssets(),
+ adapter.getIcon()
+ ))
+ .toList();
+
+ return new ResourceSummaryDto<>(adapters, adapters.size());
}
/**
@@ -98,4 +125,10 @@ public class AdapterResourceManager extends
AbstractResourceManager<IAdapterStor
return encryptedAdapterDescription;
}
+ private boolean canReadAdapter(Authentication auth, AdapterDescription
adapter) {
+ return adapter != null
+ && adapter.getCorrespondingDataStreamElementId() != null
+ && permissionEvaluator.hasPermission(auth,
adapter.getCorrespondingDataStreamElementId(), "READ");
+ }
+
}
diff --git
a/streampipes-resource-management/src/main/java/org/apache/streampipes/resource/management/AssetResourceManager.java
b/streampipes-resource-management/src/main/java/org/apache/streampipes/resource/management/AssetResourceManager.java
new file mode 100644
index 0000000000..b8aa3a0ba4
--- /dev/null
+++
b/streampipes-resource-management/src/main/java/org/apache/streampipes/resource/management/AssetResourceManager.java
@@ -0,0 +1,62 @@
+/*
+ * 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.resource.management;
+
+import org.apache.streampipes.model.assets.AssetSummaryDto;
+import org.apache.streampipes.model.assets.SpAssetModel;
+import org.apache.streampipes.model.resource.ResourceSummaryDto;
+import
org.apache.streampipes.resource.management.permission.SpPermissionEvaluator;
+import org.apache.streampipes.storage.api.system.IAssetStorage;
+import org.apache.streampipes.storage.management.StorageDispatcher;
+
+import org.springframework.security.core.Authentication;
+
+public class AssetResourceManager extends
AbstractResourceManager<IAssetStorage> {
+
+ private final SpPermissionEvaluator permissionEvaluator;
+
+ public AssetResourceManager() {
+ super(StorageDispatcher.INSTANCE.getNoSqlStore().getAssetStorage());
+ this.permissionEvaluator = new SpPermissionEvaluator();
+ }
+
+ public ResourceSummaryDto<AssetSummaryDto> getSummary(Authentication auth) {
+ var assets = db.findAll().stream()
+ .filter(asset -> canReadAsset(auth, asset))
+ .map(this::toSummary)
+ .toList();
+
+ return new ResourceSummaryDto<>(assets, assets.size());
+ }
+
+ private boolean canReadAsset(Authentication auth, SpAssetModel asset) {
+ return asset != null
+ && asset.getElementId() != null
+ && permissionEvaluator.hasPermission(auth, asset.getElementId(),
"READ");
+ }
+
+ private AssetSummaryDto toSummary(SpAssetModel asset) {
+ return new AssetSummaryDto(
+ asset.getElementId(),
+ asset.getAssetName(),
+ asset.getAssetDescription(),
+ asset.isRemovable()
+ );
+ }
+}
diff --git
a/streampipes-resource-management/src/main/java/org/apache/streampipes/resource/management/DataExplorerResourceManager.java
b/streampipes-resource-management/src/main/java/org/apache/streampipes/resource/management/DataExplorerResourceManager.java
index f4fd8d00c0..2a5d2fc65d 100644
---
a/streampipes-resource-management/src/main/java/org/apache/streampipes/resource/management/DataExplorerResourceManager.java
+++
b/streampipes-resource-management/src/main/java/org/apache/streampipes/resource/management/DataExplorerResourceManager.java
@@ -48,10 +48,10 @@ public class DataExplorerResourceManager extends
CrudResourceManager<DashboardMo
.filter(dashboard -> permissionEvaluator.hasPermission(auth,
dashboard.getElementId(), "READ"))
.map(dashboard -> new DashboardSummaryDto(
dashboard.getElementId(),
- dashboard.getName(),
- dashboard.getDescription(),
- dashboard.getMetadata().getCreatedAtEpochMs(),
- dashboard.getMetadata().getLastModifiedEpochMs()))
+ getDashboardName(dashboard),
+ getDashboardDescription(dashboard),
+ getCreatedAt(dashboard),
+ getLastModified(dashboard)))
.toList();
return new ResourceSummaryDto<>(dashboards, dashboards.size());
@@ -76,4 +76,30 @@ public class DataExplorerResourceManager extends
CrudResourceManager<DashboardMo
.map(String.class::cast)
.toList();
}
+
+ private String getDashboardName(DashboardModel dashboard) {
+ if (dashboard == null) {
+ return null;
+ }
+
+ return dashboard.getName() != null ? dashboard.getName() :
dashboard.getElementId();
+ }
+
+ private String getDashboardDescription(DashboardModel dashboard) {
+ return dashboard != null && dashboard.getDescription() != null
+ ? dashboard.getDescription()
+ : "";
+ }
+
+ private Long getCreatedAt(DashboardModel dashboard) {
+ return dashboard != null && dashboard.getMetadata() != null
+ ? dashboard.getMetadata().getCreatedAtEpochMs()
+ : null;
+ }
+
+ private Long getLastModified(DashboardModel dashboard) {
+ return dashboard != null && dashboard.getMetadata() != null
+ ? dashboard.getMetadata().getLastModifiedEpochMs()
+ : null;
+ }
}
diff --git
a/streampipes-resource-management/src/main/java/org/apache/streampipes/resource/management/DataExplorerWidgetResourceManager.java
b/streampipes-resource-management/src/main/java/org/apache/streampipes/resource/management/DataExplorerWidgetResourceManager.java
index 54d766f152..7d6b841d1e 100644
---
a/streampipes-resource-management/src/main/java/org/apache/streampipes/resource/management/DataExplorerWidgetResourceManager.java
+++
b/streampipes-resource-management/src/main/java/org/apache/streampipes/resource/management/DataExplorerWidgetResourceManager.java
@@ -18,19 +18,43 @@
package org.apache.streampipes.resource.management;
+import org.apache.streampipes.model.datalake.ChartSummaryDto;
import org.apache.streampipes.model.datalake.DataExplorerWidgetModel;
+import org.apache.streampipes.model.resource.ResourceSummaryDto;
import org.apache.streampipes.storage.api.explorer.IDataExplorerWidgetStorage;
+import org.springframework.security.core.Authentication;
+
+import java.util.Collection;
+
public class DataExplorerWidgetResourceManager extends
CrudResourceManager<DataExplorerWidgetModel> {
private final DataExplorerResourceManager dashboardManager;
public DataExplorerWidgetResourceManager(DataExplorerResourceManager
dashboardManager,
- IDataExplorerWidgetStorage db) {
+ IDataExplorerWidgetStorage db) {
super(db, DataExplorerWidgetModel.class);
this.dashboardManager = dashboardManager;
}
+ public ResourceSummaryDto<ChartSummaryDto> getSummary(Authentication auth) {
+ var charts = findAll()
+ .stream()
+ .filter(chart -> permissionEvaluator.hasPermission(auth,
chart.getElementId(), "READ"))
+ .map(chart -> new ChartSummaryDto(
+ chart.getElementId(),
+ getChartName(chart),
+ getCreatedAt(chart),
+ getLastModified(chart),
+ chart.getWidgetType(),
+ isMultiSourceChart(chart),
+ chart.getHealthStatus()
+ ))
+ .toList();
+
+ return new ResourceSummaryDto<>(charts, charts.size());
+ }
+
@Override
public void delete(String elementId) {
deleteDataViewsFromDashboard(elementId);
@@ -42,4 +66,39 @@ public class DataExplorerWidgetResourceManager extends
CrudResourceManager<DataE
.filter(dashboard -> dashboard.getWidgets().removeIf(w ->
w.getDataViewElementId().equals(widgetElementId)))
.forEach(dashboardManager::update);
}
+
+ private boolean isMultiSourceChart(DataExplorerWidgetModel chart) {
+ if (chart == null || chart.getDataConfig() == null) {
+ return false;
+ }
+
+ Object sourceConfigs = chart.getDataConfig().get("sourceConfigs");
+
+ if (sourceConfigs instanceof Collection<?>) {
+ return ((Collection<?>) sourceConfigs).size() > 1;
+ }
+
+ return false;
+ }
+
+ private String getChartName(DataExplorerWidgetModel chart) {
+ if (chart == null || chart.getBaseAppearanceConfig() == null) {
+ return chart != null ? chart.getElementId() : null;
+ }
+
+ Object widgetTitle = chart.getBaseAppearanceConfig().get("widgetTitle");
+ return widgetTitle != null ? widgetTitle.toString() : chart.getElementId();
+ }
+
+ private Long getCreatedAt(DataExplorerWidgetModel chart) {
+ return chart != null && chart.getMetadata() != null
+ ? chart.getMetadata().getCreatedAtEpochMs()
+ : null;
+ }
+
+ private Long getLastModified(DataExplorerWidgetModel chart) {
+ return chart != null && chart.getMetadata() != null
+ ? chart.getMetadata().getLastModifiedEpochMs()
+ : null;
+ }
}
diff --git
a/streampipes-resource-management/src/main/java/org/apache/streampipes/resource/management/DataLakeMeasureResourceManager.java
b/streampipes-resource-management/src/main/java/org/apache/streampipes/resource/management/DataLakeMeasureResourceManager.java
new file mode 100644
index 0000000000..a80c7280e1
--- /dev/null
+++
b/streampipes-resource-management/src/main/java/org/apache/streampipes/resource/management/DataLakeMeasureResourceManager.java
@@ -0,0 +1,158 @@
+/*
+ * 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.resource.management;
+
+import org.apache.streampipes.model.datalake.DataLakeMeasure;
+import org.apache.streampipes.model.datalake.DatasetSummaryDto;
+import org.apache.streampipes.model.datalake.RetentionTimeConfig;
+import org.apache.streampipes.model.graph.DataSinkInvocation;
+import org.apache.streampipes.model.pipeline.Pipeline;
+import org.apache.streampipes.model.resource.ResourceSummaryDto;
+import org.apache.streampipes.model.staticproperty.FreeTextStaticProperty;
+import
org.apache.streampipes.resource.management.permission.SpPermissionEvaluator;
+import org.apache.streampipes.storage.api.explorer.IDataLakeMeasureStorage;
+import org.apache.streampipes.storage.api.pipeline.IPipelineStorage;
+import org.apache.streampipes.storage.management.StorageDispatcher;
+
+import org.springframework.security.core.Authentication;
+
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+import java.util.stream.Collectors;
+
+public class DataLakeMeasureResourceManager extends
AbstractResourceManager<IDataLakeMeasureStorage> {
+
+ private static final String DATA_LAKE_APP_ID =
"org.apache.streampipes.sinks.internal.jvm.datalake";
+ private static final String MEASURE_FIELD_INTERNAL_NAME = "db_measurement";
+ private static final List<String> FORBIDDEN_MEASURE_NAME_CHARS =
List.of("/", "?", "=", "\"");
+
+ private final IPipelineStorage pipelineStorage;
+ private final SpPermissionEvaluator permissionEvaluator;
+
+ public DataLakeMeasureResourceManager() {
+ super(StorageDispatcher.INSTANCE.getNoSqlStore().getDataLakeStorage());
+ this.pipelineStorage =
StorageDispatcher.INSTANCE.getNoSqlStore().getPipelineStorageAPI();
+ this.permissionEvaluator = new SpPermissionEvaluator();
+ }
+
+ public ResourceSummaryDto<DatasetSummaryDto> getSummary(Authentication auth)
{
+ var pipelinesByMeasure = getVisiblePipelinesByMeasure(auth);
+
+ var datasets = db.findAll().stream()
+ .filter(measure -> canReadMeasure(auth, measure))
+ .map(measure -> toSummary(measure, pipelinesByMeasure))
+ .toList();
+
+ return new ResourceSummaryDto<>(datasets, datasets.size());
+ }
+
+ private DatasetSummaryDto toSummary(
+ DataLakeMeasure measure,
+ Map<String, List<PipelineInfo>> pipelinesByMeasure
+ ) {
+ var pipelineInfos =
pipelinesByMeasure.getOrDefault(measure.getMeasureName(), List.of());
+ var pipelines = pipelineInfos.stream().map(PipelineInfo::name).toList();
+ var removable = pipelineInfos.stream().noneMatch(PipelineInfo::running);
+ var retentionConfigured = hasRetention(measure.getRetentionTime());
+ var lastExport = getLastExport(measure.getRetentionTime());
+ var lastRetentionStatus =
getLastRetentionStatus(measure.getRetentionTime());
+
+ return new DatasetSummaryDto(
+ measure.getElementId(),
+ measure.getMeasureName(),
+ retentionConfigured,
+ lastExport,
+ lastRetentionStatus,
+ pipelines,
+ removable
+ );
+ }
+
+ private Map<String, List<PipelineInfo>>
getVisiblePipelinesByMeasure(Authentication auth) {
+ return pipelineStorage.findAll().stream()
+ .filter(pipeline -> permissionEvaluator.hasPermission(auth,
pipeline.getPipelineId(), "READ"))
+ .flatMap(pipeline -> extractSinks(pipeline).stream()
+ .map(this::getMeasureName)
+ .flatMap(Optional::stream)
+ .map(measureName -> new PipelineMeasure(
+ measureName,
+ new PipelineInfo(pipeline.getName(), pipeline.isRunning())
+ )))
+ .collect(Collectors.groupingBy(PipelineMeasure::measureName,
+ Collectors.mapping(PipelineMeasure::pipelineInfo,
Collectors.toList())));
+ }
+
+ private boolean canReadMeasure(Authentication auth, DataLakeMeasure measure)
{
+ return measure != null
+ && measure.getElementId() != null
+ && permissionEvaluator.hasPermission(auth, measure.getElementId(),
"READ");
+ }
+
+ private List<DataSinkInvocation> extractSinks(Pipeline pipeline) {
+ return pipeline.getActions().stream()
+ .filter(sink -> DATA_LAKE_APP_ID.equals(sink.getAppId()))
+ .toList();
+ }
+
+ private Optional<String> getMeasureName(DataSinkInvocation sink) {
+ return sink.getStaticProperties().stream()
+ .filter(sp -> MEASURE_FIELD_INTERNAL_NAME.equals(sp.getInternalName()))
+ .filter(FreeTextStaticProperty.class::isInstance)
+ .map(FreeTextStaticProperty.class::cast)
+ .map(FreeTextStaticProperty::getValue)
+ .findFirst()
+ .map(this::sanitizeMeasureName);
+ }
+
+ private String sanitizeMeasureName(String measureName) {
+ return FORBIDDEN_MEASURE_NAME_CHARS.stream()
+ .reduce(measureName, (currentName, forbiddenChar) ->
currentName.replace(forbiddenChar, "_"));
+ }
+
+ private boolean hasRetention(RetentionTimeConfig retentionTime) {
+ return retentionTime != null && retentionTime.getDataRetentionConfig() !=
null;
+ }
+
+ private Boolean getLastRetentionStatus(RetentionTimeConfig retentionTime) {
+ if (retentionTime == null
+ || retentionTime.getRetentionExportConfig() == null
+ || retentionTime.getRetentionExportConfig().getRetentionLog() == null
+ ||
retentionTime.getRetentionExportConfig().getRetentionLog().isEmpty()) {
+ return null;
+ }
+
+ var retentionLog =
retentionTime.getRetentionExportConfig().getRetentionLog();
+ return retentionLog.get(retentionLog.size() - 1).getStatus();
+ }
+
+ private String getLastExport(RetentionTimeConfig retentionTime) {
+ if (retentionTime == null || retentionTime.getRetentionExportConfig() ==
null) {
+ return null;
+ }
+
+ return retentionTime.getRetentionExportConfig().getLastExport();
+ }
+
+ private record PipelineInfo(String name, boolean running) {
+ }
+
+ private record PipelineMeasure(String measureName, PipelineInfo
pipelineInfo) {
+ }
+}
diff --git
a/streampipes-resource-management/src/main/java/org/apache/streampipes/resource/management/SpResourceManager.java
b/streampipes-resource-management/src/main/java/org/apache/streampipes/resource/management/SpResourceManager.java
index c985766ccb..294f9ddb1b 100644
---
a/streampipes-resource-management/src/main/java/org/apache/streampipes/resource/management/SpResourceManager.java
+++
b/streampipes-resource-management/src/main/java/org/apache/streampipes/resource/management/SpResourceManager.java
@@ -21,6 +21,10 @@ import
org.apache.streampipes.storage.api.explorer.IDataExplorerWidgetStorage;
public class SpResourceManager {
+ public AssetResourceManager manageAssets() {
+ return new AssetResourceManager();
+ }
+
public AdapterResourceManager manageAdapters() {
return new AdapterResourceManager();
}
@@ -50,6 +54,10 @@ public class SpResourceManager {
return new DataStreamResourceManager();
}
+ public DataLakeMeasureResourceManager manageDataLakeMeasures() {
+ return new DataLakeMeasureResourceManager();
+ }
+
public PipelineResourceManager managePipelines() {
return new PipelineResourceManager();
}
diff --git
a/streampipes-rest/src/main/java/org/apache/streampipes/rest/impl/AssetManagementResource.java
b/streampipes-rest/src/main/java/org/apache/streampipes/rest/impl/AssetManagementResource.java
index 897285c710..27140f71f5 100644
---
a/streampipes-rest/src/main/java/org/apache/streampipes/rest/impl/AssetManagementResource.java
+++
b/streampipes-rest/src/main/java/org/apache/streampipes/rest/impl/AssetManagementResource.java
@@ -18,8 +18,11 @@
package org.apache.streampipes.rest.impl;
+import org.apache.streampipes.model.assets.AssetSummaryDto;
import org.apache.streampipes.model.assets.SpAssetModel;
import org.apache.streampipes.model.client.user.DefaultPrivilege;
+import org.apache.streampipes.model.resource.ResourceSummaryDto;
+import org.apache.streampipes.resource.management.AssetResourceManager;
import org.apache.streampipes.resource.management.CrudResourceManager;
import
org.apache.streampipes.rest.core.base.impl.AbstractAuthGuardedRestResource;
import org.apache.streampipes.rest.security.AuthConstants;
@@ -54,6 +57,12 @@ public class AssetManagementResource extends
AbstractAuthGuardedRestResource {
this.resourceManager = new CrudResourceManager<>(assetStorage,
SpAssetModel.class);
}
+ @GetMapping(path = "/summary", produces = MediaType.APPLICATION_JSON_VALUE)
+ @PreAuthorize(AuthConstants.IS_AUTHENTICATED)
+ public ResourceSummaryDto<AssetSummaryDto> getAssetSummary() {
+ return getResourceManager().getSummary(getAuthentication());
+ }
+
@GetMapping(produces = MediaType.APPLICATION_JSON_VALUE)
@PreAuthorize(AuthConstants.IS_AUTHENTICATED)
@PostFilter("hasPermission(filterObject.elementId, 'READ')")
@@ -104,4 +113,8 @@ public class AssetManagementResource extends
AbstractAuthGuardedRestResource {
public boolean hasWriteAuthority() {
return
isAdminOrHasAnyAuthority(DefaultPrivilege.Constants.PRIVILEGE_WRITE_ASSETS_VALUE);
}
+
+ private AssetResourceManager getResourceManager() {
+ return getSpResourceManager().manageAssets();
+ }
}
diff --git
a/streampipes-rest/src/main/java/org/apache/streampipes/rest/impl/connect/AdapterResource.java
b/streampipes-rest/src/main/java/org/apache/streampipes/rest/impl/connect/AdapterResource.java
index 692b49ae9a..689a739033 100644
---
a/streampipes-rest/src/main/java/org/apache/streampipes/rest/impl/connect/AdapterResource.java
+++
b/streampipes-rest/src/main/java/org/apache/streampipes/rest/impl/connect/AdapterResource.java
@@ -29,12 +29,15 @@ import
org.apache.streampipes.manager.pipeline.PipelineManager;
import org.apache.streampipes.model.client.user.DefaultRole;
import org.apache.streampipes.model.client.user.Permission;
import org.apache.streampipes.model.connect.adapter.AdapterDescription;
+import org.apache.streampipes.model.connect.adapter.AdapterSummaryDto;
import org.apache.streampipes.model.connect.adapter.PipelineUpdateInfo;
import org.apache.streampipes.model.connect.adapter.compact.CompactAdapter;
import org.apache.streampipes.model.message.Message;
import org.apache.streampipes.model.message.Notifications;
import org.apache.streampipes.model.monitoring.SpLogMessage;
+import org.apache.streampipes.model.resource.ResourceSummaryDto;
import org.apache.streampipes.model.util.ElementIdGenerator;
+import org.apache.streampipes.resource.management.AdapterResourceManager;
import org.apache.streampipes.resource.management.PermissionResourceManager;
import org.apache.streampipes.resource.management.SpResourceManager;
import
org.apache.streampipes.resource.management.permission.SpPermissionEvaluator;
@@ -339,10 +342,20 @@ public class AdapterResource extends
AbstractAdapterResource<AdapterMasterManage
return managementService.getAllAdapterInstances();
}
+ @GetMapping(path = "/summary", produces = MediaType.APPLICATION_JSON_VALUE)
+ @PreAuthorize("this.hasReadAuthority()")
+ public ResourceSummaryDto<AdapterSummaryDto> getAdapterSummary() {
+ return getResourceManager().getSummary(getAuthentication());
+ }
+
private AdapterDescription getAdapterDescription(String elementId) throws
AdapterException {
return managementService.getAdapter(elementId);
}
+ private AdapterResourceManager getResourceManager() {
+ return getSpResourceManager().manageAdapters();
+ }
+
private CompactAdapter toCompactAdapterDescription(AdapterDescription
adapterDescription) throws Exception {
return new
CompactAdapterManagement(List.of()).convertToCompactAdapter(adapterDescription);
}
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 28e12fc92e..5f94ed50c3 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
@@ -20,7 +20,10 @@ package org.apache.streampipes.rest.impl.datalake;
import org.apache.streampipes.dataexplorer.management.DataExplorerDispatcher;
import org.apache.streampipes.model.datalake.DataLakeMeasure;
+import org.apache.streampipes.model.datalake.DatasetSummaryDto;
import org.apache.streampipes.model.monitoring.SpLogMessage;
+import org.apache.streampipes.model.resource.ResourceSummaryDto;
+import
org.apache.streampipes.resource.management.DataLakeMeasureResourceManager;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
@@ -50,6 +53,12 @@ public class DataLakeMeasureResource extends
AbstractDataLakeResource {
super();
}
+ @GetMapping(path = "/summary", produces = MediaType.APPLICATION_JSON_VALUE)
+ @PreAuthorize("this.hasReadAuthority()")
+ public ResourceSummaryDto<DatasetSummaryDto> getDatasetSummary() {
+ return getResourceManager().getSummary(getAuthentication());
+ }
+
@PostMapping(produces = MediaType.APPLICATION_JSON_VALUE, consumes =
MediaType.APPLICATION_JSON_VALUE)
@PreAuthorize("this.hasWriteAuthority()")
public ResponseEntity<?> addDataLake(@RequestBody DataLakeMeasure
dataLakeMeasure) {
@@ -139,4 +148,8 @@ public class DataLakeMeasureResource extends
AbstractDataLakeResource {
}
}
+ private DataLakeMeasureResourceManager getResourceManager() {
+ return getSpResourceManager().manageDataLakeMeasures();
+ }
+
}
diff --git
a/streampipes-rest/src/main/java/org/apache/streampipes/rest/impl/datalake/DataLakeWidgetResource.java
b/streampipes-rest/src/main/java/org/apache/streampipes/rest/impl/datalake/DataLakeWidgetResource.java
index fc840505c8..ca2ebe4222 100644
---
a/streampipes-rest/src/main/java/org/apache/streampipes/rest/impl/datalake/DataLakeWidgetResource.java
+++
b/streampipes-rest/src/main/java/org/apache/streampipes/rest/impl/datalake/DataLakeWidgetResource.java
@@ -19,7 +19,9 @@
package org.apache.streampipes.rest.impl.datalake;
import org.apache.streampipes.model.client.user.DefaultPrivilege;
+import org.apache.streampipes.model.datalake.ChartSummaryDto;
import org.apache.streampipes.model.datalake.DataExplorerWidgetModel;
+import org.apache.streampipes.model.resource.ResourceSummaryDto;
import org.apache.streampipes.resource.management.DataExplorerResourceManager;
import
org.apache.streampipes.resource.management.DataExplorerWidgetResourceManager;
import org.apache.streampipes.resource.management.SpResourceManager;
@@ -58,13 +60,19 @@ public class DataLakeWidgetResource extends
AbstractAuthGuardedRestResource {
@GetMapping(produces = MediaType.APPLICATION_JSON_VALUE)
@PreAuthorize(AuthConstants.HAS_READ_DATA_EXPLORER_PRIVILEGE)
@PostFilter("hasPermission(filterObject.elementId, 'READ')")
- public List<DataExplorerWidgetModel> getAllDataExplorerWidgets() {
+ public List<DataExplorerWidgetModel> getAllCharts() {
return resourceManager.findAll();
}
- @GetMapping(path = "/{widgetId}", produces =
MediaType.APPLICATION_JSON_VALUE)
+ @GetMapping(path = "/summary", produces = MediaType.APPLICATION_JSON_VALUE)
+ @PreAuthorize("this.hasReadAuthority()")
+ public ResourceSummaryDto<ChartSummaryDto> getChartSummary() {
+ return resourceManager.getSummary(getAuthentication());
+ }
+
+ @GetMapping(path = "/{chartId}", produces = MediaType.APPLICATION_JSON_VALUE)
@PreAuthorize("this.hasReadAuthority() and hasPermission(#elementId,
'READ')")
- public ResponseEntity<DataExplorerWidgetModel>
getDataExplorerWidget(@PathVariable("widgetId") String elementId) {
+ public ResponseEntity<DataExplorerWidgetModel>
getChart(@PathVariable("chartId") String elementId) {
var widget = resourceManager.find(elementId);
if (widget != null) {
return ok(widget);
@@ -74,19 +82,19 @@ public class DataLakeWidgetResource extends
AbstractAuthGuardedRestResource {
}
@PutMapping(
- path = "/{widgetId}",
+ path = "/{chartId}",
consumes = MediaType.APPLICATION_JSON_VALUE,
produces = MediaType.APPLICATION_JSON_VALUE)
@PreAuthorize("this.hasWriteAuthority() and
hasPermission(#dataExplorerWidgetModel.elementId, 'WRITE')")
- public ResponseEntity<DataExplorerWidgetModel> modifyDataExplorerWidget(
+ public ResponseEntity<DataExplorerWidgetModel> modifyChart(
@RequestBody DataExplorerWidgetModel dataExplorerWidgetModel) {
resourceManager.update(dataExplorerWidgetModel);
return ok(resourceManager.find(dataExplorerWidgetModel.getElementId()));
}
- @DeleteMapping(path = "/{widgetId}")
+ @DeleteMapping(path = "/{chartId}")
@PreAuthorize("this.hasWriteAuthority() and hasPermission(#elementId,
'WRITE')")
- public ResponseEntity<Void>
deleteDataExplorerWidget(@PathVariable("widgetId") String elementId) {
+ public ResponseEntity<Void> deleteChart(@PathVariable("chartId") String
elementId) {
resourceManager.delete(elementId);
return ok();
}
@@ -96,7 +104,7 @@ public class DataLakeWidgetResource extends
AbstractAuthGuardedRestResource {
consumes = MediaType.APPLICATION_JSON_VALUE
)
@PreAuthorize("this.hasWriteAuthority()")
- public ResponseEntity<DataExplorerWidgetModel> createDataExplorerWidget(
+ public ResponseEntity<DataExplorerWidgetModel> createChart(
@RequestBody DataExplorerWidgetModel dataExplorerWidgetModel) {
return ok(resourceManager.create(dataExplorerWidgetModel,
getAuthenticatedUserSid()));
}
diff --git
a/ui/projects/streampipes/platform-services/src/lib/apis/adapter.service.ts
b/ui/projects/streampipes/platform-services/src/lib/apis/adapter.service.ts
index 8cebfd8263..8d00991f56 100644
--- a/ui/projects/streampipes/platform-services/src/lib/apis/adapter.service.ts
+++ b/ui/projects/streampipes/platform-services/src/lib/apis/adapter.service.ts
@@ -28,6 +28,10 @@ import {
Message,
PipelineUpdateInfo,
} from '../model/gen/streampipes-model';
+import {
+ AdapterSummaryDto,
+ ResourceSummaryDto,
+} from '../model/resource/resource-summary.model';
@Injectable({
providedIn: 'root',
@@ -48,6 +52,12 @@ export class AdapterService {
return this.requestAdapterDescriptions('/master/adapters');
}
+ getAdapterSummary(): Observable<ResourceSummaryDto<AdapterSummaryDto>> {
+ return this.http.get<ResourceSummaryDto<AdapterSummaryDto>>(
+ `${this.connectPath}/master/adapters/summary`,
+ );
+ }
+
getAdapter(id: string): Observable<AdapterDescription> {
return this.http
.get(this.connectPath + `/master/adapters/${id}`)
@@ -78,10 +88,17 @@ export class AdapterService {
stopAdapter(
adapter: AdapterDescription,
forceStop = false,
+ ): Observable<Message> {
+ return this.stopAdapterByElementId(adapter.elementId, forceStop);
+ }
+
+ stopAdapterByElementId(
+ elementId: string,
+ forceStop = false,
): Observable<Message> {
return this.http
.post(
- this.adapterMasterUrl + adapter.elementId + '/stop',
+ this.adapterMasterUrl + elementId + '/stop',
{},
{ params: { forceStop } },
)
@@ -134,16 +151,26 @@ export class AdapterService {
deleteAdapter(
adapter: AdapterDescription,
deleteAssociatedPipelines: boolean,
+ ): Observable<any> {
+ return this.deleteAdapterById(
+ adapter.elementId,
+ deleteAssociatedPipelines,
+ );
+ }
+
+ deleteAdapterById(
+ elementId: string,
+ deleteAssociatedPipelines: boolean,
): Observable<any> {
return this.deleteRequest(
- adapter,
+ elementId,
deleteAssociatedPipelines,
'master/adapters',
);
}
private deleteRequest(
- adapter: AdapterDescription,
+ elementId: string,
deleteAssociatedPipelines: boolean,
url: string,
) {
@@ -151,7 +178,7 @@ export class AdapterService {
? '?deleteAssociatedPipelines=true'
: '';
return this.http.delete(
- `${this.connectPath}/${url}/${adapter.elementId}${queryString}`,
+ `${this.connectPath}/${url}/${elementId}${queryString}`,
);
}
diff --git
a/ui/projects/streampipes/platform-services/src/lib/apis/asset-management.service.ts
b/ui/projects/streampipes/platform-services/src/lib/apis/asset-management.service.ts
index 2d1312157b..f1670af6e7 100644
---
a/ui/projects/streampipes/platform-services/src/lib/apis/asset-management.service.ts
+++
b/ui/projects/streampipes/platform-services/src/lib/apis/asset-management.service.ts
@@ -21,6 +21,10 @@ import { HttpClient } from '@angular/common/http';
import { PlatformServicesCommons } from './commons.service';
import { Observable } from 'rxjs';
import { SpAssetModel } from '../model/gen/streampipes-model';
+import {
+ AssetSummaryDto,
+ ResourceSummaryDto,
+} from '../model/resource/resource-summary.model';
@Injectable({
providedIn: 'root',
@@ -37,6 +41,12 @@ export class AssetManagementService {
return this.http.get<SpAssetModel[]>(this.assetBasePath);
}
+ getAssetSummary(): Observable<ResourceSummaryDto<AssetSummaryDto>> {
+ return this.http.get<ResourceSummaryDto<AssetSummaryDto>>(
+ `${this.assetBasePath}/summary`,
+ );
+ }
+
getAsset(assetId: string): Observable<SpAssetModel> {
return this.http.get<SpAssetModel>(`${this.assetBasePath}/${assetId}`);
}
diff --git
a/ui/projects/streampipes/platform-services/src/lib/apis/chart.service.ts
b/ui/projects/streampipes/platform-services/src/lib/apis/chart.service.ts
index 57d77b9d90..a6336f7132 100644
--- a/ui/projects/streampipes/platform-services/src/lib/apis/chart.service.ts
+++ b/ui/projects/streampipes/platform-services/src/lib/apis/chart.service.ts
@@ -25,6 +25,10 @@ import {
DataLakeMeasure,
} from '../model/gen/streampipes-model';
import { TranslateService } from '@ngx-translate/core';
+import {
+ ChartSummaryDto,
+ ResourceSummaryDto,
+} from '../model/resource/resource-summary.model';
@Injectable({
providedIn: 'root',
@@ -34,9 +38,15 @@ export class ChartService {
private translateService = inject(TranslateService);
getAllCharts(): Observable<DataExplorerWidgetModel[]> {
- return this.http
- .get(this.dashboardWidgetUrl)
- .pipe(map(res => res as DataExplorerWidgetModel[]));
+ return this.http.get<DataExplorerWidgetModel[]>(
+ this.dashboardWidgetUrl,
+ );
+ }
+
+ getChartSummary(): Observable<ResourceSummaryDto<ChartSummaryDto>> {
+ return this.http.get<ResourceSummaryDto<ChartSummaryDto>>(
+ `${this.dashboardWidgetUrl}/summary`,
+ );
}
getChart(widgetId: string): Observable<DataExplorerWidgetModel> {
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 3011e492b0..fb2ccafeff 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
@@ -29,6 +29,10 @@ import { DataLakeMeasure, SpQueryResult } from
'../model/gen/streampipes-model';
import { map } from 'rxjs/operators';
import { DatalakeQueryParameters } from
'../model/datalake/DatalakeQueryParameters';
import { NGX_LOADING_BAR_IGNORED } from '@ngx-loading-bar/http-client';
+import {
+ DatasetSummaryDto,
+ ResourceSummaryDto,
+} from '../model/resource/resource-summary.model';
import {
CsvImportPreviewRequest,
CsvImportPreviewResult,
@@ -85,6 +89,12 @@ export class DatalakeRestService {
);
}
+ getMeasurementSummary(): Observable<ResourceSummaryDto<DatasetSummaryDto>>
{
+ return this.http.get<ResourceSummaryDto<DatasetSummaryDto>>(
+ `${this.dataLakeMeasureUrl}/summary`,
+ );
+ }
+
getMeasurement(id: string): Observable<DataLakeMeasure> {
return this.http
.get(`${this.dataLakeMeasureUrl}/${id}`)
diff --git
a/ui/projects/streampipes/platform-services/src/lib/model/resource/resource-summary.model.ts
b/ui/projects/streampipes/platform-services/src/lib/model/resource/resource-summary.model.ts
index c3913ce834..b4348b7d19 100644
---
a/ui/projects/streampipes/platform-services/src/lib/model/resource/resource-summary.model.ts
+++
b/ui/projects/streampipes/platform-services/src/lib/model/resource/resource-summary.model.ts
@@ -17,7 +17,7 @@
*/
import { PipelineHealthStatus } from '../gen/streampipes-model';
-
+import { DataExplorerWidgetHealthStatus } from '../gen/streampipes-model';
export interface ResourceSummaryDto<T> {
totalCount: number;
resources: T[];
@@ -27,8 +27,37 @@ export interface DashboardSummaryDto {
elementId: string;
name: string;
description: string;
- createdAtEpochMs: number;
- lastModifiedEpochMs: number;
+ createdAtEpochMs: number | null;
+ lastModifiedEpochMs: number | null;
+}
+
+export interface AdapterSummaryDto {
+ elementId: string;
+ correspondingDataStreamElementId: string;
+ name: string;
+ description: string;
+ running: boolean;
+ createdAt: number;
+ appId: string;
+ includedAssets: string[];
+ icon: string;
+}
+
+export interface AssetSummaryDto {
+ elementId: string;
+ assetName: string;
+ assetDescription: string;
+ removable: boolean;
+}
+
+export interface DatasetSummaryDto {
+ elementId: string;
+ measureName: string;
+ retentionConfigured: boolean;
+ lastExport: string | null;
+ lastRetentionStatus: boolean | null;
+ pipelines: string[];
+ removable: boolean;
}
export interface PipelineSummaryDto {
@@ -41,3 +70,13 @@ export interface PipelineSummaryDto {
pipelineNotifications: string[];
valid: true;
}
+
+export interface ChartSummaryDto {
+ elementId: string;
+ name: string;
+ createdAtEpochMs: number | null;
+ lastModifiedEpochMs: number | null;
+ multiSourceChart: boolean;
+ widgetType: string;
+ healthStatus: DataExplorerWidgetHealthStatus;
+}
diff --git
a/ui/src/app/assets/components/asset-overview/asset-overview.component.ts
b/ui/src/app/assets/components/asset-overview/asset-overview.component.ts
index 3a875e2da7..d270b80e3b 100644
--- a/ui/src/app/assets/components/asset-overview/asset-overview.component.ts
+++ b/ui/src/app/assets/components/asset-overview/asset-overview.component.ts
@@ -26,6 +26,7 @@ import {
MatTableDataSource,
} from '@angular/material/table';
import {
+ AssetSummaryDto,
AssetManagementService,
SpAssetModel,
} from '@streampipes/platform-services';
@@ -99,16 +100,16 @@ export class SpAssetOverviewComponent implements OnInit {
private dialog = inject(MatDialog);
private translateService = inject(TranslateService);
- existingAssets: SpAssetModel[] = [];
- filteredAssets: SpAssetModel[] = [];
+ existingAssets: AssetSummaryDto[] = [];
+ filteredAssets: AssetSummaryDto[] = [];
displayedColumns: string[] = ['assetName', 'actions'];
@ViewChild(MatSort)
sort: MatSort;
- dataSource: MatTableDataSource<SpAssetModel> =
- new MatTableDataSource<SpAssetModel>();
+ dataSource: MatTableDataSource<AssetSummaryDto> =
+ new MatTableDataSource<AssetSummaryDto>();
hasWritePrivilege = false;
@@ -153,8 +154,8 @@ export class SpAssetOverviewComponent implements OnInit {
}
loadAssets(): void {
- this.assetService.getAllAssets().subscribe(result => {
- this.existingAssets = (result as SpAssetModel[]).sort((a, b) =>
+ this.assetService.getAssetSummary().subscribe(result => {
+ this.existingAssets = result.resources.sort((a, b) =>
a.assetName.localeCompare(b.assetName),
);
this.applyAssetFilters(this.currentFilterIds);
@@ -210,12 +211,12 @@ export class SpAssetOverviewComponent implements OnInit {
});
}
- goToDetailsView(asset: SpAssetModel, editMode = false) {
+ goToDetailsView(asset: AssetSummaryDto, editMode = false) {
const mode = editMode && this.hasWritePrivilege ? 'edit' : 'view';
this.router.navigate(['assets', 'details', asset.elementId, mode]);
}
- deleteAsset(asset: SpAssetModel) {
+ deleteAsset(asset: AssetSummaryDto) {
const dialogRef = this.dialog.open(ConfirmDialogComponent, {
width: '500px',
data: {
@@ -239,7 +240,7 @@ export class SpAssetOverviewComponent implements OnInit {
});
}
- openPermissionsDialog(asset: SpAssetModel) {
+ openPermissionsDialog(asset: AssetSummaryDto) {
this.dialogService.open(ObjectPermissionDialogComponent, {
panelType: PanelType.SLIDE_IN_PANEL,
title: this.translateService.instant('Manage permissions'),
diff --git
a/ui/src/app/chart/components/chart-overview/chart-overview-table/chart-overview-table.component.html
b/ui/src/app/chart/components/chart-overview/chart-overview-table/chart-overview-table.component.html
index 351402f118..6c0803791f 100644
---
a/ui/src/app/chart/components/chart-overview/chart-overview-table/chart-overview-table.component.html
+++
b/ui/src/app/chart/components/chart-overview/chart-overview-table/chart-overview-table.component.html
@@ -29,7 +29,7 @@
featureCardId="chart"
[showActionsMenu]="true"
[rowsClickable]="true"
- (rowClicked)="openDataView($event, true)"
+ (rowClicked)="openChart($event, true)"
matSort
>
<ng-container matColumnDef="name">
@@ -68,29 +68,38 @@
>
}
<div fxLayout="column" fxLayoutAlign="start start">
- <span class="text-sm">{{
- element.baseAppearanceConfig.widgetTitle
- }}</span>
+ <span class="text-sm">{{ element.name }}</span>
</div>
</div>
</td>
</ng-container>
+ <ng-container matColumnDef="chartType">
+ <th mat-header-cell mat-sort-header *matHeaderCellDef>
+ {{ 'Type' | translate }}
+ </th>
+ <td mat-cell *matCellDef="let element">
+ <div
+ fxLayout="row"
+ fxLayoutAlign="start center"
+ class="text-sm"
+ >
+ <mat-icon [matTooltip]="getChartTypeName(element)">{{
+ getChartTypeIcon(element)
+ }}</mat-icon>
+ </div>
+ </td>
+ </ng-container>
<ng-container matColumnDef="lastModified">
<th mat-header-cell mat-sort-header *matHeaderCellDef>
{{ 'Last modified' | translate }}
</th>
<td mat-cell *matCellDef="let element">
- @if (element.metadata) {
+ @if (element.lastModifiedEpochMs !== null) {
<div>
- {{
- this.formatDate(
- element.metadata.lastModifiedEpochMs
- )
- }}
+ {{ formatDate(element.lastModifiedEpochMs) }}
</div>
- }
- @if (!element.metadata) {
+ } @else {
<div>–</div>
}
</td>
@@ -101,16 +110,11 @@
{{ 'Created' | translate }}
</th>
<td mat-cell *matCellDef="let element">
- @if (element.metadata) {
+ @if (element.createdAtEpochMs !== null) {
<div>
- {{
- this.formatDate(
- element.metadata.createdAtEpochMs
- )
- }}
+ {{ formatDate(element.createdAtEpochMs) }}
</div>
- }
- @if (!element.metadata) {
+ } @else {
<div>–</div>
}
</td>
@@ -120,13 +124,9 @@
<button
mat-menu-item
[attr.data-cy]="
- 'show-data-view-' +
- element.baseAppearanceConfig.widgetTitle.replaceAll(
- ' ',
- ''
- )
+ 'show-data-view-' + element.name.replaceAll(' ', '')
"
- (click)="openDataView(element, false)"
+ (click)="openChart(element, false)"
>
<mat-icon>visibility</mat-icon>
<span>{{ 'Show' | translate }}</span>
@@ -135,13 +135,9 @@
<button
mat-menu-item
[attr.data-cy]="
- 'edit-data-view-' +
-
element.baseAppearanceConfig.widgetTitle.replaceAll(
- ' ',
- ''
- )
+ 'edit-data-view-' + element.name.replaceAll(' ',
'')
"
- (click)="openDataView(element, true)"
+ (click)="openChart(element, true)"
>
<mat-icon>edit</mat-icon>
<span>{{ 'Edit chart' | translate }}</span>
@@ -151,10 +147,7 @@
<button
[attr.data-cy]="
'open-manage-permissions-' +
-
element.baseAppearanceConfig.widgetTitle.replaceAll(
- ' ',
- ''
- )
+ element.name.replaceAll(' ', '')
"
mat-menu-item
(click)="showManageDialog(element)"
@@ -164,7 +157,7 @@
</button>
}
@if (hasDataExplorerWritePrivileges) {
- <button mat-menu-item (click)="cloneDataView(element)">
+ <button mat-menu-item (click)="cloneChart(element)">
<mat-icon>flip_to_front</mat-icon>
<span>{{ 'Clone chart' | translate }}</span>
</button>
@@ -173,11 +166,8 @@
<button
mat-menu-item
[matTooltip]=""
- [attr.data-cy]="
- 'delete-data-view-' +
- element.baseAppearanceConfig.widgetTitle
- "
- (click)="deleteDataView(element)"
+ [attr.data-cy]="'delete-data-view-' + element.name"
+ (click)="deleteChart(element)"
>
<mat-icon>delete</mat-icon>
<span>{{ 'Delete chart' | translate }}</span>
diff --git
a/ui/src/app/chart/components/chart-overview/chart-overview-table/chart-overview-table.component.ts
b/ui/src/app/chart/components/chart-overview/chart-overview-table/chart-overview-table.component.ts
index 1ff0ca0604..0968a4a169 100644
---
a/ui/src/app/chart/components/chart-overview/chart-overview-table/chart-overview-table.component.ts
+++
b/ui/src/app/chart/components/chart-overview/chart-overview-table/chart-overview-table.component.ts
@@ -16,7 +16,14 @@
*
*/
-import { Component, inject, Input, OnInit, ViewChild } from '@angular/core';
+import {
+ Component,
+ inject,
+ Input,
+ OnDestroy,
+ OnInit,
+ ViewChild,
+} from '@angular/core';
import {
MatCell,
MatCellDef,
@@ -27,6 +34,7 @@ import {
} from '@angular/material/table';
import {
ChartService,
+ ChartSummaryDto,
DataExplorerWidgetModel,
} from '@streampipes/platform-services';
import {
@@ -56,6 +64,7 @@ import {
import { MatMenuItem } from '@angular/material/menu';
import { MatIcon } from '@angular/material/icon';
import { MatTooltip } from '@angular/material/tooltip';
+import { ChartRegistry } from
'../../../../chart-shared/registry/chart-registry.service';
type ManageableChart = DataExplorerWidgetModel & {
name: string;
@@ -87,16 +96,17 @@ type ManageableChart = DataExplorerWidgetModel & {
TranslatePipe,
],
})
-export class ChartOverviewTableComponent implements OnInit {
+export class ChartOverviewTableComponent implements OnInit, OnDestroy {
@Input()
hasDataExplorerWritePrivileges: boolean;
@ViewChild(MatSort)
sort: MatSort;
- dataSource = new MatTableDataSource<DataExplorerWidgetModel>();
+ dataSource = new MatTableDataSource<ChartSummaryDto>();
displayedColumns: string[] = [
'name',
+ 'chartType',
'assetContext',
'lastModified',
'createdAt',
@@ -106,8 +116,8 @@ export class ChartOverviewTableComponent implements OnInit {
resourceLinkType: 'chart',
resourceIdKey: 'elementId',
};
- charts: DataExplorerWidgetModel[] = [];
- filteredCharts: DataExplorerWidgetModel[] = [];
+ charts: ChartSummaryDto[] = [];
+ filteredCharts: ChartSummaryDto[] = [];
private dataViewService = inject(ChartService);
private dialog = inject(MatDialog);
@@ -116,9 +126,14 @@ export class ChartOverviewTableComponent implements OnInit
{
private dateFormatService = inject(DateFormatService);
private routingService = inject(ChartRoutingService);
private assetFilterService = inject(SpAssetBrowserService);
+ private chartRegistryService = inject(ChartRegistry);
assetFilter$: Subscription;
currentFilterIds = new Set<string>();
+ private chartTypeMetadata = new Map<
+ string,
+ { icon: string; label: string }
+ >();
ngOnInit(): void {
this.assetFilterService.applyAssetLinkType('chart');
@@ -130,95 +145,104 @@ export class ChartOverviewTableComponent implements
OnInit {
this.dataSource.sortingDataAccessor = (chart, column) => {
if (column === 'name') {
- return chart.baseAppearanceConfig.widgetTitle;
+ return chart.name;
} else if (column === 'lastModified') {
- return chart.metadata.lastModifiedEpochMs;
+ return chart.lastModifiedEpochMs;
} else if (column === 'createdAt') {
- return chart.metadata.createdAtEpochMs;
+ return chart.createdAtEpochMs;
+ } else if (column === 'chartType') {
+ return chart.widgetType;
}
return chart[column];
};
- this.getDataViews();
+ this.getCharts();
}
- getDataViews(): void {
- this.dataViewService.getAllCharts().subscribe(widgets => {
- this.charts = widgets.sort((a, b) =>
- a.baseAppearanceConfig.widgetTitle.localeCompare(
- b.baseAppearanceConfig.widgetTitle,
- ),
+ getCharts(): void {
+ this.dataViewService.getChartSummary().subscribe(chartSummary => {
+ this.charts = chartSummary.resources.sort((a, b) =>
+ a.name.localeCompare(b.name),
);
this.applyChartFilters(this.currentFilterIds);
});
}
- openDataView(dataView: DataExplorerWidgetModel, editMode: boolean): void {
+ ngOnDestroy(): void {
+ this.assetFilter$?.unsubscribe();
+ }
+
+ openChart(dataView: ChartSummaryDto, editMode: boolean): void {
this.routingService.navigateToChart(
editMode && this.hasDataExplorerWritePrivileges,
dataView.elementId,
);
}
- showManageDialog(chart: DataExplorerWidgetModel) {
- const resource: ManageableChart = {
- ...chart,
- baseAppearanceConfig: { ...chart.baseAppearanceConfig },
- name: chart.baseAppearanceConfig.widgetTitle,
- description: '',
- };
- const resourceConfig:
ObjectManageDialogResourceConfig<ManageableChart> =
- {
- resourceLabel: 'Chart',
- nameLabel: 'Chart title',
- descriptionLabel: 'Chart description',
- nameProperty: 'name',
- assetLinkType: 'chart',
- assetLinkCheckboxLabel:
- 'Add the current chart to an existing asset',
- saveResource: resource => {
- resource.baseAppearanceConfig.widgetTitle = resource.name;
- const chartResource: Partial<ManageableChart> = {
- ...resource,
- };
- delete chartResource.name;
- delete chartResource.description;
- return this.dataViewService.updateChart(
- chartResource as DataExplorerWidgetModel,
- );
- },
+ showManageDialog(chartSummary: ChartSummaryDto) {
+ this.withChart(chartSummary, chart => {
+ const resource: ManageableChart = {
+ ...chart,
+ baseAppearanceConfig: { ...chart.baseAppearanceConfig },
+ name: chart.baseAppearanceConfig.widgetTitle,
+ description: '',
};
+ const resourceConfig:
ObjectManageDialogResourceConfig<ManageableChart> =
+ {
+ resourceLabel: 'Chart',
+ nameLabel: 'Chart title',
+ descriptionLabel: 'Chart description',
+ nameProperty: 'name',
+ assetLinkType: 'chart',
+ assetLinkCheckboxLabel:
+ 'Add the current chart to an existing asset',
+ saveResource: resource => {
+ resource.baseAppearanceConfig.widgetTitle =
+ resource.name;
+ const chartResource: Partial<ManageableChart> = {
+ ...resource,
+ };
+ delete chartResource.name;
+ delete chartResource.description;
+ return this.dataViewService.updateChart(
+ chartResource as DataExplorerWidgetModel,
+ );
+ },
+ };
- const dialogRef = this.dialogService.open(ObjectManageDialogComponent,
{
- panelType: PanelType.SLIDE_IN_PANEL,
- title: this.translateService.instant('Manage'),
- width: '50vw',
- data: {
- objectInstanceId: chart.elementId,
- resource,
- saveMode: 'immediate',
- resourceConfig,
- headerTitle:
- this.translateService.instant('Manage Chart ') +
- chart.baseAppearanceConfig.widgetTitle,
- },
- });
+ const dialogRef = this.dialogService.open(
+ ObjectManageDialogComponent,
+ {
+ panelType: PanelType.SLIDE_IN_PANEL,
+ title: this.translateService.instant('Manage'),
+ width: '50vw',
+ data: {
+ objectInstanceId: chart.elementId,
+ resource,
+ saveMode: 'immediate',
+ resourceConfig,
+ headerTitle:
+ this.translateService.instant('Manage Chart ') +
+ chart.baseAppearanceConfig.widgetTitle,
+ },
+ },
+ );
- dialogRef.afterClosed().subscribe(refresh => {
- if (refresh) {
- this.getDataViews();
- }
+ dialogRef.afterClosed().subscribe(refresh => {
+ if (refresh) {
+ this.getCharts();
+ }
+ });
});
}
- deleteDataView(dataView: DataExplorerWidgetModel) {
+ deleteChart(chart: ChartSummaryDto) {
const dialogRef = this.dialog.open(ConfirmDialogComponent, {
width: '600px',
data: {
title: this.translateService.instant(
'Are you sure you want to delete chart "{{chartTitle}}"?',
{
- chartTitle:
- dataView.baseAppearanceConfig.widgetTitle ?? '',
+ chartTitle: chart.name ?? '',
},
),
subtitle: this.translateService.instant(
@@ -231,17 +255,19 @@ export class ChartOverviewTableComponent implements
OnInit {
dialogRef.afterClosed().subscribe(result => {
if (result === 'confirm') {
this.dataViewService
- .deleteChart(dataView.elementId)
+ .deleteChart(chart.elementId)
.subscribe(() => {
- this.getDataViews();
+ this.getCharts();
});
}
});
}
- cloneDataView(dataView: DataExplorerWidgetModel) {
- this.dataViewService.cloneChart(dataView).subscribe(() => {
- this.getDataViews();
+ cloneChart(chartSummary: ChartSummaryDto) {
+ this.withChart(chartSummary, chart => {
+ this.dataViewService.cloneChart(chart).subscribe(() => {
+ this.getCharts();
+ });
});
}
@@ -259,15 +285,52 @@ export class ChartOverviewTableComponent implements
OnInit {
this.dataSource.data = this.filteredCharts;
}
+ getChartTypeIcon(chart: ChartSummaryDto): string {
+ return this.getChartTypeMetadata(chart.widgetType).icon;
+ }
+
+ getChartTypeName(chart: ChartSummaryDto): string {
+ return this.getChartTypeMetadata(chart.widgetType).label;
+ }
+
formatDate(timestamp?: number): string {
return this.dateFormatService.formatDate(timestamp);
}
- isLegacyMultiSourceChart(chart: DataExplorerWidgetModel): boolean {
- return (chart?.dataConfig?.sourceConfigs?.length ?? 0) > 1;
+ isLegacyMultiSourceChart(chart: ChartSummaryDto): boolean {
+ return chart.multiSourceChart;
}
- requiresAttention(chart: DataExplorerWidgetModel): boolean {
+ requiresAttention(chart: ChartSummaryDto): boolean {
return chart?.healthStatus === 'REQUIRES_ATTENTION';
}
+
+ private withChart(
+ chartSummary: ChartSummaryDto,
+ callback: (chart: DataExplorerWidgetModel) => void,
+ ): void {
+ this.dataViewService
+ .getChart(chartSummary.elementId)
+ .subscribe(chart => {
+ callback(chart);
+ });
+ }
+
+ private getChartTypeMetadata(widgetType: string): {
+ icon: string;
+ label: string;
+ } {
+ const cached = this.chartTypeMetadata.get(widgetType);
+ if (cached) {
+ return cached;
+ }
+
+ const template =
this.chartRegistryService.getChartTemplate(widgetType);
+ const metadata = {
+ icon: template?.icon ?? 'insert_chart',
+ label: template?.label ?? widgetType,
+ };
+ this.chartTypeMetadata.set(widgetType, metadata);
+ return metadata;
+ }
}
diff --git
a/ui/src/app/connect/components/existing-adapters/existing-adapters.component.ts
b/ui/src/app/connect/components/existing-adapters/existing-adapters.component.ts
index a639664909..01b82347ad 100644
---
a/ui/src/app/connect/components/existing-adapters/existing-adapters.component.ts
+++
b/ui/src/app/connect/components/existing-adapters/existing-adapters.component.ts
@@ -18,9 +18,9 @@
import { Component, inject, OnDestroy, OnInit, ViewChild } from
'@angular/core';
import {
- AdapterDescription,
AdapterMonitoringService,
AdapterService,
+ AdapterSummaryDto,
PipelineElementAssetService,
SpLogMessage,
SpMetricsEntry,
@@ -110,8 +110,8 @@ import { DatePipe } from '@angular/common';
],
})
export class ExistingAdaptersComponent implements OnInit, OnDestroy {
- existingAdapters: AdapterDescription[] = [];
- filteredAdapters: AdapterDescription[] = [];
+ existingAdapters: AdapterSummaryDto[] = [];
+ filteredAdapters: AdapterSummaryDto[] = [];
currentFilter: AdapterFilterSettingsModel;
operationInProgressAdapterId: string | undefined;
@@ -135,7 +135,7 @@ export class ExistingAdaptersComponent implements OnInit,
OnDestroy {
resourceIdKey: 'elementId',
};
- dataSource: MatTableDataSource<AdapterDescription> =
+ dataSource: MatTableDataSource<AdapterSummaryDto> =
new MatTableDataSource();
adapterMetrics: Record<string, SpMetricsEntry> = {};
@@ -193,34 +193,46 @@ export class ExistingAdaptersComponent implements OnInit,
OnDestroy {
};
}
- startAdapter(adapter: AdapterDescription) {
+ startAdapter(adapter: AdapterSummaryDto): void {
this.operationInProgressAdapterId = adapter.elementId;
- this.adapterService.startAdapter(adapter).subscribe(
- _ => {
- this.getAdaptersRunning();
- },
- error => {
- this.operationInProgressAdapterId = undefined;
- this.openAdapterStatusErrorDialog(adapter, error.error, true);
- },
- );
+ this.adapterService
+ .startAdapterByElementId(adapter.elementId)
+ .subscribe(
+ _ => {
+ this.getAdaptersRunning();
+ },
+ error => {
+ this.operationInProgressAdapterId = undefined;
+ this.openAdapterStatusErrorDialog(
+ adapter,
+ error.error,
+ true,
+ );
+ },
+ );
}
- stopAdapter(adapter: AdapterDescription, forceStop = false) {
+ stopAdapter(adapter: AdapterSummaryDto, forceStop = false): void {
this.operationInProgressAdapterId = adapter.elementId;
- this.adapterService.stopAdapter(adapter, forceStop).subscribe(
- _ => {
- this.getAdaptersRunning();
- },
- error => {
- this.operationInProgressAdapterId = undefined;
- this.openAdapterStatusErrorDialog(adapter, error.error, false);
- },
- );
+ this.adapterService
+ .stopAdapterByElementId(adapter.elementId, forceStop)
+ .subscribe(
+ _ => {
+ this.getAdaptersRunning();
+ },
+ error => {
+ this.operationInProgressAdapterId = undefined;
+ this.openAdapterStatusErrorDialog(
+ adapter,
+ error.error,
+ false,
+ );
+ },
+ );
}
startStopSelectedAdapters(
- event: SpTableMultiActionExecuteEvent<AdapterDescription>,
+ event: SpTableMultiActionExecuteEvent<AdapterSummaryDto>,
) {
if (event.action !== 'start' && event.action !== 'stop') {
return;
@@ -253,10 +265,10 @@ export class ExistingAdaptersComponent implements OnInit,
OnDestroy {
}
openAdapterStatusErrorDialog(
- adapter: AdapterDescription,
+ adapter: AdapterSummaryDto,
message: SpLogMessage,
startAction: boolean,
- ) {
+ ): void {
const title = startAction
? this.startAdapterErrorText
: this.stopAdapterErrorText;
@@ -283,7 +295,7 @@ export class ExistingAdaptersComponent implements OnInit,
OnDestroy {
});
}
- getMonitoringInfos(adapters: AdapterDescription[]) {
+ getMonitoringInfos(adapters: AdapterSummaryDto[]): void {
const filteredElementIds = adapters.map(adapter => adapter.elementId);
this.adapterMonitoringService
@@ -293,7 +305,7 @@ export class ExistingAdaptersComponent implements OnInit,
OnDestroy {
});
}
- getIconUrl(adapter: AdapterDescription) {
+ getIconUrl(adapter: AdapterSummaryDto): string | undefined {
if (adapter.includedAssets?.some(asset => asset.startsWith('icon.'))) {
return (
this.pipelineElementAssetService.getAssetUrl(adapter.appId) +
@@ -302,7 +314,7 @@ export class ExistingAdaptersComponent implements OnInit,
OnDestroy {
}
}
- showPermissionsDialog(adapter: AdapterDescription) {
+ showPermissionsDialog(adapter: AdapterSummaryDto): void {
const dialogRef = this.dialogService.open(
ObjectPermissionDialogComponent,
{
@@ -330,11 +342,11 @@ export class ExistingAdaptersComponent implements OnInit,
OnDestroy {
* Start edit mode
* @param adapter
*/
- editAdapter(adapter: AdapterDescription) {
+ editAdapter(adapter: AdapterSummaryDto): void {
this.router.navigate(['connect', 'edit', adapter.elementId]);
}
- deleteAdapter(adapter: AdapterDescription): void {
+ deleteAdapter(adapter: AdapterSummaryDto): void {
const dialogRef: DialogRef<DeleteAdapterDialogComponent> =
this.dialogService.open(DeleteAdapterDialogComponent, {
panelType: PanelType.STANDARD_PANEL,
@@ -353,12 +365,12 @@ export class ExistingAdaptersComponent implements OnInit,
OnDestroy {
}
getAdaptersRunning(): void {
- this.adapterService.getAdapters().subscribe(adapters => {
- this.existingAdapters = adapters;
+ this.adapterService.getAdapterSummary().subscribe(adapterSummary => {
+ this.existingAdapters = adapterSummary.resources;
this.existingAdapters.sort((a, b) => a.name.localeCompare(b.name));
this.applyAdapterFilters(this.currentFilterIds);
this.operationInProgressAdapterId = undefined;
- this.getMonitoringInfos(adapters);
+ this.getMonitoringInfos(this.existingAdapters);
setTimeout(() => {
this.dataSource.sort = this.sort;
});
@@ -367,21 +379,24 @@ export class ExistingAdaptersComponent implements OnInit,
OnDestroy {
applyAdapterFilters(elementIds: Set<string>): void {
this.currentFilterIds = elementIds;
- this.filteredAdapters = this.adapterFilter
- .transform(this.existingAdapters, this.currentFilter)
- .filter(a => {
- if (elementIds === undefined) {
- return false;
- } else if (elementIds.size === 0) {
- return true;
- } else {
- return elementIds.has(a.elementId);
- }
- });
+ this.filteredAdapters = (
+ this.adapterFilter.transform(
+ this.existingAdapters,
+ this.currentFilter,
+ ) as AdapterSummaryDto[]
+ ).filter(a => {
+ if (elementIds === undefined) {
+ return false;
+ } else if (elementIds.size === 0) {
+ return true;
+ } else {
+ return elementIds.has(a.elementId);
+ }
+ });
this.dataSource.data = this.filteredAdapters;
}
- startAdapterTutorial() {
+ startAdapterTutorial(): void {
this.shepherdService.startAdapterTour();
}
@@ -391,18 +406,18 @@ export class ExistingAdaptersComponent implements OnInit,
OnDestroy {
});
}
- applyFilter(filter: AdapterFilterSettingsModel) {
+ applyFilter(filter: AdapterFilterSettingsModel): void {
this.currentFilter = filter;
if (this.dataSource) {
this.applyAdapterFilters(this.currentFilterIds);
}
}
- navigateToDetailsOverviewPage(adapter: AdapterDescription): void {
+ navigateToDetailsOverviewPage(adapter: AdapterSummaryDto): void {
this.router.navigate(['connect', 'details', adapter.elementId]);
}
- ngOnDestroy() {
+ ngOnDestroy(): void {
this.user$?.unsubscribe();
this.tutorial$?.unsubscribe();
this.assetFilter$?.unsubscribe();
diff --git
a/ui/src/app/connect/dialog/delete-adapter-dialog/delete-adapter-dialog.component.ts
b/ui/src/app/connect/dialog/delete-adapter-dialog/delete-adapter-dialog.component.ts
index f1bff10041..0bfce6884e 100644
---
a/ui/src/app/connect/dialog/delete-adapter-dialog/delete-adapter-dialog.component.ts
+++
b/ui/src/app/connect/dialog/delete-adapter-dialog/delete-adapter-dialog.component.ts
@@ -19,6 +19,7 @@
import { Component, Input, inject } from '@angular/core';
import {
AdapterDescription,
+ AdapterSummaryDto,
AdapterService,
} from '@streampipes/platform-services';
import { DialogRef } from '@streampipes/shared-ui';
@@ -52,7 +53,7 @@ export class DeleteAdapterDialogComponent {
private dataMarketplaceService = inject(AdapterService);
@Input()
- adapter: AdapterDescription;
+ adapter: AdapterDescription | AdapterSummaryDto;
isInProgress = false;
currentStatus: any;
@@ -71,7 +72,10 @@ export class DeleteAdapterDialogComponent {
this.deleteAssociatedPipelines = deleteAssociatedPipelines;
this.dataMarketplaceService
- .deleteAdapter(this.adapter, deleteAssociatedPipelines)
+ .deleteAdapterById(
+ this.adapter.elementId,
+ deleteAssociatedPipelines,
+ )
.subscribe(
_data => {
this.close(true);
diff --git
a/ui/src/app/connect/dialog/start-all-adapters/all-adapter-actions-dialog.component.ts
b/ui/src/app/connect/dialog/start-all-adapters/all-adapter-actions-dialog.component.ts
index dd74983228..67a651f329 100644
---
a/ui/src/app/connect/dialog/start-all-adapters/all-adapter-actions-dialog.component.ts
+++
b/ui/src/app/connect/dialog/start-all-adapters/all-adapter-actions-dialog.component.ts
@@ -20,6 +20,7 @@ import { Component, Input, OnInit, inject } from
'@angular/core';
import { DialogRef } from '@streampipes/shared-ui';
import {
AdapterDescription,
+ AdapterSummaryDto,
AdapterService,
} from '@streampipes/platform-services';
import { TranslatePipe, TranslateService } from '@ngx-translate/core';
@@ -39,9 +40,9 @@ export class AllAdapterActionsComponent implements OnInit {
private translate = inject(TranslateService);
@Input()
- adapters: AdapterDescription[];
+ adapters: Array<AdapterDescription | AdapterSummaryDto>;
- adaptersToModify: AdapterDescription[];
+ adaptersToModify: Array<AdapterDescription | AdapterSummaryDto>;
actionStatus: any;
actionFinished: boolean;
page: string;
@@ -89,7 +90,7 @@ export class AllAdapterActionsComponent implements OnInit {
});
}
- initiateAction(adapter: AdapterDescription, index) {
+ initiateAction(adapter: AdapterDescription | AdapterSummaryDto, index) {
this.actionRunning = true;
this.actionStatus.push({
name: adapter.name,
@@ -99,10 +100,10 @@ export class AllAdapterActionsComponent implements OnInit {
this.runAdapterAction(adapter, index);
}
- runAdapterAction(adapter: AdapterDescription, index) {
+ runAdapterAction(adapter: AdapterDescription | AdapterSummaryDto, index) {
const observable = this.action
- ? this.adapterService.startAdapter(adapter)
- : this.adapterService.stopAdapter(adapter);
+ ? this.adapterService.startAdapterByElementId(adapter.elementId)
+ : this.adapterService.stopAdapterByElementId(adapter.elementId);
observable
.subscribe(data => {
this.actionStatus[index].status = data.success
diff --git a/ui/src/app/connect/filter/adapter-filter.pipe.ts
b/ui/src/app/connect/filter/adapter-filter.pipe.ts
index d594dc8d02..1381c1dcf7 100644
--- a/ui/src/app/connect/filter/adapter-filter.pipe.ts
+++ b/ui/src/app/connect/filter/adapter-filter.pipe.ts
@@ -17,7 +17,10 @@
*/
import { Injectable, Pipe, PipeTransform } from '@angular/core';
-import { AdapterDescription } from '@streampipes/platform-services';
+import {
+ AdapterDescription,
+ AdapterSummaryDto,
+} from '@streampipes/platform-services';
import { AdapterFilterSettingsModel } from
'../model/adapter-filter-settings.model';
@Pipe({ name: 'adapterFilter' })
@@ -26,9 +29,9 @@ export class AdapterFilterPipe implements PipeTransform {
constructor() {}
transform(
- adapterDescriptions: AdapterDescription[],
+ adapterDescriptions: Array<AdapterDescription | AdapterSummaryDto>,
activeFilters: AdapterFilterSettingsModel,
- ): AdapterDescription[] {
+ ): Array<AdapterDescription | AdapterSummaryDto> {
if (!activeFilters) {
return adapterDescriptions;
} else {
@@ -39,7 +42,7 @@ export class AdapterFilterPipe implements PipeTransform {
}
private meetsFilterCondition(
- adapterDescription: AdapterDescription,
+ adapterDescription: AdapterDescription | AdapterSummaryDto,
activeFilters: AdapterFilterSettingsModel,
): boolean {
return this.meetsFilterTextCondition(
@@ -49,7 +52,7 @@ export class AdapterFilterPipe implements PipeTransform {
}
private meetsFilterTextCondition(
- adapterDescription: AdapterDescription,
+ adapterDescription: AdapterDescription | AdapterSummaryDto,
filterTerm: string,
): boolean {
if (filterTerm === undefined || filterTerm === '') {
diff --git
a/ui/src/app/dashboard/components/overview/dashboard-overview-table/dashboard-overview-table.component.html
b/ui/src/app/dashboard/components/overview/dashboard-overview-table/dashboard-overview-table.component.html
index fec74756b8..561f4657c3 100644
---
a/ui/src/app/dashboard/components/overview/dashboard-overview-table/dashboard-overview-table.component.html
+++
b/ui/src/app/dashboard/components/overview/dashboard-overview-table/dashboard-overview-table.component.html
@@ -61,7 +61,7 @@
<td mat-cell *matCellDef="let element">
@if (element.lastModifiedEpochMs !== null) {
<div>
- {{ this.formatDate(element.lastModifiedEpochMs) }}
+ {{ formatDate(element.lastModifiedEpochMs) }}
</div>
} @else {
<div>–</div>
@@ -76,7 +76,7 @@
<td mat-cell *matCellDef="let element">
@if (element.createdAtEpochMs !== null) {
<div>
- {{ this.formatDate(element.createdAtEpochMs) }}
+ {{ formatDate(element.createdAtEpochMs) }}
</div>
} @else {
<div>–</div>
diff --git
a/ui/src/app/dashboard/components/overview/dashboard-overview-table/dashboard-overview-table.component.ts
b/ui/src/app/dashboard/components/overview/dashboard-overview-table/dashboard-overview-table.component.ts
index d31c558a07..e1061d8447 100644
---
a/ui/src/app/dashboard/components/overview/dashboard-overview-table/dashboard-overview-table.component.ts
+++
b/ui/src/app/dashboard/components/overview/dashboard-overview-table/dashboard-overview-table.component.ts
@@ -138,7 +138,9 @@ export class DashboardOverviewTableComponent implements
OnInit, OnDestroy {
});
this.dataSource.sortingDataAccessor = (dashboard, column) => {
- if (column === 'lastModified') {
+ if (column === 'name') {
+ return dashboard.name;
+ } else if (column === 'lastModified') {
return dashboard.lastModifiedEpochMs;
} else if (column === 'createdAt') {
return dashboard.createdAtEpochMs;
@@ -149,49 +151,46 @@ export class DashboardOverviewTableComponent implements
OnInit, OnDestroy {
this.getDashboards();
}
- showManageDialog(dashboard: DashboardSummaryDto) {
- this.dashboardService
- .getDashboard(dashboard.elementId)
- .subscribe(resource => {
- const resourceConfig:
ObjectManageDialogResourceConfig<Dashboard> =
- {
- resourceLabel: 'Dashboard',
- nameLabel: 'Name',
- descriptionLabel: 'Description',
- nameProperty: 'name',
- assetLinkType: 'dashboard',
- assetLinkCheckboxLabel:
- 'Add the current dashboard to an existing asset',
- saveResource: resource =>
- this.dashboardService.updateDashboard(resource),
- };
- const dialogRef = this.dialogService.open(
- ObjectManageDialogComponent,
- {
- panelType: PanelType.SLIDE_IN_PANEL,
- title: this.translateService.instant('Manage'),
- width: '50vw',
- data: {
- objectInstanceId: resource.elementId,
- resource: { ...resource },
- saveMode: 'immediate',
- resourceConfig,
- headerTitle:
- this.translateService.instant(
- 'Manage Dashboard ',
- ) + resource.name,
- },
+ showManageDialog(dashboard: DashboardSummaryDto): void {
+ this.withDashboard(dashboard, resource => {
+ const resourceConfig: ObjectManageDialogResourceConfig<Dashboard> =
+ {
+ resourceLabel: 'Dashboard',
+ nameLabel: 'Name',
+ descriptionLabel: 'Description',
+ nameProperty: 'name',
+ assetLinkType: 'dashboard',
+ assetLinkCheckboxLabel:
+ 'Add the current dashboard to an existing asset',
+ saveResource: resource =>
+ this.dashboardService.updateDashboard(resource),
+ };
+ const dialogRef = this.dialogService.open(
+ ObjectManageDialogComponent,
+ {
+ panelType: PanelType.SLIDE_IN_PANEL,
+ title: this.translateService.instant('Manage'),
+ width: '50vw',
+ data: {
+ objectInstanceId: resource.elementId,
+ resource: { ...resource },
+ saveMode: 'immediate',
+ resourceConfig,
+ headerTitle:
+ this.translateService.instant('Manage Dashboard ')
+
+ resource.name,
},
- );
- dialogRef.afterClosed().subscribe(refresh => {
- if (refresh) {
- this.getDashboards();
- }
- });
+ },
+ );
+ dialogRef.afterClosed().subscribe(refresh => {
+ if (refresh) {
+ this.getDashboards();
+ }
});
+ });
}
- openDeleteDashboardDialog(dashboard: DashboardSummaryDto) {
+ openDeleteDashboardDialog(dashboard: DashboardSummaryDto): void {
const dialogRef = this.dialog.open(ConfirmDialogComponent, {
width: '600px',
data: {
@@ -219,15 +218,15 @@ export class DashboardOverviewTableComponent implements
OnInit, OnDestroy {
});
}
- showDashboard(dashboard: DashboardSummaryDto) {
+ showDashboard(dashboard: DashboardSummaryDto): void {
this.routingService.navigateToDashboard(false, dashboard.elementId);
}
- editDashboard(dashboard: DashboardSummaryDto) {
+ editDashboard(dashboard: DashboardSummaryDto): void {
this.routingService.navigateToDashboard(true, dashboard.elementId);
}
- getDashboards() {
+ getDashboards(): void {
this.dashboardService.getDashboardSummary().subscribe(data => {
this.dashboards = data.resources.sort((a, b) =>
a.name.localeCompare(b.name),
@@ -237,9 +236,9 @@ export class DashboardOverviewTableComponent implements
OnInit, OnDestroy {
}
applyDashboardFilters(elementIds: Set<string>): void {
- if (elementIds == undefined) {
+ if (elementIds === undefined) {
this.filteredDashboards = [];
- } else if (elementIds.size == 0) {
+ } else if (elementIds.size === 0) {
this.filteredDashboards = this.dashboards;
} else {
this.filteredDashboards = this.dashboards.filter(a =>
@@ -254,7 +253,7 @@ export class DashboardOverviewTableComponent implements
OnInit, OnDestroy {
return this.dateFormatService.formatDate(timestamp);
}
- openDashboardInKioskMode(dashboard: Dashboard) {
+ openDashboardInKioskMode(dashboard: DashboardSummaryDto): void {
this.router.navigate(['dashboard-kiosk', dashboard.elementId]);
}
@@ -263,33 +262,42 @@ export class DashboardOverviewTableComponent implements
OnInit, OnDestroy {
}
openCloneDialog(dashboardSummary: DashboardSummaryDto): void {
- this.dashboardService
- .getDashboard(dashboardSummary.elementId)
- .subscribe(dashboard => {
- const dialogRef = this.dialogService.open(
- CloneDashboardDialogComponent,
- {
- panelType: PanelType.SLIDE_IN_PANEL,
- title: this.translateService.instant('Clone
dashboard'),
- width: '50vw',
- data: {
- dashboard: dashboard,
- },
+ this.withDashboard(dashboardSummary, dashboard => {
+ const dialogRef = this.dialogService.open(
+ CloneDashboardDialogComponent,
+ {
+ panelType: PanelType.SLIDE_IN_PANEL,
+ title: this.translateService.instant('Clone dashboard'),
+ width: '50vw',
+ data: {
+ dashboard: dashboard,
},
- );
- dialogRef.afterClosed().subscribe(result => {
- if (result) {
- this.getDashboards();
- }
- });
+ },
+ );
+ dialogRef.afterClosed().subscribe(result => {
+ if (result) {
+ this.getDashboards();
+ }
});
+ });
}
- onRowClicked(dashboard: DashboardSummaryDto) {
+ onRowClicked(dashboard: DashboardSummaryDto): void {
this.showDashboard(dashboard);
}
- ngOnDestroy() {
+ ngOnDestroy(): void {
this.assetFilter$?.unsubscribe();
}
+
+ private withDashboard(
+ dashboardSummary: DashboardSummaryDto,
+ callback: (dashboard: Dashboard) => void,
+ ): void {
+ this.dashboardService
+ .getDashboard(dashboardSummary.elementId)
+ .subscribe(dashboard => {
+ callback(dashboard);
+ });
+ }
}
diff --git
a/ui/src/app/dataset/components/datalake-configuration/datalake-configuration-entry.ts
b/ui/src/app/dataset/components/datalake-configuration/datalake-configuration-entry.ts
index 48bdda2273..a6b3aadef5 100644
---
a/ui/src/app/dataset/components/datalake-configuration/datalake-configuration-entry.ts
+++
b/ui/src/app/dataset/components/datalake-configuration/datalake-configuration-entry.ts
@@ -1,5 +1,3 @@
-import { RetentionTimeConfig } from '@streampipes/platform-services';
-
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
@@ -17,8 +15,10 @@ import { RetentionTimeConfig } from
'@streampipes/platform-services';
* limitations under the License.
*
*/
+
export class DataLakeConfigurationEntry {
public name: string;
+ public measureName: string;
public pipelines: string[] = [];
public eventsTotal = 0;
public eventsLatest = 0;
@@ -26,7 +26,9 @@ export class DataLakeConfigurationEntry {
public eventsLatestLoading = false;
public remove = true;
public elementId: string;
- public retention: RetentionTimeConfig;
+ public retentionConfigured = false;
+ public lastExport: string | null = null;
+ public lastRetentionStatus: boolean | null = null;
constructor() {}
}
diff --git
a/ui/src/app/dataset/components/datalake-configuration/datalake-configuration.component.html
b/ui/src/app/dataset/components/datalake-configuration/datalake-configuration.component.html
index 7f0a7a3db5..198b41c9f0 100644
---
a/ui/src/app/dataset/components/datalake-configuration/datalake-configuration.component.html
+++
b/ui/src/app/dataset/components/datalake-configuration/datalake-configuration.component.html
@@ -199,9 +199,9 @@
<i
class="material-icons"
[ngStyle]="{
- color:
configurationEntry?.retention
+ color:
configurationEntry.retentionConfigured
? 'var(--color-success)'
- : 'var(--color-neutral',
+ : 'var(--color-neutral)',
}"
>history</i
>
@@ -226,19 +226,15 @@
fxLayout="row"
fxLayoutAlign="start center"
>
- @if (configurationEntry?.retention) {
+ @if (configurationEntry.retentionConfigured) {
<button
color="accent"
mat-icon-button
[matTooltip]="
('Open Retention Log' | translate)
+
- (configurationEntry?.retention
- ?.retentionExportConfig
- ?.lastExport
+ (configurationEntry.lastExport
? ' • ' +
- (configurationEntry.retention
- .retentionExportConfig
- .lastExport
+
(configurationEntry.lastExport
| date
: 'yyyy-MM-dd
HH:mm:ss')
: '')
@@ -247,9 +243,7 @@
matTooltipPosition="above"
(click)="
openRetentionLog(
- configurationEntry?.retention
- .retentionExportConfig
- .retentionLog
+ configurationEntry.elementId
)
"
>
@@ -257,22 +251,12 @@
class="material-icons"
[ngStyle]="{
color:
- configurationEntry
- ?.retention
- ?.retentionExportConfig
- ?.retentionLog
- ?.length &&
-
configurationEntry.retention
- .retentionExportConfig
- .retentionLog[
- configurationEntry
- .retention
-
.retentionExportConfig
- .retentionLog
- .length - 1
- ].status
- ? 'green'
- : 'red',
+
configurationEntry.lastRetentionStatus ===
+ null
+ ?
'var(--color-neutral)'
+ :
configurationEntry.lastRetentionStatus
+ ? 'green'
+ : 'red',
}"
>list_alt</i
>
diff --git
a/ui/src/app/dataset/components/datalake-configuration/datalake-configuration.component.ts
b/ui/src/app/dataset/components/datalake-configuration/datalake-configuration.component.ts
index 2de04b35a0..fcfc0472aa 100644
---
a/ui/src/app/dataset/components/datalake-configuration/datalake-configuration.component.ts
+++
b/ui/src/app/dataset/components/datalake-configuration/datalake-configuration.component.ts
@@ -39,12 +39,11 @@ import {
} from '@angular/material/table';
import { DataLakeConfigurationEntry } from './datalake-configuration-entry';
import {
- ChartService,
- DataLakeMeasure,
DatalakeRestService,
+ DataLakeMeasure,
+ DatasetSummaryDto,
ExportProviderService,
ExportProviderSettings,
- RetentionLog,
} from '@streampipes/platform-services';
import { MatPaginator } from '@angular/material/paginator';
import { MatSort, MatSortHeader } from '@angular/material/sort';
@@ -143,7 +142,6 @@ export class DatalakeConfigurationComponent
spTable!: SpTableComponent<DataLakeConfigurationEntry>;
private datalakeRestService = inject(DatalakeRestService);
- private dataViewDataExplorerService = inject(ChartService);
private dialogService = inject(DialogService);
private breadcrumbService = inject(SpBreadcrumbService);
private exportProviderRestService = inject(ExportProviderService);
@@ -227,7 +225,7 @@ export class DatalakeConfigurationComponent
this.assetFilter$?.unsubscribe();
}
- loadAvailableExportProvider() {
+ loadAvailableExportProvider(): void {
this.availableExportProvider = [];
this.exportProviderRestService
.getAllExportProviders()
@@ -237,50 +235,23 @@ export class DatalakeConfigurationComponent
});
}
- loadAvailableMeasurements() {
+ loadAvailableMeasurements(): void {
this.availableMeasurements = [];
- // get all available measurements that are stored in the data lake
this.datalakeRestService
- .getAllMeasurementSeries()
- .subscribe(allMeasurements => {
- // get all measurements that are still used in pipelines
- this.dataViewDataExplorerService
- .getAllPersistedDataStreams()
- .subscribe(inUseMeasurements => {
- allMeasurements.forEach(measurement => {
- const entry = new DataLakeConfigurationEntry();
- entry.elementId = measurement.elementId;
- entry.name = measurement.measureName;
- entry.eventsLatest = -1;
- entry.eventsTotal = -1;
- if (measurement?.retentionTime != null) {
- entry.retention = measurement.retentionTime;
- }
- inUseMeasurements.forEach(inUseMeasurement => {
- if (
- inUseMeasurement.measureName ===
- measurement.measureName
- ) {
- entry.pipelines.push(
- inUseMeasurement.pipelineName,
- );
- if (inUseMeasurement.pipelineIsRunning) {
- entry.remove = false;
- }
- }
- });
- this.availableMeasurements.push(entry);
- });
-
- this.availableMeasurements.sort((a, b) =>
- a.name.localeCompare(b.name),
- );
- this.applyMeasurementFilters(this.currentFilterIds);
- });
+ .getMeasurementSummary()
+ .subscribe(datasetSummary => {
+ this.availableMeasurements = datasetSummary.resources.map(
+ measurement => this.toConfigurationEntry(measurement),
+ );
+
+ this.availableMeasurements.sort((a, b) =>
+ a.name.localeCompare(b.name),
+ );
+ this.applyMeasurementFilters(this.currentFilterIds);
});
}
- applyMeasurementFilters(elementIds: Set<string>) {
+ applyMeasurementFilters(elementIds: Set<string>): void {
this.currentFilterIds = elementIds;
if (elementIds === undefined) {
this.filteredMeasurements = [];
@@ -317,7 +288,7 @@ export class DatalakeConfigurationComponent
}
}
- createExportProvider(provider: ExportProviderSettings | null) {
+ createExportProvider(provider: ExportProviderSettings | null): void {
const dialogRef: DialogRef<ExportProviderComponent> =
this.dialogService.open(ExportProviderComponent, {
panelType: PanelType.SLIDE_IN_PANEL,
@@ -333,7 +304,7 @@ export class DatalakeConfigurationComponent
});
}
- cleanDatalakeIndex(measurementIndex: string) {
+ cleanDatalakeIndex(measurementIndex: string): void {
const dialogRef: DialogRef<DeleteDatalakeIndexComponent> =
this.dialogService.open(DeleteDatalakeIndexComponent, {
panelType: PanelType.STANDARD_PANEL,
@@ -352,7 +323,7 @@ export class DatalakeConfigurationComponent
});
}
- deleteDatalakeIndex(measurementIndex: string) {
+ deleteDatalakeIndex(measurementIndex: string): void {
const dialogRef: DialogRef<DeleteDatalakeIndexComponent> =
this.dialogService.open(DeleteDatalakeIndexComponent, {
panelType: PanelType.STANDARD_PANEL,
@@ -371,7 +342,7 @@ export class DatalakeConfigurationComponent
});
}
- deleteExportProvider(providerId: string) {
+ deleteExportProvider(providerId: string): void {
const dialogRef: DialogRef<DeleteExportProviderComponent> =
this.dialogService.open(DeleteExportProviderComponent, {
panelType: PanelType.STANDARD_PANEL,
@@ -388,7 +359,7 @@ export class DatalakeConfigurationComponent
}
});
}
- testExportProvider(providerId: string) {
+ testExportProvider(providerId: string): void {
const dialogRef: DialogRef<ExportProviderConnectionTestComponent> =
this.dialogService.open(ExportProviderConnectionTestComponent, {
panelType: PanelType.STANDARD_PANEL,
@@ -408,7 +379,7 @@ export class DatalakeConfigurationComponent
});
}
- openDownloadDialog(measurementName: string) {
+ openDownloadDialog(measurementName: string): void {
this.dialogService.open(DataDownloadDialogComponent, {
panelType: PanelType.SLIDE_IN_PANEL,
title: this.translateService.instant('Download data'),
@@ -421,7 +392,7 @@ export class DatalakeConfigurationComponent
});
}
- openRetentionDialog(measurementId: string) {
+ openRetentionDialog(measurementId: string): void {
const dialogRef: DialogRef<DataRetentionDialogComponent> =
this.dialogService.open(DataRetentionDialogComponent, {
panelType: PanelType.SLIDE_IN_PANEL,
@@ -444,37 +415,25 @@ export class DatalakeConfigurationComponent
});
}
- openRetentionLog(retentionLog: RetentionLog[]) {
- const dialogRef: DialogRef<DataRetentionLogDialogComponent> =
- this.dialogService.open(DataRetentionLogDialogComponent, {
- panelType: PanelType.STANDARD_PANEL,
- title: this.translateService.instant('Retention Log'),
- width: '100vw',
- data: {
- retentionLog: retentionLog,
- },
- });
-
- dialogRef.afterClosed().subscribe(data => {
- if (data) {
- setTimeout(() => {
- this.loadAvailableMeasurements();
- }, 1000);
- }
+ openRetentionLog(measurementId: string): void {
+ this.datalakeRestService.getMeasurement(measurementId).subscribe({
+ next: measurement => {
+ this.openRetentionLogDialog(measurement);
+ },
});
}
- onPageChange(event: any) {
+ onPageChange(event: any): void {
this.pageIndex = event.pageIndex;
this.pageSize = event.pageSize;
//this.receiveMeasurementSizes(this.pageIndex);
}
- receiveTotalMeasurementSize(entry: DataLakeConfigurationEntry) {
+ receiveTotalMeasurementSize(entry: DataLakeConfigurationEntry): void {
this.queryEntryCounts([entry.name], 'eventsTotal');
}
- receiveMeasurementSizes(pageIndex: number) {
+ receiveMeasurementSizes(pageIndex: number): void {
const start = pageIndex * this.pageSize;
const end = start + this.pageSize;
const measurements = this.filteredMeasurements
@@ -485,7 +444,7 @@ export class DatalakeConfigurationComponent
this.queryEntryCounts(measurements, 'eventsLatest', 7);
}
}
- showPermissionsDialog(element: DataLakeMeasure) {
+ showPermissionsDialog(element: DataLakeConfigurationEntry): void {
this.dialogService.open(ObjectPermissionDialogComponent, {
panelType: PanelType.SLIDE_IN_PANEL,
title: this.translateService.instant('Manage permissions'),
@@ -500,7 +459,7 @@ export class DatalakeConfigurationComponent
});
}
- openCsvImportDialog() {
+ openCsvImportDialog(): void {
const dialogRef: DialogRef<CsvImportDialogComponent> =
this.dialogService.open(CsvImportDialogComponent, {
panelType: PanelType.SLIDE_IN_PANEL,
@@ -553,4 +512,43 @@ export class DatalakeConfigurationComponent
}
});
}
+
+ private toConfigurationEntry(
+ measurement: DatasetSummaryDto,
+ ): DataLakeConfigurationEntry {
+ const entry = new DataLakeConfigurationEntry();
+ entry.elementId = measurement.elementId;
+ entry.name = measurement.measureName;
+ entry.measureName = measurement.measureName;
+ entry.pipelines = measurement.pipelines;
+ entry.retentionConfigured = measurement.retentionConfigured;
+ entry.lastExport = measurement.lastExport;
+ entry.lastRetentionStatus = measurement.lastRetentionStatus;
+ entry.remove = measurement.removable;
+ entry.eventsLatest = -1;
+ entry.eventsTotal = -1;
+ return entry;
+ }
+
+ private openRetentionLogDialog(measurement: DataLakeMeasure): void {
+ const dialogRef: DialogRef<DataRetentionLogDialogComponent> =
+ this.dialogService.open(DataRetentionLogDialogComponent, {
+ panelType: PanelType.STANDARD_PANEL,
+ title: this.translateService.instant('Retention Log'),
+ width: '100vw',
+ data: {
+ retentionLog:
+ measurement.retentionTime?.retentionExportConfig
+ ?.retentionLog ?? [],
+ },
+ });
+
+ dialogRef.afterClosed().subscribe(data => {
+ if (data) {
+ setTimeout(() => {
+ this.loadAvailableMeasurements();
+ }, 1000);
+ }
+ });
+ }
}