Skip to content

Commit

Permalink
Provide more information in notification settings (#2101)
Browse files Browse the repository at this point in the history
* Changed layout for user notification settings form

* implemented working tooltip/help message and better styling

* Updated notification settings form schema to use object instead of array, updated handlers to match, updated messages, need to finalize messages

* removed unused value

* updated user notifications settings tooltip messages

* updated notification settings tooltips to add review and meta-review tips
  • Loading branch information
AndrewPhilbin authored Sep 12, 2023
1 parent a0e0361 commit f2c3687
Show file tree
Hide file tree
Showing 6 changed files with 208 additions and 59 deletions.
22 changes: 17 additions & 5 deletions src/components/Custom/RJSFFormFieldAdapter/RJSFFormFieldAdapter.js
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,6 @@ export const CustomArrayFieldTemplate = props => {
const addLabel = props.uiSchema["ui:addLabel"] ||
<FormattedMessage {...messages.addPriorityRuleLabel} />
const deleteLabel = props.uiSchema["ui:deleteLabel"]

const itemFields = _map(props.items, element =>
<div
key={element.index}
Expand Down Expand Up @@ -96,7 +95,7 @@ export const CustomArrayFieldTemplate = props => {
{props.canAdd &&
<div className="array-field__block-controls">
<button
className="mr-button mr-button mr-button--small"
className="mr-button mr-button--small"
onClick={props.onAddClick}
>
{addLabel}
Expand Down Expand Up @@ -151,6 +150,20 @@ export const CustomFieldTemplate = function(props) {
)
}

export const CustomNotificationFieldTemplate = function(props) {
const {classNames, children, description, errors} = props
return (
<div className={classNames}>
<React.Fragment>
<LabelWithHelp {...props} control />
{children}
{errors}
{description}
</React.Fragment>
</div>
)
}


/**
* A custom select widget with the new-ui styling
Expand Down Expand Up @@ -389,8 +402,7 @@ export const MarkdownDescriptionField = ({id, description}) => {
}

export const LabelWithHelp = props => {
const {id, displayLabel, label, required, rawHelp, schema, uiSchema} = props

const {id, displayLabel, label, required, control, rawHelp, schema, uiSchema} = props
if (displayLabel === false || uiSchema["ui:displayLabel"] === false) {
return null
}
Expand All @@ -404,7 +416,7 @@ export const LabelWithHelp = props => {

return (
<div className="mr-mb-2 mr-flex">
<label htmlFor={id} className="mr-text-mango mr-text-md mr-uppercase mr-mb-2">
<label htmlFor={id} className={control ? "mr-text-base mr-text-mango" : "mr-text-mango mr-text-md mr-uppercase mr-mb-2"}>
{normalizedLabel}
{required && <span className="mr-text-red-light mr-ml-1">*</span>}
</label>
Expand Down
11 changes: 11 additions & 0 deletions src/lang/en-US.json
Original file line number Diff line number Diff line change
Expand Up @@ -1157,6 +1157,7 @@
"Profile.form.addCustomBasemap.label": "Add Custom Basemap",
"Profile.form.allowFollowing.description": "If no, users will not be able to follow your MapRoulette activity.",
"Profile.form.allowFollowing.label": "Allow Following",
"Profile.form.challengeCompletedNotifications.description": "Receive a notification when a Challenge you created has been completed.",
"Profile.form.customBasemap.description": "Insert a custom base map here. E.g. `https://'{s}'.tile.openstreetmap.org/'{z}'/'{x}'/'{y}'.png`",
"Profile.form.customBasemap.name.label": "Name",
"Profile.form.customBasemap.overlay.label": "is overlay?",
Expand All @@ -1170,6 +1171,7 @@
"Profile.form.email.description": "If you request emails in your Notification Subscriptions, they will be sent here.\n\nDecide which MapRoulette notifications you would like to receive, along with whether you would like to be sent an email informing you of the notification (either immediately or as a daily digest)",
"Profile.form.email.format": "email",
"Profile.form.email.label": "Email address",
"Profile.form.followNotifications.description": "Receive notifications when other users choose to follow you.",
"Profile.form.format.error": "should match format",
"Profile.form.isReviewer.description": "Volunteer to review tasks for which a review has been requested",
"Profile.form.isReviewer.label": "Volunteer as a Reviewer",
Expand All @@ -1178,14 +1180,23 @@
"Profile.form.locale.description": "User locale to use for MapRoulette UI.",
"Profile.form.locale.label": "Locale",
"Profile.form.mandatory.label": "Mandatory",
"Profile.form.mentionNotifications.description": "Receive a notification when someone @mentions you in a comment.",
"Profile.form.metaReviewNotifications.description": "This is a test meta review help label",
"Profile.form.needsReview.description": "Automatically request a human review of each task you complete",
"Profile.form.needsReview.label": "Request Review of all Work",
"Profile.form.no.label": "No",
"Profile.form.notification.label": "Notification",
"Profile.form.notificationSubscriptions.description": "Decide which MapRoulette notifications you would like to receive, along with whether you would like to be sent an email informing you of the notification (either immediately or as a daily digest)",
"Profile.form.notificationSubscriptions.label": "Notification Subscriptions",
"Profile.form.reviewAgainNotifications.description": "This is a test review again notifications help label",
"Profile.form.reviewApprovedNotifications.description": "Receive a notification when your task was approved following a review.",
"Profile.form.reviewCountNotifications.description": "Receive periodic notifications indicating how many task reviews you currently have pending.",
"Profile.form.reviewRejectedNotifications.description": "Receive a notification when your task needs to be revisited following a review.",
"Profile.form.revisionCountNotifications.description": "Receive periodic notifications indicating how many task revisions you currently have pending.",
"Profile.form.seeTagFixSuggestions.description": "User will see tag fix suggestions if they are provided.",
"Profile.form.seeTagFixSuggestions.label": "See Tag Fix Suggestions",
"Profile.form.systemNotifications.description": "Receive notifications for important MapRoulette system events, such as planned downtime.",
"Profile.form.teamNotifications.description": "Receive a notification when you have been invited by another user to join a team.",
"Profile.form.uniqueCustomBasemap.error": "Custom Basemap names must be unique",
"Profile.form.yes.label": "Yes",
"Profile.noUser": "User not found or you are unauthorized to view this user.",
Expand Down
55 changes: 55 additions & 0 deletions src/pages/Profile/Messages.js
Original file line number Diff line number Diff line change
Expand Up @@ -204,6 +204,61 @@ export default defineMessages({
"or as a daily digest)"
},

systemNotificationsDescription: {
id: "Profile.form.systemNotifications.description",
defaultMessage: "Receive notifications for important MapRoulette system events, such as planned downtime.",
},

mentionNotificationsDescription: {
id: "Profile.form.mentionNotifications.description",
defaultMessage: "Receive a notification when someone @mentions you in a comment.",
},

reviewApprovedNotificationsDescription: {
id: "Profile.form.reviewApprovedNotifications.description",
defaultMessage: "Receive a notification when your task was approved following a review.",
},

reviewRejectedNotificationsDescription: {
id: "Profile.form.reviewRejectedNotifications.description",
defaultMessage: "Receive a notification when your task needs to be revisited following a review.",
},

reviewAgainNotificationsDescription: {
id: "Profile.form.reviewAgainNotifications.description",
defaultMessage: "Receive a notification when your review status is updated by the mapper whose task you have reviewed.",
},

challengeCompletedNotificationsDescription: {
id: "Profile.form.challengeCompletedNotifications.description",
defaultMessage: "Receive a notification when a Challenge you created has been completed.",
},

teamNotificationsDescription: {
id: "Profile.form.teamNotifications.description",
defaultMessage: "Receive a notification when you have been invited by another user to join a team.",
},

followNotificationsDescription: {
id: "Profile.form.followNotifications.description",
defaultMessage: "Receive notifications when other users choose to follow you.",
},

metaReviewNotificationsDescription: {
id: "Profile.form.metaReviewNotifications.description",
defaultMessage: "Receive a notification when your review status is updated by another reviewer.",
},

reviewCountNotificationsDescription: {
id: "Profile.form.reviewCountNotifications.description",
defaultMessage: "Receive periodic notifications indicating how many task reviews you currently have pending.",
},

revisionCountNotificationsDescription: {
id: "Profile.form.revisionCountNotifications.description",
defaultMessage: "Receive periodic notifications indicating how many task revisions you currently have pending.",
},

yesLabel: {
id: "Profile.form.yes.label",
defaultMessage: "Yes",
Expand Down
113 changes: 92 additions & 21 deletions src/pages/Profile/UserSettings/NotificationSettingsSchema.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,26 +16,28 @@ import {
} from "../../../services/Notification/NotificationSubscription/NotificationSubscription";
import MarkdownContent from "../../../components/MarkdownContent/MarkdownContent";
import messages from "../Messages";
import { CustomNotificationFieldTemplate } from '../../../components/Custom/RJSFFormFieldAdapter/RJSFFormFieldAdapter';

const createSubscriptionInput = (
name,
notificationLabels,
subscriptionTypes,
subscriptionLabels,
intl,
defaultSelection
defaultSelection,
) => {
return {
title: `${
notificationLabels[`${name}Long`] || notificationLabels[name]
} ${intl.formatMessage(messages.notificationLabel)}`,
type: "number",
enum: _values(subscriptionTypes),
enumNames: _map(subscriptionTypes, (value, key) => subscriptionLabels[key]),
default: defaultSelection,
};
};

name: name,
title: `${
notificationLabels[`${name}Long`] || notificationLabels[name]
} ${intl.formatMessage(messages.notificationLabel)}`,
type: "number",
enum: _values(subscriptionTypes),
enumNames: _map(subscriptionTypes, (value, key) => subscriptionLabels[key]),
default: defaultSelection,

}
}
export const transformErrors = (intl) => (errors) => {
return errors.map(error => {
if (error.name === "format") {
Expand Down Expand Up @@ -65,7 +67,7 @@ export const jsSchema = (intl) => {
const localizedNotificationLabels = notificationTypeLabels(intl);
const localizedNotificationCountLabels = notificationCountTypeLabels(intl);
const localizedSubscriptionLabels = subscriptionTypeLabels(intl);
const localizedSubscriptionFrequncyLabels =
const localizedSubscriptionFrequencyLabels =
subscriptionFrequencyTypeLabels(intl);

const items = new Array(NOTIFICATION_TYPE_REVISION_COUNT).fill({});
Expand All @@ -77,7 +79,7 @@ export const jsSchema = (intl) => {
SubscriptionType,
localizedSubscriptionLabels,
intl,
SubscriptionType.noEmail
SubscriptionType.noEmail,
);
});

Expand All @@ -86,21 +88,40 @@ export const jsSchema = (intl) => {
name,
localizedNotificationCountLabels,
SubscriptionFrequencyType,
localizedSubscriptionFrequncyLabels,
localizedSubscriptionFrequencyLabels,
intl,
SubscriptionFrequencyType.ignore
SubscriptionFrequencyType.ignore,
);
});

// items are generated as array from all subscription and count types
const notificationObject = {}
items.filter(item => Boolean(item.name)).forEach((item) => {
notificationObject[item.name] = item
})

return {
$schema: "http://json-schema.org/draft-07/schema#",
type: "object",
properties: {
notificationSubscriptions: {
title: intl.formatMessage(messages.notificationSubscriptionsLabel),
type: "array",
items: items,
type: "object",
properties: {
system: notificationObject.system,
mention: notificationObject.mention,
reviewApproved: notificationObject.reviewApproved,
reviewRejected: notificationObject.reviewRejected,
reviewAgain: notificationObject.reviewAgain,
challengeCompleted: notificationObject.challengeCompleted,
team: notificationObject.team,
follow: notificationObject.follow,
metaReview: notificationObject.metaReview,
reviewCount: notificationObject.reviewCount,
revisionCount: notificationObject.revisionCount,
}
},

email: {
title: intl.formatMessage(messages.emailLabel),
type: "string",
Expand All @@ -121,23 +142,73 @@ export const jsSchema = (intl) => {
* > proper markup.
*/
export const uiSchema = (intl) => {

return {
email: {
classNames: "notification-email",
"ui:emptyValue": "",
"ui:help": (
<MarkdownContent
markdown={intl.formatMessage(messages.emailDescription)}
/>
),
},

notificationSubscriptions: {
classNames: "no-legend",
"ui:options": {
orderable: false,
removable: false,
classNames: "no-legend notification-subscriptions",
system: {
"ui:help": intl.formatMessage(messages.systemNotificationsDescription),
"ui:FieldTemplate": CustomNotificationFieldTemplate,
},
mention: {
"ui:help": intl.formatMessage(messages.mentionNotificationsDescription),
"ui:FieldTemplate": CustomNotificationFieldTemplate,
},
reviewApproved: {
"ui:help": intl.formatMessage(messages.reviewApprovedNotificationsDescription),
"ui:FieldTemplate": CustomNotificationFieldTemplate,
},
reviewRejected: {
"ui:help": intl.formatMessage(messages.reviewRejectedNotificationsDescription),
"ui:FieldTemplate": CustomNotificationFieldTemplate,
},
reviewAgain: {
"ui:help": intl.formatMessage(messages.reviewAgainNotificationsDescription),
"ui:FieldTemplate": CustomNotificationFieldTemplate,
},
challengeCompleted: {
"ui:help": intl.formatMessage(messages.challengeCompletedNotificationsDescription),
"ui:FieldTemplate": CustomNotificationFieldTemplate,
},
team: {
"ui:help": intl.formatMessage(messages.teamNotificationsDescription),
"ui:FieldTemplate": CustomNotificationFieldTemplate,
},
follow: {
"ui:help": intl.formatMessage(messages.followNotificationsDescription),
"ui:FieldTemplate": CustomNotificationFieldTemplate,
},
metaReview: {
"ui:help": intl.formatMessage(messages.metaReviewNotificationsDescription),
"ui:FieldTemplate": CustomNotificationFieldTemplate,
},
reviewCount: {
"ui:help": intl.formatMessage(messages.reviewCountNotificationsDescription),
"ui:FieldTemplate": CustomNotificationFieldTemplate,
},
revisionCount: {
"ui:help": intl.formatMessage(messages.revisionCountNotificationsDescription),
"ui:FieldTemplate": CustomNotificationFieldTemplate,
},
},

"ui:options": {
orderable: false,
removable: false,
},
"ui:order": ["email", "notificationSubscriptions"],
"ui:showTitle": false,
};
};


Loading

0 comments on commit f2c3687

Please sign in to comment.