Skip to content

Commit

Permalink
feat: dashboard date-time settings (#3421)
Browse files Browse the repository at this point in the history
- #3538 
- #3179

---------

Co-authored-by: ktx-abhay <[email protected]>
  • Loading branch information
ktx-vaidehi and ktx-abhay committed May 21, 2024
1 parent 7d6e88c commit ee29091
Show file tree
Hide file tree
Showing 8 changed files with 176 additions and 52 deletions.
15 changes: 15 additions & 0 deletions src/common/meta/dashboards/v3/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@ pub struct Dashboard {
pub tabs: Vec<Tab>,
#[serde(skip_serializing_if = "Option::is_none")]
pub variables: Option<Variables>,
#[serde(skip_serializing_if = "Option::is_none")]
pub default_datetime_duration: Option<DateTimeOptions>,
}

#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, ToSchema)]
Expand Down Expand Up @@ -244,6 +246,19 @@ pub struct Variables {
pub show_dynamic_filters: Option<bool>,
}

#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct DateTimeOptions {
#[serde(rename = "type")]
pub typee: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub relative_time_period: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub start_time: Option<i64>,
#[serde(skip_serializing_if = "Option::is_none")]
pub end_time: Option<i64>,
}

#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct VariableList {
Expand Down
1 change: 1 addition & 0 deletions web/src/components/DateTime.vue
Original file line number Diff line number Diff line change
Expand Up @@ -779,6 +779,7 @@ export default defineComponent({
setSavedDate,
optionsFn,
setDateType,
getConsumableDateTime,
};
},
});
Expand Down
5 changes: 5 additions & 0 deletions web/src/components/DateTimePickerDashboard.vue
Original file line number Diff line number Diff line change
Expand Up @@ -80,11 +80,16 @@ export default defineComponent({
dateTimePicker.value.setCustomDate(type, dateObj);
};
const getConsumableDateTime = () => {
return dateTimePicker.value.getConsumableDateTime();
};
return {
updateDateTime,
refresh,
dateTimePicker,
setCustomDate,
getConsumableDateTime,
};
},
});
Expand Down
6 changes: 6 additions & 0 deletions web/src/components/dashboards/AddDashboard.vue
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,12 @@ export default defineComponent({
list: [],
showDynamicFilters: true,
},
defaultDatetimeDuration: {
startTime: null,
endTime: null,
relativeTimePeriod: "15m",
type: "relative",
},
role: "",
owner: store.state.userInfo.name,
created: new Date().toISOString(),
Expand Down
50 changes: 46 additions & 4 deletions web/src/components/dashboards/settings/GeneralSettings.vue
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,17 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
filled
dense
/>
<div v-if="dateTimeValue">
<label>Default Duration</label>
<DateTimePickerDashboard
v-show="store.state.printMode === false"
ref="dateTimePicker"
class="dashboard-icons q-my-sm"
size="sm"
:initialTimezone="initialTimezone"
v-model="dateTimeValue"
/>
</div>
<q-toggle
v-model="dashboardData.showDynamicFilters"
label="Show Dynamic Filters"
Expand Down Expand Up @@ -74,7 +85,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
</template>

<script lang="ts">
import { defineComponent, onMounted, ref, type Ref } from "vue";
import { defineComponent, onMounted, ref, watch, type Ref } from "vue";
import { useI18n } from "vue-i18n";
import { useStore } from "vuex";
import { reactive } from "vue";
Expand All @@ -83,11 +94,13 @@ import { useRoute } from "vue-router";
import DashboardHeader from "./common/DashboardHeader.vue";
import { useLoading } from "@/composables/useLoading";
import { useQuasar } from "quasar";
import DateTimePickerDashboard from "@/components/DateTimePickerDashboard.vue";
export default defineComponent({
name: "GeneralSettings",
components: {
DashboardHeader,
DateTimePickerDashboard,
},
emits: ["save"],
setup(props, { emit }) {
Expand All @@ -98,13 +111,22 @@ export default defineComponent({
const addDashboardForm: Ref<any> = ref(null);
const closeBtn: Ref<any> = ref(null);
// initial timezone, which will come from the route query
const initialTimezone: any = ref(store.state.timezone ?? null);
const dashboardData = reactive({
title: "",
description: "",
showDynamicFilters: true,
defaultDatetimeDuration: {
startTime: null,
endTime: null,
relativeTimePeriod: "15m",
type: "relative",
},
});
let dateTimeValue: any = ref(null);
const getDashboardData = async () => {
const data = await getDashboard(
store,
Expand All @@ -116,6 +138,13 @@ export default defineComponent({
dashboardData.description = data.description;
dashboardData.showDynamicFilters =
data.variables?.showDynamicFilters ?? false;
dateTimeValue.value = {
startTime: data?.defaultDatetimeDuration?.startTime,
endTime: data?.defaultDatetimeDuration?.endTime,
relativeTimePeriod: data?.defaultDatetimeDuration?.relativeTimePeriod,
valueType: data?.defaultDatetimeDuration?.type,
};
};
onMounted(async () => {
await getDashboardData();
Expand Down Expand Up @@ -147,6 +176,13 @@ export default defineComponent({
data.variables.showDynamicFilters = dashboardData.showDynamicFilters;
}
data.defaultDatetimeDuration = {
startTime: dateTimeValue?.value?.startTime,
endTime: dateTimeValue?.value?.endTime,
relativeTimePeriod: dateTimeValue?.value?.relativeTimePeriod,
type: dateTimeValue?.value?.valueType,
};
// now lets save it
await updateDashboard(
store,
Expand All @@ -165,9 +201,7 @@ export default defineComponent({
} catch (error: any) {
$q.notify({
type: "negative",
message:
error?.message ??
"Dashboard updation failed",
message: error?.message ?? "Dashboard updation failed",
timeout: 2000,
});
}
Expand Down Expand Up @@ -198,7 +232,15 @@ export default defineComponent({
saveDashboardApi,
onSubmit,
closeBtn,
initialTimezone,
dateTimeValue,
};
},
});
</script>

<style lang="scss" scoped>
.dashboard-icons {
height: 30px;
}
</style>
6 changes: 3 additions & 3 deletions web/src/composables/shared/router.ts
Original file line number Diff line number Diff line change
Expand Up @@ -164,9 +164,9 @@ const useRoutes = () => {
name: "viewDashboard",
component: ViewDashboard,
props: true,
meta: {
keepAlive: true,
},
// meta: {
// keepAlive: true,
// },
beforeEnter(to: any, from: any, next: any) {
routeGuard(to, from, next);
},
Expand Down
109 changes: 72 additions & 37 deletions web/src/views/Dashboards/ViewDashboard.vue
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
</div>
<!-- do not show date time picker for print mode -->
<DateTimePickerDashboard
v-if="selectedDate"
v-show="store.state.printMode === false"
ref="dateTimePicker"
class="dashboard-icons q-ml-sm"
Expand Down Expand Up @@ -180,6 +181,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
</div>

<RenderDashboardCharts
v-if="selectedDate"
@variablesData="variablesDataUpdated"
:initialVariableValues="initialVariableValues"
:viewOnly="store.state.printMode"
Expand Down Expand Up @@ -258,6 +260,36 @@ export default defineComponent({
data: {},
});

// [START] date picker related variables --------

/**
* Retrieves the selected date from the query parameters.
*/
const getSelectedDateFromQueryParams = (params) => ({
valueType: params.period
? "relative"
: params.from && params.to
? "absolute"
: "relative",
startTime: params.from ? params.from : null,
endTime: params.to ? params.to : null,
relativeTimePeriod: params.period ? params.period : "15m",
});

const dateTimePicker = ref(null); // holds a reference to the date time picker

// holds the date picker v-modal
const selectedDate = ref(null);

// holds the current time for the dashboard
const currentTimeObj = ref({});

// refresh interval v-model
const refreshInterval = ref(0);

// initial timezone, which will come from the route query
const initialTimezone = ref(route.query.timezone ?? null);

// dispatch setPrintMode, to set print mode
const setPrint = (printMode: any) => {
store.dispatch("setPrintMode", printMode);
Expand Down Expand Up @@ -331,7 +363,7 @@ export default defineComponent({
});
// ======= [END] default variable values

onActivated(async () => {
onMounted(async () => {
await loadDashboard();
});

Expand Down Expand Up @@ -361,48 +393,51 @@ export default defineComponent({
variablesData.isVariablesLoading = false;
variablesData.values = [];
}

// check if route has time realated query params
// if not, take dashboard default time settings
if (!((route.query.from && route.query.to) || route.query.period)) {
// if dashboard has relative time settings
if (
(currentDashboardData.data?.defaultDatetimeDuration?.type ??
"relative") === "relative"
) {
selectedDate.value = {
valueType: "relative",
relativeTimePeriod:
currentDashboardData.data?.defaultDatetimeDuration
?.relativeTimePeriod ?? "15m",
};
} else {
// else, dashboard will have absolute time settings
selectedDate.value = {
valueType: "absolute",
startTime:
currentDashboardData.data?.defaultDatetimeDuration?.startTime,
endTime:
currentDashboardData.data?.defaultDatetimeDuration?.endTime,
};
}
} else {
// take route time related query params
selectedDate.value = getSelectedDateFromQueryParams(route.query);
}
};

const openSettingsDialog = () => {
showDashboardSettingsDialog.value = true;
};

// [START] date picker related variables --------

/**
* Retrieves the selected date from the query parameters.
*/
const getSelectedDateFromQueryParams = (params) => ({
valueType: params.period
? "relative"
: params.from && params.to
? "absolute"
: "relative",
startTime: params.from ? params.from : null,
endTime: params.to ? params.to : null,
relativeTimePeriod: params.period ? params.period : null,
});

const dateTimePicker = ref(null); // holds a reference to the date time picker

// holds the date picker v-modal
const selectedDate = ref(getSelectedDateFromQueryParams(route.query));

// holds the current time for the dashboard
const currentTimeObj = ref({});

// refresh interval v-model
const refreshInterval = ref(0);

// initial timezone, which will come from the route query
const initialTimezone = ref(route.query.timezone ?? null);

// when the date changes from the picker, update the current time object for the dashboard
watch(selectedDate, () => {
currentTimeObj.value = {
start_time: new Date(selectedDate.value.startTime),
end_time: new Date(selectedDate.value.endTime),
};
if (selectedDate.value && dateTimePicker.value) {
const date = dateTimePicker.value?.getConsumableDateTime();

currentTimeObj.value = {
start_time: new Date(date.startTime),
end_time: new Date(date.endTime),
};
}
});

const getQueryParamsForDuration = (data: any) => {
Expand Down Expand Up @@ -467,7 +502,7 @@ export default defineComponent({
};

// ------- work with query params ----------
onActivated(async () => {
onMounted(async () => {
const params = route.query;

if (params.refresh) {
Expand Down Expand Up @@ -646,7 +681,7 @@ export default defineComponent({
document.removeEventListener("fullscreenchange", onFullscreenChange);
});

onActivated(() => {
onMounted(() => {
isFullscreen.value = false;
});

Expand Down
Loading

0 comments on commit ee29091

Please sign in to comment.