@churchapps/apphelper 0.0.10 → 0.0.11

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 (190) 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/markdownEditor/editor.css +787 -787
  6. package/dist/components/markdownEditor/images/icons/arrow-clockwise.svg +3 -3
  7. package/dist/components/markdownEditor/images/icons/arrow-counterclockwise.svg +3 -3
  8. package/dist/components/markdownEditor/images/icons/chat-square-quote.svg +3 -3
  9. package/dist/components/markdownEditor/images/icons/chevron-down.svg +2 -2
  10. package/dist/components/markdownEditor/images/icons/code.svg +2 -2
  11. package/dist/components/markdownEditor/images/icons/journal-code.svg +4 -4
  12. package/dist/components/markdownEditor/images/icons/journal-text.svg +4 -4
  13. package/dist/components/markdownEditor/images/icons/justify.svg +2 -2
  14. package/dist/components/markdownEditor/images/icons/link.svg +3 -3
  15. package/dist/components/markdownEditor/images/icons/list-ol.svg +3 -3
  16. package/dist/components/markdownEditor/images/icons/list-ul.svg +2 -2
  17. package/dist/components/markdownEditor/images/icons/pencil-fill.svg +2 -2
  18. package/dist/components/markdownEditor/images/icons/text-center.svg +2 -2
  19. package/dist/components/markdownEditor/images/icons/text-left.svg +2 -2
  20. package/dist/components/markdownEditor/images/icons/text-paragraph.svg +2 -2
  21. package/dist/components/markdownEditor/images/icons/text-right.svg +2 -2
  22. package/dist/components/markdownEditor/images/icons/type-bold.svg +2 -2
  23. package/dist/components/markdownEditor/images/icons/type-h1.svg +2 -2
  24. package/dist/components/markdownEditor/images/icons/type-h2.svg +2 -2
  25. package/dist/components/markdownEditor/images/icons/type-h3.svg +2 -2
  26. package/dist/components/markdownEditor/images/icons/type-h4.svg +12 -12
  27. package/dist/components/markdownEditor/images/icons/type-italic.svg +2 -2
  28. package/dist/components/markdownEditor/images/icons/type-strikethrough.svg +2 -2
  29. package/dist/components/markdownEditor/images/icons/type-underline.svg +2 -2
  30. package/dist/components/material/SiteWrapper.js +2 -2
  31. package/dist/components/material/SiteWrapper.js.map +1 -1
  32. package/dist/helpers/SocketHelper.d.ts +3 -3
  33. package/dist/helpers/SocketHelper.d.ts.map +1 -1
  34. package/dist/helpers/SocketHelper.js +6 -6
  35. package/dist/helpers/SocketHelper.js.map +1 -1
  36. package/dist/interfaces/Messaging.d.ts +1 -2
  37. package/dist/interfaces/Messaging.d.ts.map +1 -1
  38. package/package.json +84 -84
  39. package/src/components/CreatePerson.tsx +80 -80
  40. package/src/components/DisplayBox.tsx +68 -68
  41. package/src/components/ErrorMessages.tsx +26 -26
  42. package/src/components/ExportLink.tsx +67 -67
  43. package/src/components/FloatingSupport.tsx +16 -16
  44. package/src/components/FormSubmissionEdit.tsx +120 -120
  45. package/src/components/HelpIcon.tsx +10 -10
  46. package/src/components/ImageEditor.tsx +126 -126
  47. package/src/components/InputBox.tsx +73 -73
  48. package/src/components/Loading.tsx +29 -29
  49. package/src/components/PersonAdd.tsx +75 -75
  50. package/src/components/QuestionEdit.tsx +62 -62
  51. package/src/components/SmallButton.tsx +39 -39
  52. package/src/components/SupportModal.tsx +26 -26
  53. package/src/components/TabPanel.tsx +34 -34
  54. package/src/components/gallery/GalleryModal.tsx +102 -102
  55. package/src/components/gallery/StockPhotos.tsx +74 -74
  56. package/src/components/gallery/index.ts +1 -1
  57. package/src/components/index.tsx +23 -23
  58. package/src/components/markdownEditor/Editor.tsx +132 -132
  59. package/src/components/markdownEditor/MarkdownEditor.tsx +16 -16
  60. package/src/components/markdownEditor/MarkdownModal.tsx +46 -46
  61. package/src/components/markdownEditor/MarkdownPreview.tsx +14 -14
  62. package/src/components/markdownEditor/editor.css +787 -787
  63. package/src/components/markdownEditor/images/icons/arrow-clockwise.svg +3 -3
  64. package/src/components/markdownEditor/images/icons/arrow-counterclockwise.svg +3 -3
  65. package/src/components/markdownEditor/images/icons/chat-square-quote.svg +3 -3
  66. package/src/components/markdownEditor/images/icons/chevron-down.svg +2 -2
  67. package/src/components/markdownEditor/images/icons/code.svg +2 -2
  68. package/src/components/markdownEditor/images/icons/journal-code.svg +4 -4
  69. package/src/components/markdownEditor/images/icons/journal-text.svg +4 -4
  70. package/src/components/markdownEditor/images/icons/justify.svg +2 -2
  71. package/src/components/markdownEditor/images/icons/link.svg +3 -3
  72. package/src/components/markdownEditor/images/icons/list-ol.svg +3 -3
  73. package/src/components/markdownEditor/images/icons/list-ul.svg +2 -2
  74. package/src/components/markdownEditor/images/icons/pencil-fill.svg +2 -2
  75. package/src/components/markdownEditor/images/icons/text-center.svg +2 -2
  76. package/src/components/markdownEditor/images/icons/text-left.svg +2 -2
  77. package/src/components/markdownEditor/images/icons/text-paragraph.svg +2 -2
  78. package/src/components/markdownEditor/images/icons/text-right.svg +2 -2
  79. package/src/components/markdownEditor/images/icons/type-bold.svg +2 -2
  80. package/src/components/markdownEditor/images/icons/type-h1.svg +2 -2
  81. package/src/components/markdownEditor/images/icons/type-h2.svg +2 -2
  82. package/src/components/markdownEditor/images/icons/type-h3.svg +2 -2
  83. package/src/components/markdownEditor/images/icons/type-h4.svg +12 -12
  84. package/src/components/markdownEditor/images/icons/type-italic.svg +2 -2
  85. package/src/components/markdownEditor/images/icons/type-strikethrough.svg +2 -2
  86. package/src/components/markdownEditor/images/icons/type-underline.svg +2 -2
  87. package/src/components/markdownEditor/index.ts +2 -2
  88. package/src/components/markdownEditor/plugins/AutoLinkPlugin.tsx +35 -35
  89. package/src/components/markdownEditor/plugins/ControlledEditorPlugin.tsx +24 -24
  90. package/src/components/markdownEditor/plugins/ListMaxIndentLevelPlugin.tsx +68 -68
  91. package/src/components/markdownEditor/plugins/MarkdownTransformers.ts +106 -106
  92. package/src/components/markdownEditor/plugins/ReadOnlyPlugin.tsx +15 -15
  93. package/src/components/markdownEditor/plugins/ToolbarPlugin.tsx +401 -401
  94. package/src/components/markdownEditor/plugins/customLink/CustomLinkNode.tsx +224 -224
  95. package/src/components/markdownEditor/plugins/customLink/CustomLinkNodePlugin.tsx +32 -32
  96. package/src/components/markdownEditor/plugins/customLink/CustomLinkNodeTransformer.tsx +102 -102
  97. package/src/components/markdownEditor/plugins/customLink/FloatingLinkEditor.tsx +243 -243
  98. package/src/components/markdownEditor/plugins/customLink/FloatingLinkEditor.types.ts +11 -11
  99. package/src/components/markdownEditor/plugins/emoji/EmojiNode.tsx +95 -95
  100. package/src/components/markdownEditor/plugins/emoji/EmojiNodeTransform.ts +41 -41
  101. package/src/components/markdownEditor/plugins/emoji/EmojiPickerPlugin.tsx +152 -152
  102. package/src/components/markdownEditor/plugins/emoji/EmojisPlugin.tsx +65 -65
  103. package/src/components/markdownEditor/plugins/index.ts +6 -6
  104. package/src/components/markdownEditor/theme.ts +65 -65
  105. package/src/components/material/AppList.tsx +20 -20
  106. package/src/components/material/ChurchList.tsx +22 -22
  107. package/src/components/material/NavItem.tsx +41 -41
  108. package/src/components/material/NewPrivateMessage.tsx +103 -103
  109. package/src/components/material/PrivateMessageDetails.tsx +23 -23
  110. package/src/components/material/PrivateMessages.tsx +87 -87
  111. package/src/components/material/SiteWrapper.tsx +140 -140
  112. package/src/components/material/UserMenu.tsx +141 -141
  113. package/src/components/material/iconPicker/IconNamesList.ts +2240 -2240
  114. package/src/components/material/iconPicker/IconPicker.tsx +153 -153
  115. package/src/components/material/index.tsx +6 -6
  116. package/src/components/notes/AddNote.tsx +90 -90
  117. package/src/components/notes/Conversation.tsx +82 -82
  118. package/src/components/notes/Conversations.tsx +58 -58
  119. package/src/components/notes/NewConversation.tsx +78 -78
  120. package/src/components/notes/Note.tsx +44 -44
  121. package/src/components/notes/Notes.tsx +52 -52
  122. package/src/components/notes/index.ts +5 -5
  123. package/src/components/reporting/ChartReport.tsx +98 -98
  124. package/src/components/reporting/ReportFilter.tsx +54 -54
  125. package/src/components/reporting/ReportFilterField.tsx +160 -160
  126. package/src/components/reporting/ReportOutput.tsx +79 -79
  127. package/src/components/reporting/ReportWithFilter.tsx +70 -70
  128. package/src/components/reporting/TableReport.tsx +57 -57
  129. package/src/components/reporting/TreeReport.tsx +111 -111
  130. package/src/components/reporting/index.ts +4 -4
  131. package/src/donationComponents/DonationPage.tsx +136 -136
  132. package/src/donationComponents/components/BankForm.tsx +159 -159
  133. package/src/donationComponents/components/CardForm.tsx +104 -104
  134. package/src/donationComponents/components/DonationForm.tsx +235 -235
  135. package/src/donationComponents/components/FundDonation.tsx +49 -49
  136. package/src/donationComponents/components/FundDonations.tsx +39 -39
  137. package/src/donationComponents/components/NonAuthDonation.tsx +31 -31
  138. package/src/donationComponents/components/NonAuthDonationInner.tsx +259 -259
  139. package/src/donationComponents/components/PaymentMethods.tsx +135 -135
  140. package/src/donationComponents/components/RecurringDonations.tsx +121 -121
  141. package/src/donationComponents/components/RecurringDonationsEdit.tsx +93 -93
  142. package/src/donationComponents/components/index.tsx +9 -9
  143. package/src/donationComponents/index.ts +3 -3
  144. package/src/donationComponents/modals/DonationPreviewModal.tsx +66 -66
  145. package/src/helpers/AnalyticsHelper.ts +33 -33
  146. package/src/helpers/ApiHelper.ts +125 -125
  147. package/src/helpers/AppearanceHelper.ts +69 -69
  148. package/src/helpers/ArrayHelper.ts +81 -81
  149. package/src/helpers/CommonEnvironmentHelper.ts +80 -80
  150. package/src/helpers/CurrencyHelper.ts +10 -10
  151. package/src/helpers/DateHelper.ts +108 -108
  152. package/src/helpers/DonationHelper.ts +26 -26
  153. package/src/helpers/ErrorHelper.ts +36 -36
  154. package/src/helpers/EventHelper.ts +52 -52
  155. package/src/helpers/FileHelper.ts +31 -31
  156. package/src/helpers/PersonHelper.ts +60 -60
  157. package/src/helpers/SocketHelper.ts +76 -76
  158. package/src/helpers/Themes.ts +14 -14
  159. package/src/helpers/UniqueIdHelper.ts +36 -36
  160. package/src/helpers/UserHelper.ts +59 -59
  161. package/src/helpers/createEmotionCache.ts +17 -17
  162. package/src/helpers/index.ts +18 -18
  163. package/src/hooks/index.ts +1 -1
  164. package/src/hooks/useMountedState.ts +16 -16
  165. package/src/index.ts +6 -6
  166. package/src/interfaces/Access.ts +24 -24
  167. package/src/interfaces/Attendance.ts +8 -8
  168. package/src/interfaces/Content.ts +10 -10
  169. package/src/interfaces/Doing.ts +24 -24
  170. package/src/interfaces/Donation.ts +45 -45
  171. package/src/interfaces/Error.ts +17 -17
  172. package/src/interfaces/Membership.ts +51 -51
  173. package/src/interfaces/Messaging.ts +20 -20
  174. package/src/interfaces/Permissions.ts +68 -68
  175. package/src/interfaces/Reporting.ts +7 -7
  176. package/src/interfaces/UserContextInterface.ts +13 -13
  177. package/src/interfaces/index.ts +13 -13
  178. package/src/pageComponents/LoginPage.tsx +244 -244
  179. package/src/pageComponents/LogoutPage.tsx +28 -28
  180. package/src/pageComponents/components/Forgot.tsx +79 -79
  181. package/src/pageComponents/components/Login.tsx +54 -54
  182. package/src/pageComponents/components/LoginSetPassword.tsx +63 -63
  183. package/src/pageComponents/components/Register.tsx +107 -107
  184. package/src/pageComponents/components/SelectChurchModal.tsx +41 -41
  185. package/src/pageComponents/components/SelectChurchRegister.tsx +88 -88
  186. package/src/pageComponents/components/SelectChurchSearch.tsx +69 -69
  187. package/src/pageComponents/components/SelectableChurch.tsx +38 -38
  188. package/src/pageComponents/index.ts +3 -3
  189. package/tsconfig.json +34 -34
  190. package/tslint.json +14 -14
