Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[EASI-4639] Discussions panel views #2895

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
0c52b8a
Merge discussions card work into branch
aterstriep Nov 18, 2024
f5a92d3
Discussions panel view components
aterstriep Nov 18, 2024
3be2f26
Discussion post and reply mutations
aterstriep Nov 18, 2024
4867fba
Basic discussion form
aterstriep Nov 18, 2024
5c21106
Fix line height within side panel
aterstriep Nov 18, 2024
f1d44cb
Display discussion and replies
aterstriep Nov 18, 2024
d7eb072
Discussions list view
aterstriep Nov 18, 2024
a91ad3c
Threaded replies styling
aterstriep Nov 18, 2024
3f22274
Show/hide replies
aterstriep Nov 18, 2024
4f858e0
DiscussionsList component
aterstriep Nov 19, 2024
d164c10
Add DiscussionsList to Discussion view
aterstriep Nov 19, 2024
89f65c6
Add DiscussionsList to discussion board view
aterstriep Nov 19, 2024
f8d1ea8
Create discussion and reply mutations
aterstriep Nov 19, 2024
8d8ca6d
Discussion board list filtering
aterstriep Nov 19, 2024
1031880
ViewDiscussions unit tests
aterstriep Nov 19, 2024
ae75a04
Discussion component unit tests
aterstriep Nov 19, 2024
920dc88
Success and error messages
aterstriep Nov 19, 2024
65cdace
Merge branch 'feature/EASI-4614_grb_discussions' into EASI-4639/discu…
aterstriep Nov 19, 2024
fc35225
Feature branch merge conflict fix
aterstriep Nov 19, 2024
2e6d610
Merge branch 'feature/EASI-4614_grb_discussions' into EASI-4639/discu…
aterstriep Nov 21, 2024
f76a50f
MentionTextArea in DiscussionForm (#2898)
adamodd Nov 21, 2024
ca2b568
Fix render error when review has no discussions
aterstriep Nov 21, 2024
5988d6e
Hide replies if array is empty
aterstriep Nov 21, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 12 additions & 3 deletions src/components/MentionTextArea/index.scss
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,6 @@

/* Basic editor styles */
.tiptap {
border: 1px solid black;
padding: .5rem;

p {
margin: 0px;
}
Expand Down Expand Up @@ -45,6 +42,18 @@
font-size: 16px;
line-height: 22px;
}

&.usa-textarea {
padding: 0;

div[contenteditable] {
font-family: inherit;
font-size: inherit;
line-height: inherit;
height: inherit;
padding: .5rem;
}
}
}
}

