Skip to content

Commit

Permalink
DESENG-675 Make widget component "reusable"
Browse files Browse the repository at this point in the history
  • Loading branch information
Baelx committed Aug 21, 2024
1 parent e2d09dd commit 143a4cf
Show file tree
Hide file tree
Showing 26 changed files with 192 additions and 3 deletions.
24 changes: 24 additions & 0 deletions met-api/migrations/versions/c2a384ddfe6a_add_widget_location.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
"""Add locations to widgets
Revision ID: c2a384ddfe6a
Revises: 901a6724bca2
Create Date: 2024-08-21 16:04:25.726651
"""
from alembic import op
import sqlalchemy as sa


# revision identifiers, used by Alembic.
revision = 'c2a384ddfe6a'
down_revision = '901a6724bca2'
branch_labels = None
depends_on = None


def upgrade():
op.add_column('widget', sa.Column('location', sa.Integer(), nullable=True))


def downgrade():
op.drop_column('widget', 'location')
2 changes: 2 additions & 0 deletions met-api/src/met_api/models/widget.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ class Widget(BaseModel): # pylint: disable=too-few-public-methods
title = db.Column(db.String(100), comment='Custom title for the widget.')
items = db.relationship('WidgetItem', backref='widget', cascade='all, delete', order_by='WidgetItem.sort_index')
sort_index = db.Column(db.Integer, nullable=False, default=1)
location = db.Column(db.Integer, nullable=False)

@classmethod
def get_widget_by_id(cls, widget_id):
Expand Down Expand Up @@ -67,6 +68,7 @@ def __create_new_widget_entity(widget):
created_by=widget.get('created_by', None),
updated_by=widget.get('updated_by', None),
title=widget.get('title', None),
location=widget.get('location', None),
)

@classmethod
Expand Down
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 @@ -23,3 +23,4 @@ class Meta: # pylint: disable=too-few-public-methods
updated_date = fields.Str(data_key='updated_date')
sort_index = fields.Int(data_key='sort_index')
items = fields.List(fields.Nested(WidgetItemSchema))
location = fields.Int(data_key='location')
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
import React, { useContext, useEffect } from 'react';
import { WidgetDrawerContext } from 'components/engagement/form/EngagementWidgets/WidgetDrawerContext';
import { Grid, Skeleton } from '@mui/material';
import { If, Else, Then } from 'react-if';
import { useAppDispatch } from 'hooks';
import { colors } from 'styles/Theme';
import { WidgetCardSwitch } from 'components/engagement/form/EngagementWidgets/WidgetCardSwitch';
import { openNotificationModal } from 'services/notificationModalService/notificationModalSlice';
import { WidgetLocation } from 'models/widget';

export const WidgetPickerButton = ({ location }: { location: WidgetLocation }) => {
const { widgets, deleteWidget, handleWidgetDrawerOpen, isWidgetsLoading, setWidgetLocation } =
useContext(WidgetDrawerContext);
const dispatch = useAppDispatch();

useEffect(() => {
setWidgetLocation(location);
return () => setWidgetLocation(0);
}, []);

const removeWidget = (widgetId: number) => {
dispatch(
openNotificationModal({
open: true,
data: {
header: 'Remove Widget',
subText: [
{ text: 'You will be removing this widget from the engagement.' },
{ text: 'Do you want to remove this widget?' },
],
handleConfirm: () => {
deleteWidget(widgetId);
},
},
type: 'confirm',
}),
);
};

return (
<Grid container spacing={2} direction="column">
<If condition={isWidgetsLoading}>
<Then>
<Grid item xs={12}>
<Skeleton width="100%" height="3em" />
</Grid>
</Then>
<Else>
<Grid item>
{/* Only ever render the first selected widget. This may change in the future. */}
{widgets.length > 0 ? (
<WidgetCardSwitch
singleSelection={true}
key={`${widgets[0].widget_type_id}`}
widget={widgets[0]}
removeWidget={removeWidget}
/>
) : (
<button
onClick={() => handleWidgetDrawerOpen(true)}
style={{
width: '100%',
borderRadius: '8px',
borderColor: colors.surface.blue[90],
borderWidth: '2px',
borderStyle: 'dashed',
backgroundColor: colors.surface.blue[10],
padding: '3rem',
fontSize: '16px',
color: colors.surface.blue[90],
cursor: 'pointer',
}}
>
Optional Content Widgets
</button>
)}
</Grid>
</Else>
</If>
</Grid>
);
};
19 changes: 19 additions & 0 deletions met-web/src/components/engagement/admin/create/widgets/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import React from 'react';
import WidgetDrawer from 'components/engagement/form/EngagementWidgets/WidgetDrawer';
import { WidgetDrawerProvider } from 'components/engagement/form/EngagementWidgets/WidgetDrawerContext';
import { WidgetPickerButton } from './WidgetPickerButton';
import { WidgetLocation } from 'models/widget';
import { ActionProvider } from 'components/engagement/form/ActionContext';

