Skip to content

Commit

Permalink
Merge branch 'bcgov:main' into main
Browse files Browse the repository at this point in the history
  • Loading branch information
aforde-aot authored Aug 8, 2023
2 parents c80907a + 45beb7e commit f4f19a4
Show file tree
Hide file tree
Showing 92 changed files with 1,373 additions and 420 deletions.
43 changes: 43 additions & 0 deletions met-api/migrations/versions/db737a0db061_.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
""" Fill empty widget titles
Revision ID: db737a0db061
Revises: df73727dc6d9b7_add_sub_tbl
Create Date: 2023-08-04 14:11:01.993136
"""

from alembic import op

# revision identifiers, used by Alembic.
revision = 'db737a0db061'
down_revision = 'df73727dc6d9b7_add_sub_tbl'
branch_labels = None
depends_on = None

def upgrade():
# ### commands auto generated by Alembic - please adjust! ###

# Execute an UPDATE statement to set 'title' based on 'widget_type_id'
op.execute("""
UPDATE widget
SET title =
CASE
WHEN widget_type_id = 1 THEN 'Who is Listening'
WHEN widget_type_id = 2 THEN 'Documents'
WHEN widget_type_id = 3 THEN 'Environmental Assessment Process'
WHEN widget_type_id = 4 THEN 'Sign Up for Updates'
WHEN widget_type_id = 5 THEN 'Events'
WHEN widget_type_id = 6 THEN 'Map'
WHEN widget_type_id = 7 THEN 'Video'
ELSE 'Default Title' -- This is for any widget_type_id not covered above
END
WHERE title IS NULL;
""")

# ### end Alembic commands ###

def downgrade():
# ### commands auto generated by Alembic - please adjust! ###

# Execute an UPDATE statement to set 'title' to NULL for all rows
op.execute("UPDATE widget SET title = NULL;")

# ### end Alembic commands ###
2 changes: 2 additions & 0 deletions met-api/src/met_api/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,8 @@ class _Config(): # pylint: disable=too-few-public-methods
SURVEY_PATH = os.getenv('SURVEY_PATH', '/surveys/submit/{survey_id}/{token}')
SUBSCRIBE_PATH = os.getenv('SUBSCRIBE_PATH', '/engagements/{engagement_id}/subscribe/{token}')
UNSUBSCRIBE_PATH = os.getenv('UNSUBSCRIBE_PATH', '/engagements/{engagement_id}/unsubscribe/{participant_id}')
ENGAGEMENT_PATH = os.getenv('ENGAGEMENT_PATH', '/engagements/{engagement_id}/view')
ENGAGEMENT_PATH_SLUG = os.getenv('ENGAGEMENT_PATH_SLUG', '/{slug}')
# engagement dashboard path is used to pass the survey result to the public user.
# The link is changed such that public user can access the comments page from the email and not the dashboard.
ENGAGEMENT_DASHBOARD_PATH = os.getenv('ENGAGEMENT_DASHBOARD_PATH', '/engagements/{engagement_id}/comments')
Expand Down
1 change: 1 addition & 0 deletions met-api/src/met_api/constants/user.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,4 @@


SYSTEM_USER = 1
SYSTEM_REVIEWER = 'System'
7 changes: 5 additions & 2 deletions met-api/src/met_api/models/submission.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,17 @@
Manages the Submission
"""
from __future__ import annotations

from datetime import datetime
from typing import List

from sqlalchemy import ForeignKey
from sqlalchemy.dialects import postgresql

from met_api.constants.comment_status import Status
from met_api.models.survey import Survey
from met_api.constants.user import SYSTEM_REVIEWER
from met_api.models.participant import Participant
from met_api.models.survey import Survey
from met_api.schemas.submission import SubmissionSchema

from .base_model import BaseModel
Expand Down Expand Up @@ -63,7 +66,7 @@ def create(cls, submission: SubmissionSchema, session=None) -> Submission:
const_review_date = None
else:
const_comment_status = Status.Approved.value
const_reviewed_by = 'System'
const_reviewed_by = SYSTEM_REVIEWER
const_review_date = datetime.utcnow()

new_submission = Submission(
Expand Down
14 changes: 14 additions & 0 deletions met-api/src/met_api/models/widget.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
"""
from __future__ import annotations
from datetime import datetime
from typing import Optional

from sqlalchemy.sql.schema import ForeignKey

Expand Down Expand Up @@ -65,6 +66,7 @@ def __create_new_widget_entity(widget):
updated_date=datetime.utcnow(),
created_by=widget.get('created_by', None),
updated_by=widget.get('updated_by', None),
title=widget.get('title', None),
)

@classmethod
Expand All @@ -87,3 +89,15 @@ def update_widgets(cls, update_mappings: list) -> None:
"""Update widgets.."""
db.session.bulk_update_mappings(Widget, update_mappings)
db.session.commit()

