Skip to content

Commit

Permalink
Merge pull request #2593 from bcgov/DESENG-670-admin-authoring-header…
Browse files Browse the repository at this point in the history
…-page

DESENG-670: Admin authoring header page
  • Loading branch information
NatSquared authored Sep 24, 2024
2 parents f51812c + 7a2c21d commit b95a8c7
Show file tree
Hide file tree
Showing 48 changed files with 1,283 additions and 733 deletions.
17 changes: 13 additions & 4 deletions CHANGELOG.MD
Original file line number Diff line number Diff line change
@@ -1,14 +1,23 @@
## September 23, 2024

- **Feature** New Hero Banner page in authoring section [🎟️ DESENG-670](https://citz-gdx.atlassian.net/browse/DESENG-670)
- Hooks into existing AuthoringTemplate component for form submission
- Added new fields for hero banner content
- Added image upload functionality
- Added layout components for engagement authoring form fields

## September 18, 2024

- **Feature** New Video Widget front end [🎟️ DESENG-692](https://citz-gdx.atlassian.net/browse/DESENG-692)

- Implemented Figma design
- Created custom layover bar for videos that shows video provider and has a custom logo
- Transcripts will not be implemented at this time

- Summary page in authoring section [🎟️ DESENG-671](https://citz-gdx.atlassian.net/browse/DESENG-671)
- Streamlined data loaders and actions to account for page changes
- Updated data structure so that summary data is pulled from engagement table
- Added 'description_title' column to engagement table
- Streamlined data loaders and actions to account for page changes
- Updated data structure so that summary data is pulled from engagement table
- Added 'description_title' column to engagement table

## September 12, 2024

Expand All @@ -17,7 +26,7 @@
- Saves values to database
- Returns success and error messages to user after form submission
- Resets form dirty state after submission

## September 9, 2024

- **Feature** Add image widget [🎟️ DESENG-689](https://citz-gdx.atlassian.net/browse/DESENG-689)
Expand Down
7 changes: 6 additions & 1 deletion CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ Examples of when to Request Changes
- Be sure to make use of shared components found under `src/components/common`. Below is a non-exhaustive list of common app components:
- `Button`: A versatile button with different style types that are complimentary of MET styling. Choose a particular button style with: `variant=<"primary"|"secondary"|"tertiary"|undefined>`
- `RichTextArea`: A WYSIWYG editor used app-wide. It will dynamically render out links and h2s as React components.
- `Header1`, `Header2`: MET-styled h1, h2 components.
- `Header1`, `Header2`, `Header3`: MET-styled h1, h2 and h3 components. Prefer these over using the native HTML headers.
- `ResponsiveContainer`: A container that decreases its padding on smaller screens.
- `ResponsiveWrapper`: A route wrapper that adds a responsive container around its child routes.
- `Pagination`: Provides a pagination UI - a wrapper around Material UI's pagination.
Expand All @@ -96,3 +96,8 @@ Examples of when to Request Changes
- `FormStep`: A wrapper around a form component that accepts a completion criteria and displays the user's progress. Accepts a `step` prop that is a number (from 1 to 9) that represents the current step in the form. This will be rendered as an icon with a checkmark if the step is complete, and a number if it's the current step or if it's incomplete.
- `SystemMessage`: An informational message that can be displayed to the user. Accepts a `type` prop that can be "error", "warning", "info", or "success", which affects the display of the message.
- `WidgetPicker`: A modular widget picker component that can be placed anywhere in the engagement editing area. In order to align widgets in the backend with the frontend, a "location" prop is required. Add new locations to the `WidgetLocation` enum.
- `ErrorMessage`: Display a form validation error message with an error icon. Used when creating a custom form element, e.g. `TextField`.
Accepts a `message` prop that is the error message to display.
- `TextInput`: A styled text input that can be used in forms. Accepts a `placeholder` and all other props that a normal MUI TextField would accept.
- `TextField`: A convenience wrapper around `TextInput` that includes a label, requirement decorations, and helper/error text. Error text is internally rendered by `ErrorMessage`.
- `RichTextArea`: A WYSIWYG editor that can be used in forms. Hook into editor state with `editorState` and `onEditorStateChange`. Accepts aria accessibility props. Manage toolbar options with the `toolbar` prop. The editor is pre-styled, but can be overridden with `wrapperStyle`, `toolbarStyle`, and `editorStyle`.
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
"""remove obsolete cta_message column from engagement_translation
Revision ID: 58923bf5bda6
Revises: 63890bdab166
Create Date: 2024-09-24 13:00:12.107334
"""
from alembic import op
import sqlalchemy as sa


# revision identifiers, used by Alembic.
revision = '58923bf5bda6'
down_revision = '63890bdab166'
branch_labels = None
depends_on = None


def upgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.drop_column('engagement_translation', 'cta_message')
# ### end Alembic commands ###


def downgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.add_column('engagement_translation', sa.Column('cta_message', sa.VARCHAR(length=50), autoincrement=False, nullable=True))
# ### end Alembic commands ###
25 changes: 25 additions & 0 deletions met-api/migrations/versions/63890bdab166_merge_heads.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
"""Merge heads
Revision ID: 63890bdab166
Revises: df693f5ddaf9, 828b4f34734a
Create Date: 2024-09-20 13:55:27.230188
"""

from alembic import op
import sqlalchemy as sa


# revision identifiers, used by Alembic.
revision = "63890bdab166"
down_revision = ("df693f5ddaf9", "828b4f34734a")
branch_labels = None
depends_on = None


def upgrade():
pass


def downgrade():
pass
174 changes: 174 additions & 0 deletions met-api/migrations/versions/828b4f34734a_status_block_updates.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,174 @@
"""Move cta_message and cta_url from engagement to engagement_status_block
Revision ID: 828b4f34734a
Revises: e706db763790
Create Date: 2024-09-16 10:18:49.858066
"""

from enum import IntEnum, Enum
from alembic import op
import sqlalchemy as sa


class SubmissionStatus(IntEnum):
"""Enum of engagement submission status."""

Upcoming = 1
Open = 2
Closed = 3
ViewResults = 4


# revision identifiers, used by Alembic.
revision = "828b4f34734a"
down_revision = "e706db763790"
branch_labels = None
depends_on = None


def upgrade():
connection = op.get_bind()
# Create a new enum type with the 'ViewResults' value
op.execute("ALTER TYPE submissionstatus RENAME TO submissionstatus_old")
op.execute(
"CREATE TYPE submissionstatus AS ENUM ('Upcoming', 'Open', 'Closed', 'ViewResults')"
)
# Commit the enum change before dropping the old one
op.execute("COMMIT")
# Convert the existing data to the new enum type
connection.execute(
"ALTER TABLE engagement_status_block ALTER COLUMN survey_status TYPE submissionstatus USING survey_status::text::submissionstatus"
)
# Drop the old enum type
op.execute("DROP TYPE submissionstatus_old")

op.add_column(
"engagement_status_block",
sa.Column("button_text", sa.String(length=20), nullable=True),
)
op.add_column(
"engagement_status_block",
sa.Column(
"link_type", sa.String(length=20), nullable=False, server_default="internal"
),
)
op.add_column(
"engagement_status_block",
sa.Column("internal_link", sa.String(length=50), nullable=True),
)
op.add_column(
"engagement_status_block",
sa.Column("external_link", sa.String(length=300), nullable=True),
)
# Migrate data from engagement to engagement_status_block
# Ad-hoc table definition for engagement
engagement_table = sa.Table(
"engagement",
sa.MetaData(),
sa.Column("id", sa.Integer),
sa.Column("cta_message", sa.String(50)),
sa.Column("cta_url", sa.String(500)),
)
# Ad-hoc table definition for engagement_status_block
engagement_status_block_table = sa.Table(
"engagement_status_block",
sa.MetaData(),
sa.Column("id", sa.Integer),
sa.Column("engagement_id", sa.Integer),
sa.Column(
"survey_status",
sa.Enum(
SubmissionStatus,
name="submissionstatus",
metadata=sa.MetaData(),
create_constraint=True,
),
),
sa.Column("block_text", sa.JSON),
sa.Column("button_text", sa.String(20)),
sa.Column("link_type", sa.String(20)),
sa.Column("internal_link", sa.String(50)),
sa.Column("external_link", sa.String(300)),
sa.Column("created_date", sa.DateTime),
sa.Column("updated_date", sa.DateTime),
)
# For each engagement...
for engagement in connection.execute(engagement_table.select()):
# Update existing engagement_status_blocks...
# If the URL starts with "http", it's an external link.
if engagement.cta_url and engagement.cta_url.startswith("http"):
link_type = "external"
external_link = engagement.cta_url
internal_link = None
else:
valid_statuses = ["hero", "description", "contentTabs", "provideFeedback"]
link_type = "internal"
external_link = None
internal_link = None
if engagement.cta_url in valid_statuses:
internal_link = engagement.cta_url
else:
internal_link = "provideFeedback"
connection.execute(
engagement_status_block_table.update()
.where(engagement_status_block_table.c.engagement_id == engagement.id)
.where(engagement_status_block_table.c.survey_status == "Open")
.values(
button_text=engagement.cta_message or "Provide Feedback",
link_type=link_type,
external_link=external_link,
internal_link=internal_link,
)
)
# And add the "View Results" block type.
connection.execute(
engagement_status_block_table.insert().values(
engagement_id=engagement.id,
survey_status=SubmissionStatus.ViewResults,
block_text={},
button_text="View Results",
link_type="internal",
internal_link="provideFeedback",
external_link=None,
created_date=sa.func.now(),
updated_date=sa.func.now(),
)
)
# Drop the columns from the engagement table
op.drop_column("engagement", "cta_message")
op.drop_column("engagement", "cta_url")


def downgrade():
op.drop_column("engagement_status_block", "external_link")
op.drop_column("engagement_status_block", "internal_link")
op.drop_column("engagement_status_block", "link_type")
op.drop_column("engagement_status_block", "button_text")
op.add_column(
"engagement",
sa.Column(
"cta_url", sa.VARCHAR(length=500), autoincrement=False, nullable=True
),
)
op.add_column(
"engagement",
sa.Column(
"cta_message", sa.VARCHAR(length=50), autoincrement=False, nullable=True
),
)
# Create a new enum type without the 'ViewResults' value
op.execute("ALTER TYPE submissionstatus RENAME TO submissionstatus_old")
op.execute("CREATE TYPE submissionstatus AS ENUM ('Upcoming', 'Open', 'Closed')")
# Commit the enum change before dropping the old one
op.execute("COMMIT")
# Convert the existing data to the new enum type
connection = op.get_bind()
connection.execute(
"UPDATE engagement_status_block SET survey_status = 'Closed' WHERE survey_status = 'ViewResults'"
)
connection.execute(
"ALTER TABLE engagement_status_block ALTER COLUMN survey_status TYPE submissionstatus USING survey_status::text::submissionstatus"
)
# Drop the old enum type
op.execute("DROP TYPE submissionstatus_old")
12 changes: 11 additions & 1 deletion met-api/src/met_api/constants/engagement_status.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
# See the License for the specific language governing permissions and
# limitations under the License.
"""Constants of engagement status."""
from enum import IntEnum
from enum import Enum, IntEnum


class Status(IntEnum):
Expand Down Expand Up @@ -43,3 +43,13 @@ class SubmissionStatus(IntEnum):
Upcoming = 1
Open = 2
Closed = 3
ViewResults = 4


class EngagementViewSections(Enum):
"""Enum of sections that can be displayed in the engagement view."""

HERO = 'hero'
DESCRIPTION = 'description'
CONTENT_TABS = 'contentTabs'
PROVIDE_FEEDBACK = 'provideFeedback'
3 changes: 0 additions & 3 deletions met-api/src/met_api/models/engagement.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,8 +57,6 @@ class Engagement(BaseModel):
is_internal = db.Column(db.Boolean, nullable=False)
consent_message = db.Column(JSON, unique=False, nullable=True)
sponsor_name = db.Column(db.String(50), nullable=True)
cta_message = db.Column(db.String(50), nullable=True)
cta_url = db.Column(db.String(500), nullable=True)

@classmethod
def get_engagements_paginated(
Expand Down Expand Up @@ -149,7 +147,6 @@ def update_engagement(cls, engagement: EngagementSchema) -> Engagement:
'consent_message': engagement.get(
'consent_message', record.consent_message),
'sponsor_name': engagement.get('sponsor_name', record.sponsor_name),
'cta_message': engagement.get('cta_message', record.cta_message),
'cta_url': engagement.get('cta_url', record.cta_url),
}
query.update(update_fields)
Expand Down
23 changes: 17 additions & 6 deletions met-api/src/met_api/models/engagement_status_block.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,22 +18,33 @@ class EngagementStatusBlock(BaseModel):

__tablename__ = 'engagement_status_block'
__table_args__ = (
db.UniqueConstraint('engagement_id', 'survey_status', name='unique_engagement_status_block'),
db.UniqueConstraint(
'engagement_id', 'survey_status', name='unique_engagement_status_block'
),
)

id = db.Column(db.Integer, primary_key=True, autoincrement=True)
engagement_id = db.Column(db.Integer, ForeignKey('engagement.id', ondelete='CASCADE'))
engagement_id = db.Column(
db.Integer, ForeignKey('engagement.id', ondelete='CASCADE')
)
survey_status = db.Column(db.Enum(SubmissionStatus), nullable=False)
block_text = db.Column(JSON, unique=False, nullable=False)
button_text = db.Column(db.String(20), nullable=True)
link_type = db.Column(db.String(20), nullable=False)
internal_link = db.Column(db.String(50), nullable=True)
external_link = db.Column(db.String(300), nullable=True)

@classmethod
def get_by_status(cls, engagement_id, survey_status):
"""Get Engagement Status by survey status."""
return db.session.query(EngagementStatusBlock) \
.filter(EngagementStatusBlock.survey_status == survey_status,
EngagementStatusBlock.engagement_id == engagement_id
) \
return (
db.session.query(EngagementStatusBlock)
.filter(
EngagementStatusBlock.survey_status == survey_status,
EngagementStatusBlock.engagement_id == engagement_id,
)
.first()
)

@classmethod
def save_status_blocks(cls, status_blocks: list) -> None:
Expand Down
2 changes: 0 additions & 2 deletions met-api/src/met_api/models/engagement_translation.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,6 @@ class EngagementTranslation(BaseModel):
open_status_block_text = db.Column(JSON, unique=False, nullable=True)
closed_status_block_text = db.Column(JSON, unique=False, nullable=True)
sponsor_name = db.Column(db.String(50))
cta_message = db.Column(db.String(50))

# Add a unique constraint on engagement_id and language_id
# A engagement has only one version in a particular language
Expand Down Expand Up @@ -80,7 +79,6 @@ def __create_new_engagement_translation_entity(data):
open_status_block_text=data.get('open_status_block_text', None),
closed_status_block_text=data.get('closed_status_block_text', None),
sponsor_name=data.get('sponsor_name', None),
cta_message=data.get('cta_message', None),
)

@staticmethod
Expand Down
2 changes: 0 additions & 2 deletions met-api/src/met_api/schemas/engagement.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,8 +49,6 @@ class Meta: # pylint: disable=too-few-public-methods
is_internal = fields.Bool(data_key='is_internal')
consent_message = fields.Str(data_key='consent_message')
sponsor_name = fields.Str(data_key='sponsor_name')
cta_message = fields.Str(data_key='cta_message')
cta_url = fields.Str(data_key='cta_url')

def get_submissions_meta_data(self, obj):
"""Get the meta data of the submissions made in the survey."""
Expand Down
Loading

0 comments on commit b95a8c7

Please sign in to comment.