@@ -1,153 +1,153 @@
1
- import * as React from "react";
2
- import { styled, Icon, InputBase, Typography, debounce, Grid, IconButton, Pagination, Stack } from "@mui/material";
3
- import MuiPaper from "@mui/material/Paper";
4
- import IconNamesList from "./IconNamesList"
5
-
6
- const UPDATE_SEARCH_INDEX_WAIT_MS = 220;
7
-
8
- const FlexSearch = require("flexsearch");
9
- const StyledIconSpan = styled("span")(({ theme }) => ({
10
- display: "inline-flex",
11
- flexDirection: "column",
12
- color: theme.palette.text.secondary,
13
- margin: "0 4px",
14
- "& > div": {
15
- display: "flex"
16
- },
17
- "& > div > *": {
18
- flexGrow: 1,
19
- fontSize: ".6rem",
20
- overflow: "hidden",
21
- textOverflow: "ellipsis",
22
- textAlign: "center",
23
- width: 0
24
- }
25
- }));
26
-
27
- const StyledIcon: any = styled(Icon)(({ theme }) => ({
28
- boxSizing: "content-box",
29
- cursor: "pointer",
30
- color: theme.palette.text.primary,
31
- borderRadius: theme.shape.borderRadius,
32
- transition: theme.transitions.create(["background-color", "box-shadow"], {
33
- duration: theme.transitions.duration.shortest
34
- }),
35
- padding: theme.spacing(1),
36
- margin: theme.spacing(0.5, 0),
37
- "&:hover": {
38
- backgroundColor: theme.palette.background.paper,
39
- boxShadow: theme.shadows[1]
40
- }
41
- }));
42
-
43
- const Icons = React.memo(function Icons(props: { icons: string[]; handleOpenClick: (name: string) => void; }) {
44
- const { icons, handleOpenClick } = props;
45
-
46
- const handleIconClick = (name: string) => {
47
- const camel = name.substring(0, 1).toLocaleLowerCase() + name.substring(1, name.length);
48
- const underscored = camel.replace(/[A-Z]/g, m => "_" + m.toLowerCase());
49
- handleOpenClick(underscored)
50
- }
51
-
52
- return (
53
- <div>
54
- {icons.map((icon) => (
55
- <StyledIconSpan key={icon}>
56
- <StyledIcon tabIndex={-1} sx={{ fontSize: "34px !important" }} onClick={() => { handleIconClick(icon) }}>
57
- {icon}
58
- </StyledIcon>
59
- </StyledIconSpan>
60
- ))}
61
- </div>
62
- );
63
- });
64
-
65
- const Paper = styled(MuiPaper)(({ theme }) => ({ padding: "2px 4px", display: "flex", alignItems: "center", marginBottom: theme.spacing(2), width: "100%" }));
66
-
67
- const Input = styled(InputBase)({ marginLeft: 8, flex: 1 });
68
-
69
- const searchIndex = new FlexSearch.Index({ tokenize: "full" });
70
-
71
- function createSearchIndex() {
72
- // create component names from icons list
73
- const iconsAndComponentNames = IconNamesList.map(icon => {
74
- const split = icon.split("_");
75
- const capitalizedSplit = split.map(s => {
76
- if (isAlphabet(s[0])) {
77
- s = s[0].toUpperCase() + s.slice(1)
78
- }
79
- return s
80
- })
81
- return {
82
- iconName: icon,
83
- componentName: capitalizedSplit.join("")
84
- };
85
- })
86
-
87
- // create search index
88
- iconsAndComponentNames.forEach(icon => {
89
- let searchTerm = icon.iconName + " " + icon.componentName;
90
-
91
- searchIndex.addAsync(icon.iconName, searchTerm)
92
- })
93
-
94
- }
95
-
96
- function isAlphabet(character: string) {
97
- return /[a-zA-Z]/.test(character);
98
- }
99
-
100
- createSearchIndex();
101
-
102
- type Props = {
103
- onSelect: (iconName: string) => void;
104
- };
105
-
106
- const defaultIcons = ["person", "group", "groups", "contact_mail", "mail", "church", "favorite", "volunteer_activism", "link", "home", "apps", "web", "public", "rss_feed", "videocam", "live_tv", "music_note", "menu_book", "star", "accessible", "woman", "man", "child_care", "handshake", "location_on", "restaurant", "local_cafe" ];
107
-
108
- export function IconPicker(props: Props) {
109
- const pageSize = 27;
110
- const [keys, setKeys] = React.useState<any[] | null>(null);
111
- const [query, setQuery] = React.useState("");
112
- const [page, setPage] = React.useState(1);
113
-
114
- const updateSearchResults = React.useMemo(
115
- () =>
116
- debounce((value) => {
117
- if (value === "") setKeys(defaultIcons);
118
- else searchIndex.searchAsync(value, { limit: 3000 }).then((results: any) => { setKeys(results); setPage(1); });
119
- }, UPDATE_SEARCH_INDEX_WAIT_MS),
120
- []
121
- );
122
-
123
- React.useEffect(() => { updateSearchResults(query); return () => { updateSearchResults.clear(); }; }, [query, updateSearchResults]);
124
-
125
- function paged<T>(array: Array<T>, p: number) {
126
- return array.slice((p - 1) * pageSize, p * pageSize);
127
- }
128
-
129
- const icons = keys || IconNamesList;
130
-
131
- const pagesCount = Math.ceil(icons.length / pageSize);
132
-
133
- return (
134
- <Grid container sx={{ minHeight: 360, padding: "16px" }}>
135
- <Grid item>
136
- <Paper>
137
- <IconButton sx={{ padding: "10px" }} aria-label="search">
138
- <Icon>search</Icon>
139
- </IconButton>
140
- <Input autoFocus value={query} onChange={(event) => setQuery(event.target.value)} placeholder="Search icons…" inputProps={{ "aria-label": "search icons" }} />
141
- </Paper>
142
- {(query === "") && <Typography sx={{ mb: 1 }}>{`${IconNamesList.length} icons available`}</Typography>}
143
- {(query !== "") && <Typography sx={{ mb: 1 }}>{`${icons.length} matching results`}</Typography>}
144
-
145
- <Icons icons={paged(icons, page)} handleOpenClick={props.onSelect} />
146
- </Grid>
147
-
148
- <Stack spacing={2} sx={{ margin: "0 auto" }}>
149
- <Pagination count={pagesCount} page={page} onChange={(_, p) => setPage(p)} size="small" />
150
- </Stack>
151
- </Grid>
152
- );
153
- }
1
+ import * as React from "react";
2
+ import { styled, Icon, InputBase, Typography, debounce, Grid, IconButton, Pagination, Stack } from "@mui/material";
3
+ import MuiPaper from "@mui/material/Paper";
4
+ import IconNamesList from "./IconNamesList"
5
+
6
+ const UPDATE_SEARCH_INDEX_WAIT_MS = 220;
7
+
8
+ const FlexSearch = require("flexsearch");
9
+ const StyledIconSpan = styled("span")(({ theme }) => ({
10
+ display: "inline-flex",
11
+ flexDirection: "column",
12
+ color: theme.palette.text.secondary,
13
+ margin: "0 4px",
14
+ "& > div": {
15
+ display: "flex"
16
+ },
17
+ "& > div > *": {
18
+ flexGrow: 1,
19
+ fontSize: ".6rem",
20
+ overflow: "hidden",
21
+ textOverflow: "ellipsis",
22
+ textAlign: "center",
23
+ width: 0
24
+ }
25
+ }));
26
+
27
+ const StyledIcon: any = styled(Icon)(({ theme }) => ({
28
+ boxSizing: "content-box",
29
+ cursor: "pointer",
30
+ color: theme.palette.text.primary,
31
+ borderRadius: theme.shape.borderRadius,
32
+ transition: theme.transitions.create(["background-color", "box-shadow"], {
33
+ duration: theme.transitions.duration.shortest
34
+ }),
35
+ padding: theme.spacing(1),
36
+ margin: theme.spacing(0.5, 0),
37
+ "&:hover": {
38
+ backgroundColor: theme.palette.background.paper,
39
+ boxShadow: theme.shadows[1]
40
+ }
41
+ }));
42
+
43
+ const Icons = React.memo(function Icons(props: { icons: string[]; handleOpenClick: (name: string) => void; }) {
44
+ const { icons, handleOpenClick } = props;
45
+
46
+ const handleIconClick = (name: string) => {
47
+ const camel = name.substring(0, 1).toLocaleLowerCase() + name.substring(1, name.length);
48
+ const underscored = camel.replace(/[A-Z]/g, m => "_" + m.toLowerCase());
49
+ handleOpenClick(underscored)
50
+ }
51
+
52
+ return (
53
+ <div>
54
+ {icons.map((icon) => (
55
+ <StyledIconSpan key={icon}>
56
+ <StyledIcon tabIndex={-1} sx={{ fontSize: "34px !important" }} onClick={() => { handleIconClick(icon) }}>
57
+ {icon}
58
+ </StyledIcon>
59
+ </StyledIconSpan>
60
+ ))}
61
+ </div>
62
+ );
63
+ });
64
+
65
+ const Paper = styled(MuiPaper)(({ theme }) => ({ padding: "2px 4px", display: "flex", alignItems: "center", marginBottom: theme.spacing(2), width: "100%" }));
66
+
67
+ const Input = styled(InputBase)({ marginLeft: 8, flex: 1 });
68
+
69
+ const searchIndex = new FlexSearch.Index({ tokenize: "full" });
70
+
71
+ function createSearchIndex() {
72
+ // create component names from icons list
73
+ const iconsAndComponentNames = IconNamesList.map(icon => {
74
+ const split = icon.split("_");
75
+ const capitalizedSplit = split.map(s => {
76
+ if (isAlphabet(s[0])) {
77
+ s = s[0].toUpperCase() + s.slice(1)
78
+ }
79
+ return s
80
+ })
81
+ return {
82
+ iconName: icon,
83
+ componentName: capitalizedSplit.join("")
84
+ };
85
+ })
86
+
87
+ // create search index
88
+ iconsAndComponentNames.forEach(icon => {
89
+ let searchTerm = icon.iconName + " " + icon.componentName;
90
+
91
+ searchIndex.addAsync(icon.iconName, searchTerm)
92
+ })
93
+
94
+ }
95
+
96
+ function isAlphabet(character: string) {
97
+ return /[a-zA-Z]/.test(character);
98
+ }
99
+
100
+ createSearchIndex();
101
+
102
+ type Props = {
103
+ onSelect: (iconName: string) => void;
104
+ };
105
+
106
+ const defaultIcons = ["person", "group", "groups", "contact_mail", "mail", "church", "favorite", "volunteer_activism", "link", "home", "apps", "web", "public", "rss_feed", "videocam", "live_tv", "music_note", "menu_book", "star", "accessible", "woman", "man", "child_care", "handshake", "location_on", "restaurant", "local_cafe" ];
107
+
108
+ export function IconPicker(props: Props) {
109
+ const pageSize = 27;
110
+ const [keys, setKeys] = React.useState<any[] | null>(null);
111
+ const [query, setQuery] = React.useState("");
112
+ const [page, setPage] = React.useState(1);
113
+
114
+ const updateSearchResults = React.useMemo(
115
+ () =>
116
+ debounce((value) => {
117
+ if (value === "") setKeys(defaultIcons);
118
+ else searchIndex.searchAsync(value, { limit: 3000 }).then((results: any) => { setKeys(results); setPage(1); });
119
+ }, UPDATE_SEARCH_INDEX_WAIT_MS),
120
+ []
121
+ );
122
+
123
+ React.useEffect(() => { updateSearchResults(query); return () => { updateSearchResults.clear(); }; }, [query, updateSearchResults]);
124
+
125
+ function paged<T>(array: Array<T>, p: number) {
126
+ return array.slice((p - 1) * pageSize, p * pageSize);
127
+ }
128
+
129
+ const icons = keys || IconNamesList;
130
+
131
+ const pagesCount = Math.ceil(icons.length / pageSize);
132
+
133
+ return (
134
+ <Grid container sx={{ minHeight: 360, padding: "16px" }}>
135
+ <Grid item>
136
+ <Paper>
137
+ <IconButton sx={{ padding: "10px" }} aria-label="search">
138
+ <Icon>search</Icon>
139
+ </IconButton>
140
+ <Input autoFocus value={query} onChange={(event) => setQuery(event.target.value)} placeholder="Search icons…" inputProps={{ "aria-label": "search icons" }} />
141
+ </Paper>
142
+ {(query === "") && <Typography sx={{ mb: 1 }}>{`${IconNamesList.length} icons available`}</Typography>}
143
+ {(query !== "") && <Typography sx={{ mb: 1 }}>{`${icons.length} matching results`}</Typography>}
144
+
145
+ <Icons icons={paged(icons, page)} handleOpenClick={props.onSelect} />
146
+ </Grid>
147
+
148
+ <Stack spacing={2} sx={{ margin: "0 auto" }}>
149
+ <Pagination count={pagesCount} page={page} onChange={(_, p) => setPage(p)} size="small" />
150
+ </Stack>
151
+ </Grid>
152
+ );
153
+ }
@@ -1,6 +1,6 @@
1
- export { NavItem } from "./NavItem";
2
- export { AppList } from "./AppList";
3
- export { SiteWrapper } from "./SiteWrapper";
4
- export { ChurchList } from "./ChurchList";
5
- export { UserMenu } from "./UserMenu";
6
- export { IconPicker } from "./iconPicker/IconPicker";
1
+ export { NavItem } from "./NavItem";
2
+ export { AppList } from "./AppList";
3
+ export { SiteWrapper } from "./SiteWrapper";
4
+ export { ChurchList } from "./ChurchList";
5
+ export { UserMenu } from "./UserMenu";
6
+ export { IconPicker } from "./iconPicker/IconPicker";
@@ -1,90 +1,90 @@
1
- import React, { useState, useEffect } from "react"
2
- import { ApiHelper, PersonHelper } from "../../helpers"
3
- import { MessageInterface, UserContextInterface } from "../../interfaces"
4
- import { Icon, Stack, TextField } from "@mui/material"
5
- import { ErrorMessages } from "../ErrorMessages"
6
- import { SmallButton } from "../SmallButton"
7
-
8
- type Props = {
9
- messageId?: string;
10
- onUpdate: () => void;
11
- createConversation: () => Promise<string>;
12
- conversationId?: string;
13
- context: UserContextInterface
14
- };
15
-
16
- export function AddNote({ context, ...props }: Props) {
17
- const [message, setMessage] = useState<MessageInterface>()
18
- const [errors, setErrors] = React.useState<string[]>([]);
19
- const [isSubmitting, setIsSubmitting] = React.useState(false);
20
- const headerText = props.messageId ? "Edit note" : "Add a note"
21
-
22
- useEffect(() => {
23
- if (props.messageId) ApiHelper.get(`/messages/${props.messageId}`, "MessagingApi").then(n => setMessage(n));
24
- else setMessage({ conversationId: props.conversationId, content: "" });
25
- return () => {
26
- setMessage(null);
27
- };
28
- }, [props.messageId, props.conversationId])
29
-
30
- const handleChange = (e: React.ChangeEvent<HTMLInputElement | HTMLSelectElement | HTMLTextAreaElement>) => {
31
- setErrors([]);
32
- const m = { ...message } as MessageInterface;
33
- m.content = e.target.value;
34
- setMessage(m);
35
- }
36
-
37
- const validate = () => {
38
- const result = [];
39
- if (!message.content.trim()) result.push("Please enter a note.");
40
- setErrors(result);
41
- return result.length === 0;
42
- }
43
-
44
- async function handleSave() {
45
- if (validate()) {
46
- setIsSubmitting(true);
47
- let cId = props.conversationId;
48
- if (!cId) cId = await props.createConversation();
49
-
50
- const m = { ...message };
51
- m.conversationId = cId;
52
- ApiHelper.post("/messages", [m], "MessagingApi")
53
- .then(() => {
54
- props.onUpdate();
55
- const m = { ...message } as MessageInterface;
56
- m.content = "";
57
- setMessage(m);
58
- })
59
- .finally(() => { setIsSubmitting(false); });
60
- }
61
- };
62
-
63
- async function deleteNote() {
64
- await ApiHelper.delete(`/messages/${props.messageId}`, "MessagingApi")
65
- props.onUpdate()
66
- }
67
-
68
- const deleteFunction = props.messageId ? deleteNote : null;
69
-
70
- const image = PersonHelper.getPhotoUrl(context?.person)
71
-
72
- return (
73
- <>
74
- <ErrorMessages errors={errors} />
75
-
76
- <Stack direction="row" spacing={1.5} style={{ marginTop: 15 }} justifyContent="end">
77
-
78
- {image ? <img src={image} alt="user" style={{ width: 60, height: 45, borderRadius: 5, marginLeft: 8 }} /> : <Icon>person</Icon>}
79
- <Stack direction="column" spacing={2} style={{ width: "100%" }} justifyContent="end">
80
- <div><b>{context?.person?.name?.display}</b></div>
81
- <TextField fullWidth name="noteText" aria-label={headerText} placeholder="Add a note" multiline style={{ marginTop: 0, border: "none" }} variant="standard" onChange={handleChange} value={message?.content} />
82
- </Stack>
83
- <Stack direction="column" spacing={1} justifyContent="end">
84
- <SmallButton icon="send" onClick={handleSave} />
85
- {deleteFunction && <SmallButton icon="delete" onClick={deleteFunction} disabled={isSubmitting} />}
86
- </Stack>
87
- </Stack>
88
- </>
89
- );
90
- }
1
+ import React, { useState, useEffect } from "react"
2
+ import { ApiHelper, PersonHelper } from "../../helpers"
3
+ import { MessageInterface, UserContextInterface } from "../../interfaces"
4
+ import { Icon, Stack, TextField } from "@mui/material"
5
+ import { ErrorMessages } from "../ErrorMessages"
6
+ import { SmallButton } from "../SmallButton"
7
+
8
+ type Props = {
9
+ messageId?: string;
10
+ onUpdate: () => void;
11
+ createConversation: () => Promise<string>;
12
+ conversationId?: string;
13
+ context: UserContextInterface
14
+ };
15
+
16
+ export function AddNote({ context, ...props }: Props) {
17
+ const [message, setMessage] = useState<MessageInterface>()
18
+ const [errors, setErrors] = React.useState<string[]>([]);
19
+ const [isSubmitting, setIsSubmitting] = React.useState(false);
20
+ const headerText = props.messageId ? "Edit note" : "Add a note"
21
+
22
+ useEffect(() => {
23
+ if (props.messageId) ApiHelper.get(`/messages/${props.messageId}`, "MessagingApi").then(n => setMessage(n));
24
+ else setMessage({ conversationId: props.conversationId, content: "" });
25
+ return () => {
26
+ setMessage(null);
27
+ };
28
+ }, [props.messageId, props.conversationId])
29
+
30
+ const handleChange = (e: React.ChangeEvent<HTMLInputElement | HTMLSelectElement | HTMLTextAreaElement>) => {
31
+ setErrors([]);
32
+ const m = { ...message } as MessageInterface;
33
+ m.content = e.target.value;
34
+ setMessage(m);
35
+ }
36
+
37
+ const validate = () => {
38
+ const result = [];
39
+ if (!message.content.trim()) result.push("Please enter a note.");
40
+ setErrors(result);
41
+ return result.length === 0;
42
+ }
43
+
44
+ async function handleSave() {
45
+ if (validate()) {
46
+ setIsSubmitting(true);
47
+ let cId = props.conversationId;
48
+ if (!cId) cId = await props.createConversation();
49
+
50
+ const m = { ...message };
51
+ m.conversationId = cId;
52
+ ApiHelper.post("/messages", [m], "MessagingApi")
53
+ .then(() => {
54
+ props.onUpdate();
55
+ const m = { ...message } as MessageInterface;
56
+ m.content = "";
57
+ setMessage(m);
58
+ })
59
+ .finally(() => { setIsSubmitting(false); });
60
+ }
61
+ };
62
+
63
+ async function deleteNote() {
64
+ await ApiHelper.delete(`/messages/${props.messageId}`, "MessagingApi")
65
+ props.onUpdate()
66
+ }
67
+
68
+ const deleteFunction = props.messageId ? deleteNote : null;
69
+
70
+ const image = PersonHelper.getPhotoUrl(context?.person)
71
+
72
+ return (
73
+ <>
74
+ <ErrorMessages errors={errors} />
75
+
76
+ <Stack direction="row" spacing={1.5} style={{ marginTop: 15 }} justifyContent="end">
77
+
78
+ {image ? <img src={image} alt="user" style={{ width: 60, height: 45, borderRadius: 5, marginLeft: 8 }} /> : <Icon>person</Icon>}
79
+ <Stack direction="column" spacing={2} style={{ width: "100%" }} justifyContent="end">
80
+ <div><b>{context?.person?.name?.display}</b></div>
81
+ <TextField fullWidth name="noteText" aria-label={headerText} placeholder="Add a note" multiline style={{ marginTop: 0, border: "none" }} variant="standard" onChange={handleChange} value={message?.content} />
82
+ </Stack>
83
+ <Stack direction="column" spacing={1} justifyContent="end">
84
+ <SmallButton icon="send" onClick={handleSave} />
85
+ {deleteFunction && <SmallButton icon="delete" onClick={deleteFunction} disabled={isSubmitting} />}
86
+ </Stack>
87
+ </Stack>
88
+ </>
89
+ );
90
+ }