Skip to content

Commit

Permalink
Merge branch 'master' into ui/instance-tab-case-page-shrink
Browse files Browse the repository at this point in the history
  • Loading branch information
wssheldon authored Dec 6, 2023
2 parents 5b67326 + 9f9c4d7 commit 9a8a09d
Show file tree
Hide file tree
Showing 9 changed files with 235 additions and 108 deletions.
4 changes: 2 additions & 2 deletions src/dispatch/case/messaging.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ def send_case_close_reminder(case: Case, db_session: SessionLocal):
items = [
{
"name": case.name,
"dispatch_ui_case_url": f"{DISPATCH_UI_URL}/{case.project.organization.name}/cases/{case.id}", # noqa
"dispatch_ui_case_url": f"{DISPATCH_UI_URL}/{case.project.organization.name}/cases/{case.name}", # noqa
"title": case.title,
"status": case.status,
}
Expand Down Expand Up @@ -77,7 +77,7 @@ def send_case_triage_reminder(case: Case, db_session: SessionLocal):
"name": case.name,
"title": case.title,
"status": case.status,
"dispatch_ui_case_url": f"{DISPATCH_UI_URL}/{case.project.organization.name}/cases/{case.id}", # noqa
"dispatch_ui_case_url": f"{DISPATCH_UI_URL}/{case.project.organization.name}/cases/{case.name}", # noqa
}
]

