Skip to content
This repository was archived by the owner on Sep 3, 2025. It is now read-only.
Merged
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
"""Adds attorney form schema and scoring schema to forms type

Revision ID: b07bb852fd67
Revises: 50e99c66e72f
Create Date: 2024-04-10 15:51:10.914748

"""
from alembic import op
import sqlalchemy as sa

# revision identifiers, used by Alembic.
revision = "b07bb852fd67"
down_revision = "50e99c66e72f"
branch_labels = None
depends_on = None


def upgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.add_column("forms_type", sa.Column("attorney_form_schema", sa.String(), nullable=True))
op.add_column("forms_type", sa.Column("scoring_schema", sa.String(), nullable=True))
op.add_column("forms", sa.Column("attorney_form_data", sa.String(), nullable=True))
# ### end Alembic commands ###


def downgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.drop_column("forms_type", "scoring_schema")
op.drop_column("forms_type", "attorney_form_schema")
op.drop_column("forms", "attorney_form_data")
# ### end Alembic commands ###
2 changes: 2 additions & 0 deletions src/dispatch/forms/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ class Forms(TimeStampMixin, ProjectMixin, Base):
attorney_status = Column(String, default=FormAttorneyStatus.not_reviewed, nullable=True)
attorney_questions = Column(String, nullable=True)
attorney_analysis = Column(String, nullable=True)
attorney_form_data = Column(String, nullable=True)

# Relationships
creator_id = Column(Integer, ForeignKey("individual_contact.id"))
Expand All @@ -39,6 +40,7 @@ class FormsBase(DispatchBase):
form_type: Optional[FormsTypeRead]
creator: Optional[IndividualContactReadMinimal]
form_data: Optional[str] = Field(None, nullable=True)
attorney_form_data: Optional[str] = Field(None, nullable=True)
status: Optional[str] = Field(None, nullable=True)
attorney_status: Optional[str] = Field(None, nullable=True)
project: Optional[ProjectRead]
Expand Down
4 changes: 4 additions & 0 deletions src/dispatch/forms/type/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ class FormsType(ProjectMixin, TimeStampMixin, Base):
description = Column(String, nullable=True)
enabled = Column(Boolean, default=True)
form_schema = Column(String, nullable=True)
attorney_form_schema = Column(String, nullable=True)
scoring_schema = Column(String, nullable=True)

# Relationships
creator_id = Column(Integer, ForeignKey("individual_contact.id"))
Expand All @@ -42,6 +44,8 @@ class FormsTypeBase(DispatchBase):
description: Optional[str] = Field(None, nullable=True)
enabled: Optional[bool]
form_schema: Optional[str] = Field(None, nullable=True)
attorney_form_schema: Optional[str] = Field(None, nullable=True)
scoring_schema: Optional[str] = Field(None, nullable=True)
creator: Optional[IndividualContactReadMinimal]
project: Optional[ProjectRead]
service: Optional[ServiceRead]
Expand Down
45 changes: 37 additions & 8 deletions src/dispatch/static/dispatch/src/forms/store.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,9 @@ const getDefaultSelectedState = () => {
attorney_analysis: null,
form_type: null,
project: null,
form_schema: [],
form_schema: null,
attorney_form_data: null,
scoring_schema: null,
}
}

Expand Down Expand Up @@ -58,6 +60,7 @@ const state = {
project_id: null,
incident_data: null,
has_formkit_pro: hasFormkitPro,
attorney_page_schema: null,
}