Expand Down
159 changes: 79 additions & 80 deletions src/components/MentionTextArea/index.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import React, { useState } from 'react';
import { useTranslation } from 'react-i18next';
// import { useTranslation } from 'react-i18next';
import Mention from '@tiptap/extension-mention';
import {
Expand All @@ -10,7 +11,6 @@ import {
import StarterKit from '@tiptap/starter-kit';
import classNames from 'classnames';

// import { sortBy } from 'lodash';
import Alert from 'components/shared/Alert';

import suggestion from './suggestion';
Expand Down Expand Up @@ -58,62 +58,57 @@ const CustomMention = Mention.extend({
}
});

const MentionTextArea = ({
id,
setFieldValue,
editable,
disabled,
initialContent,
className
}: {
id: string;
setFieldValue?: (
field: string,
value: any,
shouldValidate?: boolean | undefined
) => void;
editable?: boolean;
disabled?: boolean;
initialContent?: any;
className?: string;
}) => {
// const { t } = useTranslation('');
const MentionTextArea = React.forwardRef<
HTMLDivElement,
{
id: string;
setFieldValue?: (value: any, shouldValidate?: boolean | undefined) => void;
editable?: boolean;
disabled?: boolean;
initialContent?: string;
className?: string;
}
>(
(
{ id, setFieldValue, editable, disabled, initialContent, className },
ref
) => {
const { t } = useTranslation('discussions');

const [tagAlert, setTagAlert] = useState<boolean>(false);
const [tagAlert, setTagAlert] = useState<boolean>(false);

const fetchUsers = ({ query }: { query: string }) => {
return [
{ username: 'a', displayName: 'Admin lead', tagType: 'other' },
{
username: 'b',
displayName: 'Governance Admin Team',
tagType: 'other'
},
{
username: 'c',
displayName: 'Governance Review Board (GRB)',
tagType: 'other'
},
{
username: 'OSYC',
displayName: 'Grant Eliezer',
tagType: 'user'
},
{
username: 'MKCK',
displayName: 'Forest Brown',
tagType: 'user'
},
{
username: 'PJEA',
displayName: 'Janae Stokes',
tagType: 'user'
}
];
};
const fetchUsers = ({ query }: { query: string }) => {
return [
{ username: 'a', displayName: 'Admin lead', tagType: 'other' },
{
username: 'b',
displayName: 'Governance Admin Team',
tagType: 'other'
},
{
username: 'c',
displayName: 'Governance Review Board (GRB)',
tagType: 'other'
},
{
username: 'OSYC',
displayName: 'Grant Eliezer',
tagType: 'user'
},
{
username: 'MKCK',
displayName: 'Forest Brown',
tagType: 'user'
},
{
username: 'PJEA',
displayName: 'Janae Stokes',
tagType: 'user'
}
];
};

const editor = useEditor(
{
const editor = useEditor({
editable: editable && !disabled,
editorProps: {
attributes: {
Expand All @@ -132,41 +127,45 @@ const MentionTextArea = ({
}
})
],
onUpdate: ({ editor: input }: any) => {
// Uses the form setter prop (Formik) for mutation input
onUpdate: ({ editor: input }) => {
const inputContent = input?.getHTML();
const inputText = input?.getText();

if (setFieldValue) {
setFieldValue('content', input?.getHTML());
if (inputText === '') {
setFieldValue('');
return;
}
setFieldValue(inputContent);
}
},
// Sets a alert of a mention is selected, and users/teams will be emailed
onSelectionUpdate: ({ editor: input }: any) => {
setTagAlert(!!getMentions(input?.getJSON()).length);
},
content: initialContent
},
[initialContent, disabled]
);
});

return (
<>
<EditorContent
editor={editor}
id={id}
className={classNames(className, {
tiptap__readonly: !editable,
tiptap__editable: editable
})}
/>
return (
<>
<EditorContent
innerRef={ref}
editor={editor}
id={id}
className={classNames(className, 'usa-textarea', {
tiptap__readonly: !editable,
tiptap__editable: editable
})}
/>

{tagAlert && editable && (
<Alert type="info" slim>
{/* t() */}
When you save your discussion, the selected team(s) and individual(s)
will be notified via email.
</Alert>
)}
</>
);
};
{tagAlert && editable && (
<Alert type="info" slim>
{t('general.alerts.saveDiscussion')}
</Alert>
)}
</>
);
}
);

export default MentionTextArea;
80 changes: 78 additions & 2 deletions src/data/mock/discussions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import {
import { systemIntake } from './systemIntake';
import users from './users';

const mockDiscussions = (
export const mockDiscussions = (
systemIntakeID: string = systemIntake.id
): SystemIntakeGRBReviewDiscussionFragment[] => [
{
Expand Down Expand Up @@ -62,4 +62,80 @@ const mockDiscussions = (
}
];

export default mockDiscussions;
export const mockDiscussionsWithoutReplies = (
systemIntakeID: string = systemIntake.id
): SystemIntakeGRBReviewDiscussionFragment[] => [
{
__typename: 'SystemIntakeGRBReviewDiscussion',
initialPost: {
__typename: 'SystemIntakeGRBReviewDiscussionPost',
id: 'd6cd88e2-d330-4b7c-9006-d6cf95b775e9',
content: '<p>This is a discussion without replies.</p>',
votingRole: SystemIntakeGRBReviewerVotingRole.NON_VOTING,
grbRole: SystemIntakeGRBReviewerRole.CCIIO_REP,
createdByUserAccount: {
__typename: 'UserAccount',
id: '3f750a9d-a2a2-414f-a013-59554ed32c75',
commonName: users[2].commonName
},
systemIntakeID,
createdAt: '2024-11-18T10:00:00.368862Z'
},
replies: []
},
{
__typename: 'SystemIntakeGRBReviewDiscussion',
initialPost: {
__typename: 'SystemIntakeGRBReviewDiscussionPost',
id: '372bf1c0-3f33-4046-a973-bc063f39dc59',
content: '<p>This is another discussion without replies.</p>',
votingRole: SystemIntakeGRBReviewerVotingRole.VOTING,
grbRole: SystemIntakeGRBReviewerRole.CO_CHAIR_HCA,
createdByUserAccount: {
__typename: 'UserAccount',
id: '32c29aac-e20c-4fce-9ecb-8eb2f4c87e5f',
commonName: users[9].commonName
},
systemIntakeID,
createdAt: '2024-11-17T10:00:00.368862Z'
},
replies: []
},
{
__typename: 'SystemIntakeGRBReviewDiscussion',
initialPost: {
__typename: 'SystemIntakeGRBReviewDiscussionPost',
id: '39823b79-987d-4f81-9fcb-ae45f4c5bfeb',
content: '<p>This is a third discussion without replies.</p>',
votingRole: SystemIntakeGRBReviewerVotingRole.VOTING,
grbRole: SystemIntakeGRBReviewerRole.QIO_REP,
createdByUserAccount: {
__typename: 'UserAccount',
id: 'a9628365-16a5-49bf-9acc-7dbdade7288f',
commonName: users[3].commonName
},
systemIntakeID,
createdAt: '2024-11-17T9:00:00.368862Z'
},
replies: []
},
{
__typename: 'SystemIntakeGRBReviewDiscussion',
initialPost: {
__typename: 'SystemIntakeGRBReviewDiscussionPost',
id: 'df00daf2-f666-4014-98d3-fd28630fe996',
content:
'<p>This discussion without replies should not show up until list is expanded.</p>',
votingRole: SystemIntakeGRBReviewerVotingRole.ALTERNATE,
grbRole: SystemIntakeGRBReviewerRole.FED_ADMIN_BDG_CHAIR,
createdByUserAccount: {
__typename: 'UserAccount',
id: 'c7eefa37-b917-4fa3-8fc0-b86fa5de7df2',
commonName: users[8].commonName
},
systemIntakeID,
createdAt: '2024-11-17T9:30:00.368862Z'
},
replies: []
}
];
11 changes: 11 additions & 0 deletions src/gql/apolloGQL/grbReview/CreateSystemIntakeGRBDiscussionPost.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { gql } from '@apollo/client';

export default gql(/* GraphQL */ `
mutation CreateSystemIntakeGRBDiscussionPost(
$input: createSystemIntakeGRBDiscussionPostInput!
) {
createSystemIntakeGRBDiscussionPost(input: $input) {
id
}
}
`);
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { gql } from '@apollo/client';

export default gql(/* GraphQL */ `
mutation CreateSystemIntakeGRBDiscussionReply(
$input: createSystemIntakeGRBDiscussionReplyInput!
) {
createSystemIntakeGRBDiscussionReply(input: $input) {
id
}
}
`);
Loading