@churchapps/apphelper 0.0.8 → 0.0.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (185) hide show
  1. package/.eslintignore +3 -3
  2. package/.eslintrc.json +22 -22
  3. package/LICENSE +21 -21
  4. package/README.md +16 -16
  5. package/dist/components/ExportLink.d.ts.map +1 -1
  6. package/dist/components/ExportLink.js +10 -7
  7. package/dist/components/ExportLink.js.map +1 -1
  8. package/dist/components/markdownEditor/editor.css +787 -787
  9. package/dist/components/markdownEditor/images/icons/arrow-clockwise.svg +3 -3
  10. package/dist/components/markdownEditor/images/icons/arrow-counterclockwise.svg +3 -3
  11. package/dist/components/markdownEditor/images/icons/chat-square-quote.svg +3 -3
  12. package/dist/components/markdownEditor/images/icons/chevron-down.svg +2 -2
  13. package/dist/components/markdownEditor/images/icons/code.svg +2 -2
  14. package/dist/components/markdownEditor/images/icons/journal-code.svg +4 -4
  15. package/dist/components/markdownEditor/images/icons/journal-text.svg +4 -4
  16. package/dist/components/markdownEditor/images/icons/justify.svg +2 -2
  17. package/dist/components/markdownEditor/images/icons/link.svg +3 -3
  18. package/dist/components/markdownEditor/images/icons/list-ol.svg +3 -3
  19. package/dist/components/markdownEditor/images/icons/list-ul.svg +2 -2
  20. package/dist/components/markdownEditor/images/icons/pencil-fill.svg +2 -2
  21. package/dist/components/markdownEditor/images/icons/text-center.svg +2 -2
  22. package/dist/components/markdownEditor/images/icons/text-left.svg +2 -2
  23. package/dist/components/markdownEditor/images/icons/text-paragraph.svg +2 -2
  24. package/dist/components/markdownEditor/images/icons/text-right.svg +2 -2
  25. package/dist/components/markdownEditor/images/icons/type-bold.svg +2 -2
  26. package/dist/components/markdownEditor/images/icons/type-h1.svg +2 -2
  27. package/dist/components/markdownEditor/images/icons/type-h2.svg +2 -2
  28. package/dist/components/markdownEditor/images/icons/type-h3.svg +2 -2
  29. package/dist/components/markdownEditor/images/icons/type-h4.svg +12 -12
  30. package/dist/components/markdownEditor/images/icons/type-italic.svg +2 -2
  31. package/dist/components/markdownEditor/images/icons/type-strikethrough.svg +2 -2
  32. package/dist/components/markdownEditor/images/icons/type-underline.svg +2 -2
  33. package/package.json +84 -84
  34. package/src/components/CreatePerson.tsx +80 -80
  35. package/src/components/DisplayBox.tsx +68 -68
  36. package/src/components/ErrorMessages.tsx +26 -26
  37. package/src/components/ExportLink.tsx +67 -61
  38. package/src/components/FloatingSupport.tsx +16 -16
  39. package/src/components/FormSubmissionEdit.tsx +120 -120
  40. package/src/components/HelpIcon.tsx +10 -10
  41. package/src/components/ImageEditor.tsx +126 -126
  42. package/src/components/InputBox.tsx +73 -73
  43. package/src/components/Loading.tsx +29 -29
  44. package/src/components/PersonAdd.tsx +75 -75
  45. package/src/components/QuestionEdit.tsx +62 -62
  46. package/src/components/SmallButton.tsx +39 -39
  47. package/src/components/SupportModal.tsx +26 -26
  48. package/src/components/TabPanel.tsx +34 -34
  49. package/src/components/gallery/GalleryModal.tsx +102 -102
  50. package/src/components/gallery/StockPhotos.tsx +74 -74
  51. package/src/components/gallery/index.ts +1 -1
  52. package/src/components/index.tsx +23 -23
  53. package/src/components/markdownEditor/Editor.tsx +132 -132
  54. package/src/components/markdownEditor/MarkdownEditor.tsx +16 -16
  55. package/src/components/markdownEditor/MarkdownModal.tsx +46 -46
  56. package/src/components/markdownEditor/MarkdownPreview.tsx +14 -14
  57. package/src/components/markdownEditor/editor.css +787 -787
  58. package/src/components/markdownEditor/images/icons/arrow-clockwise.svg +3 -3
  59. package/src/components/markdownEditor/images/icons/arrow-counterclockwise.svg +3 -3
  60. package/src/components/markdownEditor/images/icons/chat-square-quote.svg +3 -3
  61. package/src/components/markdownEditor/images/icons/chevron-down.svg +2 -2
  62. package/src/components/markdownEditor/images/icons/code.svg +2 -2
  63. package/src/components/markdownEditor/images/icons/journal-code.svg +4 -4
  64. package/src/components/markdownEditor/images/icons/journal-text.svg +4 -4
  65. package/src/components/markdownEditor/images/icons/justify.svg +2 -2
  66. package/src/components/markdownEditor/images/icons/link.svg +3 -3
  67. package/src/components/markdownEditor/images/icons/list-ol.svg +3 -3
  68. package/src/components/markdownEditor/images/icons/list-ul.svg +2 -2
  69. package/src/components/markdownEditor/images/icons/pencil-fill.svg +2 -2
  70. package/src/components/markdownEditor/images/icons/text-center.svg +2 -2
  71. package/src/components/markdownEditor/images/icons/text-left.svg +2 -2
  72. package/src/components/markdownEditor/images/icons/text-paragraph.svg +2 -2
  73. package/src/components/markdownEditor/images/icons/text-right.svg +2 -2
  74. package/src/components/markdownEditor/images/icons/type-bold.svg +2 -2
  75. package/src/components/markdownEditor/images/icons/type-h1.svg +2 -2
  76. package/src/components/markdownEditor/images/icons/type-h2.svg +2 -2
  77. package/src/components/markdownEditor/images/icons/type-h3.svg +2 -2
  78. package/src/components/markdownEditor/images/icons/type-h4.svg +12 -12
  79. package/src/components/markdownEditor/images/icons/type-italic.svg +2 -2
  80. package/src/components/markdownEditor/images/icons/type-strikethrough.svg +2 -2
  81. package/src/components/markdownEditor/images/icons/type-underline.svg +2 -2
  82. package/src/components/markdownEditor/index.ts +2 -2
  83. package/src/components/markdownEditor/plugins/AutoLinkPlugin.tsx +35 -35
  84. package/src/components/markdownEditor/plugins/ControlledEditorPlugin.tsx +24 -24
  85. package/src/components/markdownEditor/plugins/ListMaxIndentLevelPlugin.tsx +68 -68
  86. package/src/components/markdownEditor/plugins/MarkdownTransformers.ts +106 -106
  87. package/src/components/markdownEditor/plugins/ReadOnlyPlugin.tsx +15 -15
  88. package/src/components/markdownEditor/plugins/ToolbarPlugin.tsx +401 -401
  89. package/src/components/markdownEditor/plugins/customLink/CustomLinkNode.tsx +224 -224
  90. package/src/components/markdownEditor/plugins/customLink/CustomLinkNodePlugin.tsx +32 -32
  91. package/src/components/markdownEditor/plugins/customLink/CustomLinkNodeTransformer.tsx +102 -102
  92. package/src/components/markdownEditor/plugins/customLink/FloatingLinkEditor.tsx +243 -243
  93. package/src/components/markdownEditor/plugins/customLink/FloatingLinkEditor.types.ts +11 -11
  94. package/src/components/markdownEditor/plugins/emoji/EmojiNode.tsx +95 -95
  95. package/src/components/markdownEditor/plugins/emoji/EmojiNodeTransform.ts +41 -41
  96. package/src/components/markdownEditor/plugins/emoji/EmojiPickerPlugin.tsx +152 -152
  97. package/src/components/markdownEditor/plugins/emoji/EmojisPlugin.tsx +65 -65
  98. package/src/components/markdownEditor/plugins/index.ts +6 -6
  99. package/src/components/markdownEditor/theme.ts +65 -65
  100. package/src/components/material/AppList.tsx +20 -20
  101. package/src/components/material/ChurchList.tsx +22 -22
  102. package/src/components/material/NavItem.tsx +41 -41
  103. package/src/components/material/NewPrivateMessage.tsx +103 -103
  104. package/src/components/material/PrivateMessageDetails.tsx +23 -23
  105. package/src/components/material/PrivateMessages.tsx +87 -87
  106. package/src/components/material/SiteWrapper.tsx +140 -140
  107. package/src/components/material/UserMenu.tsx +141 -141
  108. package/src/components/material/iconPicker/IconNamesList.ts +2240 -2240
  109. package/src/components/material/iconPicker/IconPicker.tsx +153 -153
  110. package/src/components/material/index.tsx +6 -6
  111. package/src/components/notes/AddNote.tsx +90 -90
  112. package/src/components/notes/Conversation.tsx +82 -82
  113. package/src/components/notes/Conversations.tsx +58 -58
  114. package/src/components/notes/NewConversation.tsx +78 -78
  115. package/src/components/notes/Note.tsx +44 -44
  116. package/src/components/notes/Notes.tsx +52 -52
  117. package/src/components/notes/index.ts +5 -5
  118. package/src/components/reporting/ChartReport.tsx +98 -98
  119. package/src/components/reporting/ReportFilter.tsx +54 -54
  120. package/src/components/reporting/ReportFilterField.tsx +160 -160
  121. package/src/components/reporting/ReportOutput.tsx +79 -79
  122. package/src/components/reporting/ReportWithFilter.tsx +70 -70
  123. package/src/components/reporting/TableReport.tsx +57 -57
  124. package/src/components/reporting/TreeReport.tsx +111 -111
  125. package/src/components/reporting/index.ts +4 -4
  126. package/src/donationComponents/DonationPage.tsx +136 -136
  127. package/src/donationComponents/components/BankForm.tsx +159 -159
  128. package/src/donationComponents/components/CardForm.tsx +104 -104
  129. package/src/donationComponents/components/DonationForm.tsx +235 -235
  130. package/src/donationComponents/components/FundDonation.tsx +49 -49
  131. package/src/donationComponents/components/FundDonations.tsx +39 -39
  132. package/src/donationComponents/components/NonAuthDonation.tsx +31 -31
  133. package/src/donationComponents/components/NonAuthDonationInner.tsx +259 -259
  134. package/src/donationComponents/components/PaymentMethods.tsx +135 -135
  135. package/src/donationComponents/components/RecurringDonations.tsx +121 -121
  136. package/src/donationComponents/components/RecurringDonationsEdit.tsx +93 -93
  137. package/src/donationComponents/components/index.tsx +9 -9
  138. package/src/donationComponents/index.ts +3 -3
  139. package/src/donationComponents/modals/DonationPreviewModal.tsx +66 -66
  140. package/src/helpers/AnalyticsHelper.ts +33 -33
  141. package/src/helpers/ApiHelper.ts +125 -125
  142. package/src/helpers/AppearanceHelper.ts +69 -69
  143. package/src/helpers/ArrayHelper.ts +81 -81
  144. package/src/helpers/CommonEnvironmentHelper.ts +80 -80
  145. package/src/helpers/CurrencyHelper.ts +10 -10
  146. package/src/helpers/DateHelper.ts +108 -108
  147. package/src/helpers/DonationHelper.ts +26 -26
  148. package/src/helpers/ErrorHelper.ts +36 -36
  149. package/src/helpers/EventHelper.ts +52 -52
  150. package/src/helpers/FileHelper.ts +31 -31
  151. package/src/helpers/PersonHelper.ts +60 -60
  152. package/src/helpers/SocketHelper.ts +76 -76
  153. package/src/helpers/Themes.ts +14 -14
  154. package/src/helpers/UniqueIdHelper.ts +36 -36
  155. package/src/helpers/UserHelper.ts +59 -59
  156. package/src/helpers/createEmotionCache.ts +17 -17
  157. package/src/helpers/index.ts +18 -18
  158. package/src/hooks/index.ts +1 -1
  159. package/src/hooks/useMountedState.ts +16 -16
  160. package/src/index.ts +6 -6
  161. package/src/interfaces/Access.ts +24 -24
  162. package/src/interfaces/Attendance.ts +8 -8
  163. package/src/interfaces/Content.ts +10 -10
  164. package/src/interfaces/Doing.ts +24 -24
  165. package/src/interfaces/Donation.ts +45 -45
  166. package/src/interfaces/Error.ts +17 -17
  167. package/src/interfaces/Membership.ts +51 -51
  168. package/src/interfaces/Messaging.ts +20 -20
  169. package/src/interfaces/Permissions.ts +68 -68
  170. package/src/interfaces/Reporting.ts +7 -7
  171. package/src/interfaces/UserContextInterface.ts +13 -13
  172. package/src/interfaces/index.ts +13 -13
  173. package/src/pageComponents/LoginPage.tsx +244 -244
  174. package/src/pageComponents/LogoutPage.tsx +28 -28
  175. package/src/pageComponents/components/Forgot.tsx +79 -79
  176. package/src/pageComponents/components/Login.tsx +54 -54
  177. package/src/pageComponents/components/LoginSetPassword.tsx +63 -63
  178. package/src/pageComponents/components/Register.tsx +107 -107
  179. package/src/pageComponents/components/SelectChurchModal.tsx +41 -41
  180. package/src/pageComponents/components/SelectChurchRegister.tsx +88 -88
  181. package/src/pageComponents/components/SelectChurchSearch.tsx +69 -69
  182. package/src/pageComponents/components/SelectableChurch.tsx +38 -38
  183. package/src/pageComponents/index.ts +3 -3
  184. package/tsconfig.json +34 -34
  185. package/tslint.json +14 -14
