@drodil/backstage-plugin-qeta-react 2.14.0 → 3.0.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.
- package/dist/api.esm.js +8 -0
- package/dist/api.esm.js.map +1 -0
- package/dist/components/AnswerCard/AnswerCard.esm.js +113 -0
- package/dist/components/AnswerCard/AnswerCard.esm.js.map +1 -0
- package/dist/components/AnswerForm/AnswerForm.esm.js +153 -0
- package/dist/components/AnswerForm/AnswerForm.esm.js.map +1 -0
- package/dist/components/AnswersContainer/AnswerList.esm.js +100 -0
- package/dist/components/AnswersContainer/AnswerList.esm.js.map +1 -0
- package/dist/components/AnswersContainer/AnswerListItem.esm.js +90 -0
- package/dist/components/AnswersContainer/AnswerListItem.esm.js.map +1 -0
- package/dist/components/AnswersContainer/AnswersContainer.esm.js +210 -0
- package/dist/components/AnswersContainer/AnswersContainer.esm.js.map +1 -0
- package/dist/components/ArticleContent/ArticleButtons.esm.js +90 -0
- package/dist/components/ArticleContent/ArticleButtons.esm.js.map +1 -0
- package/dist/components/ArticleContent/ArticleContent.esm.js +78 -0
- package/dist/components/ArticleContent/ArticleContent.esm.js.map +1 -0
- package/dist/components/AuthorBox/AuthorBox.esm.js +25 -0
- package/dist/components/AuthorBox/AuthorBox.esm.js.map +1 -0
- package/dist/components/Buttons/AddToCollectionButton.esm.js +68 -0
- package/dist/components/Buttons/AddToCollectionButton.esm.js.map +1 -0
- package/dist/components/Buttons/AskQuestionButton.esm.js +40 -0
- package/dist/components/Buttons/AskQuestionButton.esm.js.map +1 -0
- package/dist/components/Buttons/BackToArticlesButton.esm.js +40 -0
- package/dist/components/Buttons/BackToArticlesButton.esm.js.map +1 -0
- package/dist/components/Buttons/BackToCollectionsButton.esm.js +25 -0
- package/dist/components/Buttons/BackToCollectionsButton.esm.js.map +1 -0
- package/dist/components/Buttons/BackToQuestionsButton.esm.js +40 -0
- package/dist/components/Buttons/BackToQuestionsButton.esm.js.map +1 -0
- package/dist/components/Buttons/CreateCollectionButton.esm.js +29 -0
- package/dist/components/Buttons/CreateCollectionButton.esm.js.map +1 -0
- package/dist/components/Buttons/EntityFollowButton.esm.js +34 -0
- package/dist/components/Buttons/EntityFollowButton.esm.js.map +1 -0
- package/dist/components/Buttons/FavoriteButton.esm.js +45 -0
- package/dist/components/Buttons/FavoriteButton.esm.js.map +1 -0
- package/dist/components/Buttons/LinkButton.esm.js +28 -0
- package/dist/components/Buttons/LinkButton.esm.js.map +1 -0
- package/dist/components/Buttons/TagFollowButton.esm.js +34 -0
- package/dist/components/Buttons/TagFollowButton.esm.js.map +1 -0
- package/dist/components/Buttons/VoteButtons.esm.js +75 -0
- package/dist/components/Buttons/VoteButtons.esm.js.map +1 -0
- package/dist/components/Buttons/WriteArticleButton.esm.js +40 -0
- package/dist/components/Buttons/WriteArticleButton.esm.js.map +1 -0
- package/dist/components/CollectionCard/CollectionCard.esm.js +63 -0
- package/dist/components/CollectionCard/CollectionCard.esm.js.map +1 -0
- package/dist/components/CollectionForm/CollectionForm.esm.js +251 -0
- package/dist/components/CollectionForm/CollectionForm.esm.js.map +1 -0
- package/dist/components/CollectionsGrid/CollectionsGrid.esm.js +40 -0
- package/dist/components/CollectionsGrid/CollectionsGrid.esm.js.map +1 -0
- package/dist/components/CollectionsGrid/CollectionsGridContent.esm.js +67 -0
- package/dist/components/CollectionsGrid/CollectionsGridContent.esm.js.map +1 -0
- package/dist/components/CollectionsGrid/CollectionsGridItem.esm.js +48 -0
- package/dist/components/CollectionsGrid/CollectionsGridItem.esm.js.map +1 -0
- package/dist/components/CommentSection/CommentList.esm.js +47 -0
- package/dist/components/CommentSection/CommentList.esm.js.map +1 -0
- package/dist/components/CommentSection/CommentSection.esm.js +126 -0
- package/dist/components/CommentSection/CommentSection.esm.js.map +1 -0
- package/dist/components/DeleteModal/DeleteModal.esm.js +88 -0
- package/dist/components/DeleteModal/DeleteModal.esm.js.map +1 -0
- package/dist/components/EntitiesGrid/EntitiesGrid.esm.js +45 -0
- package/dist/components/EntitiesGrid/EntitiesGrid.esm.js.map +1 -0
- package/dist/components/EntitiesGrid/EntitiesGridItem.esm.js +61 -0
- package/dist/components/EntitiesGrid/EntitiesGridItem.esm.js.map +1 -0
- package/dist/components/FilterPanel/DateRangeFilter.esm.js +110 -0
- package/dist/components/FilterPanel/DateRangeFilter.esm.js.map +1 -0
- package/dist/components/FilterPanel/FilterPanel.esm.js +238 -0
- package/dist/components/FilterPanel/FilterPanel.esm.js.map +1 -0
- package/dist/components/FollowedLists/FollowedEntitiesList.esm.js +43 -0
- package/dist/components/FollowedLists/FollowedEntitiesList.esm.js.map +1 -0
- package/dist/components/FollowedLists/FollowedTagsList.esm.js +43 -0
- package/dist/components/FollowedLists/FollowedTagsList.esm.js.map +1 -0
- package/dist/components/HomePageCards/ImpactCard.esm.js +22 -0
- package/dist/components/HomePageCards/ImpactCard.esm.js.map +1 -0
- package/dist/components/HomePageCards/PostsCard.esm.js +42 -0
- package/dist/components/HomePageCards/PostsCard.esm.js.map +1 -0
- package/dist/components/Links/Links.esm.js +33 -0
- package/dist/components/Links/Links.esm.js.map +1 -0
- package/dist/components/MarkdownEditor/MarkdownEditor.esm.js +63 -0
- package/dist/components/MarkdownEditor/MarkdownEditor.esm.js.map +1 -0
- package/dist/components/MarkdownRenderer/MarkdownRenderer.esm.js +97 -0
- package/dist/components/MarkdownRenderer/MarkdownRenderer.esm.js.map +1 -0
- package/dist/components/PostAnonymouslyCheckbox/PostAnonymouslyCheckbox.esm.js +34 -0
- package/dist/components/PostAnonymouslyCheckbox/PostAnonymouslyCheckbox.esm.js.map +1 -0
- package/dist/components/PostForm/EntitiesInput.esm.js +100 -0
- package/dist/components/PostForm/EntitiesInput.esm.js.map +1 -0
- package/dist/components/PostForm/PostForm.esm.js +283 -0
- package/dist/components/PostForm/PostForm.esm.js.map +1 -0
- package/dist/components/PostForm/TagInput.esm.js +81 -0
- package/dist/components/PostForm/TagInput.esm.js.map +1 -0
- package/dist/components/PostHighlightList/PostHighlightList.esm.js +72 -0
- package/dist/components/PostHighlightList/PostHighlightList.esm.js.map +1 -0
- package/dist/components/PostsContainer/NoPostsCard.esm.js +50 -0
- package/dist/components/PostsContainer/NoPostsCard.esm.js.map +1 -0
- package/dist/components/PostsContainer/PostList.esm.js +113 -0
- package/dist/components/PostsContainer/PostList.esm.js.map +1 -0
- package/dist/components/PostsContainer/PostListItem.esm.js +138 -0
- package/dist/components/PostsContainer/PostListItem.esm.js.map +1 -0
- package/dist/components/PostsContainer/PostsContainer.esm.js +152 -0
- package/dist/components/PostsContainer/PostsContainer.esm.js.map +1 -0
- package/dist/components/PostsGrid/PostsGrid.esm.js +146 -0
- package/dist/components/PostsGrid/PostsGrid.esm.js.map +1 -0
- package/dist/components/PostsGrid/PostsGridContent.esm.js +90 -0
- package/dist/components/PostsGrid/PostsGridContent.esm.js.map +1 -0
- package/dist/components/PostsGrid/PostsGridItem.esm.js +57 -0
- package/dist/components/PostsGrid/PostsGridItem.esm.js.map +1 -0
- package/dist/components/QuestionCard/QuestionCard.esm.js +107 -0
- package/dist/components/QuestionCard/QuestionCard.esm.js.map +1 -0
- package/dist/components/QuestionsTable/QuestionTableRow.esm.js +21 -0
- package/dist/components/QuestionsTable/QuestionTableRow.esm.js.map +1 -0
- package/dist/components/QuestionsTable/QuestionsTable.esm.js +131 -0
- package/dist/components/QuestionsTable/QuestionsTable.esm.js.map +1 -0
- package/dist/components/RelativeTimeWithTooltip/RelativeTimeWithTooltip.esm.js +22 -0
- package/dist/components/RelativeTimeWithTooltip/RelativeTimeWithTooltip.esm.js.map +1 -0
- package/dist/components/StatsChart/StatsChart.esm.js +245 -0
- package/dist/components/StatsChart/StatsChart.esm.js.map +1 -0
- package/dist/components/SummaryStatsGrid/SummaryStatsGrid.esm.js +53 -0
- package/dist/components/SummaryStatsGrid/SummaryStatsGrid.esm.js.map +1 -0
- package/dist/components/TagsAndEntities/EntityChip.esm.js +80 -0
- package/dist/components/TagsAndEntities/EntityChip.esm.js.map +1 -0
- package/dist/components/TagsAndEntities/TagChip.esm.js +78 -0
- package/dist/components/TagsAndEntities/TagChip.esm.js.map +1 -0
- package/dist/components/TagsAndEntities/TagsAndEntities.esm.js +32 -0
- package/dist/components/TagsAndEntities/TagsAndEntities.esm.js.map +1 -0
- package/dist/components/TagsGrid/EditTagModal.esm.js +73 -0
- package/dist/components/TagsGrid/EditTagModal.esm.js.map +1 -0
- package/dist/components/TagsGrid/TagGridItem.esm.js +56 -0
- package/dist/components/TagsGrid/TagGridItem.esm.js.map +1 -0
- package/dist/components/TagsGrid/TagsGrid.esm.js +45 -0
- package/dist/components/TagsGrid/TagsGrid.esm.js.map +1 -0
- package/dist/components/TopRankingUsersCard/TopRankingUsersCard.esm.js +161 -0
- package/dist/components/TopRankingUsersCard/TopRankingUsersCard.esm.js.map +1 -0
- package/dist/components/TopRankingUsersCard/TrophyIcon.esm.js +19 -0
- package/dist/components/TopRankingUsersCard/TrophyIcon.esm.js.map +1 -0
- package/dist/components/TopRankingUsersCard/styles.esm.js +23 -0
- package/dist/components/TopRankingUsersCard/styles.esm.js.map +1 -0
- package/dist/components/UsersGrid/UsersGrid.esm.js +43 -0
- package/dist/components/UsersGrid/UsersGrid.esm.js.map +1 -0
- package/dist/components/UsersGrid/UsersGridItem.esm.js +66 -0
- package/dist/components/UsersGrid/UsersGridItem.esm.js.map +1 -0
- package/dist/index.d.ts +568 -1
- package/dist/index.esm.js +45 -1
- package/dist/index.esm.js.map +1 -1
- package/dist/routes.esm.js +56 -1
- package/dist/routes.esm.js.map +1 -1
- package/dist/translation.esm.js +470 -0
- package/dist/translation.esm.js.map +1 -0
- package/dist/utils/hooks.esm.js +734 -0
- package/dist/utils/hooks.esm.js.map +1 -0
- package/dist/utils/utils.esm.js +93 -0
- package/dist/utils/utils.esm.js.map +1 -0
- package/package.json +32 -5
|
@@ -0,0 +1,238 @@
|
|
|
1
|
+
import React, { useEffect } from 'react';
|
|
2
|
+
import { Box, Grid, FormGroup, FormControlLabel, Checkbox, FormControl, FormLabel, RadioGroup, TextField, Divider, Radio } from '@material-ui/core';
|
|
3
|
+
import { useStyles, useQetaApi, useTranslation } from '../../utils/hooks.esm.js';
|
|
4
|
+
import { Autocomplete } from '@material-ui/lab';
|
|
5
|
+
import { stringifyEntityRef } from '@backstage/catalog-model';
|
|
6
|
+
import { useApi } from '@backstage/core-plugin-api';
|
|
7
|
+
import { catalogApiRef } from '@backstage/plugin-catalog-react';
|
|
8
|
+
import { getEntityTitle } from '../../utils/utils.esm.js';
|
|
9
|
+
import { DateRangeFilter } from './DateRangeFilter.esm.js';
|
|
10
|
+
|
|
11
|
+
const radioSelect = (value, label) => {
|
|
12
|
+
return /* @__PURE__ */ React.createElement(
|
|
13
|
+
FormControlLabel,
|
|
14
|
+
{
|
|
15
|
+
value,
|
|
16
|
+
control: /* @__PURE__ */ React.createElement(Radio, { size: "small" }),
|
|
17
|
+
label
|
|
18
|
+
}
|
|
19
|
+
);
|
|
20
|
+
};
|
|
21
|
+
const filterKeys = [
|
|
22
|
+
"orderBy",
|
|
23
|
+
"order",
|
|
24
|
+
"noAnswers",
|
|
25
|
+
"noCorrectAnswer",
|
|
26
|
+
"noVotes",
|
|
27
|
+
"entity",
|
|
28
|
+
"tags",
|
|
29
|
+
"dateRange"
|
|
30
|
+
];
|
|
31
|
+
const FilterPanel = (props) => {
|
|
32
|
+
const {
|
|
33
|
+
onChange,
|
|
34
|
+
filters,
|
|
35
|
+
showEntityFilter = true,
|
|
36
|
+
showTagFilter = true,
|
|
37
|
+
answerFilters = false,
|
|
38
|
+
type
|
|
39
|
+
} = props;
|
|
40
|
+
const styles = useStyles();
|
|
41
|
+
const { value: refs } = useQetaApi((api) => api.getEntities(), []);
|
|
42
|
+
const { value: tags } = useQetaApi((api) => api.getTags(), []);
|
|
43
|
+
const catalogApi = useApi(catalogApiRef);
|
|
44
|
+
const { t } = useTranslation();
|
|
45
|
+
const [availableEntities, setAvailableEntities] = React.useState(null);
|
|
46
|
+
const [selectedEntity, setSelectedEntity] = React.useState(void 0);
|
|
47
|
+
const [availableTags, setAvailableTags] = React.useState(
|
|
48
|
+
null
|
|
49
|
+
);
|
|
50
|
+
useEffect(() => {
|
|
51
|
+
if (tags && tags.length > 0 || filters.tags) {
|
|
52
|
+
const ts = (tags ?? []).map((tag) => tag.tag);
|
|
53
|
+
if (filters.tags) {
|
|
54
|
+
ts.push(...filters.tags);
|
|
55
|
+
}
|
|
56
|
+
setAvailableTags([...new Set(ts)]);
|
|
57
|
+
}
|
|
58
|
+
}, [tags, filters.tags]);
|
|
59
|
+
useEffect(() => {
|
|
60
|
+
const entityRefs = [];
|
|
61
|
+
if (filters.entity && !Array.isArray(filters.entity)) {
|
|
62
|
+
entityRefs.push(filters.entity);
|
|
63
|
+
}
|
|
64
|
+
if (refs && refs?.length > 0) {
|
|
65
|
+
refs?.forEach((ref) => {
|
|
66
|
+
if (ref.entityRef !== filters.entity) {
|
|
67
|
+
entityRefs.push(ref.entityRef);
|
|
68
|
+
}
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
if (entityRefs.length > 0) {
|
|
72
|
+
catalogApi.getEntitiesByRefs({
|
|
73
|
+
entityRefs,
|
|
74
|
+
fields: [
|
|
75
|
+
"kind",
|
|
76
|
+
"metadata.name",
|
|
77
|
+
"metadata.namespace",
|
|
78
|
+
"metadata.title"
|
|
79
|
+
]
|
|
80
|
+
}).then((resp) => {
|
|
81
|
+
const filtered = resp.items.filter((i) => i !== void 0);
|
|
82
|
+
setAvailableEntities(filtered);
|
|
83
|
+
});
|
|
84
|
+
}
|
|
85
|
+
}, [filters.entity, catalogApi, refs]);
|
|
86
|
+
useEffect(() => {
|
|
87
|
+
if (filters.entity && availableEntities) {
|
|
88
|
+
const value = availableEntities.find(
|
|
89
|
+
(e) => stringifyEntityRef(e) === filters.entity
|
|
90
|
+
);
|
|
91
|
+
setSelectedEntity(value);
|
|
92
|
+
if (!value) {
|
|
93
|
+
onChange("entity", "");
|
|
94
|
+
}
|
|
95
|
+
} else {
|
|
96
|
+
setSelectedEntity(void 0);
|
|
97
|
+
}
|
|
98
|
+
}, [availableEntities, filters.entity, onChange]);
|
|
99
|
+
const handleChange = (event) => {
|
|
100
|
+
let value = event.target.value;
|
|
101
|
+
if (event.target.type === "checkbox") {
|
|
102
|
+
value = event.target.checked ? "true" : "false";
|
|
103
|
+
}
|
|
104
|
+
onChange(event.target.name, value);
|
|
105
|
+
};
|
|
106
|
+
return /* @__PURE__ */ React.createElement(Box, { className: `qetaFilterPanel ${styles.filterPanel}` }, /* @__PURE__ */ React.createElement(Grid, { container: true, spacing: 4 }, /* @__PURE__ */ React.createElement(Grid, { item: true, md: 3, xs: 4 }, /* @__PURE__ */ React.createElement(FormGroup, null, !answerFilters && type !== "article" && /* @__PURE__ */ React.createElement(
|
|
107
|
+
FormControlLabel,
|
|
108
|
+
{
|
|
109
|
+
control: /* @__PURE__ */ React.createElement(
|
|
110
|
+
Checkbox,
|
|
111
|
+
{
|
|
112
|
+
size: "small",
|
|
113
|
+
name: "noAnswers",
|
|
114
|
+
onChange: handleChange,
|
|
115
|
+
checked: filters.noAnswers === "true"
|
|
116
|
+
}
|
|
117
|
+
),
|
|
118
|
+
label: t("filterPanel.noAnswers.label")
|
|
119
|
+
}
|
|
120
|
+
), type !== "article" && /* @__PURE__ */ React.createElement(
|
|
121
|
+
FormControlLabel,
|
|
122
|
+
{
|
|
123
|
+
control: /* @__PURE__ */ React.createElement(
|
|
124
|
+
Checkbox,
|
|
125
|
+
{
|
|
126
|
+
size: "small",
|
|
127
|
+
name: "noCorrectAnswer",
|
|
128
|
+
checked: filters.noCorrectAnswer === "true",
|
|
129
|
+
onChange: handleChange
|
|
130
|
+
}
|
|
131
|
+
),
|
|
132
|
+
label: t("filterPanel.noCorrectAnswers.label")
|
|
133
|
+
}
|
|
134
|
+
), /* @__PURE__ */ React.createElement(
|
|
135
|
+
FormControlLabel,
|
|
136
|
+
{
|
|
137
|
+
control: /* @__PURE__ */ React.createElement(
|
|
138
|
+
Checkbox,
|
|
139
|
+
{
|
|
140
|
+
size: "small",
|
|
141
|
+
name: "noVotes",
|
|
142
|
+
checked: filters.noVotes === "true",
|
|
143
|
+
onChange: handleChange
|
|
144
|
+
}
|
|
145
|
+
),
|
|
146
|
+
label: t("filterPanel.noVotes.label")
|
|
147
|
+
}
|
|
148
|
+
))), /* @__PURE__ */ React.createElement(Grid, { item: true, md: 2, xs: 4 }, /* @__PURE__ */ React.createElement(FormControl, null, /* @__PURE__ */ React.createElement(FormLabel, { id: "qeta-filter-order-by" }, t("filterPanel.orderBy.label")), /* @__PURE__ */ React.createElement(
|
|
149
|
+
RadioGroup,
|
|
150
|
+
{
|
|
151
|
+
"aria-labelledby": "qeta-filter-order-by",
|
|
152
|
+
name: "orderBy",
|
|
153
|
+
value: filters.orderBy,
|
|
154
|
+
onChange: handleChange
|
|
155
|
+
},
|
|
156
|
+
radioSelect("created", t("filterPanel.orderBy.created")),
|
|
157
|
+
!answerFilters && radioSelect("views", t("filterPanel.orderBy.views")),
|
|
158
|
+
radioSelect("score", t("filterPanel.orderBy.score")),
|
|
159
|
+
!answerFilters && radioSelect("answersCount", t("filterPanel.orderBy.answers")),
|
|
160
|
+
radioSelect("updated", t("filterPanel.orderBy.updated"))
|
|
161
|
+
))), /* @__PURE__ */ React.createElement(Grid, { item: true, md: 2, xs: 4 }, /* @__PURE__ */ React.createElement(FormControl, null, /* @__PURE__ */ React.createElement(FormLabel, { id: "qeta-filter-order" }, t("filterPanel.order.label")), /* @__PURE__ */ React.createElement(
|
|
162
|
+
RadioGroup,
|
|
163
|
+
{
|
|
164
|
+
"aria-labelledby": "qeta-filter-order",
|
|
165
|
+
name: "order",
|
|
166
|
+
value: filters.order,
|
|
167
|
+
onChange: handleChange
|
|
168
|
+
},
|
|
169
|
+
radioSelect("desc", t("filterPanel.order.desc")),
|
|
170
|
+
radioSelect("asc", t("filterPanel.order.asc"))
|
|
171
|
+
))), (availableEntities && availableEntities.length > 0 || availableTags && availableTags.length > 0) && (showEntityFilter || showTagFilter) && /* @__PURE__ */ React.createElement(Grid, { item: true, md: 4, xs: 8 }, /* @__PURE__ */ React.createElement(FormLabel, { id: "qeta-filter-entity" }, t("filterPanel.filters.label")), showEntityFilter && availableEntities && availableEntities.length > 0 && /* @__PURE__ */ React.createElement(
|
|
172
|
+
Autocomplete,
|
|
173
|
+
{
|
|
174
|
+
multiple: false,
|
|
175
|
+
className: "qetaEntityFilter",
|
|
176
|
+
value: selectedEntity ?? null,
|
|
177
|
+
id: "entities-select",
|
|
178
|
+
options: availableEntities,
|
|
179
|
+
getOptionLabel: getEntityTitle,
|
|
180
|
+
getOptionSelected: (o, v) => {
|
|
181
|
+
if (!o || !v) {
|
|
182
|
+
return false;
|
|
183
|
+
}
|
|
184
|
+
return stringifyEntityRef(o) === stringifyEntityRef(v);
|
|
185
|
+
},
|
|
186
|
+
onChange: (_e, newValue) => {
|
|
187
|
+
handleChange({
|
|
188
|
+
target: {
|
|
189
|
+
name: "entity",
|
|
190
|
+
value: newValue ? stringifyEntityRef(newValue) : ""
|
|
191
|
+
}
|
|
192
|
+
});
|
|
193
|
+
},
|
|
194
|
+
renderInput: (params) => /* @__PURE__ */ React.createElement(
|
|
195
|
+
TextField,
|
|
196
|
+
{
|
|
197
|
+
...params,
|
|
198
|
+
variant: "outlined",
|
|
199
|
+
margin: "normal",
|
|
200
|
+
label: t("filterPanel.filters.entity.label"),
|
|
201
|
+
placeholder: t(
|
|
202
|
+
"filterPanel.filters.entity.placeholder"
|
|
203
|
+
)
|
|
204
|
+
}
|
|
205
|
+
)
|
|
206
|
+
}
|
|
207
|
+
), showTagFilter && availableTags && availableTags.length > 0 && /* @__PURE__ */ React.createElement(
|
|
208
|
+
Autocomplete,
|
|
209
|
+
{
|
|
210
|
+
multiple: true,
|
|
211
|
+
className: "qetaTagFilter",
|
|
212
|
+
value: filters.tags,
|
|
213
|
+
id: "tags-select",
|
|
214
|
+
options: availableTags,
|
|
215
|
+
onChange: (_e, newValue) => {
|
|
216
|
+
handleChange({
|
|
217
|
+
target: {
|
|
218
|
+
name: "tags",
|
|
219
|
+
value: newValue
|
|
220
|
+
}
|
|
221
|
+
});
|
|
222
|
+
},
|
|
223
|
+
renderInput: (params) => /* @__PURE__ */ React.createElement(
|
|
224
|
+
TextField,
|
|
225
|
+
{
|
|
226
|
+
...params,
|
|
227
|
+
variant: "outlined",
|
|
228
|
+
margin: "normal",
|
|
229
|
+
label: t("filterPanel.filters.tag.label"),
|
|
230
|
+
placeholder: t("filterPanel.filters.tag.placeholder")
|
|
231
|
+
}
|
|
232
|
+
)
|
|
233
|
+
}
|
|
234
|
+
))), /* @__PURE__ */ React.createElement(Box, { marginY: "24px" }, /* @__PURE__ */ React.createElement(Divider, null)), /* @__PURE__ */ React.createElement(DateRangeFilter, { value: filters.dateRange, onChange }));
|
|
235
|
+
};
|
|
236
|
+
|
|
237
|
+
export { FilterPanel, filterKeys };
|
|
238
|
+
//# sourceMappingURL=FilterPanel.esm.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"FilterPanel.esm.js","sources":["../../../src/components/FilterPanel/FilterPanel.tsx"],"sourcesContent":["import React, { useEffect } from 'react';\nimport {\n Box,\n Checkbox,\n Divider,\n FormControl,\n FormControlLabel,\n FormGroup,\n FormLabel,\n Grid,\n Radio,\n RadioGroup,\n TextField,\n} from '@material-ui/core';\nimport { useQetaApi, useStyles, useTranslation } from '../../utils/hooks';\nimport { Autocomplete } from '@material-ui/lab';\nimport { Entity, stringifyEntityRef } from '@backstage/catalog-model';\nimport { useApi } from '@backstage/core-plugin-api';\nimport { catalogApiRef } from '@backstage/plugin-catalog-react';\nimport { getEntityTitle } from '../../utils/utils';\nimport { DateRangeFilter } from './DateRangeFilter';\nimport { PostType } from '@drodil/backstage-plugin-qeta-common';\n\nconst radioSelect = (value: string, label: string) => {\n return (\n <FormControlLabel\n value={value}\n control={<Radio size=\"small\" />}\n label={label}\n />\n );\n};\n\nexport const filterKeys = [\n 'orderBy',\n 'order',\n 'noAnswers',\n 'noCorrectAnswer',\n 'noVotes',\n 'entity',\n 'tags',\n 'dateRange',\n] as const;\nexport type FilterKey = (typeof filterKeys)[number];\n\nexport type Filters = {\n order: string;\n orderBy: string;\n noAnswers?: string;\n noCorrectAnswer: string;\n noVotes: string;\n searchQuery: string;\n entity?: string;\n tags?: string[];\n dateRange?: string;\n collectionId?: number;\n};\n\nexport interface FilterPanelProps {\n onChange: (key: FilterKey, value: string | string[]) => void;\n filters: Filters;\n showEntityFilter?: boolean;\n showTagFilter?: boolean;\n answerFilters?: boolean;\n type?: PostType;\n}\n\nexport const FilterPanel = (props: FilterPanelProps) => {\n const {\n onChange,\n filters,\n showEntityFilter = true,\n showTagFilter = true,\n answerFilters = false,\n type,\n } = props;\n const styles = useStyles();\n const { value: refs } = useQetaApi(api => api.getEntities(), []);\n const { value: tags } = useQetaApi(api => api.getTags(), []);\n const catalogApi = useApi(catalogApiRef);\n const { t } = useTranslation();\n const [availableEntities, setAvailableEntities] = React.useState<\n Entity[] | null\n >(null);\n const [selectedEntity, setSelectedEntity] = React.useState<\n Entity | undefined\n >(undefined);\n const [availableTags, setAvailableTags] = React.useState<string[] | null>(\n null,\n );\n\n useEffect(() => {\n if ((tags && tags.length > 0) || filters.tags) {\n const ts = (tags ?? []).map(tag => tag.tag);\n if (filters.tags) {\n ts.push(...filters.tags);\n }\n setAvailableTags([...new Set(ts)]);\n }\n }, [tags, filters.tags]);\n\n useEffect(() => {\n const entityRefs: string[] = [];\n if (filters.entity && !Array.isArray(filters.entity)) {\n entityRefs.push(filters.entity);\n }\n if (refs && refs?.length > 0) {\n refs?.forEach(ref => {\n // ignore currently selected entity if exist in refs\n if (ref.entityRef !== filters.entity) {\n entityRefs.push(ref.entityRef);\n }\n });\n }\n if (entityRefs.length > 0) {\n catalogApi\n .getEntitiesByRefs({\n entityRefs,\n fields: [\n 'kind',\n 'metadata.name',\n 'metadata.namespace',\n 'metadata.title',\n ],\n })\n .then(resp => {\n const filtered = resp.items.filter(i => i !== undefined) as Entity[];\n setAvailableEntities(filtered);\n });\n }\n }, [filters.entity, catalogApi, refs]);\n\n useEffect(() => {\n if (filters.entity && availableEntities) {\n const value = availableEntities.find(\n e => stringifyEntityRef(e) === filters.entity,\n );\n setSelectedEntity(value);\n if (!value) {\n onChange('entity', '');\n }\n } else {\n setSelectedEntity(undefined);\n }\n }, [availableEntities, filters.entity, onChange]);\n\n const handleChange = (event: {\n target: {\n value: string | string[];\n type?: string;\n name: string;\n checked?: boolean;\n };\n }) => {\n let value = event.target.value;\n if (event.target.type === 'checkbox') {\n value = event.target.checked ? 'true' : 'false';\n }\n onChange(event.target.name as FilterKey, value);\n };\n\n return (\n <Box className={`qetaFilterPanel ${styles.filterPanel}`}>\n <Grid container spacing={4}>\n <Grid item md={3} xs={4}>\n <FormGroup>\n {!answerFilters && type !== 'article' && (\n <FormControlLabel\n control={\n <Checkbox\n size=\"small\"\n name=\"noAnswers\"\n onChange={handleChange}\n checked={filters.noAnswers === 'true'}\n />\n }\n label={t('filterPanel.noAnswers.label')}\n />\n )}\n {type !== 'article' && (\n <FormControlLabel\n control={\n <Checkbox\n size=\"small\"\n name=\"noCorrectAnswer\"\n checked={filters.noCorrectAnswer === 'true'}\n onChange={handleChange}\n />\n }\n label={t('filterPanel.noCorrectAnswers.label')}\n />\n )}\n <FormControlLabel\n control={\n <Checkbox\n size=\"small\"\n name=\"noVotes\"\n checked={filters.noVotes === 'true'}\n onChange={handleChange}\n />\n }\n label={t('filterPanel.noVotes.label')}\n />\n </FormGroup>\n </Grid>\n <Grid item md={2} xs={4}>\n <FormControl>\n <FormLabel id=\"qeta-filter-order-by\">\n {t('filterPanel.orderBy.label')}\n </FormLabel>\n <RadioGroup\n aria-labelledby=\"qeta-filter-order-by\"\n name=\"orderBy\"\n value={filters.orderBy}\n onChange={handleChange}\n >\n {radioSelect('created', t('filterPanel.orderBy.created'))}\n {!answerFilters &&\n radioSelect('views', t('filterPanel.orderBy.views'))}\n {radioSelect('score', t('filterPanel.orderBy.score'))}\n {!answerFilters &&\n radioSelect('answersCount', t('filterPanel.orderBy.answers'))}\n {radioSelect('updated', t('filterPanel.orderBy.updated'))}\n </RadioGroup>\n </FormControl>\n </Grid>\n <Grid item md={2} xs={4}>\n <FormControl>\n <FormLabel id=\"qeta-filter-order\">\n {t('filterPanel.order.label')}\n </FormLabel>\n <RadioGroup\n aria-labelledby=\"qeta-filter-order\"\n name=\"order\"\n value={filters.order}\n onChange={handleChange}\n >\n {radioSelect('desc', t('filterPanel.order.desc'))}\n {radioSelect('asc', t('filterPanel.order.asc'))}\n </RadioGroup>\n </FormControl>\n </Grid>\n {((availableEntities && availableEntities.length > 0) ||\n (availableTags && availableTags.length > 0)) &&\n (showEntityFilter || showTagFilter) && (\n <Grid item md={4} xs={8}>\n <FormLabel id=\"qeta-filter-entity\">\n {t('filterPanel.filters.label')}\n </FormLabel>\n {showEntityFilter &&\n availableEntities &&\n availableEntities.length > 0 && (\n <Autocomplete\n multiple={false}\n className=\"qetaEntityFilter\"\n value={selectedEntity ?? null}\n id=\"entities-select\"\n options={availableEntities}\n getOptionLabel={getEntityTitle}\n getOptionSelected={(o, v) => {\n if (!o || !v) {\n return false;\n }\n return stringifyEntityRef(o) === stringifyEntityRef(v);\n }}\n onChange={(_e, newValue) => {\n handleChange({\n target: {\n name: 'entity',\n value: newValue ? stringifyEntityRef(newValue) : '',\n },\n });\n }}\n renderInput={params => (\n <TextField\n {...params}\n variant=\"outlined\"\n margin=\"normal\"\n label={t('filterPanel.filters.entity.label')}\n placeholder={t(\n 'filterPanel.filters.entity.placeholder',\n )}\n />\n )}\n />\n )}\n {showTagFilter && availableTags && availableTags.length > 0 && (\n <Autocomplete\n multiple\n className=\"qetaTagFilter\"\n value={filters.tags}\n id=\"tags-select\"\n options={availableTags}\n onChange={(_e, newValue) => {\n handleChange({\n target: {\n name: 'tags',\n value: newValue,\n },\n });\n }}\n renderInput={params => (\n <TextField\n {...params}\n variant=\"outlined\"\n margin=\"normal\"\n label={t('filterPanel.filters.tag.label')}\n placeholder={t('filterPanel.filters.tag.placeholder')}\n />\n )}\n />\n )}\n </Grid>\n )}\n </Grid>\n <Box marginY=\"24px\">\n <Divider />\n </Box>\n <DateRangeFilter value={filters.dateRange} onChange={onChange} />\n </Box>\n );\n};\n"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { Box, List, ListSubheader, Divider, ListItem } from '@material-ui/core';
|
|
2
|
+
import React from 'react';
|
|
3
|
+
import { useStyles, useEntityFollow, useTranslation } from '../../utils/hooks.esm.js';
|
|
4
|
+
import { EntityChip } from '../TagsAndEntities/EntityChip.esm.js';
|
|
5
|
+
|
|
6
|
+
const FollowedEntitiesList = () => {
|
|
7
|
+
const classes = useStyles();
|
|
8
|
+
const entities = useEntityFollow();
|
|
9
|
+
const { t } = useTranslation();
|
|
10
|
+
if (entities.entities.length === 0 || entities.loading) {
|
|
11
|
+
return null;
|
|
12
|
+
}
|
|
13
|
+
return /* @__PURE__ */ React.createElement(
|
|
14
|
+
Box,
|
|
15
|
+
{
|
|
16
|
+
className: `qetaPostHighlightList ${classes.postHighlightListContainer}`,
|
|
17
|
+
display: { md: "none", lg: "block" }
|
|
18
|
+
},
|
|
19
|
+
/* @__PURE__ */ React.createElement(
|
|
20
|
+
List,
|
|
21
|
+
{
|
|
22
|
+
component: "nav",
|
|
23
|
+
"aria-labelledby": "nested-list-subheader",
|
|
24
|
+
className: `qetaPostHighlightListList ${classes.postHighlightList}`,
|
|
25
|
+
subheader: /* @__PURE__ */ React.createElement(
|
|
26
|
+
ListSubheader,
|
|
27
|
+
{
|
|
28
|
+
disableSticky: true,
|
|
29
|
+
component: "p",
|
|
30
|
+
id: "nested-list-subheader",
|
|
31
|
+
color: "primary"
|
|
32
|
+
},
|
|
33
|
+
t("rightMenu.followedEntities")
|
|
34
|
+
)
|
|
35
|
+
},
|
|
36
|
+
/* @__PURE__ */ React.createElement(Divider, null),
|
|
37
|
+
/* @__PURE__ */ React.createElement(ListItem, { style: { display: "block" } }, entities.entities.map((entity) => /* @__PURE__ */ React.createElement(EntityChip, { key: entity, entity })))
|
|
38
|
+
)
|
|
39
|
+
);
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
export { FollowedEntitiesList };
|
|
43
|
+
//# sourceMappingURL=FollowedEntitiesList.esm.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"FollowedEntitiesList.esm.js","sources":["../../../src/components/FollowedLists/FollowedEntitiesList.tsx"],"sourcesContent":["import { Box, Divider, List, ListItem, ListSubheader } from '@material-ui/core';\nimport React from 'react';\nimport { useEntityFollow, useStyles, useTranslation } from '../../utils/hooks';\nimport { EntityChip } from '../TagsAndEntities/EntityChip';\n\nexport const FollowedEntitiesList = () => {\n const classes = useStyles();\n const entities = useEntityFollow();\n const { t } = useTranslation();\n\n if (entities.entities.length === 0 || entities.loading) {\n return null;\n }\n\n return (\n <Box\n className={`qetaPostHighlightList ${classes.postHighlightListContainer}`}\n display={{ md: 'none', lg: 'block' }}\n >\n <List\n component=\"nav\"\n aria-labelledby=\"nested-list-subheader\"\n className={`qetaPostHighlightListList ${classes.postHighlightList}`}\n subheader={\n <ListSubheader\n disableSticky\n component=\"p\"\n id=\"nested-list-subheader\"\n color=\"primary\"\n >\n {t('rightMenu.followedEntities')}\n </ListSubheader>\n }\n >\n <Divider />\n <ListItem style={{ display: 'block' }}>\n {entities.entities.map(entity => (\n <EntityChip key={entity} entity={entity} />\n ))}\n </ListItem>\n </List>\n </Box>\n );\n};\n"],"names":[],"mappings":";;;;;AAKO,MAAM,uBAAuB,MAAM;AACxC,EAAA,MAAM,UAAU,SAAU,EAAA,CAAA;AAC1B,EAAA,MAAM,WAAW,eAAgB,EAAA,CAAA;AACjC,EAAM,MAAA,EAAE,CAAE,EAAA,GAAI,cAAe,EAAA,CAAA;AAE7B,EAAA,IAAI,QAAS,CAAA,QAAA,CAAS,MAAW,KAAA,CAAA,IAAK,SAAS,OAAS,EAAA;AACtD,IAAO,OAAA,IAAA,CAAA;AAAA,GACT;AAEA,EACE,uBAAA,KAAA,CAAA,aAAA;AAAA,IAAC,GAAA;AAAA,IAAA;AAAA,MACC,SAAA,EAAW,CAAyB,sBAAA,EAAA,OAAA,CAAQ,0BAA0B,CAAA,CAAA;AAAA,MACtE,OAAS,EAAA,EAAE,EAAI,EAAA,MAAA,EAAQ,IAAI,OAAQ,EAAA;AAAA,KAAA;AAAA,oBAEnC,KAAA,CAAA,aAAA;AAAA,MAAC,IAAA;AAAA,MAAA;AAAA,QACC,SAAU,EAAA,KAAA;AAAA,QACV,iBAAgB,EAAA,uBAAA;AAAA,QAChB,SAAA,EAAW,CAA6B,0BAAA,EAAA,OAAA,CAAQ,iBAAiB,CAAA,CAAA;AAAA,QACjE,SACE,kBAAA,KAAA,CAAA,aAAA;AAAA,UAAC,aAAA;AAAA,UAAA;AAAA,YACC,aAAa,EAAA,IAAA;AAAA,YACb,SAAU,EAAA,GAAA;AAAA,YACV,EAAG,EAAA,uBAAA;AAAA,YACH,KAAM,EAAA,SAAA;AAAA,WAAA;AAAA,UAEL,EAAE,4BAA4B,CAAA;AAAA,SACjC;AAAA,OAAA;AAAA,0CAGD,OAAQ,EAAA,IAAA,CAAA;AAAA,0CACR,QAAS,EAAA,EAAA,KAAA,EAAO,EAAE,OAAA,EAAS,SACzB,EAAA,EAAA,QAAA,CAAS,QAAS,CAAA,GAAA,CAAI,4BACpB,KAAA,CAAA,aAAA,CAAA,UAAA,EAAA,EAAW,KAAK,MAAQ,EAAA,MAAA,EAAgB,CAC1C,CACH,CAAA;AAAA,KACF;AAAA,GACF,CAAA;AAEJ;;;;"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { Box, List, ListSubheader, Divider, ListItem } from '@material-ui/core';
|
|
2
|
+
import React from 'react';
|
|
3
|
+
import { useStyles, useTagsFollow, useTranslation } from '../../utils/hooks.esm.js';
|
|
4
|
+
import { TagChip } from '../TagsAndEntities/TagChip.esm.js';
|
|
5
|
+
|
|
6
|
+
const FollowedTagsList = () => {
|
|
7
|
+
const classes = useStyles();
|
|
8
|
+
const tags = useTagsFollow();
|
|
9
|
+
const { t } = useTranslation();
|
|
10
|
+
if (tags.tags.length === 0 || tags.loading) {
|
|
11
|
+
return null;
|
|
12
|
+
}
|
|
13
|
+
return /* @__PURE__ */ React.createElement(
|
|
14
|
+
Box,
|
|
15
|
+
{
|
|
16
|
+
className: `qetaQuestionHighlightList ${classes.postHighlightListContainer}`,
|
|
17
|
+
display: { md: "none", lg: "block" }
|
|
18
|
+
},
|
|
19
|
+
/* @__PURE__ */ React.createElement(
|
|
20
|
+
List,
|
|
21
|
+
{
|
|
22
|
+
component: "nav",
|
|
23
|
+
"aria-labelledby": "nested-list-subheader",
|
|
24
|
+
className: `qetaQuestionHighlightListList ${classes.postHighlightList}`,
|
|
25
|
+
subheader: /* @__PURE__ */ React.createElement(
|
|
26
|
+
ListSubheader,
|
|
27
|
+
{
|
|
28
|
+
disableSticky: true,
|
|
29
|
+
component: "p",
|
|
30
|
+
id: "nested-list-subheader",
|
|
31
|
+
color: "primary"
|
|
32
|
+
},
|
|
33
|
+
t("rightMenu.followedTags")
|
|
34
|
+
)
|
|
35
|
+
},
|
|
36
|
+
/* @__PURE__ */ React.createElement(Divider, null),
|
|
37
|
+
/* @__PURE__ */ React.createElement(ListItem, { style: { display: "block" } }, tags.tags.map((tag) => /* @__PURE__ */ React.createElement(TagChip, { key: tag, tag })))
|
|
38
|
+
)
|
|
39
|
+
);
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
export { FollowedTagsList };
|
|
43
|
+
//# sourceMappingURL=FollowedTagsList.esm.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"FollowedTagsList.esm.js","sources":["../../../src/components/FollowedLists/FollowedTagsList.tsx"],"sourcesContent":["import { Box, Divider, List, ListItem, ListSubheader } from '@material-ui/core';\nimport React from 'react';\nimport { useStyles, useTagsFollow, useTranslation } from '../../utils/hooks';\nimport { TagChip } from '../TagsAndEntities/TagChip';\n\nexport const FollowedTagsList = () => {\n const classes = useStyles();\n const tags = useTagsFollow();\n const { t } = useTranslation();\n\n if (tags.tags.length === 0 || tags.loading) {\n return null;\n }\n\n return (\n <Box\n className={`qetaQuestionHighlightList ${classes.postHighlightListContainer}`}\n display={{ md: 'none', lg: 'block' }}\n >\n <List\n component=\"nav\"\n aria-labelledby=\"nested-list-subheader\"\n className={`qetaQuestionHighlightListList ${classes.postHighlightList}`}\n subheader={\n <ListSubheader\n disableSticky\n component=\"p\"\n id=\"nested-list-subheader\"\n color=\"primary\"\n >\n {t('rightMenu.followedTags')}\n </ListSubheader>\n }\n >\n <Divider />\n <ListItem style={{ display: 'block' }}>\n {tags.tags.map(tag => (\n <TagChip key={tag} tag={tag} />\n ))}\n </ListItem>\n </List>\n </Box>\n );\n};\n"],"names":[],"mappings":";;;;;AAKO,MAAM,mBAAmB,MAAM;AACpC,EAAA,MAAM,UAAU,SAAU,EAAA,CAAA;AAC1B,EAAA,MAAM,OAAO,aAAc,EAAA,CAAA;AAC3B,EAAM,MAAA,EAAE,CAAE,EAAA,GAAI,cAAe,EAAA,CAAA;AAE7B,EAAA,IAAI,IAAK,CAAA,IAAA,CAAK,MAAW,KAAA,CAAA,IAAK,KAAK,OAAS,EAAA;AAC1C,IAAO,OAAA,IAAA,CAAA;AAAA,GACT;AAEA,EACE,uBAAA,KAAA,CAAA,aAAA;AAAA,IAAC,GAAA;AAAA,IAAA;AAAA,MACC,SAAA,EAAW,CAA6B,0BAAA,EAAA,OAAA,CAAQ,0BAA0B,CAAA,CAAA;AAAA,MAC1E,OAAS,EAAA,EAAE,EAAI,EAAA,MAAA,EAAQ,IAAI,OAAQ,EAAA;AAAA,KAAA;AAAA,oBAEnC,KAAA,CAAA,aAAA;AAAA,MAAC,IAAA;AAAA,MAAA;AAAA,QACC,SAAU,EAAA,KAAA;AAAA,QACV,iBAAgB,EAAA,uBAAA;AAAA,QAChB,SAAA,EAAW,CAAiC,8BAAA,EAAA,OAAA,CAAQ,iBAAiB,CAAA,CAAA;AAAA,QACrE,SACE,kBAAA,KAAA,CAAA,aAAA;AAAA,UAAC,aAAA;AAAA,UAAA;AAAA,YACC,aAAa,EAAA,IAAA;AAAA,YACb,SAAU,EAAA,GAAA;AAAA,YACV,EAAG,EAAA,uBAAA;AAAA,YACH,KAAM,EAAA,SAAA;AAAA,WAAA;AAAA,UAEL,EAAE,wBAAwB,CAAA;AAAA,SAC7B;AAAA,OAAA;AAAA,0CAGD,OAAQ,EAAA,IAAA,CAAA;AAAA,0CACR,QAAS,EAAA,EAAA,KAAA,EAAO,EAAE,OAAA,EAAS,SACzB,EAAA,EAAA,IAAA,CAAK,IAAK,CAAA,GAAA,CAAI,yBACZ,KAAA,CAAA,aAAA,CAAA,OAAA,EAAA,EAAQ,KAAK,GAAK,EAAA,GAAA,EAAU,CAC9B,CACH,CAAA;AAAA,KACF;AAAA,GACF,CAAA;AAEJ;;;;"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { useTranslation, useQetaApi } from '../../utils/hooks.esm.js';
|
|
2
|
+
import React from 'react';
|
|
3
|
+
import { Box, Card, CardContent, Typography } from '@material-ui/core';
|
|
4
|
+
import numeral from 'numeral';
|
|
5
|
+
|
|
6
|
+
const ImpactCard = () => {
|
|
7
|
+
const { t } = useTranslation();
|
|
8
|
+
const {
|
|
9
|
+
value: response,
|
|
10
|
+
loading,
|
|
11
|
+
error
|
|
12
|
+
} = useQetaApi((api) => api.getUserImpact(), []);
|
|
13
|
+
if (loading || error || !response) {
|
|
14
|
+
return null;
|
|
15
|
+
}
|
|
16
|
+
return /* @__PURE__ */ React.createElement(Box, { display: { md: "none", lg: "block" } }, /* @__PURE__ */ React.createElement(Card, null, /* @__PURE__ */ React.createElement(CardContent, null, /* @__PURE__ */ React.createElement(Typography, { variant: "h5" }, t("impactCard.title")), /* @__PURE__ */ React.createElement(Typography, { variant: "h5" }, response.impact >= 1e3 ? numeral(response.impact).format("0.0 a") : response.impact, /* @__PURE__ */ React.createElement(Typography, { variant: "caption", style: { marginLeft: "1rem" } }, t("impactCard.views"))), /* @__PURE__ */ React.createElement(Typography, { variant: "body2" }, t("impactCard.contributions", {
|
|
17
|
+
lastWeek: response.lastWeekImpact.toString(10)
|
|
18
|
+
})))));
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
export { ImpactCard };
|
|
22
|
+
//# sourceMappingURL=ImpactCard.esm.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ImpactCard.esm.js","sources":["../../../src/components/HomePageCards/ImpactCard.tsx"],"sourcesContent":["import { useQetaApi, useTranslation } from '../../utils/hooks';\nimport React from 'react';\nimport { Box, Card, CardContent, Typography } from '@material-ui/core';\nimport numeral from 'numeral';\n\nexport const ImpactCard = () => {\n const { t } = useTranslation();\n const {\n value: response,\n loading,\n error,\n } = useQetaApi(api => api.getUserImpact(), []);\n\n if (loading || error || !response) {\n return null;\n }\n\n return (\n <Box display={{ md: 'none', lg: 'block' }}>\n <Card>\n <CardContent>\n <Typography variant=\"h5\">{t('impactCard.title')}</Typography>\n <Typography variant=\"h5\">\n {response.impact >= 1000\n ? numeral(response.impact).format('0.0 a')\n : response.impact}\n <Typography variant=\"caption\" style={{ marginLeft: '1rem' }}>\n {t('impactCard.views')}\n </Typography>\n </Typography>\n <Typography variant=\"body2\">\n {t('impactCard.contributions', {\n lastWeek: response.lastWeekImpact.toString(10),\n })}\n </Typography>\n </CardContent>\n </Card>\n </Box>\n );\n};\n"],"names":[],"mappings":";;;;;AAKO,MAAM,aAAa,MAAM;AAC9B,EAAM,MAAA,EAAE,CAAE,EAAA,GAAI,cAAe,EAAA,CAAA;AAC7B,EAAM,MAAA;AAAA,IACJ,KAAO,EAAA,QAAA;AAAA,IACP,OAAA;AAAA,IACA,KAAA;AAAA,MACE,UAAW,CAAA,CAAA,GAAA,KAAO,IAAI,aAAc,EAAA,EAAG,EAAE,CAAA,CAAA;AAE7C,EAAI,IAAA,OAAA,IAAW,KAAS,IAAA,CAAC,QAAU,EAAA;AACjC,IAAO,OAAA,IAAA,CAAA;AAAA,GACT;AAEA,EACE,uBAAA,KAAA,CAAA,aAAA,CAAC,GAAI,EAAA,EAAA,OAAA,EAAS,EAAE,EAAA,EAAI,MAAQ,EAAA,EAAA,EAAI,OAAQ,EAAA,EAAA,kBACrC,KAAA,CAAA,aAAA,CAAA,IAAA,EAAA,IAAA,kBACE,KAAA,CAAA,aAAA,CAAA,WAAA,EAAA,IAAA,sCACE,UAAW,EAAA,EAAA,OAAA,EAAQ,IAAM,EAAA,EAAA,CAAA,CAAE,kBAAkB,CAAE,CAChD,kBAAA,KAAA,CAAA,aAAA,CAAC,UAAW,EAAA,EAAA,OAAA,EAAQ,IACjB,EAAA,EAAA,QAAA,CAAS,MAAU,IAAA,GAAA,GAChB,QAAQ,QAAS,CAAA,MAAM,CAAE,CAAA,MAAA,CAAO,OAAO,CAAA,GACvC,QAAS,CAAA,MAAA,kBACZ,KAAA,CAAA,aAAA,CAAA,UAAA,EAAA,EAAW,OAAQ,EAAA,SAAA,EAAU,KAAO,EAAA,EAAE,YAAY,MAAO,EAAA,EAAA,EACvD,CAAE,CAAA,kBAAkB,CACvB,CACF,CACA,kBAAA,KAAA,CAAA,aAAA,CAAC,UAAW,EAAA,EAAA,OAAA,EAAQ,OACjB,EAAA,EAAA,CAAA,CAAE,0BAA4B,EAAA;AAAA,IAC7B,QAAU,EAAA,QAAA,CAAS,cAAe,CAAA,QAAA,CAAS,EAAE,CAAA;AAAA,GAC9C,CACH,CACF,CACF,CACF,CAAA,CAAA;AAEJ;;;;"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { Card, CardHeader, Grid, Divider } from '@material-ui/core';
|
|
2
|
+
import React from 'react';
|
|
3
|
+
import { useQetaApi } from '../../utils/hooks.esm.js';
|
|
4
|
+
import '@material-ui/lab';
|
|
5
|
+
import '@backstage/catalog-model';
|
|
6
|
+
import '@backstage/core-plugin-api';
|
|
7
|
+
import '@backstage/plugin-catalog-react';
|
|
8
|
+
import 'file-type';
|
|
9
|
+
import '@backstage/core-components';
|
|
10
|
+
import { PostListItem } from '../PostsContainer/PostListItem.esm.js';
|
|
11
|
+
import '@material-ui/icons/HelpOutline';
|
|
12
|
+
import '../../routes.esm.js';
|
|
13
|
+
import '@material-ui/icons/FilterList';
|
|
14
|
+
import '@backstage/plugin-permission-react';
|
|
15
|
+
import '@drodil/backstage-plugin-qeta-common';
|
|
16
|
+
import '@material-ui/icons/Visibility';
|
|
17
|
+
import '@material-ui/icons/VisibilityOff';
|
|
18
|
+
import 'react-router-dom';
|
|
19
|
+
import '@material-ui/icons/ChevronLeft';
|
|
20
|
+
import '@material-ui/icons/Create';
|
|
21
|
+
import '@material-ui/icons/PlaylistAdd';
|
|
22
|
+
import '@material-ui/icons/AddCircle';
|
|
23
|
+
import '@material-ui/icons/RemoveCircle';
|
|
24
|
+
import '../../api.esm.js';
|
|
25
|
+
import 'lodash';
|
|
26
|
+
|
|
27
|
+
const PostsCard = (props) => {
|
|
28
|
+
const { value: response } = useQetaApi(
|
|
29
|
+
(api) => api.getPosts({ limit: 3, type: props.postType, ...props.options }),
|
|
30
|
+
[]
|
|
31
|
+
);
|
|
32
|
+
const posts = response?.posts ?? [];
|
|
33
|
+
if (posts.length === 0) {
|
|
34
|
+
return null;
|
|
35
|
+
}
|
|
36
|
+
return /* @__PURE__ */ React.createElement(Card, null, /* @__PURE__ */ React.createElement(CardHeader, { style: { paddingBottom: "8px" }, title: props.title }), /* @__PURE__ */ React.createElement(Grid, { container: true, spacing: 2 }, posts.map((question) => {
|
|
37
|
+
return /* @__PURE__ */ React.createElement(Grid, { item: true, xs: 12, key: question.id }, /* @__PURE__ */ React.createElement(PostListItem, { post: question, type: props.postType }), /* @__PURE__ */ React.createElement(Divider, null));
|
|
38
|
+
})));
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
export { PostsCard };
|
|
42
|
+
//# sourceMappingURL=PostsCard.esm.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"PostsCard.esm.js","sources":["../../../src/components/HomePageCards/PostsCard.tsx"],"sourcesContent":["import { Card, CardHeader, Divider, Grid } from '@material-ui/core';\nimport React from 'react';\nimport { useQetaApi } from '../../utils/hooks';\nimport { PostsQuery, PostType } from '@drodil/backstage-plugin-qeta-common';\nimport { PostListItem } from '../PostsContainer';\n\nexport const PostsCard = (props: {\n type: string;\n title: string;\n options?: PostsQuery;\n icon?: React.ReactNode;\n postType?: PostType;\n}) => {\n const { value: response } = useQetaApi(\n api => api.getPosts({ limit: 3, type: props.postType, ...props.options }),\n [],\n );\n\n const posts = response?.posts ?? [];\n if (posts.length === 0) {\n return null;\n }\n\n return (\n <Card>\n <CardHeader style={{ paddingBottom: '8px' }} title={props.title} />\n <Grid container spacing={2}>\n {posts.map(question => {\n return (\n <Grid item xs={12} key={question.id}>\n <PostListItem post={question} type={props.postType} />\n <Divider />\n </Grid>\n );\n })}\n </Grid>\n </Card>\n );\n};\n"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;AAMa,MAAA,SAAA,GAAY,CAAC,KAMpB,KAAA;AACJ,EAAM,MAAA,EAAE,KAAO,EAAA,QAAA,EAAa,GAAA,UAAA;AAAA,IAC1B,CAAO,GAAA,KAAA,GAAA,CAAI,QAAS,CAAA,EAAE,KAAO,EAAA,CAAA,EAAG,IAAM,EAAA,KAAA,CAAM,QAAU,EAAA,GAAG,KAAM,CAAA,OAAA,EAAS,CAAA;AAAA,IACxE,EAAC;AAAA,GACH,CAAA;AAEA,EAAM,MAAA,KAAA,GAAQ,QAAU,EAAA,KAAA,IAAS,EAAC,CAAA;AAClC,EAAI,IAAA,KAAA,CAAM,WAAW,CAAG,EAAA;AACtB,IAAO,OAAA,IAAA,CAAA;AAAA,GACT;AAEA,EACE,uBAAA,KAAA,CAAA,aAAA,CAAC,4BACE,KAAA,CAAA,aAAA,CAAA,UAAA,EAAA,EAAW,OAAO,EAAE,aAAA,EAAe,OAAS,EAAA,KAAA,EAAO,MAAM,KAAO,EAAA,CAAA,sCAChE,IAAK,EAAA,EAAA,SAAA,EAAS,MAAC,OAAS,EAAA,CAAA,EAAA,EACtB,KAAM,CAAA,GAAA,CAAI,CAAY,QAAA,KAAA;AACrB,IAAA,2CACG,IAAK,EAAA,EAAA,IAAA,EAAI,MAAC,EAAI,EAAA,EAAA,EAAI,KAAK,QAAS,CAAA,EAAA,EAAA,sCAC9B,YAAa,EAAA,EAAA,IAAA,EAAM,UAAU,IAAM,EAAA,KAAA,CAAM,UAAU,CACpD,kBAAA,KAAA,CAAA,aAAA,CAAC,aAAQ,CACX,CAAA,CAAA;AAAA,GAEH,CACH,CACF,CAAA,CAAA;AAEJ;;;;"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { useRouteRef } from '@backstage/core-plugin-api';
|
|
3
|
+
import { useEntityPresentation } from '@backstage/plugin-catalog-react';
|
|
4
|
+
import { Link } from '@backstage/core-components';
|
|
5
|
+
import { useTranslation } from '../../utils/hooks.esm.js';
|
|
6
|
+
import { userRouteRef } from '../../routes.esm.js';
|
|
7
|
+
|
|
8
|
+
const UserLink = (props) => {
|
|
9
|
+
const { entityRef, linkProps } = props;
|
|
10
|
+
const userRoute = useRouteRef(userRouteRef);
|
|
11
|
+
const { t } = useTranslation();
|
|
12
|
+
const { primaryTitle: userName } = useEntityPresentation(
|
|
13
|
+
entityRef.startsWith("user:") ? entityRef : `user:${entityRef}`
|
|
14
|
+
);
|
|
15
|
+
if (entityRef === "anonymous") {
|
|
16
|
+
return /* @__PURE__ */ React.createElement(React.Fragment, null, t("userLink.anonymous"));
|
|
17
|
+
}
|
|
18
|
+
return /* @__PURE__ */ React.createElement(Link, { to: `${userRoute()}/${entityRef}`, ...linkProps }, userName);
|
|
19
|
+
};
|
|
20
|
+
const AuthorLink = (props) => {
|
|
21
|
+
const { entity, linkProps } = props;
|
|
22
|
+
return /* @__PURE__ */ React.createElement(UserLink, { entityRef: entity.author, linkProps });
|
|
23
|
+
};
|
|
24
|
+
const UpdatedByLink = (props) => {
|
|
25
|
+
const { entity, linkProps } = props;
|
|
26
|
+
if (!entity.updatedBy) {
|
|
27
|
+
return null;
|
|
28
|
+
}
|
|
29
|
+
return /* @__PURE__ */ React.createElement(UserLink, { entityRef: entity.updatedBy, linkProps });
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
export { AuthorLink, UpdatedByLink, UserLink };
|
|
33
|
+
//# sourceMappingURL=Links.esm.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Links.esm.js","sources":["../../../src/components/Links/Links.tsx"],"sourcesContent":["import React from 'react';\nimport { useRouteRef } from '@backstage/core-plugin-api';\nimport { useEntityPresentation } from '@backstage/plugin-catalog-react';\nimport { Link, LinkProps } from '@backstage/core-components';\nimport { useTranslation } from '../../utils/hooks';\nimport { userRouteRef } from '../../routes';\nimport { Answer, Comment, Post } from '@drodil/backstage-plugin-qeta-common';\n\nexport const UserLink = (props: {\n entityRef: string;\n linkProps?: LinkProps;\n}) => {\n const { entityRef, linkProps } = props;\n const userRoute = useRouteRef(userRouteRef);\n const { t } = useTranslation();\n const { primaryTitle: userName } = useEntityPresentation(\n entityRef.startsWith('user:') ? entityRef : `user:${entityRef}`,\n );\n if (entityRef === 'anonymous') {\n return <>{t('userLink.anonymous')}</>;\n }\n return (\n <Link to={`${userRoute()}/${entityRef}`} {...linkProps}>\n {userName}\n </Link>\n );\n};\n\nexport const AuthorLink = (props: {\n entity: Post | Answer | Comment;\n linkProps?: LinkProps;\n}) => {\n const { entity, linkProps } = props;\n return <UserLink entityRef={entity.author} linkProps={linkProps} />;\n};\n\nexport const UpdatedByLink = (props: {\n entity: Post | Answer | Comment;\n linkProps?: LinkProps;\n}) => {\n const { entity, linkProps } = props;\n if (!entity.updatedBy) {\n return null;\n }\n return <UserLink entityRef={entity.updatedBy} linkProps={linkProps} />;\n};\n"],"names":[],"mappings":";;;;;;;AAQa,MAAA,QAAA,GAAW,CAAC,KAGnB,KAAA;AACJ,EAAM,MAAA,EAAE,SAAW,EAAA,SAAA,EAAc,GAAA,KAAA,CAAA;AACjC,EAAM,MAAA,SAAA,GAAY,YAAY,YAAY,CAAA,CAAA;AAC1C,EAAM,MAAA,EAAE,CAAE,EAAA,GAAI,cAAe,EAAA,CAAA;AAC7B,EAAM,MAAA,EAAE,YAAc,EAAA,QAAA,EAAa,GAAA,qBAAA;AAAA,IACjC,UAAU,UAAW,CAAA,OAAO,CAAI,GAAA,SAAA,GAAY,QAAQ,SAAS,CAAA,CAAA;AAAA,GAC/D,CAAA;AACA,EAAA,IAAI,cAAc,WAAa,EAAA;AAC7B,IAAO,uBAAA,KAAA,CAAA,aAAA,CAAA,KAAA,CAAA,QAAA,EAAA,IAAA,EAAG,CAAE,CAAA,oBAAoB,CAAE,CAAA,CAAA;AAAA,GACpC;AACA,EACE,uBAAA,KAAA,CAAA,aAAA,CAAC,IAAK,EAAA,EAAA,EAAA,EAAI,CAAG,EAAA,SAAA,EAAW,CAAA,CAAA,EAAI,SAAS,CAAA,CAAA,EAAK,GAAG,SAAA,EAAA,EAC1C,QACH,CAAA,CAAA;AAEJ,EAAA;AAEa,MAAA,UAAA,GAAa,CAAC,KAGrB,KAAA;AACJ,EAAM,MAAA,EAAE,MAAQ,EAAA,SAAA,EAAc,GAAA,KAAA,CAAA;AAC9B,EAAA,uBAAQ,KAAA,CAAA,aAAA,CAAA,QAAA,EAAA,EAAS,SAAW,EAAA,MAAA,CAAO,QAAQ,SAAsB,EAAA,CAAA,CAAA;AACnE,EAAA;AAEa,MAAA,aAAA,GAAgB,CAAC,KAGxB,KAAA;AACJ,EAAM,MAAA,EAAE,MAAQ,EAAA,SAAA,EAAc,GAAA,KAAA,CAAA;AAC9B,EAAI,IAAA,CAAC,OAAO,SAAW,EAAA;AACrB,IAAO,OAAA,IAAA,CAAA;AAAA,GACT;AACA,EAAA,uBAAQ,KAAA,CAAA,aAAA,CAAA,QAAA,EAAA,EAAS,SAAW,EAAA,MAAA,CAAO,WAAW,SAAsB,EAAA,CAAA,CAAA;AACtE;;;;"}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import ReactMde from 'react-mde';
|
|
3
|
+
import 'react-mde/lib/styles/css/react-mde.css';
|
|
4
|
+
import 'react-mde/lib/styles/css/react-mde-editor.css';
|
|
5
|
+
import 'react-mde/lib/styles/css/react-mde-toolbar.css';
|
|
6
|
+
import { useStyles } from '../../utils/hooks.esm.js';
|
|
7
|
+
import { useApi, errorApiRef } from '@backstage/core-plugin-api';
|
|
8
|
+
import { qetaApiRef } from '../../api.esm.js';
|
|
9
|
+
import { MarkdownRenderer } from '../MarkdownRenderer/MarkdownRenderer.esm.js';
|
|
10
|
+
import { imageUpload } from '../../utils/utils.esm.js';
|
|
11
|
+
|
|
12
|
+
const MarkdownEditor = (props) => {
|
|
13
|
+
const { config, value, onChange, height, error, placeholder } = props;
|
|
14
|
+
const [selectedTab, setSelectedTab] = React.useState(
|
|
15
|
+
"write"
|
|
16
|
+
);
|
|
17
|
+
const styles = useStyles();
|
|
18
|
+
const errorApi = useApi(errorApiRef);
|
|
19
|
+
const qetaApi = useApi(qetaApiRef);
|
|
20
|
+
const isUploadDisabled = config?.getOptionalBoolean("qeta.storage.disabled") || false;
|
|
21
|
+
return /* @__PURE__ */ React.createElement(
|
|
22
|
+
ReactMde,
|
|
23
|
+
{
|
|
24
|
+
classes: {
|
|
25
|
+
reactMde: `qetaMarkdownEditorEdit ${styles.markdownEditor}`,
|
|
26
|
+
textArea: error ? `qetaMarkdownEditorError ${styles.markdownEditorError}` : void 0,
|
|
27
|
+
preview: "qetaMarkdownEditorPreview",
|
|
28
|
+
toolbar: "qetaMarkdownEditorToolbar"
|
|
29
|
+
},
|
|
30
|
+
value,
|
|
31
|
+
onChange,
|
|
32
|
+
selectedTab,
|
|
33
|
+
onTabChange: setSelectedTab,
|
|
34
|
+
minEditorHeight: height,
|
|
35
|
+
minPreviewHeight: height - 10,
|
|
36
|
+
childProps: {
|
|
37
|
+
textArea: {
|
|
38
|
+
required: true,
|
|
39
|
+
placeholder
|
|
40
|
+
}
|
|
41
|
+
},
|
|
42
|
+
generateMarkdownPreview: (content) => Promise.resolve(
|
|
43
|
+
/* @__PURE__ */ React.createElement(
|
|
44
|
+
MarkdownRenderer,
|
|
45
|
+
{
|
|
46
|
+
content,
|
|
47
|
+
className: `qetaMarkdownEditorPreview ${styles.markdownContent}`
|
|
48
|
+
}
|
|
49
|
+
)
|
|
50
|
+
),
|
|
51
|
+
paste: isUploadDisabled ? void 0 : {
|
|
52
|
+
saveImage: imageUpload({
|
|
53
|
+
qetaApi,
|
|
54
|
+
errorApi,
|
|
55
|
+
onImageUpload: props.onImageUpload
|
|
56
|
+
})
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
);
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
export { MarkdownEditor };
|
|
63
|
+
//# sourceMappingURL=MarkdownEditor.esm.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"MarkdownEditor.esm.js","sources":["../../../src/components/MarkdownEditor/MarkdownEditor.tsx"],"sourcesContent":["/* eslint-disable no-console */\nimport React from 'react';\nimport ReactMde from 'react-mde';\n\nimport { Config } from '@backstage/config';\nimport 'react-mde/lib/styles/css/react-mde.css';\nimport 'react-mde/lib/styles/css/react-mde-editor.css';\nimport 'react-mde/lib/styles/css/react-mde-toolbar.css';\nimport { useStyles } from '../../utils';\nimport { errorApiRef, useApi } from '@backstage/core-plugin-api';\nimport { qetaApiRef } from '../../api';\nimport { MarkdownRenderer } from '../MarkdownRenderer';\nimport { imageUpload } from '../../utils/utils';\n\nexport const MarkdownEditor = (props: {\n config: Config;\n value: string;\n onChange: (value: string) => void;\n height: number;\n error?: boolean;\n placeholder?: string;\n onImageUpload: (imageId: number) => void;\n}) => {\n const { config, value, onChange, height, error, placeholder } = props;\n const [selectedTab, setSelectedTab] = React.useState<'write' | 'preview'>(\n 'write',\n );\n const styles = useStyles();\n const errorApi = useApi(errorApiRef);\n const qetaApi = useApi(qetaApiRef);\n\n const isUploadDisabled =\n config?.getOptionalBoolean('qeta.storage.disabled') || false;\n\n return (\n <ReactMde\n classes={{\n reactMde: `qetaMarkdownEditorEdit ${styles.markdownEditor}`,\n textArea: error\n ? `qetaMarkdownEditorError ${styles.markdownEditorError}`\n : undefined,\n preview: 'qetaMarkdownEditorPreview',\n toolbar: 'qetaMarkdownEditorToolbar',\n }}\n value={value}\n onChange={onChange}\n selectedTab={selectedTab}\n onTabChange={setSelectedTab}\n minEditorHeight={height}\n minPreviewHeight={height - 10}\n childProps={{\n textArea: {\n required: true,\n placeholder,\n },\n }}\n generateMarkdownPreview={content =>\n Promise.resolve(\n <MarkdownRenderer\n content={content}\n className={`qetaMarkdownEditorPreview ${styles.markdownContent}`}\n />,\n )\n }\n paste={\n isUploadDisabled\n ? undefined\n : {\n saveImage: imageUpload({\n qetaApi,\n errorApi,\n onImageUpload: props.onImageUpload,\n }),\n }\n }\n />\n );\n};\n"],"names":[],"mappings":";;;;;;;;;;;AAca,MAAA,cAAA,GAAiB,CAAC,KAQzB,KAAA;AACJ,EAAA,MAAM,EAAE,MAAQ,EAAA,KAAA,EAAO,UAAU,MAAQ,EAAA,KAAA,EAAO,aAAgB,GAAA,KAAA,CAAA;AAChE,EAAA,MAAM,CAAC,WAAA,EAAa,cAAc,CAAA,GAAI,KAAM,CAAA,QAAA;AAAA,IAC1C,OAAA;AAAA,GACF,CAAA;AACA,EAAA,MAAM,SAAS,SAAU,EAAA,CAAA;AACzB,EAAM,MAAA,QAAA,GAAW,OAAO,WAAW,CAAA,CAAA;AACnC,EAAM,MAAA,OAAA,GAAU,OAAO,UAAU,CAAA,CAAA;AAEjC,EAAA,MAAM,gBACJ,GAAA,MAAA,EAAQ,kBAAmB,CAAA,uBAAuB,CAAK,IAAA,KAAA,CAAA;AAEzD,EACE,uBAAA,KAAA,CAAA,aAAA;AAAA,IAAC,QAAA;AAAA,IAAA;AAAA,MACC,OAAS,EAAA;AAAA,QACP,QAAA,EAAU,CAA0B,uBAAA,EAAA,MAAA,CAAO,cAAc,CAAA,CAAA;AAAA,QACzD,QAAU,EAAA,KAAA,GACN,CAA2B,wBAAA,EAAA,MAAA,CAAO,mBAAmB,CACrD,CAAA,GAAA,KAAA,CAAA;AAAA,QACJ,OAAS,EAAA,2BAAA;AAAA,QACT,OAAS,EAAA,2BAAA;AAAA,OACX;AAAA,MACA,KAAA;AAAA,MACA,QAAA;AAAA,MACA,WAAA;AAAA,MACA,WAAa,EAAA,cAAA;AAAA,MACb,eAAiB,EAAA,MAAA;AAAA,MACjB,kBAAkB,MAAS,GAAA,EAAA;AAAA,MAC3B,UAAY,EAAA;AAAA,QACV,QAAU,EAAA;AAAA,UACR,QAAU,EAAA,IAAA;AAAA,UACV,WAAA;AAAA,SACF;AAAA,OACF;AAAA,MACA,uBAAA,EAAyB,aACvB,OAAQ,CAAA,OAAA;AAAA,wBACN,KAAA,CAAA,aAAA;AAAA,UAAC,gBAAA;AAAA,UAAA;AAAA,YACC,OAAA;AAAA,YACA,SAAA,EAAW,CAA6B,0BAAA,EAAA,MAAA,CAAO,eAAe,CAAA,CAAA;AAAA,WAAA;AAAA,SAChE;AAAA,OACF;AAAA,MAEF,KAAA,EACE,mBACI,KACA,CAAA,GAAA;AAAA,QACE,WAAW,WAAY,CAAA;AAAA,UACrB,OAAA;AAAA,UACA,QAAA;AAAA,UACA,eAAe,KAAM,CAAA,aAAA;AAAA,SACtB,CAAA;AAAA,OACH;AAAA,KAAA;AAAA,GAER,CAAA;AAEJ;;;;"}
|