@drodil/backstage-plugin-qeta-react 3.3.0 → 3.4.0

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 (199) hide show
  1. package/dist/components/AnswerCard/AnswerCard.esm.js +6 -1
  2. package/dist/components/AnswerCard/AnswerCard.esm.js.map +1 -1
  3. package/dist/components/AnswerForm/AnswerForm.esm.js +5 -1
  4. package/dist/components/AnswerForm/AnswerForm.esm.js.map +1 -1
  5. package/dist/components/AnswersContainer/AnswerList.esm.js +16 -38
  6. package/dist/components/AnswersContainer/AnswerList.esm.js.map +1 -1
  7. package/dist/components/AnswersContainer/AnswerListItem.esm.js +6 -1
  8. package/dist/components/AnswersContainer/AnswerListItem.esm.js.map +1 -1
  9. package/dist/components/AnswersContainer/AnswersContainer.esm.js +5 -1
  10. package/dist/components/AnswersContainer/AnswersContainer.esm.js.map +1 -1
  11. package/dist/components/ArticleContent/ArticleButtons.esm.js +6 -1
  12. package/dist/components/ArticleContent/ArticleButtons.esm.js.map +1 -1
  13. package/dist/components/ArticleContent/ArticleContent.esm.js +7 -1
  14. package/dist/components/ArticleContent/ArticleContent.esm.js.map +1 -1
  15. package/dist/components/AuthorBox/AuthorBox.esm.js +7 -1
  16. package/dist/components/AuthorBox/AuthorBox.esm.js.map +1 -1
  17. package/dist/components/Buttons/AddToCollectionButton.esm.js +4 -1
  18. package/dist/components/Buttons/AddToCollectionButton.esm.js.map +1 -1
  19. package/dist/components/Buttons/AskQuestionButton.esm.js +5 -1
  20. package/dist/components/Buttons/AskQuestionButton.esm.js.map +1 -1
  21. package/dist/components/Buttons/BackToArticlesButton.esm.js +5 -1
  22. package/dist/components/Buttons/BackToArticlesButton.esm.js.map +1 -1
  23. package/dist/components/Buttons/BackToCollectionsButton.esm.js +5 -1
  24. package/dist/components/Buttons/BackToCollectionsButton.esm.js.map +1 -1
  25. package/dist/components/Buttons/BackToQuestionsButton.esm.js +5 -1
  26. package/dist/components/Buttons/BackToQuestionsButton.esm.js.map +1 -1
  27. package/dist/components/Buttons/CollectionFollowButton.esm.js +40 -0
  28. package/dist/components/Buttons/CollectionFollowButton.esm.js.map +1 -0
  29. package/dist/components/Buttons/CreateCollectionButton.esm.js +5 -1
  30. package/dist/components/Buttons/CreateCollectionButton.esm.js.map +1 -1
  31. package/dist/components/Buttons/EntityFollowButton.esm.js +7 -1
  32. package/dist/components/Buttons/EntityFollowButton.esm.js.map +1 -1
  33. package/dist/components/Buttons/FavoriteButton.esm.js +4 -1
  34. package/dist/components/Buttons/FavoriteButton.esm.js.map +1 -1
  35. package/dist/components/Buttons/LinkButton.esm.js +6 -1
  36. package/dist/components/Buttons/LinkButton.esm.js.map +1 -1
  37. package/dist/components/Buttons/TagFollowButton.esm.js +7 -1
  38. package/dist/components/Buttons/TagFollowButton.esm.js.map +1 -1
  39. package/dist/components/Buttons/UserFollowButton.esm.js +7 -1
  40. package/dist/components/Buttons/UserFollowButton.esm.js.map +1 -1
  41. package/dist/components/Buttons/VoteButtons.esm.js +1 -1
  42. package/dist/components/Buttons/VoteButtons.esm.js.map +1 -1
  43. package/dist/components/Buttons/WriteArticleButton.esm.js +5 -1
  44. package/dist/components/Buttons/WriteArticleButton.esm.js.map +1 -1
  45. package/dist/components/CollectionCard/CollectionCard.esm.js +7 -3
  46. package/dist/components/CollectionCard/CollectionCard.esm.js.map +1 -1
  47. package/dist/components/CollectionForm/CollectionForm.esm.js +5 -1
  48. package/dist/components/CollectionForm/CollectionForm.esm.js.map +1 -1
  49. package/dist/components/CollectionsGrid/CollectionsGrid.esm.js +57 -14
  50. package/dist/components/CollectionsGrid/CollectionsGrid.esm.js.map +1 -1
  51. package/dist/components/CollectionsGrid/CollectionsGridContent.esm.js +13 -27
  52. package/dist/components/CollectionsGrid/CollectionsGridContent.esm.js.map +1 -1
  53. package/dist/components/CollectionsGrid/CollectionsGridItem.esm.js +28 -19
  54. package/dist/components/CollectionsGrid/CollectionsGridItem.esm.js.map +1 -1
  55. package/dist/components/CommentSection/CommentList.esm.js +4 -1
  56. package/dist/components/CommentSection/CommentList.esm.js.map +1 -1
  57. package/dist/components/CommentSection/CommentSection.esm.js +4 -1
  58. package/dist/components/CommentSection/CommentSection.esm.js.map +1 -1
  59. package/dist/components/DeleteModal/DeleteModal.esm.js +5 -1
  60. package/dist/components/DeleteModal/DeleteModal.esm.js.map +1 -1
  61. package/dist/components/EntitiesGrid/EntitiesGrid.esm.js +61 -22
  62. package/dist/components/EntitiesGrid/EntitiesGrid.esm.js.map +1 -1
  63. package/dist/components/EntitiesGrid/EntitiesGridContent.esm.js +31 -0
  64. package/dist/components/EntitiesGrid/EntitiesGridContent.esm.js.map +1 -0
  65. package/dist/components/EntitiesGrid/EntitiesGridItem.esm.js +6 -1
  66. package/dist/components/EntitiesGrid/EntitiesGridItem.esm.js.map +1 -1
  67. package/dist/components/FilterPanel/DateRangeFilter.esm.js +6 -1
  68. package/dist/components/FilterPanel/DateRangeFilter.esm.js.map +1 -1
  69. package/dist/components/FilterPanel/FilterPanel.esm.js +9 -5
  70. package/dist/components/FilterPanel/FilterPanel.esm.js.map +1 -1
  71. package/dist/components/FollowedLists/FollowedCollectionsList.esm.js +49 -0
  72. package/dist/components/FollowedLists/FollowedCollectionsList.esm.js.map +1 -0
  73. package/dist/components/FollowedLists/FollowedEntitiesList.esm.js +7 -1
  74. package/dist/components/FollowedLists/FollowedEntitiesList.esm.js.map +1 -1
  75. package/dist/components/FollowedLists/FollowedTagsList.esm.js +7 -1
  76. package/dist/components/FollowedLists/FollowedTagsList.esm.js.map +1 -1
  77. package/dist/components/HeaderImageInput/HeaderImageInput.esm.js +5 -1
  78. package/dist/components/HeaderImageInput/HeaderImageInput.esm.js.map +1 -1
  79. package/dist/components/HomePageCards/ImpactCard.esm.js +6 -1
  80. package/dist/components/HomePageCards/ImpactCard.esm.js.map +1 -1
  81. package/dist/components/HomePageCards/PostsCard.esm.js +8 -3
  82. package/dist/components/HomePageCards/PostsCard.esm.js.map +1 -1
  83. package/dist/components/LeftMenu/LeftMenu.esm.js +11 -3
  84. package/dist/components/LeftMenu/LeftMenu.esm.js.map +1 -1
  85. package/dist/components/Links/Links.esm.js +5 -1
  86. package/dist/components/Links/Links.esm.js.map +1 -1
  87. package/dist/components/MarkdownEditor/MarkdownEditor.esm.js.map +1 -1
  88. package/dist/components/MarkdownRenderer/MarkdownRenderer.esm.js +1 -1
  89. package/dist/components/MarkdownRenderer/MarkdownRenderer.esm.js.map +1 -1
  90. package/dist/components/PostAnonymouslyCheckbox/PostAnonymouslyCheckbox.esm.js +6 -1
  91. package/dist/components/PostAnonymouslyCheckbox/PostAnonymouslyCheckbox.esm.js.map +1 -1
  92. package/dist/components/PostForm/EntitiesInput.esm.js +5 -1
  93. package/dist/components/PostForm/EntitiesInput.esm.js.map +1 -1
  94. package/dist/components/PostForm/PostForm.esm.js +42 -5
  95. package/dist/components/PostForm/PostForm.esm.js.map +1 -1
  96. package/dist/components/PostForm/TagInput.esm.js +5 -2
  97. package/dist/components/PostForm/TagInput.esm.js.map +1 -1
  98. package/dist/components/PostHighlightList/PostHighlightList.esm.js +5 -1
  99. package/dist/components/PostHighlightList/PostHighlightList.esm.js.map +1 -1
  100. package/dist/components/PostsContainer/NoPostsCard.esm.js +6 -1
  101. package/dist/components/PostsContainer/NoPostsCard.esm.js.map +1 -1
  102. package/dist/components/PostsContainer/PostList.esm.js +16 -38
  103. package/dist/components/PostsContainer/PostList.esm.js.map +1 -1
  104. package/dist/components/PostsContainer/PostListItem.esm.js +6 -1
  105. package/dist/components/PostsContainer/PostListItem.esm.js.map +1 -1
  106. package/dist/components/PostsContainer/PostsContainer.esm.js +6 -2
  107. package/dist/components/PostsContainer/PostsContainer.esm.js.map +1 -1
  108. package/dist/components/PostsGrid/PostsGrid.esm.js +11 -3
  109. package/dist/components/PostsGrid/PostsGrid.esm.js.map +1 -1
  110. package/dist/components/PostsGrid/PostsGridContent.esm.js +23 -12
  111. package/dist/components/PostsGrid/PostsGridContent.esm.js.map +1 -1
  112. package/dist/components/PostsGrid/PostsGridItem.esm.js +6 -1
  113. package/dist/components/PostsGrid/PostsGridItem.esm.js.map +1 -1
  114. package/dist/components/QetaPagination/QetaPagination.esm.js +55 -0
  115. package/dist/components/QetaPagination/QetaPagination.esm.js.map +1 -0
  116. package/dist/components/QuestionCard/QuestionCard.esm.js +5 -1
  117. package/dist/components/QuestionCard/QuestionCard.esm.js.map +1 -1
  118. package/dist/components/QuestionsTable/QuestionsTable.esm.js +6 -1
  119. package/dist/components/QuestionsTable/QuestionsTable.esm.js.map +1 -1
  120. package/dist/components/SelectTemplateList/SelectTemplateList.esm.js +48 -0
  121. package/dist/components/SelectTemplateList/SelectTemplateList.esm.js.map +1 -0
  122. package/dist/components/StatsChart/StatsChart.esm.js +37 -13
  123. package/dist/components/StatsChart/StatsChart.esm.js.map +1 -1
  124. package/dist/components/StatsChart/util.esm.js +9 -0
  125. package/dist/components/StatsChart/util.esm.js.map +1 -0
  126. package/dist/components/SummaryStatsGrid/SummaryStatsGrid.esm.js +25 -1
  127. package/dist/components/SummaryStatsGrid/SummaryStatsGrid.esm.js.map +1 -1
  128. package/dist/components/TagsAndEntities/CollectionChip.esm.js +85 -0
  129. package/dist/components/TagsAndEntities/CollectionChip.esm.js.map +1 -0
  130. package/dist/components/TagsAndEntities/EntityChip.esm.js +5 -1
  131. package/dist/components/TagsAndEntities/EntityChip.esm.js.map +1 -1
  132. package/dist/components/TagsAndEntities/TagChip.esm.js +5 -1
  133. package/dist/components/TagsAndEntities/TagChip.esm.js.map +1 -1
  134. package/dist/components/TagsAndEntities/TagsAndEntities.esm.js +3 -0
  135. package/dist/components/TagsAndEntities/TagsAndEntities.esm.js.map +1 -1
  136. package/dist/components/TagsGrid/EditTagModal.esm.js +4 -1
  137. package/dist/components/TagsGrid/EditTagModal.esm.js.map +1 -1
  138. package/dist/components/TagsGrid/TagGridItem.esm.js +6 -1
  139. package/dist/components/TagsGrid/TagGridItem.esm.js.map +1 -1
  140. package/dist/components/TagsGrid/TagsGrid.esm.js +64 -22
  141. package/dist/components/TagsGrid/TagsGrid.esm.js.map +1 -1
  142. package/dist/components/TagsGrid/TagsGridContent.esm.js +31 -0
  143. package/dist/components/TagsGrid/TagsGridContent.esm.js.map +1 -0
  144. package/dist/components/TemplateList/TemplateForm.esm.js +207 -0
  145. package/dist/components/TemplateList/TemplateForm.esm.js.map +1 -0
  146. package/dist/components/TemplateList/TemplateList.esm.js +105 -0
  147. package/dist/components/TemplateList/TemplateList.esm.js.map +1 -0
  148. package/dist/components/TopRankingUsersCard/TopRankingUsersCard.esm.js +6 -1
  149. package/dist/components/TopRankingUsersCard/TopRankingUsersCard.esm.js.map +1 -1
  150. package/dist/components/UsersGrid/UsersGrid.esm.js +49 -19
  151. package/dist/components/UsersGrid/UsersGrid.esm.js.map +1 -1
  152. package/dist/components/UsersGrid/UsersGridContent.esm.js +31 -0
  153. package/dist/components/UsersGrid/UsersGridContent.esm.js.map +1 -0
  154. package/dist/components/UsersGrid/UsersGridItem.esm.js +7 -1
  155. package/dist/components/UsersGrid/UsersGridItem.esm.js.map +1 -1
  156. package/dist/hooks/useBasePath.esm.js +12 -0
  157. package/dist/hooks/useBasePath.esm.js.map +1 -0
  158. package/dist/hooks/useBaseUrl.esm.js +13 -0
  159. package/dist/hooks/useBaseUrl.esm.js.map +1 -0
  160. package/dist/hooks/useCollectionsFollow.esm.js +59 -0
  161. package/dist/hooks/useCollectionsFollow.esm.js.map +1 -0
  162. package/dist/hooks/useEntityAuthor.esm.js +90 -0
  163. package/dist/hooks/useEntityAuthor.esm.js.map +1 -0
  164. package/dist/hooks/useEntityFollow.esm.js +49 -0
  165. package/dist/hooks/useEntityFollow.esm.js.map +1 -0
  166. package/dist/hooks/useEntityQueryParameter.esm.js +14 -0
  167. package/dist/hooks/useEntityQueryParameter.esm.js.map +1 -0
  168. package/dist/hooks/useFormStyles.esm.js +26 -0
  169. package/dist/hooks/useFormStyles.esm.js.map +1 -0
  170. package/dist/hooks/useIdentityApi.esm.js +12 -0
  171. package/dist/hooks/useIdentityApi.esm.js.map +1 -0
  172. package/dist/hooks/useIsDarkTheme.esm.js +12 -0
  173. package/dist/hooks/useIsDarkTheme.esm.js.map +1 -0
  174. package/dist/hooks/useIsModerator.esm.js +23 -0
  175. package/dist/hooks/useIsModerator.esm.js.map +1 -0
  176. package/dist/hooks/usePaginatedPosts.esm.js +176 -0
  177. package/dist/hooks/usePaginatedPosts.esm.js.map +1 -0
  178. package/dist/hooks/useQetaApi.esm.js +13 -0
  179. package/dist/hooks/useQetaApi.esm.js.map +1 -0
  180. package/dist/hooks/useStyles.esm.js +141 -0
  181. package/dist/hooks/useStyles.esm.js.map +1 -0
  182. package/dist/hooks/useTagsFollow.esm.js +53 -0
  183. package/dist/hooks/useTagsFollow.esm.js.map +1 -0
  184. package/dist/hooks/useTranslation.esm.js +9 -0
  185. package/dist/hooks/useTranslation.esm.js.map +1 -0
  186. package/dist/hooks/useUserFollow.esm.js +53 -0
  187. package/dist/hooks/useUserFollow.esm.js.map +1 -0
  188. package/dist/hooks/useVoting.esm.js +110 -0
  189. package/dist/hooks/useVoting.esm.js.map +1 -0
  190. package/dist/index.d.ts +402 -306
  191. package/dist/index.esm.js +14 -2
  192. package/dist/index.esm.js.map +1 -1
  193. package/dist/routes.esm.js +6 -1
  194. package/dist/routes.esm.js.map +1 -1
  195. package/dist/translation.esm.js +63 -4
  196. package/dist/translation.esm.js.map +1 -1
  197. package/package.json +5 -2
  198. package/dist/utils/hooks.esm.js +0 -701
  199. package/dist/utils/hooks.esm.js.map +0 -1
