Skip to content
This repository was archived by the owner on Sep 3, 2025. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
132 changes: 130 additions & 2 deletions src/dispatch/static/dispatch/src/events/ReportSubmissionCard.vue
Original file line number Diff line number Diff line change
Expand Up @@ -65,9 +65,13 @@
import { required } from "@/util/form"
import { mapFields } from "vuex-map-fields"
import { mapActions } from "vuex"
import { resolveProject } from "@/util/project"

import router from "@/router"
import CasePrioritySelect from "@/case/priority/CasePrioritySelect.vue"
import CaseTypeApi from "@/case/type/api"
import CasePriorityApi from "@/case/priority/api"
import CaseSeverityApi from "@/case/severity/api"

export default {
setup() {
Expand All @@ -83,6 +87,7 @@ export default {
formIsValid: false,
titleValid: false,
descriptionValid: false,
projectValid: false,
page_oncall: false,
items: [],
}
Expand All @@ -102,6 +107,8 @@ export default {
"selected.project",
"selected.id",
"selected.case_priority",
"selected.case_type",
"selected.case_severity",
"selected.event",
"default_project",
]),
Expand All @@ -117,6 +124,10 @@ export default {
this.descriptionValid = !!this.description
this.checkFormValidity()
},
project() {
this.projectValid = !!this.project
this.checkFormValidity()
},
},

methods: {
Expand All @@ -131,13 +142,128 @@ export default {
}
},
checkFormValidity() {
this.formIsValid = this.titleValid && this.descriptionValid
this.formIsValid = this.titleValid && this.descriptionValid && this.projectValid
},

loadDefaults(project) {
// Load default case type for the project
CaseTypeApi.getAll({
filter: JSON.stringify({
and: [
{
model: "Project",
field: "id",
op: "==",
value: project.id,
},
{
field: "default",
op: "==",
value: true,
},
],
}),
}).then((response) => {
if (response.data.items.length) {
this.case_type = response.data.items[0]
}
})

// Load default case severity for the project
CaseSeverityApi.getAll({
filter: JSON.stringify({
and: [
{
model: "Project",
field: "id",
op: "==",
value: project.id,
},
{
field: "default",
op: "==",
value: true,
},
],
}),
}).then((response) => {
if (response.data.items.length) {
this.case_severity = response.data.items[0]
}
})

// Load default case priority for the project
CasePriorityApi.getAll({
filter: JSON.stringify({
and: [
{
model: "Project",
field: "id",
op: "==",
value: project.id,
},
{
field: "default",
op: "==",
value: true,
},
],
}),
}).then((response) => {
if (response.data.items.length) {
this.case_priority = response.data.items[0]
}
})

// Set other defaults
this.visibility = "Open"
},

fetchData() {
// If project is not available yet, we'll load priorities later in onProjectResolved
if (!this.project) {
return
}

// Load case priority items for the urgent checkbox
CasePriorityApi.getAll({
filter: JSON.stringify({
and: [
{
model: "Project",
field: "id",
op: "==",
value: this.project.id,
},
],
}),
}).then((response) => {
this.items = response.data.items
})
},

...mapActions("case_management", ["report", "get", "resetSelected"]),
},

created() {
this.event = true
this.dedicated_channel = true

// Use the utility function to resolve the project
resolveProject({
component: this,
onProjectResolved: (project) => {
// Project has been resolved and set
this.projectValid = !!this.project
this.checkFormValidity()

// Auto-populate defaults based on the project
this.loadDefaults(project)

// Fetch case priority items now that we have a project
this.fetchData()
},
})

if (this.$route.query.title) {
this.title = this.$route.query.title
Expand All @@ -148,12 +274,14 @@ export default {
if (this.$route.query.description) {
this.description = this.$route.query.description
}
this.fetchData()

// We'll call fetchData after project is resolved

this.$watch(
(vm) => [vm.project, vm.title, vm.description],
() => {
var queryParams = {
project: this.project ? this.project.name : null,
title: this.title,
description: this.description,
}
Expand Down
108 changes: 108 additions & 0 deletions src/dispatch/static/dispatch/src/util/project.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
import ProjectApi from "@/project/api"
import AuthApi from "@/auth/api"

/**
* Resolves a project for a component based on various fallback strategies
*
* @param {Object} options - Configuration options
* @param {Object} options.component - Vue component instance (for accessing this.project, this.default_project)
* @param {Function} options.onProjectResolved - Callback when project is resolved
* @param {Boolean} options.setDirectly - Whether to set component.project directly (default: true)
* @returns {Promise} - Promise that resolves when project resolution is complete
*/
export const resolveProject = async ({ component, onProjectResolved, setDirectly = true }) => {
// Check if project is already set
if (component.project) {
return component.project
}

// Try to get project from URL query parameters
if (component.$route && component.$route.query.project) {
const params = {
filter: { field: "name", op: "==", value: component.$route.query.project },
}

try {
const response = await ProjectApi.getAll(params)
if (response.data.items.length) {
const project = response.data.items[0]
if (setDirectly) {
component.project = project
}
if (onProjectResolved) {
onProjectResolved(project)
}
return project
}
} catch (error) {
console.error("Error fetching project from query params:", error)
}
}

// Try to get project from user's projects
if (component.projects && component.projects.length) {
const project = component.projects[0].project
if (setDirectly) {
component.project = project
}
if (onProjectResolved) {
onProjectResolved(project)
}
return project
}

// Try to get user's default project or organization default
try {
const response = await AuthApi.getUserInfo()

// If project was set while waiting for API response, exit
if (component.project) {
return component.project
}

// Check for user's default project
const defaultUserProject = response.data.projects.filter((v) => v.default === true)
if (defaultUserProject.length) {
const project = defaultUserProject[0].project
if (setDirectly) {
component.project = project
}
if (onProjectResolved) {
onProjectResolved(project)
}
return project
}

// Try component's default_project
if (component.default_project) {
if (setDirectly) {
component.project = component.default_project
}
if (onProjectResolved) {
onProjectResolved(component.default_project)
}
return component.default_project
}

// Last resort: get organization default project
const defaultParams = {
filter: { field: "default", op: "==", value: true },
}

const projectResponse = await ProjectApi.getAll(defaultParams)
if (projectResponse.data.items.length) {
const project = projectResponse.data.items[0]
if (setDirectly) {
component.project = project
}
if (onProjectResolved) {
onProjectResolved(project)
}
return project
}
} catch (error) {
console.error("Error resolving project:", error)
}

return null
}
Loading