@@ -1,82 +1,82 @@
1
- import { Box, Paper, Stack } from "@mui/material";
2
- import React from "react";
3
- import { ApiHelper, ArrayHelper, DateHelper, PersonHelper } from "../../helpers";
4
- import { ConversationInterface, MessageInterface, UserContextInterface } from "../../interfaces";
5
- import { AddNote } from "./AddNote";
6
- import { Note } from "./Note";
7
-
8
- interface Props {
9
- conversation: ConversationInterface;
10
- context: UserContextInterface;
11
- showCommentCount?: boolean;
12
- noWrapper?: boolean;
13
- }
14
-
15
- export function Conversation(props: Props) {
16
- const [conversation, setConversation] = React.useState<ConversationInterface>(null)
17
- const [editMessageId, setEditMessageId] = React.useState(null)
18
-
19
- const loadNotes = async () => {
20
- const messages: MessageInterface[] = (conversation.id) ? await ApiHelper.get("/messages/conversation/" + conversation.id, "MessagingApi") : [];
21
- if (messages.length > 0) {
22
- const peopleIds = ArrayHelper.getIds(messages, "personId");
23
- const people = await ApiHelper.get("/people/ids?ids=" + peopleIds.join(","), "MembershipApi");
24
- messages.forEach(n => {
25
- n.person = ArrayHelper.getOne(people, "id", n.personId);
26
- })
27
- }
28
- const c = { ...conversation }
29
- c.messages = messages;
30
- setConversation(c);
31
- setEditMessageId(null);
32
- };
33
-
34
- React.useEffect(() => { setConversation(props.conversation) }, [props.conversation]); //eslint-disable-line
35
-
36
- if (conversation === null) return null;
37
- else {
38
- const message = conversation.messages[0];
39
- const photoUrl = PersonHelper.getPhotoUrl(message.person);
40
- let datePosted = new Date(message.timeUpdated || message.timeSent);
41
- const displayDuration = DateHelper.getDisplayDuration(datePosted);
42
-
43
- const isEdited = message.timeUpdated && message.timeUpdated !== message.timeSent && <>(edited)</>;
44
- const contents = message.content?.split("\n");
45
-
46
- const getNotes = () => {
47
- let noteArray: React.ReactNode[] = [];
48
- for (let i = 1; i < conversation.messages.length; i++) noteArray.push(<Note message={conversation.messages[i]} key={conversation.messages[i].id} showEditNote={setEditMessageId} />);
49
- return noteArray;
50
- }
51
-
52
- let result = (<>
53
- <div className="conversation">
54
- <div className="postedBy">
55
- <img src={photoUrl} alt="avatar" />
56
- </div>
57
- <Box sx={{ width: "100%" }} className="conversationContents">
58
- <Stack direction="row" justifyContent="space-between">
59
- <div>
60
- <b>{message.person?.name?.display}</b> · <span className="text-grey">{displayDuration}{isEdited}</span>
61
- {contents.map((c, i) => c ? <p key={i}>{c}</p> : <br />)}
62
- </div>
63
- </Stack>
64
- </Box>
65
- </div>
66
- {props.showCommentCount && (
67
- <div className="commentCount">
68
- <div>{(conversation.postCount === 1) ? "1 comment" : conversation.postCount + " comments"}</div>
69
- {(conversation.postCount > conversation.messages.length) ? <a href="about:blank" onClick={(e) => { e.preventDefault(); loadNotes(); }}>View all {conversation.postCount} comments</a> : <>&nbsp;</>}
70
- </div>
71
- )}
72
- <div className="messages">
73
- {getNotes()}
74
- <AddNote context={props.context} conversationId={props.conversation.id} onUpdate={loadNotes} createConversation={async () => (props.conversation.id)} messageId={editMessageId} />
75
- </div>
76
- </>);
77
-
78
-
79
- if (props.noWrapper) return result;
80
- else return (<Paper sx={{ padding: 1, marginBottom: 2 }}>{result}</Paper>);
81
- }
82
- };
1
+ import { Box, Paper, Stack } from "@mui/material";
2
+ import React from "react";
3
+ import { ApiHelper, ArrayHelper, DateHelper, PersonHelper } from "../../helpers";
4
+ import { ConversationInterface, MessageInterface, UserContextInterface } from "../../interfaces";
5
+ import { AddNote } from "./AddNote";
6
+ import { Note } from "./Note";
7
+
8
+ interface Props {
9
+ conversation: ConversationInterface;
10
+ context: UserContextInterface;
11
+ showCommentCount?: boolean;
12
+ noWrapper?: boolean;
13
+ }
14
+
15
+ export function Conversation(props: Props) {
16
+ const [conversation, setConversation] = React.useState<ConversationInterface>(null)
17
+ const [editMessageId, setEditMessageId] = React.useState(null)
18
+
19
+ const loadNotes = async () => {
20
+ const messages: MessageInterface[] = (conversation.id) ? await ApiHelper.get("/messages/conversation/" + conversation.id, "MessagingApi") : [];
21
+ if (messages.length > 0) {
22
+ const peopleIds = ArrayHelper.getIds(messages, "personId");
23
+ const people = await ApiHelper.get("/people/ids?ids=" + peopleIds.join(","), "MembershipApi");
24
+ messages.forEach(n => {
25
+ n.person = ArrayHelper.getOne(people, "id", n.personId);
26
+ })
27
+ }
28
+ const c = { ...conversation }
29
+ c.messages = messages;
30
+ setConversation(c);
31
+ setEditMessageId(null);
32
+ };
33
+
34
+ React.useEffect(() => { setConversation(props.conversation) }, [props.conversation]); //eslint-disable-line
35
+
36
+ if (conversation === null) return null;
37
+ else {
38
+ const message = conversation.messages[0];
39
+ const photoUrl = PersonHelper.getPhotoUrl(message.person);
40
+ let datePosted = new Date(message.timeUpdated || message.timeSent);
41
+ const displayDuration = DateHelper.getDisplayDuration(datePosted);
42
+
43
+ const isEdited = message.timeUpdated && message.timeUpdated !== message.timeSent && <>(edited)</>;
44
+ const contents = message.content?.split("\n");
45
+
46
+ const getNotes = () => {
47
+ let noteArray: React.ReactNode[] = [];
48
+ for (let i = 1; i < conversation.messages.length; i++) noteArray.push(<Note message={conversation.messages[i]} key={conversation.messages[i].id} showEditNote={setEditMessageId} />);
49
+ return noteArray;
50
+ }
51
+
52
+ let result = (<>
53
+ <div className="conversation">
54
+ <div className="postedBy">
55
+ <img src={photoUrl} alt="avatar" />
56
+ </div>
57
+ <Box sx={{ width: "100%" }} className="conversationContents">
58
+ <Stack direction="row" justifyContent="space-between">
59
+ <div>
60
+ <b>{message.person?.name?.display}</b> · <span className="text-grey">{displayDuration}{isEdited}</span>
61
+ {contents.map((c, i) => c ? <p key={i}>{c}</p> : <br />)}
62
+ </div>
63
+ </Stack>
64
+ </Box>
65
+ </div>
66
+ {props.showCommentCount && (
67
+ <div className="commentCount">
68
+ <div>{(conversation.postCount === 1) ? "1 comment" : conversation.postCount + " comments"}</div>
69
+ {(conversation.postCount > conversation.messages.length) ? <a href="about:blank" onClick={(e) => { e.preventDefault(); loadNotes(); }}>View all {conversation.postCount} comments</a> : <>&nbsp;</>}
70
+ </div>
71
+ )}
72
+ <div className="messages">
73
+ {getNotes()}
74
+ <AddNote context={props.context} conversationId={props.conversation.id} onUpdate={loadNotes} createConversation={async () => (props.conversation.id)} messageId={editMessageId} />
75
+ </div>
76
+ </>);
77
+
78
+
79
+ if (props.noWrapper) return result;
80
+ else return (<Paper sx={{ padding: 1, marginBottom: 2 }}>{result}</Paper>);
81
+ }
82
+ };
@@ -1,58 +1,58 @@
1
- import React from "react";
2
- import { Loading } from "../";
3
- import { ApiHelper, ArrayHelper } from "../../helpers";
4
- import { ConversationInterface, UserContextInterface } from "../../interfaces";
5
- import { Conversation } from "./Conversation";
6
- import { NewConversation } from "./NewConversation";
7
-
8
- interface Props {
9
- contentType: string;
10
- contentId: string;
11
- groupId: string;
12
- context: UserContextInterface;
13
- }
14
-
15
- export function Conversations(props: Props) {
16
-
17
- const [conversations, setConversations] = React.useState<ConversationInterface[]>(null)
18
- //const [editMessageId, setEditMessageId] = React.useState(null)
19
-
20
- const loadConversations = async () => {
21
- const conversations: ConversationInterface[] = (props.contentId) ? await ApiHelper.get("/conversations/" + props.contentType + "/" + props.contentId, "MessagingApi") : [];
22
- if (conversations.length > 0) {
23
- const peopleIds: string[] = [];
24
- conversations.forEach(c => {
25
- c.messages.forEach(m => {
26
- if (peopleIds.indexOf(m.personId) === -1) peopleIds.push(m.personId);
27
- });
28
- })
29
- const people = await ApiHelper.get("/people/ids?ids=" + peopleIds.join(","), "MembershipApi");
30
- conversations.forEach(c => {
31
- c.messages.forEach(m => {
32
- m.person = ArrayHelper.getOne(people, "id", m.personId);
33
- });
34
- })
35
- }
36
- setConversations(conversations);
37
- //setEditMessageId(null);
38
- };
39
-
40
- const getConversations = () => {
41
- if (conversations.length === 0) return <></>
42
- else {
43
- let noteArray: React.ReactNode[] = [];
44
- for (let i = 0; i < conversations.length; i++) noteArray.push(<Conversation context={props.context} conversation={conversations[i]} key={conversations[i].id} />);
45
- return noteArray;
46
- }
47
- }
48
-
49
- React.useEffect(() => { loadConversations() }, [props.contentId]); //eslint-disable-line
50
-
51
- if (!conversations) return <Loading />
52
- else return (
53
- <>
54
- <NewConversation context={props.context} contentType={props.contentType} contentId={props.contentId} onUpdate={loadConversations} groupId={props.groupId} visibility="public" />
55
- {getConversations()}
56
- </>
57
- );
58
- };
1
+ import React from "react";
2
+ import { Loading } from "../";
3
+ import { ApiHelper, ArrayHelper } from "../../helpers";
4
+ import { ConversationInterface, UserContextInterface } from "../../interfaces";
5
+ import { Conversation } from "./Conversation";
6
+ import { NewConversation } from "./NewConversation";
7
+
8
+ interface Props {
9
+ contentType: string;
10
+ contentId: string;
11
+ groupId: string;
12
+ context: UserContextInterface;
13
+ }
14
+
15
+ export function Conversations(props: Props) {
16
+
17
+ const [conversations, setConversations] = React.useState<ConversationInterface[]>(null)
18
+ //const [editMessageId, setEditMessageId] = React.useState(null)
19
+
20
+ const loadConversations = async () => {
21
+ const conversations: ConversationInterface[] = (props.contentId) ? await ApiHelper.get("/conversations/" + props.contentType + "/" + props.contentId, "MessagingApi") : [];
22
+ if (conversations.length > 0) {
23
+ const peopleIds: string[] = [];
24
+ conversations.forEach(c => {
25
+ c.messages.forEach(m => {
26
+ if (peopleIds.indexOf(m.personId) === -1) peopleIds.push(m.personId);
27
+ });
28
+ })
29
+ const people = await ApiHelper.get("/people/ids?ids=" + peopleIds.join(","), "MembershipApi");
30
+ conversations.forEach(c => {
31
+ c.messages.forEach(m => {
32
+ m.person = ArrayHelper.getOne(people, "id", m.personId);
33
+ });
34
+ })
35
+ }
36
+ setConversations(conversations);
37
+ //setEditMessageId(null);
38
+ };
39
+
40
+ const getConversations = () => {
41
+ if (conversations.length === 0) return <></>
42
+ else {
43
+ let noteArray: React.ReactNode[] = [];
44
+ for (let i = 0; i < conversations.length; i++) noteArray.push(<Conversation context={props.context} conversation={conversations[i]} key={conversations[i].id} />);
45
+ return noteArray;
46
+ }
47
+ }
48
+
49
+ React.useEffect(() => { loadConversations() }, [props.contentId]); //eslint-disable-line
50
+
51
+ if (!conversations) return <Loading />
52
+ else return (
53
+ <>
54
+ <NewConversation context={props.context} contentType={props.contentType} contentId={props.contentId} onUpdate={loadConversations} groupId={props.groupId} visibility="public" />
55
+ {getConversations()}
56
+ </>
57
+ );
58
+ };
@@ -1,78 +1,78 @@
1
- import { Icon, Paper, Stack, TextField } from "@mui/material";
2
- import React from "react";
3
- import { ApiHelper, PersonHelper } from "../../helpers";
4
- import { ConversationInterface, MessageInterface, UserContextInterface } from "../../interfaces";
5
- import { ErrorMessages } from "../ErrorMessages";
6
- import { SmallButton } from "../SmallButton";
7
-
8
- interface Props {
9
- contentType: string;
10
- contentId: string;
11
- groupId: string;
12
- visibility: "public" | "hidden";
13
- context: UserContextInterface;
14
- onUpdate: () => void;
15
- }
16
-
17
- export function NewConversation({ context, ...props }: Props) {
18
- const [message, setMessage] = React.useState<MessageInterface>({})
19
- const [errors, setErrors] = React.useState<string[]>([]);
20
- const [isSubmitting, setIsSubmitting] = React.useState(false);
21
-
22
- const handleChange = (e: React.ChangeEvent<HTMLInputElement | HTMLSelectElement | HTMLTextAreaElement>) => {
23
- setErrors([]);
24
- const m = { ...message } as MessageInterface;
25
- m.content = e.target.value;
26
- setMessage(m);
27
- }
28
-
29
- const validate = () => {
30
- const result = [];
31
- if (!message.content.trim()) result.push("Please enter a note.");
32
- setErrors(result);
33
- return result.length === 0;
34
- }
35
-
36
- async function handleSave() {
37
- if (validate()) {
38
- setIsSubmitting(true);
39
-
40
- const conv: ConversationInterface = { contentType: props.contentType, contentId: props.contentId, title: props.contentType + " " + props.contentId + " Conversation", groupId: props.groupId, visibility: props.visibility, allowAnonymousPosts: false }
41
- const result = await ApiHelper.post("/conversations", [conv], "MessagingApi");
42
- const cId = result[0].id;
43
-
44
- const m = { ...message };
45
- m.conversationId = cId;
46
- ApiHelper.post("/messages", [m], "MessagingApi")
47
- .then(() => {
48
- props.onUpdate();
49
- const m = { ...message } as MessageInterface;
50
- m.content = "";
51
- setMessage(m);
52
- })
53
- .finally(() => { setIsSubmitting(false); });
54
-
55
- }
56
- };
57
-
58
- const image = PersonHelper.getPhotoUrl(context?.person)
59
-
60
- return (
61
- <Paper sx={{ padding: 1, marginBottom: 2 }}>
62
- <ErrorMessages errors={errors} />
63
-
64
- <Stack direction="row" spacing={1.5} style={{ marginTop: 15 }} justifyContent="end">
65
-
66
- {image ? <img src={image} alt="user" style={{ width: 60, height: 45, borderRadius: 5, marginLeft: 8 }} /> : <Icon>person</Icon>}
67
- <Stack direction="column" spacing={2} style={{ width: "100%" }} justifyContent="end">
68
- <div><b>{context?.person?.name?.display}</b></div>
69
- <TextField fullWidth name="noteText" aria-label={"Start a conversation"} placeholder="Start a conversation" multiline style={{ marginTop: 0, border: "none" }} variant="standard" onChange={handleChange} value={message.content} />
70
- </Stack>
71
- <Stack direction="column" spacing={1} justifyContent="end">
72
- <SmallButton icon="send" onClick={handleSave} disabled={isSubmitting} />
73
- </Stack>
74
- </Stack>
75
- </Paper>
76
- );
77
-
78
- };
1
+ import { Icon, Paper, Stack, TextField } from "@mui/material";
2
+ import React from "react";
3
+ import { ApiHelper, PersonHelper } from "../../helpers";
4
+ import { ConversationInterface, MessageInterface, UserContextInterface } from "../../interfaces";
5
+ import { ErrorMessages } from "../ErrorMessages";
6
+ import { SmallButton } from "../SmallButton";
7
+
8
+ interface Props {
9
+ contentType: string;
10
+ contentId: string;
11
+ groupId: string;
12
+ visibility: "public" | "hidden";
13
+ context: UserContextInterface;
14
+ onUpdate: () => void;
15
+ }
16
+
17
+ export function NewConversation({ context, ...props }: Props) {
18
+ const [message, setMessage] = React.useState<MessageInterface>({})
19
+ const [errors, setErrors] = React.useState<string[]>([]);
20
+ const [isSubmitting, setIsSubmitting] = React.useState(false);
21
+
22
+ const handleChange = (e: React.ChangeEvent<HTMLInputElement | HTMLSelectElement | HTMLTextAreaElement>) => {
23
+ setErrors([]);
24
+ const m = { ...message } as MessageInterface;
25
+ m.content = e.target.value;
26
+ setMessage(m);
27
+ }
28
+
29
+ const validate = () => {
30
+ const result = [];
31
+ if (!message.content.trim()) result.push("Please enter a note.");
32
+ setErrors(result);
33
+ return result.length === 0;
34
+ }
35
+
36
+ async function handleSave() {
37
+ if (validate()) {
38
+ setIsSubmitting(true);
39
+
40
+ const conv: ConversationInterface = { contentType: props.contentType, contentId: props.contentId, title: props.contentType + " " + props.contentId + " Conversation", groupId: props.groupId, visibility: props.visibility, allowAnonymousPosts: false }
41
+ const result = await ApiHelper.post("/conversations", [conv], "MessagingApi");
42
+ const cId = result[0].id;
43
+
44
+ const m = { ...message };
45
+ m.conversationId = cId;
46
+ ApiHelper.post("/messages", [m], "MessagingApi")
47
+ .then(() => {
48
+ props.onUpdate();
49
+ const m = { ...message } as MessageInterface;
50
+ m.content = "";
51
+ setMessage(m);
52
+ })
53
+ .finally(() => { setIsSubmitting(false); });
54
+
55
+ }
56
+ };
57
+
58
+ const image = PersonHelper.getPhotoUrl(context?.person)
59
+
60
+ return (
61
+ <Paper sx={{ padding: 1, marginBottom: 2 }}>
62
+ <ErrorMessages errors={errors} />
63
+
64
+ <Stack direction="row" spacing={1.5} style={{ marginTop: 15 }} justifyContent="end">
65
+
66
+ {image ? <img src={image} alt="user" style={{ width: 60, height: 45, borderRadius: 5, marginLeft: 8 }} /> : <Icon>person</Icon>}
67
+ <Stack direction="column" spacing={2} style={{ width: "100%" }} justifyContent="end">
68
+ <div><b>{context?.person?.name?.display}</b></div>
69
+ <TextField fullWidth name="noteText" aria-label={"Start a conversation"} placeholder="Start a conversation" multiline style={{ marginTop: 0, border: "none" }} variant="standard" onChange={handleChange} value={message.content} />
70
+ </Stack>
71
+ <Stack direction="column" spacing={1} justifyContent="end">
72
+ <SmallButton icon="send" onClick={handleSave} disabled={isSubmitting} />
73
+ </Stack>
74
+ </Stack>
75
+ </Paper>
76
+ );
77
+
78
+ };
@@ -1,44 +1,44 @@
1
- import { Icon, IconButton, Stack, Box } from "@mui/material";
2
- import React, { useState, useEffect } from "react";
3
- import { DateHelper, PersonHelper } from "../../helpers"
4
- import { MessageInterface } from "../../interfaces"
5
-
6
- interface Props {
7
- message: MessageInterface;
8
- showEditNote: (noteId?: string) => void
9
- }
10
-
11
- export const Note: React.FC<Props> = (props) => {
12
- const [message, setMessage] = useState<MessageInterface>(null);
13
-
14
- useEffect(() => setMessage(props.message), [props.message]);
15
-
16
- if (message === null) return null;
17
- const photoUrl = PersonHelper.getPhotoUrl(message.person);
18
- let datePosted = new Date(message.timeUpdated || message.timeSent);
19
- const displayDuration = DateHelper.getDisplayDuration(datePosted);
20
-
21
- const isEdited = message.timeUpdated && message.timeUpdated !== message.timeSent && <>(edited)</>;
22
- const contents = message.content?.split("\n");
23
- return (
24
- <div className="note">
25
- <div className="postedBy">
26
- <img src={photoUrl} alt="avatar" />
27
- </div>
28
- <Box sx={{ width: "100%" }} className="note-contents">
29
- <Stack direction="row" justifyContent="space-between">
30
- <div>
31
- <b>{message.person?.name?.display}</b> · <span className="text-grey">{displayDuration}{isEdited}</span>
32
- {contents.map((c, i) => c ? <p key={i}>{c}</p> : <br />)}
33
- </div>
34
- <div>
35
- <IconButton aria-label="editNote" onClick={() => props.showEditNote(message.id)}>
36
- <Icon style={{ color: "#03a9f4" }}>edit</Icon>
37
- </IconButton>
38
- </div>
39
- </Stack>
40
-
41
- </Box>
42
- </div>
43
- );
44
- };
1
+ import { Icon, IconButton, Stack, Box } from "@mui/material";
2
+ import React, { useState, useEffect } from "react";
3
+ import { DateHelper, PersonHelper } from "../../helpers"
4
+ import { MessageInterface } from "../../interfaces"
5
+
6
+ interface Props {
7
+ message: MessageInterface;
8
+ showEditNote: (noteId?: string) => void
9
+ }
10
+
11
+ export const Note: React.FC<Props> = (props) => {
12
+ const [message, setMessage] = useState<MessageInterface>(null);
13
+
14
+ useEffect(() => setMessage(props.message), [props.message]);
15
+
16
+ if (message === null) return null;
17
+ const photoUrl = PersonHelper.getPhotoUrl(message.person);
18
+ let datePosted = new Date(message.timeUpdated || message.timeSent);
19
+ const displayDuration = DateHelper.getDisplayDuration(datePosted);
20
+
21
+ const isEdited = message.timeUpdated && message.timeUpdated !== message.timeSent && <>(edited)</>;
22
+ const contents = message.content?.split("\n");
23
+ return (
24
+ <div className="note">
25
+ <div className="postedBy">
26
+ <img src={photoUrl} alt="avatar" />
27
+ </div>
28
+ <Box sx={{ width: "100%" }} className="note-contents">
29
+ <Stack direction="row" justifyContent="space-between">
30
+ <div>
31
+ <b>{message.person?.name?.display}</b> · <span className="text-grey">{displayDuration}{isEdited}</span>
32
+ {contents.map((c, i) => c ? <p key={i}>{c}</p> : <br />)}
33
+ </div>
34
+ <div>
35
+ <IconButton aria-label="editNote" onClick={() => props.showEditNote(message.id)}>
36
+ <Icon style={{ color: "#03a9f4" }}>edit</Icon>
37
+ </IconButton>
38
+ </div>
39
+ </Stack>
40
+
41
+ </Box>
42
+ </div>
43
+ );
44
+ };
@@ -1,52 +1,52 @@
1
- import React from "react";
2
- import { Note } from "./Note";
3
- import { AddNote } from "./AddNote";
4
- import { DisplayBox, Loading } from "../";
5
- import { ApiHelper, ArrayHelper } from "../../helpers";
6
- import { MessageInterface, UserContextInterface } from "../../interfaces";
7
-
8
- interface Props {
9
- //showEditNote: (messageId?: string) => void;
10
- conversationId: string;
11
- createConversation?: () => Promise<string>;
12
- noDisplayBox?: boolean;
13
- context: UserContextInterface;
14
- }
15
-
16
- export function Notes(props: Props) {
17
-
18
- const [messages, setMessages] = React.useState<MessageInterface[]>(null)
19
- const [editMessageId, setEditMessageId] = React.useState(null)
20
-
21
- const loadNotes = async () => {
22
- const messages: MessageInterface[] = (props.conversationId) ? await ApiHelper.get("/messages/conversation/" + props.conversationId, "MessagingApi") : [];
23
- if (messages.length > 0) {
24
- const peopleIds = ArrayHelper.getIds(messages, "personId");
25
- const people = await ApiHelper.get("/people/ids?ids=" + peopleIds.join(","), "MembershipApi");
26
- messages.forEach(n => {
27
- n.person = ArrayHelper.getOne(people, "id", n.personId);
28
- })
29
- }
30
- setMessages(messages);
31
- setEditMessageId(null);
32
- };
33
-
34
- const getNotes = () => {
35
- if (!messages) return <Loading />
36
- if (messages.length === 0) return <></>
37
- else {
38
- let noteArray: React.ReactNode[] = [];
39
- for (let i = 0; i < messages.length; i++) noteArray.push(<Note message={messages[i]} key={messages[i].id} showEditNote={setEditMessageId} />);
40
- return noteArray;
41
- }
42
- }
43
-
44
- React.useEffect(() => { loadNotes() }, [props.conversationId]); //eslint-disable-line
45
-
46
- let result = <>
47
- {getNotes()}
48
- {messages && (<AddNote context={props.context} conversationId={props.conversationId} onUpdate={loadNotes} createConversation={props.createConversation} messageId={editMessageId} />)}
49
- </>
50
- if (props.noDisplayBox) return result;
51
- else return (<DisplayBox id="notesBox" data-cy="notes-box" headerIcon="sticky_note_2" headerText="Notes">{result}</DisplayBox>);
52
- };
1
+ import React from "react";
2
+ import { Note } from "./Note";
3
+ import { AddNote } from "./AddNote";
4
+ import { DisplayBox, Loading } from "../";
5
+ import { ApiHelper, ArrayHelper } from "../../helpers";
6
+ import { MessageInterface, UserContextInterface } from "../../interfaces";
7
+
8
+ interface Props {
9
+ //showEditNote: (messageId?: string) => void;
10
+ conversationId: string;
11
+ createConversation?: () => Promise<string>;
12
+ noDisplayBox?: boolean;
13
+ context: UserContextInterface;
14
+ }
15
+
16
+ export function Notes(props: Props) {
17
+
18
+ const [messages, setMessages] = React.useState<MessageInterface[]>(null)
19
+ const [editMessageId, setEditMessageId] = React.useState(null)
20
+
21
+ const loadNotes = async () => {
22
+ const messages: MessageInterface[] = (props.conversationId) ? await ApiHelper.get("/messages/conversation/" + props.conversationId, "MessagingApi") : [];
23
+ if (messages.length > 0) {
24
+ const peopleIds = ArrayHelper.getIds(messages, "personId");
25
+ const people = await ApiHelper.get("/people/ids?ids=" + peopleIds.join(","), "MembershipApi");
26
+ messages.forEach(n => {
27
+ n.person = ArrayHelper.getOne(people, "id", n.personId);
28
+ })
29
+ }
30
+ setMessages(messages);
31
+ setEditMessageId(null);
32
+ };
33
+
34
+ const getNotes = () => {
35
+ if (!messages) return <Loading />
36
+ if (messages.length === 0) return <></>
37
+ else {
38
+ let noteArray: React.ReactNode[] = [];
39
+ for (let i = 0; i < messages.length; i++) noteArray.push(<Note message={messages[i]} key={messages[i].id} showEditNote={setEditMessageId} />);
40
+ return noteArray;
41
+ }
42
+ }
43
+
44
+ React.useEffect(() => { loadNotes() }, [props.conversationId]); //eslint-disable-line
45
+
46
+ let result = <>
47
+ {getNotes()}
48
+ {messages && (<AddNote context={props.context} conversationId={props.conversationId} onUpdate={loadNotes} createConversation={props.createConversation} messageId={editMessageId} />)}
49
+ </>
50
+ if (props.noDisplayBox) return result;
51
+ else return (<DisplayBox id="notesBox" data-cy="notes-box" headerIcon="sticky_note_2" headerText="Notes">{result}</DisplayBox>);
52
+ };
@@ -1,5 +1,5 @@
1
- export { Notes } from "./Notes";
2
- export { Note } from "./Note";
3
- export { Conversation } from "./Conversation";
4
- export { Conversations } from "./Conversations";
5
- export { AddNote } from "./AddNote";
1
+ export { Notes } from "./Notes";
2
+ export { Note } from "./Note";
3
+ export { Conversation } from "./Conversation";
4
+ export { Conversations } from "./Conversations";
5
+ export { AddNote } from "./AddNote";