@@ -1,701 +0,0 @@
1
- import useAsync from 'react-use/lib/useAsync';
2
- import { useApi, identityApiRef, useAnalytics, appThemeApiRef, configApiRef } from '@backstage/core-plugin-api';
3
- import { makeStyles } from '@material-ui/core';
4
- import { catalogApiRef, useEntityPresentation } from '@backstage/plugin-catalog-react';
5
- import { trimEnd } from 'lodash';
6
- import { useSearchParams } from 'react-router-dom';
7
- import React, { useEffect, useMemo, useCallback, useState } from 'react';
8
- import { filterTags } from '@drodil/backstage-plugin-qeta-common';
9
- import DataLoader from 'dataloader';
10
- import { useTranslationRef } from '@backstage/core-plugin-api/alpha';
11
- import { qetaTranslationRef } from '../translation.esm.js';
12
- import { qetaApiRef } from '../api.esm.js';
13
- import { filterKeys } from '../components/FilterPanel/FilterPanel.esm.js';
14
- import useDebounce from 'react-use/lib/useDebounce';
15
- import { getFiltersWithDateRange } from './utils.esm.js';
16
- import { useSignal } from '@backstage/plugin-signals-react';
17
- import { useAsyncRetry } from 'react-use';
18
-
19
- const useTranslation = () => {
20
- return useTranslationRef(qetaTranslationRef);
21
- };
22
- const useFormStyles = makeStyles(
23
- (theme) => {
24
- return {
25
- headerImage: {
26
- marginBottom: "1rem",
27
- marginTop: "1rem",
28
- height: "250px",
29
- objectFit: "cover",
30
- width: "100%",
31
- border: `1px solid ${theme.palette.background.paper}`,
32
- boxShadow: theme.shadows[1]
33
- },
34
- postButton: {
35
- marginTop: theme.spacing(1),
36
- marginBottom: theme.spacing(1)
37
- },
38
- form: {}
39
- };
40
- },
41
- { name: "QetaForm" }
42
- );
43
- function usePaginatedPosts(props) {
44
- const { type, tags, author, entity, favorite, initialPageSize } = props;
45
- const analytics = useAnalytics();
46
- const [page, setPage] = React.useState(1);
47
- const [pageCount, setPageCount] = React.useState(1);
48
- const [postsPerPage, setPostsPerPage] = React.useState(initialPageSize ?? 10);
49
- const [showFilterPanel, setShowFilterPanel] = React.useState(false);
50
- const [searchParams, setSearchParams] = useSearchParams();
51
- const [searchQuery, setSearchQuery] = React.useState("");
52
- const [filters, setFilters] = React.useState({
53
- order: "desc",
54
- orderBy: "created",
55
- noAnswers: "false",
56
- noCorrectAnswer: "false",
57
- noVotes: "false",
58
- searchQuery: "",
59
- entity: entity ?? "",
60
- tags: tags ?? [],
61
- dateRange: "",
62
- collectionId: props.collectionId
63
- });
64
- const onPageChange = (value) => {
65
- setPage(value);
66
- setSearchParams((prev) => {
67
- const newValue = prev;
68
- newValue.set("page", String(value));
69
- return newValue;
70
- });
71
- };
72
- const loadNextPage = () => {
73
- setPage((prev) => prev + 1);
74
- };
75
- const onFilterChange = (key, value) => {
76
- if (filters[key] === value) {
77
- return;
78
- }
79
- setPage(1);
80
- setFilters({ ...filters, ...{ [key]: value } });
81
- setSearchParams((prev) => {
82
- const newValue = prev;
83
- if (!value || value === "false") {
84
- newValue.delete(key);
85
- } else if (Array.isArray(value)) {
86
- if (value.length === 0) {
87
- newValue.delete(key);
88
- } else {
89
- newValue.set(key, value.join(","));
90
- }
91
- } else if (value.length > 0) {
92
- newValue.set(key, value);
93
- } else {
94
- newValue.delete(key);
95
- }
96
- return newValue;
97
- });
98
- };
99
- const onSearchQueryChange = (event) => {
100
- onPageChange(1);
101
- if (event.target.value) {
102
- analytics.captureEvent("qeta_search", event.target.value);
103
- }
104
- setSearchQuery(event.target.value);
105
- };
106
- useDebounce(
107
- () => {
108
- if (filters.searchQuery !== searchQuery) {
109
- setFilters({ ...filters, searchQuery });
110
- }
111
- },
112
- 400,
113
- [searchQuery]
114
- );
115
- useEffect(() => {
116
- let filtersApplied = false;
117
- searchParams.forEach((value, key) => {
118
- try {
119
- if (key === "page") {
120
- const pv = Number.parseInt(value, 10);
121
- if (pv > 0) {
122
- setPage(pv);
123
- } else {
124
- setPage(1);
125
- }
126
- } else if (key === "postsPerPage") {
127
- const qpp = Number.parseInt(value, 10);
128
- if (qpp > 0) setPostsPerPage(qpp);
129
- } else if (filterKeys.includes(key)) {
130
- filtersApplied = true;
131
- if (key === "tags") {
132
- filters.tags = filterTags(value) ?? [];
133
- } else {
134
- filters[key] = value;
135
- }
136
- }
137
- } catch (_e) {
138
- }
139
- });
140
- setFilters(filters);
141
- if (filtersApplied) {
142
- setShowFilterPanel(true);
143
- }
144
- }, [searchParams, filters]);
145
- const {
146
- value: response,
147
- loading,
148
- error
149
- } = useQetaApi(
150
- (api) => {
151
- return api.getPosts({
152
- type,
153
- limit: postsPerPage,
154
- offset: (page - 1) * postsPerPage,
155
- includeEntities: true,
156
- author,
157
- favorite,
158
- ...getFiltersWithDateRange(filters)
159
- });
160
- },
161
- [type, page, filters, postsPerPage]
162
- );
163
- useEffect(() => {
164
- if (response) {
165
- setPageCount(Math.ceil(response.total / postsPerPage));
166
- }
167
- }, [response, postsPerPage]);
168
- const onPageSizeChange = (value) => {
169
- if (response) {
170
- let newPage = page;
171
- while (newPage * value > response.total) {
172
- newPage -= 1;
173
- }
174
- onPageChange(Math.max(1, newPage));
175
- }
176
- setPostsPerPage(value);
177
- setSearchParams((prev) => {
178
- const newValue = prev;
179
- newValue.set("postsPerPage", String(value));
180
- return newValue;
181
- });
182
- };
183
- return {
184
- page,
185
- setPage,
186
- postsPerPage,
187
- setPostsPerPage,
188
- showFilterPanel,
189
- setShowFilterPanel,
190
- searchParams,
191
- setSearchParams,
192
- searchQuery,
193
- setSearchQuery,
194
- filters,
195
- setFilters,
196
- onPageChange,
197
- onPageSizeChange,
198
- onFilterChange,
199
- onSearchQueryChange,
200
- response,
201
- loading,
202
- error,
203
- loadNextPage,
204
- pageCount
205
- };
206
- }
207
- function useVoting(resp) {
208
- const [entity, setEntity] = React.useState(
209
- resp
210
- );
211
- const [ownVote, setOwnVote] = React.useState(entity.ownVote ?? 0);
212
- const [correctAnswer, setCorrectAnswer] = useState(
213
- "postId" in entity ? entity.correct : false
214
- );
215
- const [score, setScore] = useState(entity.score);
216
- const analytics = useAnalytics();
217
- const qetaApi = useApi(qetaApiRef);
218
- const { t } = useTranslation();
219
- const isQuestion = "title" in entity;
220
- const own = entity.own ?? false;
221
- const { lastSignal } = useSignal(
222
- isQuestion ? `qeta:question_${entity.id}` : `qeta:answer_${entity.id}`
223
- );
224
- useEffect(() => {
225
- if (entity) {
226
- setScore(entity.score);
227
- }
228
- }, [entity]);
229
- useEffect(() => {
230
- if (lastSignal?.type === "post_stats" || lastSignal?.type === "answer_stats") {
231
- setCorrectAnswer(lastSignal.correctAnswer);
232
- setScore(lastSignal.score);
233
- }
234
- }, [lastSignal]);
235
- const voteUp = () => {
236
- if (isQuestion) {
237
- qetaApi.votePostUp(entity.id).then((response) => {
238
- setOwnVote(1);
239
- analytics.captureEvent("vote", "question", { value: 1 });
240
- setEntity(response);
241
- });
242
- } else if ("postId" in entity) {
243
- qetaApi.voteAnswerUp(entity.postId, entity.id).then((response) => {
244
- setOwnVote(1);
245
- analytics.captureEvent("vote", "answer", { value: 1 });
246
- setEntity(response);
247
- });
248
- }
249
- };
250
- const voteDown = () => {
251
- if (isQuestion) {
252
- qetaApi.votePostDown(entity.id).then((response) => {
253
- setOwnVote(-1);
254
- analytics.captureEvent("vote", "question", { value: -1 });
255
- setEntity(response);
256
- });
257
- } else if ("postId" in entity) {
258
- qetaApi.voteAnswerDown(entity.postId, entity.id).then((response) => {
259
- setOwnVote(-1);
260
- analytics.captureEvent("vote", "answer", { value: -1 });
261
- setEntity(response);
262
- });
263
- }
264
- };
265
- let correctTooltip = correctAnswer ? t("voteButtons.answer.markIncorrect") : t("voteButtons.answer.markCorrect");
266
- if (!entity?.own) {
267
- correctTooltip = correctAnswer ? t("voteButtons.answer.marked") : "";
268
- }
269
- let voteUpTooltip = isQuestion ? t("voteButtons.question.good") : t("voteButtons.answer.good");
270
- if (own) {
271
- voteUpTooltip = isQuestion ? t("voteButtons.question.own") : t("voteButtons.answer.own");
272
- }
273
- let voteDownTooltip = isQuestion ? t("voteButtons.question.bad") : t("voteButtons.answer.bad");
274
- if (own) {
275
- voteDownTooltip = voteUpTooltip;
276
- }
277
- const toggleCorrectAnswer = () => {
278
- if (!("postId" in entity)) {
279
- return;
280
- }
281
- if (correctAnswer) {
282
- qetaApi.markAnswerIncorrect(entity.postId, entity.id).then((response) => {
283
- if (response) {
284
- setCorrectAnswer(false);
285
- }
286
- });
287
- } else {
288
- qetaApi.markAnswerCorrect(entity.postId, entity.id).then((response) => {
289
- if (response) {
290
- setCorrectAnswer(true);
291
- }
292
- });
293
- }
294
- };
295
- return {
296
- entity,
297
- ownVote,
298
- correctAnswer,
299
- score,
300
- voteUp,
301
- voteDown,
302
- toggleCorrectAnswer,
303
- voteUpTooltip,
304
- voteDownTooltip,
305
- correctTooltip
306
- };
307
- }
308
- function useQetaApi(f, deps = []) {
309
- const qetaApi = useApi(qetaApiRef);
310
- return useAsyncRetry(async () => {
311
- return await f(qetaApi);
312
- }, deps);
313
- }
314
- function useIdentityApi(f, deps = []) {
315
- const identityApi = useApi(identityApiRef);
316
- return useAsync(async () => {
317
- return await f(identityApi);
318
- }, deps);
319
- }
320
- function useEntityQueryParameter(entity) {
321
- const [searchParams] = useSearchParams();
322
- const [entityRef, setEntityRef] = React.useState(entity);
323
- useEffect(() => {
324
- setEntityRef(searchParams.get("entity") ?? void 0);
325
- }, [searchParams, setEntityRef]);
326
- return entityRef;
327
- }
328
- function useIsDarkTheme() {
329
- const appThemeApi = useApi(appThemeApiRef);
330
- const themes = appThemeApi.getInstalledThemes();
331
- const theme = useMemo(() => appThemeApi.getActiveThemeId(), [appThemeApi]);
332
- return Boolean(themes.find((t) => t.id === theme)?.variant === "dark");
333
- }
334
- const useStyles = makeStyles(
335
- (theme) => {
336
- return {
337
- questionDivider: {
338
- marginTop: theme.spacing(2),
339
- marginBottom: theme.spacing(2)
340
- },
341
- questionCard: {
342
- marginBottom: theme.spacing(1),
343
- position: "relative"
344
- },
345
- questionCardVote: {
346
- textAlign: "center",
347
- width: "32px",
348
- marginRight: "20px",
349
- marginLeft: "5px",
350
- display: "inline-block",
351
- verticalAlign: "top"
352
- },
353
- questionCardContent: {
354
- minHeight: "160px"
355
- },
356
- questionListItem: {
357
- padding: "0.7rem",
358
- paddingBottom: "1.4rem"
359
- },
360
- questionListItemStats: {
361
- width: "70px",
362
- textAlign: "right",
363
- marginRight: "5px",
364
- display: "inline-block",
365
- verticalAlign: "top"
366
- },
367
- questionListItemContent: {
368
- display: "inline-block",
369
- width: "calc(100% - 80px)"
370
- },
371
- questionListItemAuthor: {
372
- display: "inline",
373
- float: "right"
374
- },
375
- questionListItemAvatar: {
376
- display: "inline-flex !important",
377
- marginRight: "0.25rem",
378
- fontSize: "1rem",
379
- maxWidth: "1rem",
380
- maxHeight: "1rem"
381
- },
382
- answerCardContent: {
383
- display: "inline-block",
384
- width: "calc(100% - 70px)"
385
- },
386
- questionListPagination: {
387
- marginTop: theme.spacing(2)
388
- },
389
- questionsPerPageInput: {
390
- paddingTop: "10px"
391
- },
392
- questionsPerPage: {
393
- marginRight: theme.spacing(3)
394
- },
395
- postHighlightListContainer: {
396
- width: "100%",
397
- backgroundColor: theme.palette.background.paper,
398
- border: `1px solid ${theme.palette.action.selected}`,
399
- borderRadius: theme.shape.borderRadius,
400
- "&:not(:first-child)": {
401
- marginTop: theme.spacing(2)
402
- }
403
- },
404
- postHighlightList: {
405
- paddingBottom: "0px",
406
- "& p": {
407
- marginTop: "0",
408
- marginBottom: "0"
409
- }
410
- },
411
- filterPanel: {
412
- border: `1px solid ${theme.palette.action.selected}`,
413
- borderRadius: theme.shape.borderRadius,
414
- padding: theme.spacing(3)
415
- },
416
- questionCardMetadata: {
417
- marginTop: theme.spacing(3)
418
- },
419
- marginRight: {
420
- marginRight: theme.spacing(1)
421
- },
422
- marginLeft: {
423
- marginLeft: theme.spacing(1)
424
- },
425
- questionCardActions: {
426
- marginTop: theme.spacing(2),
427
- "& a": {
428
- marginRight: theme.spacing(1)
429
- }
430
- },
431
- noPadding: {
432
- padding: `0 !important`
433
- },
434
- deleteModal: {
435
- position: "absolute",
436
- top: "20%",
437
- left: "50%",
438
- transform: "translate(-50%, -50%)",
439
- width: 400,
440
- backgroundColor: theme.palette.background.default,
441
- border: `1px solid ${theme.palette.action.selected}`,
442
- borderRadius: theme.shape.borderRadius,
443
- padding: theme.spacing(2),
444
- "& button": {
445
- marginTop: theme.spacing(2),
446
- float: "right"
447
- }
448
- },
449
- highlight: {
450
- animation: "$highlight 2s"
451
- },
452
- "@keyframes highlight": {
453
- "0%": {
454
- boxShadow: `0px 0px 0px 3px ${theme.palette.secondary.light}`
455
- },
456
- "100%": {
457
- boxShadow: "none"
458
- }
459
- },
460
- dateFilter: {
461
- minWidth: "200px",
462
- marginTop: theme.spacing(2),
463
- marginBottom: theme.spacing(2)
464
- }
465
- };
466
- },
467
- { name: "Qeta" }
468
- );
469
- const useBaseUrl = () => {
470
- try {
471
- const config = useApi(configApiRef);
472
- return config.getOptionalString("app.baseUrl");
473
- } catch {
474
- return void 0;
475
- }
476
- };
477
- const useBasePath = () => {
478
- const base = "http://sample.dev";
479
- const url = useBaseUrl() ?? "/";
480
- const { pathname } = new URL(url, base);
481
- return trimEnd(pathname, "/");
482
- };
483
- const userCache = /* @__PURE__ */ new Map();
484
- const dataLoaderFactory = (catalogApi) => new DataLoader(
485
- async (entityRefs) => {
486
- const { items } = await catalogApi.getEntitiesByRefs({
487
- fields: [
488
- "kind",
489
- "metadata.name",
490
- "metadata.namespace",
491
- "spec.profile.displayName",
492
- "spec.profile.picture"
493
- ],
494
- entityRefs
495
- });
496
- entityRefs.forEach((entityRef, index) => {
497
- userCache.set(entityRef, items[index]);
498
- });
499
- return items;
500
- },
501
- {
502
- name: "EntityAuthorLoader",
503
- cacheMap: /* @__PURE__ */ new Map(),
504
- maxBatchSize: 100,
505
- batchScheduleFn: (callback) => {
506
- setTimeout(callback, 50);
507
- }
508
- }
509
- );
510
- const useEntityAuthor = (entity) => {
511
- const catalogApi = useApi(catalogApiRef);
512
- const identityApi = useApi(identityApiRef);
513
- const [name, setName] = React.useState(void 0);
514
- const [user, setUser] = React.useState(null);
515
- const [initials, setInitials] = React.useState(null);
516
- const [currentUser, setCurrentUser] = React.useState(null);
517
- const anonymous = "anonymous" in entity ? entity.anonymous ?? false : false;
518
- let author = (
519
- // eslint-disable-next-line no-nested-ternary
520
- "author" in entity ? entity.author : "userRef" in entity ? entity.userRef : entity.owner
521
- );
522
- if (!author.startsWith("user:")) {
523
- author = `user:${author}`;
524
- }
525
- const { primaryTitle: userName } = useEntityPresentation(author);
526
- useEffect(() => {
527
- if (anonymous) {
528
- return;
529
- }
530
- if (userCache.get(author)) {
531
- setUser(userCache.get(author));
532
- return;
533
- }
534
- dataLoaderFactory(catalogApi).load(author).then((data) => {
535
- if (data) {
536
- setUser(data);
537
- } else {
538
- setUser(null);
539
- }
540
- }).catch(() => {
541
- setUser(null);
542
- });
543
- }, [catalogApi, author, anonymous]);
544
- useEffect(() => {
545
- identityApi.getBackstageIdentity().then((res) => {
546
- setCurrentUser(res.userEntityRef ?? "user:default/guest");
547
- });
548
- }, [identityApi]);
549
- useEffect(() => {
550
- let displayName = userName;
551
- if (author === currentUser) {
552
- displayName = "You";
553
- if (anonymous) {
554
- displayName += " (anonymous)";
555
- }
556
- }
557
- setName(displayName);
558
- }, [author, anonymous, currentUser, userName]);
559
- useEffect(() => {
560
- const init = (name ?? "").split(" ").map((p) => p[0]).join("").substring(0, 2).toUpperCase();
561
- setInitials(init);
562
- }, [name]);
563
- return { name, initials, user };
564
- };
565
- let followedTags = void 0;
566
- const useTagsFollow = () => {
567
- const [tags, setTags] = React.useState(followedTags ?? []);
568
- const [loading, setLoading] = React.useState(followedTags === void 0);
569
- const qetaApi = useApi(qetaApiRef);
570
- useEffect(() => {
571
- if (followedTags === void 0) {
572
- qetaApi.getFollowedTags().then((res) => {
573
- followedTags = res.tags;
574
- setTags(res.tags);
575
- setLoading(false);
576
- });
577
- } else {
578
- setTags(followedTags);
579
- }
580
- }, [qetaApi]);
581
- const followTag = useCallback(
582
- (tag) => {
583
- qetaApi.followTag(tag).then(() => {
584
- setTags((prev) => [...prev, tag]);
585
- followedTags?.push(tag);
586
- });
587
- },
588
- [qetaApi]
589
- );
590
- const unfollowTag = useCallback(
591
- (tag) => {
592
- qetaApi.unfollowTag(tag).then(() => {
593
- setTags((prev) => prev.filter((t) => t !== tag));
594
- followedTags = followedTags?.filter((t) => t !== tag);
595
- });
596
- },
597
- [qetaApi]
598
- );
599
- const isFollowingTag = useCallback(
600
- (tag) => tags.includes(tag),
601
- [tags]
602
- );
603
- return {
604
- tags,
605
- followTag,
606
- unfollowTag,
607
- isFollowingTag,
608
- loading
609
- };
610
- };
611
- let followedEntities = void 0;
612
- const useEntityFollow = () => {
613
- const [entities, setEntities] = React.useState(
614
- followedEntities ?? []
615
- );
616
- const [loading, setLoading] = React.useState(followedEntities === void 0);
617
- const qetaApi = useApi(qetaApiRef);
618
- useEffect(() => {
619
- if (followedEntities === void 0) {
620
- qetaApi.getFollowedEntities().then((res) => {
621
- followedEntities = res.entityRefs;
622
- setEntities(res.entityRefs);
623
- setLoading(false);
624
- });
625
- } else {
626
- setEntities(followedEntities);
627
- }
628
- }, [qetaApi]);
629
- const followEntity = useCallback(
630
- (entityRef) => {
631
- qetaApi.followEntity(entityRef).then(() => {
632
- setEntities((prev) => [...prev, entityRef]);
633
- followedEntities?.push(entityRef);
634
- });
635
- },
636
- [qetaApi]
637
- );
638
- const unfollowEntity = useCallback(
639
- (entityRef) => {
640
- qetaApi.unfollowEntity(entityRef).then(() => {
641
- setEntities((prev) => prev.filter((t) => t !== entityRef));
642
- followedEntities = followedEntities?.filter((t) => t !== entityRef);
643
- });
644
- },
645
- [qetaApi]
646
- );
647
- const isFollowingEntity = useCallback(
648
- (entityRef) => entities.includes(entityRef),
649
- [entities]
650
- );
651
- return { entities, followEntity, unfollowEntity, isFollowingEntity, loading };
652
- };
653
- let followedUsers = void 0;
654
- const useUserFollow = () => {
655
- const [users, setUsers] = React.useState(followedUsers ?? []);
656
- const [loading, setLoading] = React.useState(followedUsers === void 0);
657
- const qetaApi = useApi(qetaApiRef);
658
- useEffect(() => {
659
- if (followedUsers === void 0) {
660
- qetaApi.getFollowedUsers().then((res) => {
661
- followedUsers = res.followedUserRefs;
662
- setUsers(res.followedUserRefs);
663
- setLoading(false);
664
- });
665
- } else {
666
- setUsers(followedUsers);
667
- }
668
- }, [qetaApi]);
669
- const followUser = useCallback(
670
- (user) => {
671
- qetaApi.followUser(user).then(() => {
672
- setUsers((prev) => [...prev, user]);
673
- followedUsers?.push(user);
674
- });
675
- },
676
- [qetaApi]
677
- );
678
- const unfollowUser = useCallback(
679
- (user) => {
680
- qetaApi.unfollowUser(user).then(() => {
681
- setUsers((prev) => prev.filter((t) => t !== user));
682
- followedUsers = followedUsers?.filter((t) => t !== user);
683
- });
684
- },
685
- [qetaApi]
686
- );
687
- const isFollowingUser = useCallback(
688
- (user) => users.includes(user),
689
- [users]
690
- );
691
- return {
692
- users,
693
- followUser,
694
- unfollowUser,
695
- isFollowingUser,
696
- loading
697
- };
698
- };
699
-
700
- export { useBasePath, useBaseUrl, useEntityAuthor, useEntityFollow, useEntityQueryParameter, useFormStyles, useIdentityApi, useIsDarkTheme, usePaginatedPosts, useQetaApi, useStyles, useTagsFollow, useTranslation, useUserFollow, useVoting };
701
- //# sourceMappingURL=hooks.esm.js.map