@classmethod
def update_widget(cls, engagement_id, widget_id, widget_data: dict) -> Optional[Widget]:
"""Update widget."""
query = Widget.query.filter_by(id=widget_id, engagement_id=engagement_id)
widget: Widget = query.first()
if not widget:
return None
widget_data['updated_date'] = datetime.utcnow()
query.update(widget_data)
db.session.commit()
return widget
2 changes: 1 addition & 1 deletion met-api/src/met_api/models/widgets_subscribe.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ def get_all_by_type(cls, type_, widget_id):
return db.session.query(cls).filter_by(type=type_, widget_id=widget_id).all()

@classmethod
def update_widget_events_bulk(cls, update_mappings: list) -> list[WidgetSubscribe]:
def update_widget_subscribes_bulk(cls, update_mappings: list) -> list[WidgetSubscribe]:
"""Save widget subscribe sorting."""
db.session.bulk_update_mappings(WidgetSubscribe, update_mappings)
db.session.commit()
Expand Down
3 changes: 1 addition & 2 deletions met-api/src/met_api/resources/engagement.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,7 @@ class Engagement(Resource):
def get(engagement_id):
"""Fetch a single engagement matching the provided id."""
try:
user_id = TokenInfo.get_id()
engagement_record = EngagementService().get_engagement(engagement_id, user_id)
engagement_record = EngagementService().get_engagement(engagement_id)

if engagement_record:
return engagement_record, HTTPStatus.OK
Expand Down
1 change: 0 additions & 1 deletion met-api/src/met_api/resources/survey.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,6 @@ def get(survey_id):
try:
user_id = TokenInfo.get_id()
if user_id:
# authenticated users have access to any survey/engagement status
survey_record = SurveyService().get(survey_id)
else:
survey_record = SurveyService().get_open(survey_id)
Expand Down
23 changes: 21 additions & 2 deletions met-api/src/met_api/resources/widget.py
Original file line number Diff line number Diff line change
Expand Up @@ -89,8 +89,8 @@ def patch(engagement_id):
return {'message': err.error}, err.status_code


@cors_preflight('DELETE')
@API.route('/engagement/<engagement_id>/widget/<widget_id>')
@cors_preflight('DELETE, PATCH')
@API.route('/<widget_id>/engagements/<engagement_id>')
class EngagementWidget(Resource):
"""Resource for managing widgets with engagements."""

Expand All @@ -107,6 +107,25 @@ def delete(engagement_id, widget_id):
except ValueError as err:
return str(err), HTTPStatus.INTERNAL_SERVER_ERROR

@staticmethod
@cross_origin(origins=allowedorigins())
@_jwt.requires_auth
def patch(engagement_id, widget_id):
"""Update widget."""
try:
user_id = TokenInfo.get_id()
widget_data = request.get_json()
valid_format, errors = schema_utils.validate(widget_data, 'widget_update')
if not valid_format:
return {'message': schema_utils.serialize(errors)}, HTTPStatus.BAD_REQUEST

updated_widget = WidgetService().update_widget(engagement_id, widget_id, widget_data, user_id)
return updated_widget, HTTPStatus.OK
except (KeyError, ValueError) as err:
return str(err), HTTPStatus.INTERNAL_SERVER_ERROR
except ValidationError as err:
return str(err.messages), HTTPStatus.INTERNAL_SERVER_ERROR