const getters = {
Expand Down Expand Up @@ -97,7 +100,6 @@ function formatTacticalReport(tactical_report) {
}

function buildIncidentDoc(incident) {
// todo - will need to use api to get incident so you can retrieve the last_tactical_report
let output_qa = []
if (incident) {
output_qa.push({
Expand Down Expand Up @@ -151,6 +153,9 @@ function getCurrentPage(form_schema) {
state.has_formkit_pro = hasFormkitPro
let schema = JSON.parse(form_schema)
let output_schema = []
if (schema == null) {
return output_schema
}
for (let item of schema) {
let obj = {
name: item.name,
Expand Down Expand Up @@ -242,23 +247,25 @@ function getCurrentPage(form_schema) {
return output_schema
}

function createPayload() {
function createPayload(selected) {
const payload = {}
const validKeys = [
"id",
"form_data",
"attorney_form_data",
"status",
"attorney_status",
"attorney_questions",
"attorney_analysis",
"incident_id",
"form_type_id",
]
Object.keys(state.selected).forEach((key) => {
if (validKeys.includes(key)) payload[key] = state.selected[key]
Object.keys(selected).forEach((key) => {
if (validKeys.includes(key)) payload[key] = selected[key]
})
payload["form_data"] = JSON.stringify(payload["form_data"])
payload["project_id"] = state.selected.project.id
payload["attorney_form_data"] = JSON.stringify(payload["attorney_form_data"])
payload["project_id"] = selected.project.id
return payload
}

Expand Down Expand Up @@ -362,6 +369,7 @@ const actions = {
FormsTypeApi.get(form_type_id)
.then((response) => {
commit("SET_PAGE_SCHEMA", getCurrentPage(response.data.form_schema))
commit("SET_ATTORNEY_PAGE_SCHEMA", getCurrentPage(response.data.attorney_form_schema))
commit("SET_FORM_TYPE", response.data)
commit("SET_DIALOG_CREATE_EDIT", true)
})
Expand All @@ -372,11 +380,20 @@ const actions = {
editShow({ commit }, selected) {
commit("SET_SELECTED", selected)
commit("SET_PAGE_SCHEMA", getCurrentPage(selected.form_type.form_schema))
commit("SET_ATTORNEY_PAGE_SCHEMA", getCurrentPage(selected.form_type.attorney_form_schema))
commit("SET_DIALOG_CREATE_EDIT", true)
},
attorneyEditShow({ commit }, selected) {
commit("SET_SELECTED", selected)
commit("SET_PAGE_DATA", buildFormDoc(selected.form_type.form_schema, selected.form_data))
commit("SET_ATTORNEY_PAGE_SCHEMA", getCurrentPage(selected.form_type.attorney_form_schema))
commit(
"SET_PAGE_DATA",
buildFormDoc(
selected.form_type.form_schema,
selected.form_data,
selected.form_type.attorney_form_schema
)
)
IncidentApi.get(selected.incident.id).then((response) => {
commit("SET_INCIDENT_DATA", buildIncidentDoc(response.data))
commit("SET_DIALOG_ATTORNEY_EDIT", true)
Expand All @@ -389,7 +406,14 @@ const actions = {
let selected = response.data
commit("SET_TABLE_LOADING", false)
commit("SET_SELECTED", selected)
commit("SET_PAGE_DATA", buildFormDoc(selected.form_type.form_schema, selected.form_data))
commit(
"SET_PAGE_DATA",
buildFormDoc(
selected.form_type.form_schema,
selected.form_data,
selected.form_type.attorney_form_schema
)
)
IncidentApi.get(selected.incident.id).then((response) => {
commit("SET_INCIDENT_DATA", buildIncidentDoc(response.data))
commit("SET_DIALOG_ATTORNEY_EDIT", true)
Expand Down Expand Up @@ -455,10 +479,14 @@ const mutations = {
SET_SELECTED(state, value) {
state.selected = Object.assign(state.selected, value)
state.selected.form_data = JSON.parse(state.selected.form_data)
state.selected.attorney_form_data = JSON.parse(state.selected.attorney_form_data)
},
SET_FORM_SCHEMA(state, value) {
state.selected.form_schema = value
},
SET_ATTORNEY_PAGE_SCHEMA(state, value) {
state.attorney_page_schema = value
},
SET_PAGE_SCHEMA(state, value) {
state.page_schema = value
state.has_formkit_pro = hasFormkitPro
Expand Down Expand Up @@ -501,6 +529,7 @@ const mutations = {
state.incident_id = null
state.project_id = null
state.page_schema = null
state.attorney_page_schema = null
},
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,10 +52,20 @@
<v-textarea v-model="attorney_analysis" label="Attorney analysis" />
</v-col>
</v-row>
<div v-if="attorney_page_schema">
<span class="text-body-1 mt-3 text-medium-emphasis">Additional attorney questions</span>
<FormKit
style="margin-left: 20px; margin-right: 20px; margin-top: 10px"
type="form"
v-model="attorney_form_data"
:actions="false"
>
<FormKitSchema :schema="attorney_page_schema" :data="attorney_form_data" />
</FormKit>
</div>
</v-container>
<v-card-actions>
<v-spacer />

<div>
<v-menu anchor="bottom end">
<template #activator="{ props }">
Expand Down Expand Up @@ -100,6 +110,7 @@ export default {
"dialogs.showAttorneyEdit",
"selected.id",
"selected.form_schema",
"selected.attorney_form_data",
"selected.form_type",
"selected.form_data",
"selected.incident_id",
Expand All @@ -109,6 +120,7 @@ export default {
"selected.project",
"selected.incident",
"page_data",
"attorney_page_schema",
"incident_data",
]),
...mapFields("incident", { selected_incident: "selected" }),
Expand Down
50 changes: 2 additions & 48 deletions src/dispatch/static/dispatch/src/forms/table/store.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,8 @@ const getDefaultSelectedState = () => {
attorney_analysis: null,
form_type: null,
project: null,
form_schema: [],
form_schema: null,
attorney_form_schema: null,
}
}

Expand Down Expand Up @@ -60,51 +61,6 @@ const getters = {
getField,
}

function getCurrentPage() {
return [
{
$formkit: "text",
name: "email",
prefixIcon: "email",
label: "Email",
value: "hello@formkit.com",
help: "This email will be used for account notifications.",
validation: "required|email",
},
{
$formkit: "number",
name: "users",
prefixIcon: "avatarMan",
id: "users",
min: "1",
max: "100",
value: "3",
label: "Users",
help: "How many users do you need on your plan?",
},
{
$formkit: "checkbox",
name: "eu_company",
id: "eu",
label: "Are you located in the European Union?",
},
{
$formkit: "select",
// 👀 Oooo, conditionals!
if: "$get(eu).value",
name: "cookie_notice",
label: "Cookie notice frequency",
prefixIcon: "warning",
options: {
refresh: "Every page load",
hourly: "Ever hour",
daily: "Every day",
},
help: "How often should we display a cookie notice?",
},
]
}

function createPayload() {
const payload = {}
const validKeys = [
Expand Down Expand Up @@ -189,7 +145,6 @@ const actions = {
state.selected.form_type_id = form_type_id
FormsTypeApi.get(form_type_id)
.then((response) => {
commit("SET_PAGE_SCHEMA", getCurrentPage())
commit("SET_FORM_TYPE", response.data)
commit("SET_DIALOG_CREATE_EDIT", true)
})
Expand All @@ -199,7 +154,6 @@ const actions = {
},
editShow({ commit }, selected) {
commit("SET_SELECTED", selected)
commit("SET_PAGE_SCHEMA", getCurrentPage())
commit("SET_DIALOG_CREATE_EDIT", true)
},
showDeleteDialog({ commit }, form) {
Expand Down
20 changes: 20 additions & 0 deletions src/dispatch/static/dispatch/src/forms/types/NewEditSheet.vue
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,24 @@
</span>
<service-select label="Oncall Service" :project="project" v-model="service" />
</v-col>
<v-col cols="12">
<v-textarea
v-model="attorney_form_schema"
label="Attorney Form Schema (optional)"
hint="The schema used to define the attorney questions."
clearable
name="Attorney Form Schema (optional)"
/>
</v-col>
<v-col cols="12">
<v-textarea
v-model="scoring_schema"
label="Scoring Schema (optional)"
hint="The scoring schema used with this form."
clearable
name="Scoring Schema (optional)"
/>
</v-col>
<div v-if="!has_formkit_pro" class="ml-11 text-caption text-grey">
For more advanced form components, upgrade to
<a href="https://formkit.com/pro" target="_blank" rel="noopener noreferrer"
Expand Down Expand Up @@ -115,6 +133,8 @@ export default {
"selected.project",
"selected.service",
"selected.form_schema",
"selected.attorney_form_schema",
"selected.scoring_schema",
"dialogs.showCreateEdit",
"has_formkit_pro",
]),
Expand Down
4 changes: 3 additions & 1 deletion src/dispatch/static/dispatch/src/forms/types/store.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,9 @@ const getDefaultSelectedState = () => {
enabled: false,
created_at: null,
updated_at: null,
form_schema: "",
form_schema: null,
attorney_form_schema: null,
scoring_schema: null,
service: null,
creator: null,
project: null,
Expand Down