From 9ad94bacdf47ccb89de72488fb24fa516b835c39 Mon Sep 17 00:00:00 2001 From: Matheus Domingos Date: Tue, 5 Nov 2024 17:25:16 -0300 Subject: [PATCH 1/6] BA-1738 add storybook for notifications components --- .../.storybook/decorators/withProviders.tsx | 18 +- packages/components/.storybook/preview.ts | 10 + .../NotificationItemWithQuery.graphql.ts | 340 ++++++++++++++++++ .../NotificationsPopoverFragment.graphql.ts | 41 +++ .../NotificationsPopoverWithQuery.graphql.ts | 150 ++++++++ .../NotificationItemWithQuery/index.tsx | 23 ++ .../__storybook__/mockResolvers.ts | 28 ++ .../__storybook__/stories.tsx | 33 ++ .../__storybook__/mockResolvers.ts | 322 +++++++++++++++++ .../__storybook__/stories.tsx | 83 +++++ .../__storybook__/mockResolvers.ts | 7 + .../__storybook__/stories.tsx | 104 ++++++ 12 files changed, 1154 insertions(+), 5 deletions(-) create mode 100644 packages/components/__generated__/NotificationItemWithQuery.graphql.ts create mode 100644 packages/components/__generated__/NotificationsPopoverFragment.graphql.ts create mode 100644 packages/components/__generated__/NotificationsPopoverWithQuery.graphql.ts create mode 100644 packages/components/modules/notifications/NotificationsList/NotificationItem/__storybook__/NotificationItemWithQuery/index.tsx create mode 100644 packages/components/modules/notifications/NotificationsList/NotificationItem/__storybook__/mockResolvers.ts create mode 100644 packages/components/modules/notifications/NotificationsList/NotificationItem/__storybook__/stories.tsx create mode 100644 packages/components/modules/notifications/NotificationsList/__storybook__/mockResolvers.ts create mode 100644 packages/components/modules/notifications/NotificationsList/__storybook__/stories.tsx create mode 100644 packages/components/modules/notifications/NotificationsPopover/__storybook__/mockResolvers.ts create mode 100644 packages/components/modules/notifications/NotificationsPopover/__storybook__/stories.tsx diff --git a/packages/components/.storybook/decorators/withProviders.tsx b/packages/components/.storybook/decorators/withProviders.tsx index 8b8262f7..3f3227d4 100644 --- a/packages/components/.storybook/decorators/withProviders.tsx +++ b/packages/components/.storybook/decorators/withProviders.tsx @@ -1,4 +1,4 @@ -import React from 'react' +import React, { useEffect } from 'react' import { LoadingState, ThemeProvider } from '@baseapp-frontend/design-system' import { RelayTestProvider, createTestEnvironment } from '@baseapp-frontend/graphql' @@ -17,13 +17,21 @@ const withProviders = (Story: StoryFn, context: StoryContext) => { // TODO: registering a few tailwind classess (used by @baseapp-frontend/design-system components), need to figure out why the @baseapp-frontend/components storybook are not including it correctly // pb-3 px-3 w-full rounded-md bg-background-neutral px-2 py-1 const relayMockEnvironment = createTestEnvironment() - const { environment, queueOperationResolver } = relayMockEnvironment + const { environment, queueOperationResolver, resolveMostRecentOperation } = relayMockEnvironment context.parameters.relayMockEnvironment = relayMockEnvironment - const mockResolvers = context.parameters.mockResolvers || {} - - queueOperationResolver(mockResolvers) + const mockResolvers = context.parameters.mockResolvers || undefined + const mockData = context.parameters.mockData || {} + + useEffect(() => { + if (!!mockResolvers) { + queueOperationResolver(mockResolvers) + } + if (mockData) { + resolveMostRecentOperation({ mockResolvers, data: mockData }) + } + }, [mockData, resolveMostRecentOperation, queueOperationResolver, mockResolvers]) return ( diff --git a/packages/components/.storybook/preview.ts b/packages/components/.storybook/preview.ts index 5f79f54b..d8d90ce0 100644 --- a/packages/components/.storybook/preview.ts +++ b/packages/components/.storybook/preview.ts @@ -59,6 +59,11 @@ const preview: Preview = { // General 'Logo', 'Scrollbar', + // Notifications + 'NotificationsPopover', + 'NotificationsList', + 'NotificationItem', + 'NotificationUserMenu', ] const componentsStoriesOrder = [ @@ -104,6 +109,11 @@ const preview: Preview = { 'CommentUpsertActions', 'ReactionButton', 'Timestamp', + //Notifications + 'NotificationsPopover', + 'NotificationsList', + 'NotificationItem', + 'NotificationUserMenu', ] const final = [...storiesOrder, ...componentsStoriesOrder] diff --git a/packages/components/__generated__/NotificationItemWithQuery.graphql.ts b/packages/components/__generated__/NotificationItemWithQuery.graphql.ts new file mode 100644 index 00000000..631d1874 --- /dev/null +++ b/packages/components/__generated__/NotificationItemWithQuery.graphql.ts @@ -0,0 +1,340 @@ +/** + * @generated SignedSource<<2be8361b76383cb89c29eb2821435085>> + * @lightSyntaxTransform + * @nogrep + */ + +/* tslint:disable */ + +/* eslint-disable */ +// @ts-nocheck +import { ConcreteRequest, Query } from 'relay-runtime' +import { FragmentRefs } from 'relay-runtime' + +export type NotificationItemWithQuery$variables = Record +export type NotificationItemWithQuery$data = { + readonly target: + | { + readonly ' $fragmentSpreads': FragmentRefs<'NotificationItemFragment'> + } + | null + | undefined +} +export type NotificationItemWithQuery = { + response: NotificationItemWithQuery$data + variables: NotificationItemWithQuery$variables +} + +const node: ConcreteRequest = (function () { + var v0 = [ + { + kind: 'Literal', + name: 'id', + value: 'test-id', + }, + ], + v1 = { + alias: null, + args: null, + kind: 'ScalarField', + name: '__typename', + storageKey: null, + }, + v2 = { + alias: null, + args: null, + kind: 'ScalarField', + name: 'id', + storageKey: null, + }, + v3 = { + enumValues: null, + nullable: true, + plural: false, + type: 'Node', + }, + v4 = { + enumValues: null, + nullable: false, + plural: false, + type: 'String', + }, + v5 = { + enumValues: null, + nullable: true, + plural: false, + type: 'String', + }, + v6 = { + enumValues: null, + nullable: false, + plural: false, + type: 'ID', + } + return { + fragment: { + argumentDefinitions: [], + kind: 'Fragment', + metadata: null, + name: 'NotificationItemWithQuery', + selections: [ + { + alias: 'target', + args: v0 /*: any*/, + concreteType: null, + kind: 'LinkedField', + name: 'node', + plural: false, + selections: [ + { + args: null, + kind: 'FragmentSpread', + name: 'NotificationItemFragment', + }, + ], + storageKey: 'node(id:"test-id")', + }, + ], + type: 'Query', + abstractKey: null, + }, + kind: 'Request', + operation: { + argumentDefinitions: [], + kind: 'Operation', + name: 'NotificationItemWithQuery', + selections: [ + { + alias: 'target', + args: v0 /*: any*/, + concreteType: null, + kind: 'LinkedField', + name: 'node', + plural: false, + selections: [ + v1 /*: any*/, + v2 /*: any*/, + { + kind: 'InlineFragment', + selections: [ + { + alias: null, + args: null, + kind: 'ScalarField', + name: 'pk', + storageKey: null, + }, + { + alias: null, + args: null, + kind: 'ScalarField', + name: 'unread', + storageKey: null, + }, + { + alias: null, + args: null, + kind: 'ScalarField', + name: 'timestamp', + storageKey: null, + }, + { + alias: null, + args: null, + kind: 'ScalarField', + name: 'level', + storageKey: null, + }, + { + alias: null, + args: null, + kind: 'ScalarField', + name: 'verb', + storageKey: null, + }, + { + alias: null, + args: null, + kind: 'ScalarField', + name: 'description', + storageKey: null, + }, + { + alias: null, + args: null, + kind: 'ScalarField', + name: 'data', + storageKey: null, + }, + { + alias: null, + args: null, + concreteType: null, + kind: 'LinkedField', + name: 'actor', + plural: false, + selections: [ + v1 /*: any*/, + v2 /*: any*/, + { + kind: 'InlineFragment', + selections: [ + { + alias: null, + args: [ + { + kind: 'Literal', + name: 'height', + value: 48, + }, + { + kind: 'Literal', + name: 'width', + value: 48, + }, + ], + concreteType: 'File', + kind: 'LinkedField', + name: 'avatar', + plural: false, + selections: [ + { + alias: null, + args: null, + kind: 'ScalarField', + name: 'url', + storageKey: null, + }, + ], + storageKey: 'avatar(height:48,width:48)', + }, + { + alias: null, + args: null, + kind: 'ScalarField', + name: 'fullName', + storageKey: null, + }, + ], + type: 'User', + abstractKey: null, + }, + ], + storageKey: null, + }, + { + alias: null, + args: null, + concreteType: null, + kind: 'LinkedField', + name: 'target', + plural: false, + selections: [v2 /*: any*/, v1 /*: any*/], + storageKey: null, + }, + { + alias: null, + args: null, + concreteType: null, + kind: 'LinkedField', + name: 'actionObject', + plural: false, + selections: [ + v2 /*: any*/, + v1 /*: any*/, + { + kind: 'InlineFragment', + selections: [ + { + alias: null, + args: null, + kind: 'ScalarField', + name: 'body', + storageKey: null, + }, + ], + type: 'Comment', + abstractKey: null, + }, + ], + storageKey: null, + }, + ], + type: 'Notification', + abstractKey: null, + }, + ], + storageKey: 'node(id:"test-id")', + }, + ], + }, + params: { + cacheID: 'd5565b82e75201f15bdef373c501af6d', + id: null, + metadata: { + relayTestingSelectionTypeInfo: { + target: v3 /*: any*/, + 'target.__typename': v4 /*: any*/, + 'target.actionObject': v3 /*: any*/, + 'target.actionObject.__typename': v4 /*: any*/, + 'target.actionObject.body': v5 /*: any*/, + 'target.actionObject.id': v6 /*: any*/, + 'target.actor': v3 /*: any*/, + 'target.actor.__typename': v4 /*: any*/, + 'target.actor.avatar': { + enumValues: null, + nullable: true, + plural: false, + type: 'File', + }, + 'target.actor.avatar.url': v4 /*: any*/, + 'target.actor.fullName': v5 /*: any*/, + 'target.actor.id': v6 /*: any*/, + 'target.data': { + enumValues: null, + nullable: true, + plural: false, + type: 'GenericScalar', + }, + 'target.description': v5 /*: any*/, + 'target.id': v6 /*: any*/, + 'target.level': { + enumValues: ['SUCCESS', 'INFO', 'WARNING', 'ERROR'], + nullable: false, + plural: false, + type: 'BaseappNotificationsNotificationLevelChoices', + }, + 'target.pk': { + enumValues: null, + nullable: false, + plural: false, + type: 'Int', + }, + 'target.target': v3 /*: any*/, + 'target.target.__typename': v4 /*: any*/, + 'target.target.id': v6 /*: any*/, + 'target.timestamp': { + enumValues: null, + nullable: false, + plural: false, + type: 'DateTime', + }, + 'target.unread': { + enumValues: null, + nullable: false, + plural: false, + type: 'Boolean', + }, + 'target.verb': v4 /*: any*/, + }, + }, + name: 'NotificationItemWithQuery', + operationKind: 'query', + text: 'query NotificationItemWithQuery {\n target: node(id: "test-id") {\n __typename\n ...NotificationItemFragment\n id\n }\n}\n\nfragment NotificationItemFragment on Notification {\n id\n pk\n unread\n timestamp\n level\n verb\n description\n data\n actor {\n __typename\n id\n ... on User {\n avatar(width: 48, height: 48) {\n url\n }\n fullName\n }\n }\n target {\n id\n __typename\n }\n actionObject {\n id\n __typename\n ... on Comment {\n id\n body\n }\n }\n}\n', + }, + } +})() + +;(node as any).hash = 'fdd4687d40d788b8c366d75a02c97403' + +export default node diff --git a/packages/components/__generated__/NotificationsPopoverFragment.graphql.ts b/packages/components/__generated__/NotificationsPopoverFragment.graphql.ts new file mode 100644 index 00000000..a5115699 --- /dev/null +++ b/packages/components/__generated__/NotificationsPopoverFragment.graphql.ts @@ -0,0 +1,41 @@ +/** + * @generated SignedSource<<47be4b188bda7b767468fd209eb62178>> + * @lightSyntaxTransform + * @nogrep + */ + +/* tslint:disable */ + +/* eslint-disable */ +// @ts-nocheck +import { Fragment, ReaderFragment } from 'relay-runtime' +import { FragmentRefs } from 'relay-runtime' + +export type NotificationsPopoverFragment$data = { + readonly ' $fragmentSpreads': FragmentRefs<'NotificationUserMenuFragment'> + readonly ' $fragmentType': 'NotificationsPopoverFragment' +} +export type NotificationsPopoverFragment$key = { + readonly ' $data'?: NotificationsPopoverFragment$data + readonly ' $fragmentSpreads': FragmentRefs<'NotificationsPopoverFragment'> +} + +const node: ReaderFragment = { + argumentDefinitions: [], + kind: 'Fragment', + metadata: null, + name: 'NotificationsPopoverFragment', + selections: [ + { + args: null, + kind: 'FragmentSpread', + name: 'NotificationUserMenuFragment', + }, + ], + type: 'User', + abstractKey: null, +} + +;(node as any).hash = 'aa7937f53433c977e2d19769946ec689' + +export default node diff --git a/packages/components/__generated__/NotificationsPopoverWithQuery.graphql.ts b/packages/components/__generated__/NotificationsPopoverWithQuery.graphql.ts new file mode 100644 index 00000000..5787cddf --- /dev/null +++ b/packages/components/__generated__/NotificationsPopoverWithQuery.graphql.ts @@ -0,0 +1,150 @@ +/** + * @generated SignedSource<<2019611df1126cfaea95f44b33087e85>> + * @lightSyntaxTransform + * @nogrep + */ + +/* tslint:disable */ + +/* eslint-disable */ +// @ts-nocheck +import { ConcreteRequest, Query } from 'relay-runtime' +import { FragmentRefs } from 'relay-runtime' + +export type NotificationsPopoverWithQuery$variables = Record +export type NotificationsPopoverWithQuery$data = { + readonly target: + | { + readonly ' $fragmentSpreads': FragmentRefs<'NotificationsPopoverFragment'> + } + | null + | undefined +} +export type NotificationsPopoverWithQuery = { + response: NotificationsPopoverWithQuery$data + variables: NotificationsPopoverWithQuery$variables +} + +const node: ConcreteRequest = (function () { + var v0 = [ + { + kind: 'Literal', + name: 'id', + value: 'test-id', + }, + ] + return { + fragment: { + argumentDefinitions: [], + kind: 'Fragment', + metadata: null, + name: 'NotificationsPopoverWithQuery', + selections: [ + { + alias: 'target', + args: v0 /*: any*/, + concreteType: null, + kind: 'LinkedField', + name: 'node', + plural: false, + selections: [ + { + args: null, + kind: 'FragmentSpread', + name: 'NotificationsPopoverFragment', + }, + ], + storageKey: 'node(id:"test-id")', + }, + ], + type: 'Query', + abstractKey: null, + }, + kind: 'Request', + operation: { + argumentDefinitions: [], + kind: 'Operation', + name: 'NotificationsPopoverWithQuery', + selections: [ + { + alias: 'target', + args: v0 /*: any*/, + concreteType: null, + kind: 'LinkedField', + name: 'node', + plural: false, + selections: [ + { + alias: null, + args: null, + kind: 'ScalarField', + name: '__typename', + storageKey: null, + }, + { + alias: null, + args: null, + kind: 'ScalarField', + name: 'id', + storageKey: null, + }, + { + kind: 'InlineFragment', + selections: [ + { + alias: null, + args: null, + kind: 'ScalarField', + name: 'notificationsUnreadCount', + storageKey: null, + }, + ], + type: 'User', + abstractKey: null, + }, + ], + storageKey: 'node(id:"test-id")', + }, + ], + }, + params: { + cacheID: 'd209f52a732e0b615d9d587c64ee7ba1', + id: null, + metadata: { + relayTestingSelectionTypeInfo: { + target: { + enumValues: null, + nullable: true, + plural: false, + type: 'Node', + }, + 'target.__typename': { + enumValues: null, + nullable: false, + plural: false, + type: 'String', + }, + 'target.id': { + enumValues: null, + nullable: false, + plural: false, + type: 'ID', + }, + 'target.notificationsUnreadCount': { + enumValues: null, + nullable: true, + plural: false, + type: 'Int', + }, + }, + }, + name: 'NotificationsPopoverWithQuery', + operationKind: 'query', + text: 'query NotificationsPopoverWithQuery {\n target: node(id: "test-id") {\n __typename\n ...NotificationsPopoverFragment\n id\n }\n}\n\nfragment NotificationUserMenuFragment on User {\n id\n notificationsUnreadCount\n}\n\nfragment NotificationsPopoverFragment on User {\n ...NotificationUserMenuFragment\n}\n', + }, + } +})() + +;(node as any).hash = '2bc67125981d8f8d37483054ac8830f0' + +export default node diff --git a/packages/components/modules/notifications/NotificationsList/NotificationItem/__storybook__/NotificationItemWithQuery/index.tsx b/packages/components/modules/notifications/NotificationsList/NotificationItem/__storybook__/NotificationItemWithQuery/index.tsx new file mode 100644 index 00000000..e0f9fe4f --- /dev/null +++ b/packages/components/modules/notifications/NotificationsList/NotificationItem/__storybook__/NotificationItemWithQuery/index.tsx @@ -0,0 +1,23 @@ +import { graphql, useLazyLoadQuery } from 'react-relay' + +import NotificationItem from '../..' +import { NotificationItemFragment$key } from '../../../../../../__generated__/NotificationItemFragment.graphql' +import { NotificationItemWithQuery as Query } from '../../../../../../__generated__/NotificationItemWithQuery.graphql' +import { NotificationItemProps } from '../../types' + +const NotificationItemWithQuery = (props: NotificationItemProps) => { + const data = useLazyLoadQuery( + graphql` + query NotificationItemWithQuery @relay_test_operation { + target: node(id: "test-id") { + ...NotificationItemFragment + } + } + `, + {}, + ) + + return +} + +export default NotificationItemWithQuery diff --git a/packages/components/modules/notifications/NotificationsList/NotificationItem/__storybook__/mockResolvers.ts b/packages/components/modules/notifications/NotificationsList/NotificationItem/__storybook__/mockResolvers.ts new file mode 100644 index 00000000..9453d671 --- /dev/null +++ b/packages/components/modules/notifications/NotificationsList/NotificationItem/__storybook__/mockResolvers.ts @@ -0,0 +1,28 @@ +export const mockResolvers = { + Node: () => ({ + id: 'Tm90aWZpY2F0aW9uOjIyNQ==', + unread: true, + pk: 225, + timestamp: '2024-10-25T19:46:09.288290+00:00', + level: 'INFO', + verb: 'COMMENTS.COMMENT_REPLY_CREATED', + description: 'Someone replied to your comment 1.', + data: { + extra: {}, + }, + actor: { + __typename: 'Profile', + id: 'UHJvZmlsZToxNTM=', + }, + target: { + id: 'Q29tbWVudDoyMzc=', + __typename: 'Comment', + }, + actionObject: { + id: 'Q29tbWVudDoyNDg=', + __typename: 'Comment', + body: 'This is the first comment reply.', + }, + __typename: 'Notification', + }), +} diff --git a/packages/components/modules/notifications/NotificationsList/NotificationItem/__storybook__/stories.tsx b/packages/components/modules/notifications/NotificationsList/NotificationItem/__storybook__/stories.tsx new file mode 100644 index 00000000..5790c66f --- /dev/null +++ b/packages/components/modules/notifications/NotificationsList/NotificationItem/__storybook__/stories.tsx @@ -0,0 +1,33 @@ +import type { Meta, StoryObj } from '@storybook/react' + +import NotificationItem from '..' +import NotificationItemWithQuery from './NotificationItemWithQuery' +import { mockResolvers } from './mockResolvers' + +const meta: Meta = { + title: '@baseapp-frontend | components/Notifications/NotificationItem', + component: NotificationItemWithQuery, + tags: ['autodocs'], + argTypes: { + notification: { + description: 'The notification data.', + control: 'object', + table: { + type: { + summary: 'NotificationItem_notification$key', + }, + }, + }, + }, +} + +export default meta + +type Story = StoryObj + +export const DefaultNotificationItem: Story = { + name: 'Default NotificationItem', + parameters: { + mockResolvers, + }, +} diff --git a/packages/components/modules/notifications/NotificationsList/__storybook__/mockResolvers.ts b/packages/components/modules/notifications/NotificationsList/__storybook__/mockResolvers.ts new file mode 100644 index 00000000..6f0f34bd --- /dev/null +++ b/packages/components/modules/notifications/NotificationsList/__storybook__/mockResolvers.ts @@ -0,0 +1,322 @@ +export const emptyNotificationsListMockData = { + data: { + me: { + id: 'user-1', + notificationsUnreadCount: 12, + notifications: { + edges: [], + pageInfo: { + hasNextPage: false, + endCursor: null, + }, + }, + }, + }, +} + +export const notificationsListMockData = { + data: { + me: { + id: 'user-1', + notificationsUnreadCount: 12, + notifications: { + edges: [ + { + cursor: 'cursor-1', + node: { + id: 'Tm90aWZpY2F0aW9uOjIyNQ==', + unread: true, + pk: 225, + timestamp: '2024-10-25T19:46:09.288290+00:00', + level: 'INFO', + verb: 'COMMENTS.COMMENT_REPLY_CREATED', + description: 'Someone replied to your comment 1.', + data: { + extra: {}, + }, + actor: { + __typename: 'Profile', + id: 'UHJvZmlsZToxNTM=', + }, + target: { + id: 'Q29tbWVudDoyMzc=', + __typename: 'Comment', + }, + actionObject: { + id: 'Q29tbWVudDoyNDg=', + __typename: 'Comment', + body: 'This is the first comment reply.', + }, + __typename: 'Notification', + }, + }, + { + cursor: 'cursor-2', + node: { + id: 'Tm90aWZpY2F0aW9uOjIyNA==', + unread: true, + pk: 224, + timestamp: '2024-10-25T19:46:05.469607+00:00', + level: 'INFO', + verb: 'COMMENTS.COMMENT_REPLY_CREATED', + description: 'Someone replied to your comment 2.', + data: { + extra: {}, + }, + actor: { + __typename: 'Profile', + id: 'UHJvZmlsZToxNTM=', + }, + target: { + id: 'Q29tbWVudDoyMzc=', + __typename: 'Comment', + }, + actionObject: { + id: 'Q29tbWVudDoyNDc=', + __typename: 'Comment', + body: 'This is the second comment reply.', + }, + __typename: 'Notification', + }, + }, + { + cursor: 'cursor-3', + node: { + id: 'Tm90aWZpY2F0aW9uOjIyMw==', + unread: true, + pk: 223, + timestamp: '2024-10-25T19:45:37.278737+00:00', + level: 'INFO', + verb: 'COMMENTS.COMMENT_REPLY_CREATED', + description: 'Someone replied to your comment 3.', + data: { + extra: {}, + }, + actor: { + __typename: 'Profile', + id: 'UHJvZmlsZToxNTM=', + }, + target: { + id: 'Q29tbWVudDoyMzc=', + __typename: 'Comment', + }, + actionObject: { + id: 'Q29tbWVudDoyNDY=', + __typename: 'Comment', + body: 'This is the third comment reply.', + }, + __typename: 'Notification', + }, + }, + { + cursor: 'cursor-4', + node: { + id: 'Tm90aWZpY2F0aW9uOjIyMg==', + unread: true, + pk: 222, + timestamp: '2024-10-25T19:44:54.738158+00:00', + level: 'INFO', + verb: 'COMMENTS.COMMENT_REPLY_CREATED', + description: 'Someone replied to your comment 4.', + data: { + extra: {}, + }, + actor: { + __typename: 'Profile', + id: 'UHJvZmlsZToxNTM=', + }, + target: { + id: 'Q29tbWVudDoyMzc=', + __typename: 'Comment', + }, + actionObject: { + id: 'Q29tbWVudDoyNDU=', + __typename: 'Comment', + body: 'This is the fourth comment reply.', + }, + __typename: 'Notification', + }, + }, + { + cursor: 'cursor-5', + node: { + id: 'Tm90aWZpY2F0aW9uOjIyMQ==', + unread: true, + pk: 221, + timestamp: '2024-10-25T19:44:51.597059+00:00', + level: 'INFO', + verb: 'COMMENTS.COMMENT_REPLY_CREATED', + description: 'Someone replied to your comment 5.', + data: { + extra: {}, + }, + actor: { + __typename: 'Profile', + id: 'UHJvZmlsZToxNTM=', + }, + target: { + id: 'Q29tbWVudDoyMzc=', + __typename: 'Comment', + }, + actionObject: { + id: 'Q29tbWVudDoyNDQ=', + __typename: 'Comment', + body: 'This is the fifth comment reply.', + }, + __typename: 'Notification', + }, + }, + { + cursor: 'cursor-6', + node: { + id: 'Tm90aWZpY2F0aW9uOjIyMA==', + unread: true, + pk: 220, + timestamp: '2024-10-25T19:44:43.404373+00:00', + level: 'INFO', + verb: 'COMMENTS.COMMENT_REPLY_CREATED', + description: 'Someone replied to your comment 6.', + data: { + extra: {}, + }, + actor: { + __typename: 'Profile', + id: 'UHJvZmlsZToxNTM=', + }, + target: { + id: 'Q29tbWVudDoyMzc=', + __typename: 'Comment', + }, + actionObject: { + id: 'Q29tbWVudDoyNDM=', + __typename: 'Comment', + body: 'This is the sixth comment reply.', + }, + __typename: 'Notification', + }, + }, + { + cursor: 'cursor-7', + node: { + id: 'Tm90aWZpY2F0aW9uOjIxOQ==', + unread: true, + pk: 219, + timestamp: '2024-10-25T19:44:40.187542+00:00', + level: 'INFO', + verb: 'COMMENTS.COMMENT_REPLY_CREATED', + description: 'Someone replied to your comment 7.', + data: { + extra: {}, + }, + actor: { + __typename: 'Profile', + id: 'UHJvZmlsZToxNTM=', + }, + target: { + id: 'Q29tbWVudDoyMzc=', + __typename: 'Comment', + }, + actionObject: { + id: 'Q29tbWVudDoyNDI=', + __typename: 'Comment', + body: 'This is the seventh comment reply.', + }, + __typename: 'Notification', + }, + }, + { + cursor: 'cursor-8', + node: { + id: 'Tm90aWZpY2F0aW9uOjIxOA==', + unread: true, + pk: 218, + timestamp: '2024-10-25T19:44:37.056281+00:00', + level: 'INFO', + verb: 'COMMENTS.COMMENT_REPLY_CREATED', + description: 'Someone replied to your comment 8.', + data: { + extra: {}, + }, + actor: { + __typename: 'Profile', + id: 'UHJvZmlsZToxNTM=', + }, + target: { + id: 'Q29tbWVudDoyMzc=', + __typename: 'Comment', + }, + actionObject: { + id: 'Q29tbWVudDoyNDE=', + __typename: 'Comment', + body: 'This is the eighth comment reply.', + }, + __typename: 'Notification', + }, + }, + { + cursor: 'cursor-9', + node: { + id: 'Tm90aWZpY2F0aW9uOjIxNw==', + unread: true, + pk: 217, + timestamp: '2024-10-25T19:44:32.462967+00:00', + level: 'INFO', + verb: 'COMMENTS.COMMENT_REPLY_CREATED', + description: 'Someone replied to your comment 9.', + data: { + extra: {}, + }, + actor: { + __typename: 'Profile', + id: 'UHJvZmlsZToxNTM=', + }, + target: { + id: 'Q29tbWVudDoyMzc=', + __typename: 'Comment', + }, + actionObject: { + id: 'Q29tbWVudDoyNDA=', + __typename: 'Comment', + body: 'This is the ninth comment reply.', + }, + __typename: 'Notification', + }, + }, + { + cursor: 'cursor-10', + node: { + id: 'Tm90aWZpY2F0aW9uOjIxNg==', + unread: true, + pk: 216, + timestamp: '2024-10-25T19:44:23.109884+00:00', + level: 'INFO', + verb: 'COMMENTS.COMMENT_REPLY_CREATED', + description: 'Someone replied to your comment 10.', + data: { + extra: {}, + }, + actor: { + __typename: 'Profile', + id: 'UHJvZmlsZToxNTM=', + }, + target: { + id: 'Q29tbWVudDoyMzc=', + __typename: 'Comment', + }, + actionObject: { + id: 'Q29tbWVudDoyMzk=', + __typename: 'Comment', + body: 'This is the tenth comment reply.', + }, + __typename: 'Notification', + }, + }, + ], + pageInfo: { + hasNextPage: true, + endCursor: 'cursor-10', + }, + }, + }, + }, +} diff --git a/packages/components/modules/notifications/NotificationsList/__storybook__/stories.tsx b/packages/components/modules/notifications/NotificationsList/__storybook__/stories.tsx new file mode 100644 index 00000000..96c24532 --- /dev/null +++ b/packages/components/modules/notifications/NotificationsList/__storybook__/stories.tsx @@ -0,0 +1,83 @@ +import type { Meta, StoryObj } from '@storybook/react' + +import NotificationsList from '..' +import { emptyNotificationsListMockData, notificationsListMockData } from './mockResolvers' + +const meta: Meta = { + title: '@baseapp-frontend | components/Notifications/NotificationsList', + component: NotificationsList, + tags: ['autodocs'], + argTypes: { + setIsDrawerOpened: { + control: false, + description: 'Function to toggle the Drawer open/close state.', + table: { + type: { + summary: 'Dispatch>', + }, + }, + }, + EmptyState: { + control: false, + description: 'Overrides the EmptyState component.', + table: { + type: { + summary: 'FC', + }, + }, + }, + LoadingState: { + control: false, + description: 'Overrides the LoadingState component.', + table: { + type: { + summary: 'FC', + }, + }, + }, + LoadingStateProps: { + control: 'object', + description: 'Props to pass to the LoadingState component.', + table: { + type: { + summary: 'LoadingStateProps', + }, + }, + }, + NotificationItem: { + control: false, + description: 'Overrides the NotificationItem component.', + table: { + type: { + summary: 'FC', + }, + }, + }, + }, +} + +export default meta + +type Story = StoryObj + +export const DefaultNotificationsList: Story = { + name: 'Default NotificationsList', + args: {}, + parameters: { + mockData: notificationsListMockData, + }, +} + +export const EmptyNotificationsList: Story = { + name: 'Empty NotificationsList', + args: {}, + parameters: { + mockData: emptyNotificationsListMockData, + }, +} + +export const LoadingNotificationsList: Story = { + name: 'Loading NotificationsList', + args: {}, + parameters: {}, +} diff --git a/packages/components/modules/notifications/NotificationsPopover/__storybook__/mockResolvers.ts b/packages/components/modules/notifications/NotificationsPopover/__storybook__/mockResolvers.ts new file mode 100644 index 00000000..d34894b5 --- /dev/null +++ b/packages/components/modules/notifications/NotificationsPopover/__storybook__/mockResolvers.ts @@ -0,0 +1,7 @@ +export const unreadNotificationsMockData = { + data: { me: { id: 'user-1', notificationsUnreadCount: 2 } }, +} + +export const unreadNotificationsEmptyMockData = { + data: { me: { id: 'user-1', notificationsUnreadCount: 0 } }, +} diff --git a/packages/components/modules/notifications/NotificationsPopover/__storybook__/stories.tsx b/packages/components/modules/notifications/NotificationsPopover/__storybook__/stories.tsx new file mode 100644 index 00000000..4e81b401 --- /dev/null +++ b/packages/components/modules/notifications/NotificationsPopover/__storybook__/stories.tsx @@ -0,0 +1,104 @@ +import type { Meta, StoryObj } from '@storybook/react' + +import NotificationsPopover from '..' +import { unreadNotificationsEmptyMockData, unreadNotificationsMockData } from './mockResolvers' + +const meta: Meta = { + title: '@baseapp-frontend | components/Notifications/NotificationsPopover', + component: NotificationsPopover, + tags: ['autodocs'], + argTypes: { + Drawer: { + control: false, + description: 'Overrides the Drawer component.', + table: { + type: { + summary: 'FC', + }, + }, + }, + DrawerProps: { + control: 'object', + description: 'Props to pass to the Drawer component.', + table: { + type: { + summary: 'Partial', + }, + }, + }, + Badge: { + control: false, + description: 'Overrides the Badge component.', + table: { + type: { + summary: 'FC', + }, + }, + }, + BadgeProps: { + control: 'object', + description: 'Props to pass to the Badge component.', + table: { + type: { + summary: 'Partial', + }, + }, + }, + NotificationBellIcon: { + control: false, + description: 'Overrides the NotificationBellIcon component.', + table: { + type: { + summary: 'FC', + }, + }, + }, + NotificationBellIconProps: { + control: 'object', + description: 'Props to pass to the NotificationBellIcon component.', + table: { + type: { + summary: 'Partial', + }, + }, + }, + NotificationsList: { + control: false, + description: 'Overrides the NotificationsList component.', + table: { + type: { + summary: 'FC', + }, + }, + }, + NotificationsListProps: { + control: 'object', + description: 'Props to pass to the NotificationsList component.', + table: { + type: { + summary: 'Partial', + }, + }, + }, + }, +} + +export default meta + +type Story = StoryObj + +export const DefaultNotificationsPopover: Story = { + name: 'Default NotificationsPopover', + args: {}, + parameters: { + mockData: unreadNotificationsEmptyMockData, + }, +} + +export const NotificationsPopoverWithUnreadNotifications: Story = { + name: 'With unread notifications', + args: {}, + parameters: { + mockData: unreadNotificationsMockData, + }, +} From 6c6e2027633b5e615672758b92dfd116ed9a4ad7 Mon Sep 17 00:00:00 2001 From: Matheus Domingos Date: Tue, 5 Nov 2024 17:51:37 -0300 Subject: [PATCH 2/6] Update changelog --- packages/components/CHANGELOG.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/packages/components/CHANGELOG.md b/packages/components/CHANGELOG.md index 3be78a8d..f23c95a5 100644 --- a/packages/components/CHANGELOG.md +++ b/packages/components/CHANGELOG.md @@ -1,5 +1,11 @@ # @baseapp-frontend/components +## 0.0.15 + +### Patch Changes + +- Add Storybook for notifications components. + ## 0.0.14 ### Patch Changes From d4eb4def55aabc985bf2f29604d7cfe5571044a4 Mon Sep 17 00:00:00 2001 From: Matheus Domingos Date: Tue, 5 Nov 2024 18:33:44 -0300 Subject: [PATCH 3/6] Remove unnecessary component --- packages/components/.storybook/preview.ts | 1 - .../NotificationsPopoverFragment.graphql.ts | 41 ----- .../NotificationsPopoverWithQuery.graphql.ts | 150 ------------------ 3 files changed, 192 deletions(-) delete mode 100644 packages/components/__generated__/NotificationsPopoverFragment.graphql.ts delete mode 100644 packages/components/__generated__/NotificationsPopoverWithQuery.graphql.ts diff --git a/packages/components/.storybook/preview.ts b/packages/components/.storybook/preview.ts index d8d90ce0..271f2d76 100644 --- a/packages/components/.storybook/preview.ts +++ b/packages/components/.storybook/preview.ts @@ -63,7 +63,6 @@ const preview: Preview = { 'NotificationsPopover', 'NotificationsList', 'NotificationItem', - 'NotificationUserMenu', ] const componentsStoriesOrder = [ diff --git a/packages/components/__generated__/NotificationsPopoverFragment.graphql.ts b/packages/components/__generated__/NotificationsPopoverFragment.graphql.ts deleted file mode 100644 index a5115699..00000000 --- a/packages/components/__generated__/NotificationsPopoverFragment.graphql.ts +++ /dev/null @@ -1,41 +0,0 @@ -/** - * @generated SignedSource<<47be4b188bda7b767468fd209eb62178>> - * @lightSyntaxTransform - * @nogrep - */ - -/* tslint:disable */ - -/* eslint-disable */ -// @ts-nocheck -import { Fragment, ReaderFragment } from 'relay-runtime' -import { FragmentRefs } from 'relay-runtime' - -export type NotificationsPopoverFragment$data = { - readonly ' $fragmentSpreads': FragmentRefs<'NotificationUserMenuFragment'> - readonly ' $fragmentType': 'NotificationsPopoverFragment' -} -export type NotificationsPopoverFragment$key = { - readonly ' $data'?: NotificationsPopoverFragment$data - readonly ' $fragmentSpreads': FragmentRefs<'NotificationsPopoverFragment'> -} - -const node: ReaderFragment = { - argumentDefinitions: [], - kind: 'Fragment', - metadata: null, - name: 'NotificationsPopoverFragment', - selections: [ - { - args: null, - kind: 'FragmentSpread', - name: 'NotificationUserMenuFragment', - }, - ], - type: 'User', - abstractKey: null, -} - -;(node as any).hash = 'aa7937f53433c977e2d19769946ec689' - -export default node diff --git a/packages/components/__generated__/NotificationsPopoverWithQuery.graphql.ts b/packages/components/__generated__/NotificationsPopoverWithQuery.graphql.ts deleted file mode 100644 index 5787cddf..00000000 --- a/packages/components/__generated__/NotificationsPopoverWithQuery.graphql.ts +++ /dev/null @@ -1,150 +0,0 @@ -/** - * @generated SignedSource<<2019611df1126cfaea95f44b33087e85>> - * @lightSyntaxTransform - * @nogrep - */ - -/* tslint:disable */ - -/* eslint-disable */ -// @ts-nocheck -import { ConcreteRequest, Query } from 'relay-runtime' -import { FragmentRefs } from 'relay-runtime' - -export type NotificationsPopoverWithQuery$variables = Record -export type NotificationsPopoverWithQuery$data = { - readonly target: - | { - readonly ' $fragmentSpreads': FragmentRefs<'NotificationsPopoverFragment'> - } - | null - | undefined -} -export type NotificationsPopoverWithQuery = { - response: NotificationsPopoverWithQuery$data - variables: NotificationsPopoverWithQuery$variables -} - -const node: ConcreteRequest = (function () { - var v0 = [ - { - kind: 'Literal', - name: 'id', - value: 'test-id', - }, - ] - return { - fragment: { - argumentDefinitions: [], - kind: 'Fragment', - metadata: null, - name: 'NotificationsPopoverWithQuery', - selections: [ - { - alias: 'target', - args: v0 /*: any*/, - concreteType: null, - kind: 'LinkedField', - name: 'node', - plural: false, - selections: [ - { - args: null, - kind: 'FragmentSpread', - name: 'NotificationsPopoverFragment', - }, - ], - storageKey: 'node(id:"test-id")', - }, - ], - type: 'Query', - abstractKey: null, - }, - kind: 'Request', - operation: { - argumentDefinitions: [], - kind: 'Operation', - name: 'NotificationsPopoverWithQuery', - selections: [ - { - alias: 'target', - args: v0 /*: any*/, - concreteType: null, - kind: 'LinkedField', - name: 'node', - plural: false, - selections: [ - { - alias: null, - args: null, - kind: 'ScalarField', - name: '__typename', - storageKey: null, - }, - { - alias: null, - args: null, - kind: 'ScalarField', - name: 'id', - storageKey: null, - }, - { - kind: 'InlineFragment', - selections: [ - { - alias: null, - args: null, - kind: 'ScalarField', - name: 'notificationsUnreadCount', - storageKey: null, - }, - ], - type: 'User', - abstractKey: null, - }, - ], - storageKey: 'node(id:"test-id")', - }, - ], - }, - params: { - cacheID: 'd209f52a732e0b615d9d587c64ee7ba1', - id: null, - metadata: { - relayTestingSelectionTypeInfo: { - target: { - enumValues: null, - nullable: true, - plural: false, - type: 'Node', - }, - 'target.__typename': { - enumValues: null, - nullable: false, - plural: false, - type: 'String', - }, - 'target.id': { - enumValues: null, - nullable: false, - plural: false, - type: 'ID', - }, - 'target.notificationsUnreadCount': { - enumValues: null, - nullable: true, - plural: false, - type: 'Int', - }, - }, - }, - name: 'NotificationsPopoverWithQuery', - operationKind: 'query', - text: 'query NotificationsPopoverWithQuery {\n target: node(id: "test-id") {\n __typename\n ...NotificationsPopoverFragment\n id\n }\n}\n\nfragment NotificationUserMenuFragment on User {\n id\n notificationsUnreadCount\n}\n\nfragment NotificationsPopoverFragment on User {\n ...NotificationUserMenuFragment\n}\n', - }, - } -})() - -;(node as any).hash = '2bc67125981d8f8d37483054ac8830f0' - -export default node From 363f3b07392b86eff4ae4a39f8960ddf27612029 Mon Sep 17 00:00:00 2001 From: Matheus Domingos Date: Fri, 8 Nov 2024 12:29:33 -0300 Subject: [PATCH 4/6] remove unused component --- packages/components/.storybook/preview.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/components/.storybook/preview.ts b/packages/components/.storybook/preview.ts index 271f2d76..6a9bd777 100644 --- a/packages/components/.storybook/preview.ts +++ b/packages/components/.storybook/preview.ts @@ -112,7 +112,6 @@ const preview: Preview = { 'NotificationsPopover', 'NotificationsList', 'NotificationItem', - 'NotificationUserMenu', ] const final = [...storiesOrder, ...componentsStoriesOrder] From d55898f0d3992bb3da2596660e71bb3155401341 Mon Sep 17 00:00:00 2001 From: Matheus Domingos Date: Mon, 11 Nov 2024 15:42:54 -0300 Subject: [PATCH 5/6] Rename storiesOrder and fix components order and add signature --- packages/components/.storybook/preview.ts | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/packages/components/.storybook/preview.ts b/packages/components/.storybook/preview.ts index 6a9bd777..46494c1b 100644 --- a/packages/components/.storybook/preview.ts +++ b/packages/components/.storybook/preview.ts @@ -33,8 +33,8 @@ const preview: Preview = { // @ts-ignore storySort: (a, b) => { // NOTE: Storybook does not accept importing external variables for storySort, - // so the `storiesOrder` and `componentsStoriesOrder` are defined inline. - const storiesOrder = [ + // so the `designSystemStoriesOrder` and `componentsStoriesOrder` are defined inline. + const designSystemStoriesOrder = [ 'Iconography', // Avatars 'AvatarWithPlaceholder', @@ -59,10 +59,6 @@ const preview: Preview = { // General 'Logo', 'Scrollbar', - // Notifications - 'NotificationsPopover', - 'NotificationsList', - 'NotificationItem', ] const componentsStoriesOrder = [ @@ -99,6 +95,10 @@ const preview: Preview = { 'NavHorizontal', 'NavCentered', 'NavVertical', + //Notifications + 'NotificationItem', + 'NotificationsList', + 'NotificationsPopover', // Social 'Comments', 'CommentsList', @@ -108,12 +108,8 @@ const preview: Preview = { 'CommentUpsertActions', 'ReactionButton', 'Timestamp', - //Notifications - 'NotificationsPopover', - 'NotificationsList', - 'NotificationItem', ] - const final = [...storiesOrder, ...componentsStoriesOrder] + const final = [...designSystemStoriesOrder, ...componentsStoriesOrder] const titleA = a.title || '' const titleB = b.title || '' From 60e7d90f7b529c5af3df1ccd31052b1a814aa972 Mon Sep 17 00:00:00 2001 From: Matheus Domingos Date: Tue, 12 Nov 2024 16:40:21 -0300 Subject: [PATCH 6/6] bump components package.json version --- packages/components/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/components/package.json b/packages/components/package.json index a096c205..8cd6c31f 100644 --- a/packages/components/package.json +++ b/packages/components/package.json @@ -1,7 +1,7 @@ { "name": "@baseapp-frontend/components", "description": "BaseApp components modules such as comments, notifications, messages, and more.", - "version": "0.0.14", + "version": "0.0.15", "main": "./index.ts", "types": "dist/index.d.ts", "sideEffects": false,