@cors_preflight('POST,OPTIONS')
@API.route('/<widget_id>/items')
Expand Down
30 changes: 18 additions & 12 deletions met-api/src/met_api/resources/widget_subscribe.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@
"""


@cors_preflight('GET, POST, OPTIONS, DELETE')
@cors_preflight('GET, POST, OPTIONS')
@API.route('')
class WidgetSubscribe(Resource):
"""Resource for managing a Widget Subscribe."""
Expand All @@ -59,17 +59,6 @@ def post(widget_id):
except BusinessException as err:
return str(err), err.status_code

@staticmethod
@cross_origin(origins=allowedorigins())
def delete(widget_id, subscribe_id):
"""Delete an subscribe ."""
try:
WidgetSubscribeService().delete_subscribe(subscribe_id, widget_id)
response, status = {}, HTTPStatus.OK
except BusinessException as err:
response, status = str(err), err.status_code
return response, status


@cors_preflight('GET,POST,OPTIONS')
@API.route('/<int:subscribe_id>/items', methods=['GET', 'DELETE', 'OPTIONS'])
Expand Down Expand Up @@ -124,3 +113,20 @@ def patch(widget_id):
return WidgetSubscribeSchema().dump(sort_widget_subscribe), HTTPStatus.OK
except BusinessException as err:
return str(err), err.status_code


@cors_preflight('DELETE')
@API.route('/<int:subscribe_id>', methods=['DELETE'])
class WidgetEvent(Resource):
"""Resource for managing a Widget Events."""

@staticmethod
@cross_origin(origins=allowedorigins())
def delete(widget_id, subscribe_id):
"""Delete an subscribe ."""
try:
WidgetSubscribeService().delete_subscribe(subscribe_id, widget_id)
response, status = {}, HTTPStatus.OK
except BusinessException as err:
response, status = str(err), err.status_code
return response, status
17 changes: 7 additions & 10 deletions met-api/src/met_api/schemas/engagement.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,12 @@

from marshmallow import EXCLUDE, Schema, ValidationError, fields, validate, validates_schema

from met_api.constants.engagement_status import Status, SubmissionStatus
from met_api.constants.comment_status import Status as CommentStatus
from met_api.constants.engagement_status import Status, SubmissionStatus
from met_api.schemas.engagement_status_block import EngagementStatusBlockSchema
from met_api.schemas.engagement_survey import EngagementSurveySchema
from met_api.schemas.utils import count_comments_by_status
from met_api.utils.datetime import local_datetime
from met_api.schemas.engagement_status_block import EngagementStatusBlockSchema

from .engagement_status import EngagementStatusSchema

Expand Down Expand Up @@ -61,18 +62,14 @@ def get_submissions_meta_data(self, obj):
submissions = obj.surveys[0].submissions
return {
'total': len(submissions),
'pending': self._count_comments_by_status(submissions, CommentStatus.Pending.value),
'approved': self._count_comments_by_status(submissions, CommentStatus.Approved.value),
'rejected': self._count_comments_by_status(submissions, CommentStatus.Rejected.value),
'needs_further_review': self._count_comments_by_status(
'pending': count_comments_by_status(submissions, CommentStatus.Pending.value),
'approved': count_comments_by_status(submissions, CommentStatus.Approved.value),
'rejected': count_comments_by_status(submissions, CommentStatus.Rejected.value),
'needs_further_review': count_comments_by_status(
submissions,
CommentStatus.Needs_further_review.value)
}

def _count_comments_by_status(self, submissios, status):
return len([submission for submission in submissios
if submission.comment_status_id == status])

def get_submission_status(self, obj):
"""Get the submission status of the engagement."""
if obj.status_id == Status.Draft.value or obj.status_id == Status.Scheduled.value:
Expand Down
23 changes: 23 additions & 0 deletions met-api/src/met_api/schemas/schemas/widget_update.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
{
"$schema": "http://json-schema.org/draft-07/schema",
"$id": "https://met.gov.bc.ca/.well_known/schemas/widget_update",
"type": "object",
"title": "The root schema",
"description": "The root schema comprises the entire JSON document.",
"default": {},
"examples": [
{
"title": "Who is Listening"
}
],
"required": ["title"],
"properties": {
"title": {
"$id": "#/properties/title",
"type": "string",
"title": "Widget title",
"description": "The title of the widget.",
"examples": ["Who is Listening"]
}
}
}
17 changes: 8 additions & 9 deletions met-api/src/met_api/schemas/survey.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,11 @@
"""

from marshmallow import EXCLUDE, Schema, fields
from .engagement import EngagementSchema

from met_api.constants.comment_status import Status
from met_api.schemas.utils import count_comments_by_status

from .engagement import EngagementSchema


class SurveySchema(Schema):
Expand Down Expand Up @@ -34,14 +37,10 @@ def get_comments_meta_data(self, obj):
"""Get the meta data of the comments made in the survey."""
return {
'total': len(obj.submissions),
'pending': self._count_comments_by_status(obj.submissions, Status.Pending.value),
'approved': self._count_comments_by_status(obj.submissions, Status.Approved.value),
'rejected': self._count_comments_by_status(obj.submissions, Status.Rejected.value),
'needs_further_review': self._count_comments_by_status(
'pending': count_comments_by_status(obj.submissions, Status.Pending.value),
'approved': count_comments_by_status(obj.submissions, Status.Approved.value),
'rejected': count_comments_by_status(obj.submissions, Status.Rejected.value),
'needs_further_review': count_comments_by_status(
obj.submissions,
Status.Needs_further_review.value)
}

def _count_comments_by_status(self, submissios, status):
return len([submission for submission in submissios
if submission.comment_status_id == status])
16 changes: 16 additions & 0 deletions met-api/src/met_api/schemas/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
from typing import Tuple

from jsonschema import Draft7Validator, RefResolver, SchemaError, draft7_format_checker
from met_api.constants.user import SYSTEM_REVIEWER


BASE_URI = 'https://met.gov.bc.ca/.well_known/schemas'
Expand Down Expand Up @@ -115,3 +116,18 @@ def serialize(errors):
for error in errors:
error_message.append(error.message)
return error_message


def count_comments_by_status(submissions, status):
"""Count the comments by their status.
:param submissions: List of submissions
:param status: Status of the comments
:return: Number of comments with the provided status
"""
return len([
submission
for submission in submissions
if (submission.comment_status_id == status and
submission.reviewed_by != SYSTEM_REVIEWER)
])
1 change: 1 addition & 0 deletions met-api/src/met_api/schemas/widget.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ class Meta: # pylint: disable=too-few-public-methods
unknown = EXCLUDE

id = fields.Int(data_key='id')
title = fields.Str(data_key='title')
widget_type_id = fields.Int(data_key='widget_type_id', required=True)
engagement_id = fields.Int(data_key='engagement_id', required=True)
created_by = fields.Str(data_key='created_by')
Expand Down
Loading

0 comments on commit f4f19a4

Please sign in to comment.