Skip to content

Nations modal #1066

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 12 commits into from
Oct 23, 2023
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
"""added notes and pip fields to indigenous nations.

Revision ID: 7deec389ae56
Revises: d8b405f9d663
Create Date: 2023-10-18 11:46:46.577009

"""
from alembic import op
import sqlalchemy as sa


# revision identifiers, used by Alembic.
revision = '7deec389ae56'
down_revision = 'd8b405f9d663'
branch_labels = None
depends_on = None


def upgrade():
# ### commands auto generated by Alembic - please adjust! ###
with op.batch_alter_table('indigenous_nations', schema=None) as batch_op:
batch_op.add_column(sa.Column('notes', sa.String(), nullable=True))
batch_op.add_column(sa.Column('pip_org_type_id', sa.Integer(), nullable=True))
batch_op.create_foreign_key(None, 'pip_org_types', ['pip_org_type_id'], ['id'])

with op.batch_alter_table('indigenous_nations_history', schema=None) as batch_op:
batch_op.add_column(sa.Column('notes', sa.String(), autoincrement=False, nullable=True))
batch_op.add_column(sa.Column('pip_org_type_id', sa.Integer(), autoincrement=False, nullable=True))
batch_op.create_foreign_key(None, 'pip_org_types', ['pip_org_type_id'], ['id'])

# ### end Alembic commands ###


def downgrade():
# ### commands auto generated by Alembic - please adjust! ###
with op.batch_alter_table('indigenous_nations_history', schema=None) as batch_op:
batch_op.drop_constraint(None, type_='foreignkey')
batch_op.drop_column('pip_org_type_id')
batch_op.drop_column('notes')

with op.batch_alter_table('indigenous_nations', schema=None) as batch_op:
batch_op.drop_constraint(None, type_='foreignkey')
batch_op.drop_column('pip_org_type_id')
batch_op.drop_column('notes')

# ### end Alembic commands ###
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
"""create pip_org_type table

Revision ID: d8b405f9d663
Revises: 47b41964f6df
Create Date: 2023-10-18 11:45:36.531064

"""
from alembic import op
import sqlalchemy as sa
from sqlalchemy.dialects import postgresql

# revision identifiers, used by Alembic.
revision = 'd8b405f9d663'
down_revision = '47b41964f6df'
branch_labels = None
depends_on = None


def upgrade():
# ### commands auto generated by Alembic - please adjust! ###
pip_org_type = op.create_table('pip_org_types',
sa.Column('id', sa.Integer(), autoincrement=True, nullable=False),
sa.Column('name', sa.String(), nullable=False),
sa.Column('created_by', sa.String(length=255), nullable=True),
sa.Column('created_at', sa.DateTime(timezone=True), server_default=sa.text("TIMEZONE('utc', CURRENT_TIMESTAMP)"), nullable=True),
sa.Column('updated_by', sa.String(length=255), nullable=True),
sa.Column('updated_at', sa.DateTime(timezone=True), nullable=True),
sa.Column('is_active', sa.Boolean(), server_default='t', nullable=False),
sa.Column('is_deleted', sa.Boolean(), server_default='f', nullable=False),
sa.PrimaryKeyConstraint('id'),
sqlite_autoincrement=True
)
op.create_table('pip_org_types_history',
sa.Column('id', sa.Integer(), autoincrement=False, nullable=False),
sa.Column('name', sa.String(), autoincrement=False, nullable=False),
sa.Column('created_by', sa.String(length=255), autoincrement=False, nullable=True),
sa.Column('created_at', sa.DateTime(timezone=True), autoincrement=False, nullable=True),
sa.Column('updated_by', sa.String(length=255), autoincrement=False, nullable=True),
sa.Column('updated_at', sa.DateTime(timezone=True), autoincrement=False, nullable=True),
sa.Column('is_active', sa.Boolean(), autoincrement=False, nullable=False),
sa.Column('is_deleted', sa.Boolean(), autoincrement=False, nullable=False),
sa.Column('pk', sa.Integer(), autoincrement=True, nullable=False),
sa.Column('during', postgresql.TSTZRANGE(), nullable=True),
sa.PrimaryKeyConstraint('id', 'pk'),
sqlite_autoincrement=True
)
op.bulk_insert(pip_org_type,
[
{
"name": "Clan"
},
{
"name": "First Nation"
},
{
"name": "First Nation Group"
},
{
"name": "House"
},
{
"name": "Keyoh"
},
{
"name": "Metis"
},
{
"name": "Tribal Council"
},
{
"name": "Wilp"
}
])
# ### end Alembic commands ###


def downgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.drop_table('pip_org_types_history')
op.drop_table('pip_org_types')
# ### end Alembic commands ###
1 change: 1 addition & 0 deletions epictrack-api/src/api/models/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -69,3 +69,4 @@
from .action_configuration import ActionCofiguration
from .task_event_responsibility import TaskEventResponsibility
from .act_section import ActSection
from .pip_org_type import PIPOrgType
6 changes: 6 additions & 0 deletions epictrack-api/src/api/models/indigenous_nation.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ class IndigenousNation(db.Model, CodeTableVersioned):
name = Column(String(255), nullable=False)
is_active = Column(Boolean, default=True, nullable=False)
pip_link = Column(URLType, default=None, nullable=True)
notes = Column(String)

relationship_holder_id = Column(
ForeignKey("staffs.id"), nullable=True, default=None
Expand All @@ -38,6 +39,11 @@ class IndigenousNation(db.Model, CodeTableVersioned):
"Staff", foreign_keys=[relationship_holder_id], lazy="select"
)

pip_org_type_id = Column(ForeignKey("pip_org_types.id"))
pip_org_type = relationship(
"PIPOrgType", foreign_keys=[pip_org_type_id], lazy="select"
)

def as_dict(self):
"""Return JSON Representation."""
result = CodeTableVersioned.as_dict(self)
Expand Down
28 changes: 28 additions & 0 deletions epictrack-api/src/api/models/pip_org_type.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# Copyright © 2019 Province of British Columbia
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""Model to handle all operations related to PIP Organization Types."""

from sqlalchemy import Column, Integer, String

from .code_table import CodeTableVersioned
from .db import db


class PIPOrgType(db.Model, CodeTableVersioned):
"""Model class for PIP Organization Types."""

__tablename__ = 'pip_org_types'

id = Column(Integer, primary_key=True, autoincrement=True)
name = Column(String(), nullable=False)
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,24 @@ class IndigenousNationBodyParameterSchema(RequestBodyParameterSchema):
is_active = fields.Bool(
metadata={"description": "Active state of the indigenous nation"})

notes = fields.Str(
metadata={"description": "Notes for the indigenous nation"},
allow_none=True
)

pip_org_type_id = fields.Int(
metadata={"description": "PIP organization type for the indigenous nation"},
validate=validate.Range(min=1),
allow_none=True,
missing=None
)

pip_link = fields.Str(
metadata={"description": "PIP site URL for indigenous nation"},
allow_none=True,
missing=None
)


class IndigenousNationExistenceQueryParamSchema(RequestQueryParameterSchema):
"""IndigenousNation existance check query parameters"""
Expand Down
2 changes: 1 addition & 1 deletion epictrack-web/src/components/icons/index.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React, { ReactNode } from "react";
import React from "react";
import { IconProps } from "./type";

const commonProps = {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,16 +1,19 @@
import React from "react";
import { TextField, Grid, Button } from "@mui/material";
import { TextField, Grid } from "@mui/material";
import { FormProvider, useForm } from "react-hook-form";
import * as yup from "yup";
import { yupResolver } from "@hookform/resolvers/yup";
import { ETFormLabel } from "../shared/index";
import { Staff } from "../../models/staff";
import ControlledCheckbox from "../shared/controlledInputComponents/ControlledCheckbox";
import indigenousNationService from "../../services/indigenousNationService/indigenousNationService";
import { FirstNation } from "../../models/firstNation";
import staffService from "../../services/staffService/staffService";
import ControlledSelectV2 from "../shared/controlledInputComponents/ControlledSelectV2";
import { MasterContext } from "../shared/MasterContext";
import { PIPOrgType } from "../../models/pipOrgType";
import ControlledSwitch from "../shared/controlledInputComponents/ControlledSwitch";
import RichTextEditor from "../shared/richTextEditor";
import codeService, { Code } from "../../services/codeService";

const schema = yup.object().shape({
name: yup
Expand All @@ -31,16 +34,23 @@ const schema = yup.object().shape({
return true;
}
),
pip_url: yup.string(),
});

export default function IndigenousNationForm({ ...props }) {
const [staffs, setStaffs] = React.useState<Staff[]>([]);
const [pipOrgTypes, setPipOrgTypes] = React.useState<PIPOrgType[]>([]);
const [notes, setNotes] = React.useState("");
const ctx = React.useContext(MasterContext);

React.useEffect(() => {
ctx.setFormId("indigenous-nation-form");
}, []);

React.useEffect(() => {
ctx.setTitle(ctx.item ? (ctx.item as FirstNation)?.name : "Nation");
}, [ctx.title, ctx.item]);

React.useEffect(() => {
ctx.setId(props.indigenousNationID);
}, [ctx.id]);
Expand All @@ -60,6 +70,9 @@ export default function IndigenousNationForm({ ...props }) {

React.useEffect(() => {
reset(ctx.item);
if (ctx.item) {
setNotes((ctx.item as FirstNation)?.notes || "");
}
}, [ctx.item]);

const getStaffs = async () => {
Expand All @@ -68,14 +81,37 @@ export default function IndigenousNationForm({ ...props }) {
setStaffs(staffsResult.data as never);
}
};

const codeTypes: { [x: string]: any } = {
pip_org_types: setPipOrgTypes,
};

const getCodes = async (code: Code) => {
const codeResult = await codeService.getCodes(code);
if (codeResult.status === 200) {
codeTypes[code]((codeResult.data as never)["codes"]);
}
};

React.useEffect(() => {
getStaffs();
const promises: any[] = [];
Object.keys(codeTypes).forEach(async (key) => {
promises.push(getCodes(key as Code));
});
Promise.all(promises);
}, []);

const onSubmitHandler = async (data: FirstNation) => {
data.notes = notes;
ctx.onSave(data, () => {
reset();
});
ctx.setId(undefined);
};

console.log(pipOrgTypes);

return (
<>
<FormProvider {...methods}>
Expand All @@ -87,8 +123,9 @@ export default function IndigenousNationForm({ ...props }) {
onSubmit={handleSubmit(onSubmitHandler)}
>
<Grid item xs={6}>
<ETFormLabel>Name</ETFormLabel>
<ETFormLabel required>Name</ETFormLabel>
<TextField
placeholder="Name"
fullWidth
error={!!errors?.name?.message}
helperText={errors?.name?.message?.toString()}
Expand All @@ -98,6 +135,7 @@ export default function IndigenousNationForm({ ...props }) {
<Grid item xs={6}>
<ETFormLabel>Relationship Holder</ETFormLabel>
<ControlledSelectV2
placeholder="Select a Relationship Holder"
defaultValue={
(ctx.item as FirstNation)?.relationship_holder_id || ""
}
Expand All @@ -107,8 +145,30 @@ export default function IndigenousNationForm({ ...props }) {
{...register("relationship_holder_id")}
></ControlledSelectV2>
</Grid>
<Grid item xs={6}>
<ETFormLabel>PIP Organization Type</ETFormLabel>
<ControlledSelectV2
placeholder="Select an Organization Type"
defaultValue={(ctx.item as FirstNation)?.pip_org_type_id || ""}
getOptionLabel={(o: PIPOrgType) => (o ? o.name : "")}
getOptionValue={(o: PIPOrgType) => (o ? o.id.toString() : "")}
options={pipOrgTypes || []}
{...register("pip_org_type_id")}
></ControlledSelectV2>
</Grid>
<Grid item xs={6}>
<ETFormLabel>PIP URL</ETFormLabel>
<TextField fullWidth {...register("pip_link")} />
</Grid>
<Grid item xs={12}>
<ETFormLabel>Notes</ETFormLabel>
<RichTextEditor
handleEditorStateChange={setNotes}
initialRawEditorState={(ctx.item as FirstNation)?.notes}
/>
</Grid>
<Grid item xs={6} sx={{ paddingTop: "30px !important" }}>
<ControlledCheckbox
<ControlledSwitch
defaultChecked={(ctx.item as FirstNation)?.is_active}
{...register("is_active")}
/>
Expand Down
4 changes: 4 additions & 0 deletions epictrack-web/src/models/firstNation.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,16 @@
import { ListType } from "./code";
import { Staff } from "./staff";
import { MasterBase } from "./type";
import { PIPOrgType } from "./pipOrgType";

export interface FirstNation extends ListType, MasterBase {
is_active: boolean;
relationship_holder_id?: number;
relationship_holder?: Staff;
pip_link: string;
notes?: string;
pip_org_type_id: number;
pip_org_type: PIPOrgType;
}

export interface WorkFirstNation extends ListType, MasterBase {
Expand Down
4 changes: 4 additions & 0 deletions epictrack-web/src/models/pipOrgType.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
import { ListType } from "./code";
import { MasterBase } from "./type";

export interface PIPOrgType extends ListType, MasterBase {}
3 changes: 2 additions & 1 deletion epictrack-web/src/services/codeService/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,8 @@ export type Code =
| "federal_involvements"
| "responsibilities"
| "roles"
| "substitution_acts";
| "substitution_acts"
| "pip_org_types";

const getCodes = async (codeType: Code, apiUrl?: string) => {
return await http.GetRequest(Endpoints.Codes.GET_CODES + `/${codeType}`);
Expand Down