Skip to content

Commit

Permalink
fix(ui): taskrun filters and new charts
Browse files Browse the repository at this point in the history
  • Loading branch information
tchiotludo committed Jan 27, 2025
1 parent a69f8b9 commit f1c5555
Show file tree
Hide file tree
Showing 2 changed files with 57 additions and 83 deletions.
117 changes: 35 additions & 82 deletions ui/src/components/taskruns/TaskRuns.vue
Original file line number Diff line number Diff line change
Expand Up @@ -3,73 +3,20 @@
<section class="container" v-if="ready">
<data-table @page-changed="onPageChanged" ref="dataTable" :total="total" :max="maxTaskRunSetting">
<template #navbar>
<el-form-item>
<search-field />
</el-form-item>
<el-form-item>
<namespace-select
data-type="flow"
v-if="$route.name !== 'flows/update'"
:value="$route.query.namespace"
@update:model-value="onDataTableValue('namespace', $event)"
/>
</el-form-item>
<el-form-item>
<status-filter-buttons
:value="Utils.asArray($route.query.state)"
@update:model-value="onDataTableValue('state', $event)"
/>
</el-form-item>
<el-form-item>
<date-filter
@update:is-relative="onDateFilterTypeChange"
@update:filter-value="onDataTableValue"
/>
</el-form-item>
<el-form-item>
<label-filter
:model-value="$route.query.labels"
@update:model-value="onDataTableValue('labels', $event)"
/>
</el-form-item>
<el-form-item>
<el-input
:placeholder="$t('trigger execution id')"
clearable
:model-value="$route.query.triggerExecutionId"
@update:model-value="onDataTableValue('triggerExecutionId', $event)"
/>
</el-form-item>
<el-form-item>
<el-select
:placeholder="$t('trigger filter.title')"
:model-value="$route.query.childFilter"
:persistent="false"
@update:model-value="onDataTableValue('childFilter', $event === 'ALL' ? undefined : $event)"
>
<el-option
v-for="(col, val) in $tm('trigger filter.options')"
:key="val"
:label="col"
:value="val"
/>
</el-select>
</el-form-item>
<el-form-item>
<refresh-button class="float-right" @refresh="load" :can-auto-refresh="canAutoRefresh" />
</el-form-item>
<KestraFilter
prefix="taskruns"
:include="['namespace', 'state', 'scope', 'labels', 'child', 'relative_date', 'absolute_date']"
:buttons="{
refresh: {shown: true, callback: load},
settings: {shown: true, charts: {shown: true, value: showChart, callback: onShowChartChange}}
}"
/>
</template>

<template #top>
<state-global-chart
v-if="taskRunDaily"
class="mb-4"
:ready="dailyReady"
:data="taskRunDaily"
:start-date="startDate"
:end-date="endDate"
:type="stateGlobalChartTypes.TASKRUNS"
/>
<el-card v-if="showStatChart()" shadow="never" class="mb-4">
<ExecutionsBar v-if="taskRunDaily" :data="taskRunDaily" :total="executionsCount" />
</el-card>
</template>

