Skip to content

Commit

Permalink
Merge pull request #4376 from coralproject/feat/dsa-notifications
Browse files Browse the repository at this point in the history
DSA Notifications
  • Loading branch information
nick-funk authored Nov 9, 2023
2 parents 1c62aed + 2350c0b commit 167cb14
Show file tree
Hide file tree
Showing 66 changed files with 1,550 additions and 34 deletions.
14 changes: 14 additions & 0 deletions INDEXES.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,20 @@ The goal of this document is to date-mark the indexes you add to support the cha

If you are releasing, you can use this readme to check all the indexes prior to the release you are deploying and have a good idea of what indexes you might need to deploy to Mongo along with your release of a new Coral Docker image to kubernetes.

## 2023-10-18

```
db.notifications.createIndex({ tenantID: 1, id: 1 }, { unique: true });
```

- This index creates the uniqueness constraint for the `tenantID` and `id` fields on the notifications collection

```
db.notifications.createIndex({ tenantID: 1, ownerID: 1, createdAt: 1 });
```

- This index speeds up the retrieval of notifications by `tenantID`, `ownerID`, and `createdAt` which is the most common way of retrieving notifications for pagination in the notifications tab on the stream.

## 2023-03-28

```
Expand Down
12 changes: 12 additions & 0 deletions client/src/core/client/stream/App/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import React, { FunctionComponent } from "react";

import { useCoralContext } from "coral-framework/lib/bootstrap/CoralContext";
import CLASSES from "coral-stream/classes";
import NotificationsQuery from "coral-stream/tabs/Notifications/NotificationsQuery";
import { HorizontalGutter, TabContent, TabPane } from "coral-ui/components/v2";

import Comments from "../tabs/Comments";
Expand All @@ -18,10 +19,12 @@ type TabValue = "COMMENTS" | "PROFILE" | "DISCUSSIONS" | "%future added value";

export interface AppProps {
activeTab: TabValue;
dsaFeaturesEnabled: boolean;
}

const App: FunctionComponent<AppProps> = (props) => {
const { browserInfo } = useCoralContext();

return (
<Localized id="general-commentsEmbedSection" attrs={{ "aria-label": true }}>
<HorizontalGutter
Expand Down Expand Up @@ -68,6 +71,15 @@ const App: FunctionComponent<AppProps> = (props) => {
>
<Configure />
</TabPane>
{props.dsaFeaturesEnabled && (
<TabPane
className={CLASSES.notificationsTabPane.$root}
tabID="NOTIFICATIONS"
data-testid="current-tab-pane"
>
<NotificationsQuery />
</TabPane>
)}
</TabContent>
</div>
</HorizontalGutter>
Expand Down
14 changes: 8 additions & 6 deletions client/src/core/client/stream/App/AppContainer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -30,16 +30,18 @@ interface Props {
}

const AppContainer: FunctionComponent<Props> = ({ disableListeners }) => {
const [{ activeTab }] = useLocal<AppContainerLocal>(graphql`
fragment AppContainerLocal on Local {
activeTab
}
`);
const [{ activeTab, dsaFeaturesEnabled }] =
useLocal<AppContainerLocal>(graphql`
fragment AppContainerLocal on Local {
activeTab
dsaFeaturesEnabled
}
`);
return (
<>
{disableListeners ? null : listeners}
<RefreshTokenHandler />
<App activeTab={activeTab} />
<App activeTab={activeTab} dsaFeaturesEnabled={!!dsaFeaturesEnabled} />
</>
);
};
Expand Down
9 changes: 5 additions & 4 deletions client/src/core/client/stream/App/TabBar.css
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
.smallTab {
padding-top: var(--spacing-3);
padding-bottom: var(--spacing-3);
padding-left: var(--spacing-3);
padding-right: var(--spacing-3);
padding: var(--spacing-3);
}

.condensedTab {
padding: var(--spacing-2);
}

.configureTab {
Expand Down
34 changes: 33 additions & 1 deletion client/src/core/client/stream/App/TabBar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,12 @@ import useGetMessage from "coral-framework/lib/i18n/useGetMessage";
import { GQLSTORY_MODE } from "coral-framework/schema";
import CLASSES from "coral-stream/classes";
import {
ActiveNotificationBellIcon,
CogIcon,
ConversationChatIcon,
ConversationQuestionWarningIcon,
MessagesBubbleSquareIcon,
NotificationBellIcon,
RatingStarIcon,
SingleNeutralCircleIcon,
SvgIcon,
Expand All @@ -17,14 +19,21 @@ import { MatchMedia, Tab, TabBar } from "coral-ui/components/v2";

import styles from "./TabBar.css";

type TabValue = "COMMENTS" | "PROFILE" | "DISCUSSIONS" | "%future added value";
type TabValue =
| "COMMENTS"
| "PROFILE"
| "DISCUSSIONS"
| "NOTIFICATIONS"
| "%future added value";

export interface Props {
activeTab: TabValue;
onTabClick: (tab: TabValue) => void;
showProfileTab: boolean;
showDiscussionsTab: boolean;
showConfigureTab: boolean;
showNotificationsTab: boolean;
hasNewNotifications: boolean;
mode:
| "COMMENTS"
| "QA"
Expand Down Expand Up @@ -155,6 +164,29 @@ const AppTabBar: FunctionComponent<Props> = (props) => {
)}
</Tab>
)}

{props.showNotificationsTab && (
<Tab
className={cn(CLASSES.tabBar.notifications, {
[CLASSES.tabBar.activeTab]: props.activeTab === "NOTIFICATIONS",
[styles.condensedTab]: matches,
[styles.smallTab]: !matches,
})}
tabID="NOTIFICATIONS"
variant="streamPrimary"
>
<div>
<SvgIcon
size="md"
Icon={
props.hasNewNotifications
? ActiveNotificationBellIcon
: NotificationBellIcon
}
></SvgIcon>
</div>
</Tab>
)}
</TabBar>
)}
</MatchMedia>
Expand Down
20 changes: 15 additions & 5 deletions client/src/core/client/stream/App/TabBarContainer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -30,11 +30,14 @@ export const TabBarContainer: FunctionComponent<Props> = ({
settings,
setActiveTab,
}) => {
const [{ activeTab }] = useLocal<TabBarContainerLocal>(graphql`
fragment TabBarContainerLocal on Local {
activeTab
}
`);
const [{ activeTab, dsaFeaturesEnabled, hasNewNotifications }] =
useLocal<TabBarContainerLocal>(graphql`
fragment TabBarContainerLocal on Local {
activeTab
dsaFeaturesEnabled
hasNewNotifications
}
`);
const handleSetActiveTab = useCallback(
(tab: SetActiveTabInput["tab"]) => {
void setActiveTab({ tab });
Expand All @@ -59,13 +62,20 @@ export const TabBarContainer: FunctionComponent<Props> = ({
[viewer, story]
);

const showNotificationsTab = useMemo(
() => !!viewer && !!dsaFeaturesEnabled,
[viewer, dsaFeaturesEnabled]
);

return (
<TabBar
mode={story ? story.settings.mode : GQLSTORY_MODE.COMMENTS}
activeTab={activeTab}
showProfileTab={!!viewer}
showDiscussionsTab={showDiscussionsTab}
showConfigureTab={showConfigureTab}
showNotificationsTab={showNotificationsTab}
hasNewNotifications={!!hasNewNotifications}
onTabClick={handleSetActiveTab}
/>
);
Expand Down
23 changes: 17 additions & 6 deletions client/src/core/client/stream/App/TabBarQuery.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,19 +11,23 @@ import ErrorReporterSetUserContainer from "./ErrorReporterSetUserContainer";
import TabBarContainer from "./TabBarContainer";

const TabBarQuery: FunctionComponent = () => {
const [{ storyID, storyURL }] = useLocal<TabBarQueryLocal>(graphql`
fragment TabBarQueryLocal on Local {
storyID
storyURL
}
`);
const [{ storyID, storyURL, hasNewNotifications }, setLocal] =
useLocal<TabBarQueryLocal>(graphql`
fragment TabBarQueryLocal on Local {
storyID
storyURL
hasNewNotifications
}
`);

return (
<QueryRenderer<QueryTypes>
query={graphql`
query TabBarQuery($storyID: ID, $storyURL: String) {
viewer {
...TabBarContainer_viewer
...ErrorReporterSetUserContainer_viewer
hasNewNotifications
}
story(id: $storyID, url: $storyURL) {
...TabBarContainer_story
Expand All @@ -46,6 +50,13 @@ const TabBarQuery: FunctionComponent = () => {
<ErrorReporterSetUserContainer viewer={props.viewer} />
) : null;

if (hasNewNotifications === null) {
setLocal({
hasNewNotifications:
props && props.viewer ? props.viewer.hasNewNotifications : false,
});
}

return (
<>
{ErrorReporterSetUser}
Expand Down
6 changes: 6 additions & 0 deletions client/src/core/client/stream/classes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,8 @@ const CLASSES = {
configure: "coral coral-tabBar-tab coral-tabBar-configure",

activeTab: "coral-tabBar-tab-active",

notifications: "coral coral-tabBar-tab coral-tabBar-notifications",
},

/**
Expand Down Expand Up @@ -142,6 +144,10 @@ const CLASSES = {
settings: "coral coral-tabBarSecondary-tab coral-tabBarMyProfile-settings",
},

tabBarNotifications: {
loadMore: "coral coral-tabBarNotifications-loadMore",
},

/**
* createComment is the comment creation box where a user can write a comment.
*/
Expand Down
2 changes: 2 additions & 0 deletions client/src/core/client/stream/local/initLocalState.ts
Original file line number Diff line number Diff line change
Expand Up @@ -179,5 +179,7 @@ export const createInitLocalState: (options: Options) => InitLocalState =

const dsaFeaturesEnabled = staticConfig?.dsaFeaturesEnabled ?? false;
localRecord.setValue(dsaFeaturesEnabled, "dsaFeaturesEnabled");

localRecord.setValue(null, "hasNewNotifications");
});
};
2 changes: 2 additions & 0 deletions client/src/core/client/stream/local/local.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -129,4 +129,6 @@ extend type Local {
refreshStream: Boolean

dsaFeaturesEnabled: Boolean

hasNewNotifications: Boolean
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
.toggle {
padding: 0;
margin-bottom: var(--spacing-1);

border-style: none;

background-color: transparent;

color: var(--palette-primary-300);
font-family: var(--font-family-primary);
font-style: normal;
font-weight: var(--font-weight-primary-bold);
font-size: var(--font-size-2);

&:hover,
&.mouseHover {
color: var(--palette-primary-200);
}
&:active,
&.active {
color: var(--palette-primary-400);
}
}

.content {
border-left-style: solid;
border-left-width: 2px;
border-left-color: var(--palette-grey-400);

padding-left: var(--spacing-3);
}

.timestamp {
font-family: var(--font-family-primary);
font-style: normal;
font-weight: var(--font-weight-primary-semi-bold);
font-size: var(--font-size-2);
color: var(--palette-grey-500);
}

.storyTitle {
font-family: var(--font-family-primary);
font-style: normal;
font-weight: var(--font-weight-primary-semi-bold);
font-size: var(--font-size-2);
color: var(--palette-text-900);
}
Loading

0 comments on commit 167cb14

Please sign in to comment.