Skip to content

Commit

Permalink
feat(ui/ux): add oncall service name to oncall shift feedback table (#…
Browse files Browse the repository at this point in the history
  • Loading branch information
whitdog47 authored Oct 8, 2024
1 parent cecb501 commit d61fa77
Show file tree
Hide file tree
Showing 7 changed files with 76 additions and 9 deletions.
5 changes: 5 additions & 0 deletions src/dispatch/service/service.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,11 @@ def get_by_external_id(*, db_session, external_id: str) -> Optional[Service]:
return db_session.query(Service).filter(Service.external_id == external_id).first()


def get_all_by_external_ids(*, db_session, external_ids: List[str]) -> Optional[List[Service]]:
"""Gets a service by external id (e.g. PagerDuty service id) and project id."""
return db_session.query(Service).filter(Service.external_id.in_(external_ids)).all()


def get_by_name(*, db_session, project_id: int, name: str) -> Optional[Service]:
"""Gets a service by its name."""
return (
Expand Down
21 changes: 19 additions & 2 deletions src/dispatch/service/views.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
from fastapi import APIRouter, Body, HTTPException, status
from fastapi import APIRouter, Body, HTTPException, status, Query
from pydantic.error_wrappers import ErrorWrapper, ValidationError
from typing import List

from sqlalchemy.exc import IntegrityError

Expand All @@ -9,7 +10,14 @@
from dispatch.models import PrimaryKey

from .models import ServiceCreate, ServicePagination, ServiceRead, ServiceUpdate
from .service import get, create, update, delete, get_by_external_id_and_project_name
from .service import (
get,
create,
update,
delete,
get_by_external_id_and_project_name,
get_all_by_external_ids,
)


router = APIRouter()
Expand All @@ -21,6 +29,15 @@ def get_services(common: CommonParameters):
return search_filter_sort_paginate(model="Service", **common)


@router.get("/externalids", response_model=List[ServiceRead])
def get_services_by_external_ids(
db_session: DbSession,
ids: List[str] = Query(..., alias="ids[]"),
):
"""Retrieves all services given list of external ids."""
return get_all_by_external_ids(db_session=db_session, external_ids=ids)


@router.post("", response_model=ServiceRead)
def create_service(
db_session: DbSession,
Expand Down
9 changes: 8 additions & 1 deletion src/dispatch/static/dispatch/src/feedback/service/Table.vue
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,11 @@
{{ item.project.name }}
</v-chip>
</template>
<template #item.service="{ item }">
<v-chip size="small" :color="item.project.color">
{{ item.service }}
</v-chip>
</template>
<template #item.data-table-actions="{ item }">
<v-menu location="right" origin="overlap">
<template #activator="{ props }">
Expand Down Expand Up @@ -119,6 +124,7 @@ export default {
{ title: "Rating", value: "rating", sortable: true },
{ title: "Feedback", value: "feedback", sortable: true },
{ title: "Details", value: "details", sortable: true },
{ title: "Service", value: "service", sortable: false },
{ title: "Project", value: "project.name", sortable: false },
{ title: "Created At", value: "created_at", sortable: true },
{ title: "", key: "data-table-actions", sortable: false, align: "end" },
Expand All @@ -138,6 +144,7 @@ export default {
"table.options.sortBy",
"table.options.descending",
"table.options.filters.project",
"table.options.filters.schedule",
"table.loading",
"table.rows.items",
"table.rows.total",
Expand Down Expand Up @@ -185,7 +192,7 @@ export default {
)
this.$watch(
(vm) => [vm.q, vm.itemsPerPage, vm.sortBy, vm.descending, vm.project],
(vm) => [vm.q, vm.itemsPerPage, vm.sortBy, vm.descending, vm.project, vm.schedule],
() => {
this.page = 1
RouterUtils.updateURLFilters(this.filters)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,9 @@
<v-list-item>
<project-combobox v-model="local_project" label="Projects" />
</v-list-item>
<v-list-item>
<service-select v-model="local_service" label="Oncall service" />
</v-list-item>
</v-list>
<v-card-actions>
<v-spacer />
Expand All @@ -27,12 +30,14 @@ import { sum } from "lodash"
import { mapFields } from "vuex-map-fields"
import ProjectCombobox from "@/project/ProjectCombobox.vue"
import ServiceSelect from "@/service/ServiceSelect.vue"
export default {
name: "ServiceFeedbackTableFilterDialog",
components: {
ProjectCombobox,
ServiceSelect,
},
props: {
Expand All @@ -48,22 +53,30 @@ export default {
return {
display: false,
local_project: this.projects,
local_service: null,
}
},
computed: {
...mapFields("service_feedback", ["table.options.filters.project"]),
...mapFields("service_feedback", [
"table.options.filters.project",
"table.options.filters.schedule",
]),
numFilters: function () {
return sum([this.project.length])
return sum([this.project.length, this.schedule ? this.schedule.length : 0])
},
},
methods: {
applyFilters() {
// we set the filter values
this.project = this.local_project
if (this.local_service) {
this.schedule = this.local_service.map((s) => s.external_id)
} else {
this.schedule = null
}
// we close the dialog
this.display = false
},
Expand Down
21 changes: 19 additions & 2 deletions src/dispatch/static/dispatch/src/feedback/service/store.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { debounce } from "lodash"

import SearchUtils from "@/search/utils"
import ServiceFeedbackApi from "@/feedback/service/api"
import ServiceApi from "@/service/api"

const getDefaultSelectedState = () => {
return {
Expand Down Expand Up @@ -36,6 +37,7 @@ const state = {
descending: [true],
filters: {
project: [],
schedule: null,
},
},
loading: false,
Expand All @@ -55,8 +57,23 @@ const actions = {
)
return ServiceFeedbackApi.getAll(params)
.then((response) => {
commit("SET_TABLE_LOADING", false)
commit("SET_TABLE_ROWS", response.data)
// hydrate with service name
if (response.data.items.length > 0) {
const uniqueExternalIds = [...new Set(response.data.items.map((f) => f.schedule))]
ServiceApi.getAllByIds(uniqueExternalIds).then((services) => {
response.data.items.forEach((f) => {
let service = services.data.find((s) => s.external_id === f.schedule)
if (service) {
f.service = service.name
}
})
commit("SET_TABLE_LOADING", false)
commit("SET_TABLE_ROWS", response.data)
})
} else {
commit("SET_TABLE_LOADING", false)
commit("SET_TABLE_ROWS", response.data)
}
})
.catch(() => {
commit("SET_TABLE_LOADING", false)
Expand Down
6 changes: 5 additions & 1 deletion src/dispatch/static/dispatch/src/service/ServiceSelect.vue
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,10 @@
:hint="hint"
:loading="loading"
no-filter
clearable
chips
multiple
closable-chips
/>
</template>

Expand All @@ -28,7 +32,7 @@ export default {
modelValue: {
type: Object,
default: function () {
return {}
return null
},
},
label: {
Expand Down
4 changes: 4 additions & 0 deletions src/dispatch/static/dispatch/src/service/api.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@ export default {
return API.get(`${resource}`, { params: { ...options } })
},

getAllByIds(ids) {
return API.get(`${resource}/externalids`, { params: { ids } })
},

get(serviceId) {
return API.get(`${resource}/${serviceId}`)
},
Expand Down

0 comments on commit d61fa77

Please sign in to comment.