<template #table>
Expand Down Expand Up @@ -156,8 +103,7 @@
</section>
</template>
<script setup>
import Utils from "../../utils/utils";
import DateFilter from "../executions/date-select/DateFilter.vue";
import KestraFilter from "../filter/KestraFilter.vue";
</script>
<script>
import {mapState} from "vuex";
Expand All @@ -167,43 +113,34 @@
import RouteContext from "../../mixins/routeContext";
import TopNavBar from "../../components/layout/TopNavBar.vue";
import DataTableActions from "../../mixins/dataTableActions";
import SearchField from "../layout/SearchField.vue";
import NamespaceSelect from "../namespace/NamespaceSelect.vue";
import RefreshButton from "../layout/RefreshButton.vue";
import StatusFilterButtons from "../layout/StatusFilterButtons.vue";
import StateGlobalChart from "../../components/stats/StateGlobalChart.vue";
import DateAgo from "../layout/DateAgo.vue";
import Kicon from "../Kicon.vue"
import RestoreUrl from "../../mixins/restoreUrl";
import {State} from "@kestra-io/ui-libs"
import Id from "../Id.vue";
import _merge from "lodash/merge";
import {stateGlobalChartTypes} from "../../utils/constants";
import LabelFilter from "../labels/LabelFilter.vue";
import {stateGlobalChartTypes, storageKeys} from "../../utils/constants";
import ExecutionsBar from "../../components/dashboard/components/charts/executions/Bar.vue"
export default {
mixins: [RouteContext, RestoreUrl, DataTableActions],
components: {
Status,
TextSearch,
DataTable,
SearchField,
NamespaceSelect,
RefreshButton,
StatusFilterButtons,
StateGlobalChart,
DateAgo,
Kicon,
Id,
LabelFilter,
TopNavBar
TopNavBar,
ExecutionsBar
},
data() {
return {
dailyReady: false,
isDefaultNamespaceAllow: true,
canAutoRefresh: false,
lastRefreshDate: new Date()
lastRefreshDate: new Date(),
showChart: ["true", null].includes(localStorage.getItem(storageKeys.SHOW_CHART)),
};
},
computed: {
Expand Down Expand Up @@ -234,7 +171,12 @@
// the default is PT30D
return this.$moment().subtract(30, "days").toISOString(true);
}
},
executionsCount() {
return [...this.taskRunDaily].reduce((a, b) => {
return a + Object.values(b.executionCounts).reduce((a, b) => a + b, 0);
}, 0);
},
},
created() {
this.$store.dispatch("taskrun/maxTaskRunSetting");
Expand All @@ -258,6 +200,17 @@
},
});
},
onShowChartChange(value) {
this.showChart = value;
localStorage.setItem(storageKeys.SHOW_CHART, value);
if (this.showChart) {
this.loadData();
}
},
showStatChart() {
return this.showChart;
},
loadQuery(base, stats) {
let queryFilter = this.queryWithFilter();
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package io.kestra.webserver.controllers.api;

import com.google.common.annotations.VisibleForTesting;
import io.kestra.core.models.executions.TaskRun;
import io.kestra.core.models.flows.State;
import io.kestra.core.repositories.ExecutionRepositoryInterface;
Expand All @@ -18,9 +19,11 @@
import io.swagger.v3.oas.annotations.Hidden;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.media.ExampleObject;
import jakarta.inject.Inject;
import jakarta.validation.constraints.Min;

import java.time.Duration;
import java.time.ZonedDateTime;
import java.util.List;

Expand All @@ -47,20 +50,26 @@ public PagedResults<TaskRun> findTaskRun(
@Parameter(description = "A flow id filter") @Nullable @QueryValue String flowId,
@Parameter(description = "The start datetime") @Nullable @Format("yyyy-MM-dd'T'HH:mm[:ss][.SSS][XXX]") @QueryValue ZonedDateTime startDate,
@Parameter(description = "The end datetime") @Nullable @Format("yyyy-MM-dd'T'HH:mm[:ss][.SSS][XXX]") @QueryValue ZonedDateTime endDate,
@Parameter(description = "A time range filter relative to the current time", examples = {
@ExampleObject(name = "Filter last 5 minutes", value = "PT5M"),
@ExampleObject(name = "Filter last 24 hours", value = "P1D")
}) @Nullable @QueryValue Duration timeRange,
@Parameter(description = "A state filter") @Nullable @QueryValue List<State.Type> state,
@Parameter(description = "A labels filter as a list of 'key:value'") @Nullable @QueryValue @Format("MULTI") List<String> labels,
@Parameter(description = "The trigger execution id") @Nullable @QueryValue String triggerExecutionId,
@Parameter(description = "A execution child filter") @Nullable @QueryValue ExecutionRepositoryInterface.ChildFilter childFilter
) {
validateTimeline(startDate, endDate);

final ZonedDateTime now = ZonedDateTime.now();

return PagedResults.of(executionRepository.findTaskRun(
PageableUtils.from(page, size, sort, executionRepository.sortMapping()),
query,
tenantService.resolveTenant(),
namespace,
flowId,
startDate,
resolveAbsoluteDateTime(startDate, timeRange, now),
endDate,
state,
RequestUtils.toMap(labels),
Expand All @@ -69,6 +78,18 @@ public PagedResults<TaskRun> findTaskRun(
));
}

@VisibleForTesting
ZonedDateTime resolveAbsoluteDateTime(ZonedDateTime absoluteDateTime, Duration timeRange, ZonedDateTime now) {
if (timeRange != null) {
if (absoluteDateTime != null) {
throw new IllegalArgumentException("Parameters 'startDate' and 'timeRange' are mutually exclusive");
}
return now.minus(timeRange.abs());
}

return absoluteDateTime;
}

@ExecuteOn(TaskExecutors.IO)
@Get(uri = "/maxTaskRunSetting")
@Hidden
Expand Down

0 comments on commit f1c5555

Please sign in to comment.