Expand Down
2 changes: 1 addition & 1 deletion src/dispatch/plugins/dispatch_slack/case/messages.py
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ def create_case_message(case: Case, channel_id: str) -> list[Block]:
accessory=Button(
text="View",
action_id="button-link",
url=f"{DISPATCH_UI_URL}/{case.project.organization.slug}/cases/{case.id}",
url=f"{DISPATCH_UI_URL}/{case.project.organization.slug}/cases/{case.name}",
),
),
Section(text=f"*Description* \n {case.description}"),
Expand Down
10 changes: 9 additions & 1 deletion src/dispatch/static/dispatch/src/case/CaseSignalInstanceTab.vue
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
<v-virtual-scroll :items="signalInstances" height="828" class="pt-2">
<template #default="{ item }">
<div class="d-flex align-center">
<span style="font-size: 0.8rem" class="pl-8">
<span class="pl-8 signal-name">
{{ item.signal.name }}
</span>
<span class="pl-1 dispatch-text-paragraph">
Expand Down Expand Up @@ -110,9 +110,17 @@ watch(
border: 0.5px solid rgb(216, 216, 216) !important;
border-radius: 8px !important;
}
.flex-card {
flex: 1;
min-width: 0; // Allow the card to shrink below its content size
overflow: hidden; // Clip the content and add ... if the content is too big
}
.signal-name {
font-size: 0.8rem;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
</style>
164 changes: 94 additions & 70 deletions src/dispatch/static/dispatch/src/case/CaseStatusSelectGroup.vue
Original file line number Diff line number Diff line change
Expand Up @@ -70,83 +70,107 @@
</v-item-group>
</template>

<script>
import { mapActions } from "vuex"
<script setup>
import { computed, watch, ref } from "vue"
import { useStore } from "vuex"
import { useSavingState } from "@/composables/useSavingState"
import DTooltip from "@/components/DTooltip.vue"
import CaseApi from "@/case/api"
export default {
name: "CaseStatusSelectGroup",
props: {
modelValue: {
type: Object,
required: false,
default: () => ({}),
},
const props = defineProps({
modelValue: {
type: Object,
required: false,
default: () => ({}),
},
components: {
DTooltip,
})
const store = useStore()
const { setSaving } = useSavingState()
let selectedStatus = ref(null)
let dialogVisible = ref(false)
let activeStatus = ref(props.modelValue.status)
const statuses = computed(() => [
{
name: "New",
label: "Created",
color: "red",
hoverClass: "hover-card-three",
sheetClass: "rounded-s-xl arrow",
tooltip: props.modelValue.created_at,
},
data() {
return {
selectedStatus: null,
dialogVisible: false,
}
{
name: "Triage",
label: "Triaged",
color: "red",
hoverClass: "hover-card-two",
sheetClass: "arrow",
tooltip: props.modelValue.triage_at,
},
computed: {
statuses() {
return [
{
name: "New",
label: "New",
color: "red",
hoverClass: "hover-card-three",
sheetClass: "rounded-s-xl arrow",
tooltip: this.modelValue.created_at,
},
{
name: "Triage",
label: "Triaged",
color: "red",
hoverClass: "hover-card-two",
sheetClass: "arrow",
tooltip: this.modelValue.triage_at,
},
{
name: "Closed",
label: "Resolved",
color: "green",
hoverClass: "hover-card",
sheetClass: "arrow",
tooltip: this.modelValue.closed_at,
},
{
name: "Escalated",
label: "Escalated",
color: "red",
hoverClass: "",
sheetClass: "rounded-e-xl end-sheet",
tooltip: this.modelValue.escalated_at,
},
]
},
{
name: "Closed",
label: "Resolved",
color: "green",
hoverClass: "hover-card",
sheetClass: "arrow",
tooltip: props.modelValue.closed_at,
},
methods: {
...mapActions("case_management", ["save_page"]),
changeStatus(newStatus) {
// eslint-disable-next-line vue/no-mutating-props
this.modelValue.status = newStatus
this.save_page()
this.dialogVisible = false
this.selectedStatus = null
},
openDialog(newStatus) {
this.selectedStatus = newStatus
this.dialogVisible = true
},
isActiveStatus(status) {
return this.modelValue.status === status
},
{
name: "Escalated",
label: "Escalated",
color: "red",
hoverClass: "",
sheetClass: "rounded-e-xl end-sheet",
tooltip: props.modelValue.escalated_at,
},
])
const changeStatus = async (newStatus) => {
const caseDetails = store.state.case_management.selected
const previousStatus = activeStatus.value
// Optimistically update the UI
activeStatus.value = newStatus
selectedStatus.value = null
dialogVisible.value = false
caseDetails.status = newStatus
try {
setSaving(true)
await CaseApi.update(caseDetails.id, caseDetails)
setSaving(false)
} catch (e) {
console.error(`Failed to update case status`, e)
// If the API call fails, revert the active status change
activeStatus.value = previousStatus
store.commit(
"notification_backend/addBeNotification",
{
text: `Failed to update case status`,
type: "exception",
},
{ root: true }
)
}
}
const openDialog = (newStatus) => {
selectedStatus.value = newStatus
dialogVisible.value = true
}
watch(
() => props.modelValue.status,
(newStatus) => {
activeStatus.value = newStatus
}
)
const isActiveStatus = (status) => {
return activeStatus.value === status
}
</script>

Expand Down
42 changes: 29 additions & 13 deletions src/dispatch/static/dispatch/src/case/Page.vue
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
<template>
<div>
<PageHeader
:case-id="caseDetails.id"
:case-name="caseDetails.name"
:case-visibility="caseDetails.visibility"
:case-status="caseDetails.status"
Expand Down Expand Up @@ -92,21 +93,36 @@ const toggleDrawer = () => {
}
const fetchDetails = async () => {
const caseId = parseInt(route.params.id, 10)
const caseName = route.params.name
loading.value = true
try {
// get the full data set
CaseApi.get(caseId).then((response) => {
caseDetails.value = response.data
// Save the fetched case details to the Vuex store
store.commit("case_management/SET_SELECTED", response.data)
})
} catch (e) {
console.error("Failed to fetch case details", e)
caseDetails.value = caseDefaults
CaseApi.getAll({
filter: JSON.stringify([
{ and: [{ model: "Case", field: "name", op: "==", value: caseName }] },
]),
}).then((response) => {
if (response.data.items.length) {
// get the full data set
return CaseApi.get(response.data.items[0].id).then((response) => {
caseDetails.value = response.data
// Save the fetched case details to the Vuex store
store.commit("case_management/SET_SELECTED", response.data)
loading.value = false
})
} else {
caseDetails.value = caseDefaults
store.commit(
"notification_backend/addBeNotification",
{
text: `Case '${caseName}' could not be found.`,
type: "exception",
},
{ root: true }
)
}
loading.value = false
}
})
}
const saveCaseDetails = async () => {
Expand All @@ -132,7 +148,7 @@ const handleDescriptionUpdate = (newDescription) => {
}
watch(
() => route.params.id,
() => route.params.name,
(newName, oldName) => {
if (newName !== oldName) {
fetchDetails()
Expand Down
46 changes: 27 additions & 19 deletions src/dispatch/static/dispatch/src/case/PageHeader.vue
Original file line number Diff line number Diff line change
Expand Up @@ -33,17 +33,22 @@

<script setup lang="ts">
import { useRoute } from "vue-router"
import { computed, ref } from "vue"
import { computed, ref, watch } from "vue"
import LockButton from "@/components/LockButton.vue"
import EscalateButton from "@/case/EscalateButton.vue"
import DTooltip from "@/components/DTooltip.vue"
import ParticipantAvatarGroup from "@/participant/ParticipantAvatarGroup.vue"
import SavingState from "@/components/SavingState.vue"
import CaseApi from "@/case/api"
import type { Ref } from "vue"
const route = useRoute()
const props = defineProps({
caseId: {
type: Number,
required: true,
},
caseName: {
type: String,
required: true,
Expand All @@ -68,22 +73,28 @@ const props = defineProps({
const caseParticipants = ref([])
const loading = ref(false)
const caseIdRef: Ref<any> = ref(props.caseId)
const fetchParticipants = async () => {
const caseId = route.params.id
loading.value = true
try {
// get case participants
CaseApi.getParticipants(caseId, true).then((response) => {
// Pass true to fetch minimal data
caseParticipants.value = response.data
})
loading.value = false
} catch (e) {
console.error("Failed to fetch case participants", e)
loading.value = false
}
}
watch(
() => props.caseId,
async (caseId) => {
caseIdRef.value = caseId
if (caseId) {
try {
// get case participants
CaseApi.getParticipants(caseIdRef.value, true).then((response) => {
// Pass true to fetch minimal data
caseParticipants.value = response.data
})
loading.value = false
} catch (e) {
console.error("Failed to fetch case participants", e)
loading.value = false
}
}
},
{ immediate: true }
)
const emit = defineEmits(["toggle-drawer"])
Expand All @@ -105,9 +116,6 @@ const breadcrumbItems = computed(() => {
]
return items
})
// Fetch participants immediately when the component is created
fetchParticipants()
</script>

<style scoped>
Expand Down
2 changes: 1 addition & 1 deletion src/dispatch/static/dispatch/src/case/Table.vue
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@
<v-list-item
:to="{
name: 'CasePage',
params: { id: item.id },
params: { name: item.name },
}"
>
<v-list-item-title>View</v-list-item-title>
Expand Down
2 changes: 1 addition & 1 deletion src/dispatch/static/dispatch/src/router/config.js
Original file line number Diff line number Diff line change
Expand Up @@ -205,7 +205,7 @@ export const protectedRoute = [
],
},
{
path: "/:organization/cases/:id",
path: "/:organization/cases/:name",
name: "CasePage",
meta: { title: "Page" },
component: () => import("@/case/Page.vue"),
Expand Down
Loading

0 comments on commit 9a8a09d

Please sign in to comment.