export const WidgetPicker = ({ location }: { location: WidgetLocation }) => {
return (
<ActionProvider>
<WidgetDrawerProvider>
<WidgetPickerButton location={location} />
<WidgetDrawer />
</WidgetDrawerProvider>
</ActionProvider>
);
};

export default WidgetPicker;
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ import { ENGAGEMENT_MEMBERSHIP_STATUS, EngagementTeamMember } from 'models/engag
import { Button } from 'components/common/Input';
import { faPen } from '@fortawesome/pro-regular-svg-icons';
import { LiveAnnouncer, LiveMessage } from 'react-aria-live';
import { WidgetPicker } from 'components/engagement/admin/create/widgets';
import { WidgetLocation } from 'models/widget';

export const ConfigSummary = () => {
const siteUrl = getBaseUrl();
Expand Down Expand Up @@ -178,6 +180,10 @@ export const ConfigSummary = () => {
</Grid>
</OutlineBox>
</Grid>
<Grid item>
<WidgetPicker location={WidgetLocation.engagementAuthoring} />
</Grid>

<Grid item sx={{ pt: '40px' }}>
<Button href="../config" variant="secondary" icon={<FontAwesomeIcon icon={faPen} />}>
Edit Configuration
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import ControlledSelect from 'components/common/ControlledInputComponents/Contro
import { postDocument, patchDocument, PatchDocumentRequest } from 'services/widgetService/DocumentService';
import { DOCUMENT_TYPE, DocumentItem } from 'models/document';
import { updatedDiff } from 'deep-object-diff';
import { WidgetLocation } from 'models/widget';

const schema = yup
.object({
Expand Down Expand Up @@ -91,6 +92,7 @@ const AddFileDrawer = () => {
url: data.link,
widget_id: widget.id,
type: 'file',
location: widget.location in WidgetLocation ? widget.location : null,
});
dispatch(
openNotification({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { postDocument } from 'services/widgetService/DocumentService';
import { WidgetDrawerContext } from '../WidgetDrawerContext';
import { WidgetType } from 'models/widget';
import { DOCUMENT_TYPE } from 'models/document';
import { WidgetLocation } from 'models/widget';

const CreateFolderForm = () => {
const { loadDocuments, handleAddFileDrawerOpen, setUploadFileDrawerOpen } = useContext(DocumentsContext);
Expand Down Expand Up @@ -48,6 +49,7 @@ const CreateFolderForm = () => {
title: folderName,
widget_id: widget.id,
type: DOCUMENT_TYPE.FOLDER,
location: widget.location in WidgetLocation ? widget.location : null,
});
await loadDocuments();
setCreatingFolder(false);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import { DOCUMENT_TYPE, DocumentItem } from 'models/document';
import { saveObject } from 'services/objectStorageService';
import FileUpload from 'components/common/FileUpload';
import { If, Then, Else } from 'react-if';
import { WidgetLocation } from 'models/widget';

const schema = yup
.object({
Expand Down Expand Up @@ -94,6 +95,7 @@ const UploadFileDrawer = () => {
widget_id: widget.id,
type: 'file',
is_uploaded: true,
location: widget.location in WidgetLocation ? widget.location : null,
});
dispatch(
openNotification({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import { formEventDates } from './utils';
import dayjs from 'dayjs';
import tz from 'dayjs/plugin/timezone';
import { updatedDiff } from 'deep-object-diff';
import { WidgetLocation } from 'models/widget';

dayjs.extend(tz);

Expand Down Expand Up @@ -113,6 +114,7 @@ const InPersonEventFormDrawer = () => {
end_date: formatToUTC(dateTo),
},
],
location: widget.location in WidgetLocation ? widget.location : null,
});

setEvents((prevWidgetEvents: Event[]) => [...prevWidgetEvents, createdWidgetEvent]);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import { formatToUTC, formatDate } from 'components/common/dateHelper';
import { formEventDates } from './utils';
import dayjs from 'dayjs';
import tz from 'dayjs/plugin/timezone';
import { WidgetLocation } from 'models/widget';

dayjs.extend(tz);

Expand Down Expand Up @@ -108,6 +109,7 @@ const VirtualSessionFormDrawer = () => {
end_date: formatToUTC(dateTo),
},
],
location: widget.location in WidgetLocation ? widget.location : null,
});

setEvents((prevWidgetEvents: Event[]) => [...prevWidgetEvents, createdWidgetEvent]);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import { faCircleXmark } from '@fortawesome/pro-regular-svg-icons/faCircleXmark'
import { When } from 'react-if';
import * as turf from '@turf/turf';
import { WidgetTitle } from '../WidgetTitle';
import { WidgetLocation } from 'models/widget';

const schema = yup
.object({
Expand Down Expand Up @@ -98,6 +99,7 @@ const Form = () => {
longitude: longitude,
latitude: latitude,
file: shapefile,
location: widget.location in WidgetLocation ? widget.location : null,
});
dispatch(openNotification({ severity: 'success', text: 'A new map was successfully added' }));
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import { PollStatus } from 'constants/engagementStatus';
import Alert from '@mui/material/Alert';
import usePollWidgetState from './PollWidget.hook';
import PollAnswerForm from './PollAnswerForm';
import { WidgetLocation } from 'models/widget';

interface DetailsForm {
title: string;
Expand Down Expand Up @@ -79,6 +80,7 @@ const Form = () => {
description: description,
answers: answers,
status: status,
location: widget.location in WidgetLocation ? widget.location : null,
});
dispatch(openNotification({ severity: 'success', text: 'A new Poll was successfully added' }));
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import { TimelineContext } from './TimelineContext';
import { patchTimeline, postTimeline } from 'services/widgetService/TimelineService';
import { WidgetTitle } from '../WidgetTitle';
import { TimelineEvent } from 'models/timelineWidget';
import { WidgetLocation } from 'models/widget';

interface DetailsForm {
title: string;
Expand Down Expand Up @@ -81,6 +82,7 @@ const Form = () => {
title: title,
description: description,
events: events,
location: widget.location in WidgetLocation ? widget.location : null,
});
dispatch(openNotification({ severity: 'success', text: 'A new timeline was successfully added' }));
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import { VideoContext } from './VideoContext';
import { patchVideo, postVideo } from 'services/widgetService/VideoService';
import { updatedDiff } from 'deep-object-diff';
import { WidgetTitle } from '../WidgetTitle';
import { WidgetLocation } from 'models/widget';

const schema = yup
.object({
Expand Down Expand Up @@ -61,6 +62,7 @@ const Form = () => {
engagement_id: widget.engagement_id,
video_url: videoUrl,
description: description,
location: widget.location in WidgetLocation ? widget.location : null,
});
dispatch(openNotification({ severity: 'success', text: 'A new video was successfully added' }));
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,8 @@ const WhoIsListeningForm = () => {
const [selectedContact, setSelectedContact] = useState<Contact | null>(null);
const [savingWidgetItems, setSavingWidgetItems] = useState(false);
const [createWidgetItems] = useCreateWidgetItemsMutation();

const widget = widgets.filter((widget) => widget.widget_type_id === WidgetType.WhoIsListening)[0] || null;

useEffect(() => {
const savedContacts = widget.items
.map((widget_item) => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,12 @@ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { faUserGroupSimple } from '@fortawesome/pro-regular-svg-icons/faUserGroupSimple';
import { useCreateWidgetMutation } from 'apiManager/apiSlices/widgets';
import { optionCardStyle } from '../constants';
import { WidgetLocation } from 'models/widget';

const Title = 'Who is Listening';
const WhoIsListeningOptionCard = () => {
const { savedEngagement } = useContext(ActionContext);
const { widgets, loadWidgets, handleWidgetDrawerTabValueChange } = useContext(WidgetDrawerContext);
const { widgets, loadWidgets, handleWidgetDrawerTabValueChange, widgetLocation } = useContext(WidgetDrawerContext);
const dispatch = useAppDispatch();
const [createWidget] = useCreateWidgetMutation();
const [isCreatingWidget, setIsCreatingWidget] = useState(false);
Expand All @@ -34,6 +35,7 @@ const WhoIsListeningOptionCard = () => {
widget_type_id: WidgetType.WhoIsListening,
engagement_id: savedEngagement.id,
title: Title,
location: widgetLocation in WidgetLocation ? widgetLocation : 0,
});
await loadWidgets();
dispatch(
Expand Down
Loading

0 comments on commit 143a4cf

Please sign in to comment.