@drodil/backstage-plugin-qeta 2.3.0 → 2.3.2
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/QetaClient.esm.js +434 -0
- package/dist/api/QetaClient.esm.js.map +1 -0
- package/dist/components/AskAnonymouslyCheckbox/AskAnonymouslyCheckbox.esm.js +32 -0
- package/dist/components/AskAnonymouslyCheckbox/AskAnonymouslyCheckbox.esm.js.map +1 -0
- package/dist/components/AskForm/AskForm.esm.js +218 -0
- package/dist/components/AskForm/AskForm.esm.js.map +1 -0
- package/dist/components/AskForm/EntitiesInput.esm.js +98 -0
- package/dist/components/AskForm/EntitiesInput.esm.js.map +1 -0
- package/dist/components/AskForm/TagInput.esm.js +86 -0
- package/dist/components/AskForm/TagInput.esm.js.map +1 -0
- package/dist/components/AskPage/AskPage.esm.js +38 -0
- package/dist/components/AskPage/AskPage.esm.js.map +1 -0
- package/dist/components/Buttons/AskQuestionButton.esm.js +43 -0
- package/dist/components/Buttons/AskQuestionButton.esm.js.map +1 -0
- package/dist/components/Buttons/BackToQuestionsButton.esm.js +38 -0
- package/dist/components/Buttons/BackToQuestionsButton.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 +97 -0
- package/dist/components/CommentSection/CommentSection.esm.js.map +1 -0
- package/dist/components/DeleteModal/DeleteModal.esm.js +77 -0
- package/dist/components/DeleteModal/DeleteModal.esm.js.map +1 -0
- package/dist/components/FavoritePage/FavoritePage.esm.js +13 -0
- package/dist/components/FavoritePage/FavoritePage.esm.js.map +1 -0
- package/dist/components/HomePage/HomePage.esm.js +144 -0
- package/dist/components/HomePage/HomePage.esm.js.map +1 -0
- package/dist/components/HomePage/index.esm.js +2 -0
- package/dist/components/HomePage/index.esm.js.map +1 -0
- package/dist/components/Links/Links.esm.js +31 -0
- package/dist/components/Links/Links.esm.js.map +1 -0
- package/dist/components/MarkdownEditor/MarkdownEditor.esm.js +80 -0
- package/dist/components/MarkdownEditor/MarkdownEditor.esm.js.map +1 -0
- package/dist/components/QuestionHighlightList/QuestionHighlightList.esm.js +61 -0
- package/dist/components/QuestionHighlightList/QuestionHighlightList.esm.js.map +1 -0
- package/dist/components/QuestionPage/AnswerCard.esm.js +101 -0
- package/dist/components/QuestionPage/AnswerCard.esm.js.map +1 -0
- package/dist/components/QuestionPage/AnswerForm.esm.js +130 -0
- package/dist/components/QuestionPage/AnswerForm.esm.js.map +1 -0
- package/dist/components/QuestionPage/AuthorBox.esm.js +25 -0
- package/dist/components/QuestionPage/AuthorBox.esm.js.map +1 -0
- package/dist/components/QuestionPage/EntityChip.esm.js +26 -0
- package/dist/components/QuestionPage/EntityChip.esm.js.map +1 -0
- package/dist/components/QuestionPage/FavoriteButton.esm.js +43 -0
- package/dist/components/QuestionPage/FavoriteButton.esm.js.map +1 -0
- package/dist/components/QuestionPage/LinkButton.esm.js +32 -0
- package/dist/components/QuestionPage/LinkButton.esm.js.map +1 -0
- package/dist/components/QuestionPage/QuestionCard.esm.js +103 -0
- package/dist/components/QuestionPage/QuestionCard.esm.js.map +1 -0
- package/dist/components/QuestionPage/QuestionPage.esm.js +131 -0
- package/dist/components/QuestionPage/QuestionPage.esm.js.map +1 -0
- package/dist/components/QuestionPage/TagsAndEntities.esm.js +44 -0
- package/dist/components/QuestionPage/TagsAndEntities.esm.js.map +1 -0
- package/dist/components/QuestionPage/VoteButtons.esm.js +146 -0
- package/dist/components/QuestionPage/VoteButtons.esm.js.map +1 -0
- package/dist/components/QuestionTableCard/Content.esm.js +9 -0
- package/dist/components/QuestionTableCard/Content.esm.js.map +1 -0
- package/dist/components/QuestionTableCard/QuestionTableRow.esm.js +21 -0
- package/dist/components/QuestionTableCard/QuestionTableRow.esm.js.map +1 -0
- package/dist/components/QuestionTableCard/QuestionsTable.esm.js +130 -0
- package/dist/components/QuestionTableCard/QuestionsTable.esm.js.map +1 -0
- package/dist/components/QuestionTableCard/index.esm.js +3 -0
- package/dist/components/QuestionTableCard/index.esm.js.map +1 -0
- package/dist/components/QuestionsContainer/FilterPanel.esm.js +230 -0
- package/dist/components/QuestionsContainer/FilterPanel.esm.js.map +1 -0
- package/dist/components/QuestionsContainer/NoQuestionsCard.esm.js +46 -0
- package/dist/components/QuestionsContainer/NoQuestionsCard.esm.js.map +1 -0
- package/dist/components/QuestionsContainer/QuestionList.esm.js +102 -0
- package/dist/components/QuestionsContainer/QuestionList.esm.js.map +1 -0
- package/dist/components/QuestionsContainer/QuestionListItem.esm.js +119 -0
- package/dist/components/QuestionsContainer/QuestionListItem.esm.js.map +1 -0
- package/dist/components/QuestionsContainer/QuestionsContainer.esm.js +231 -0
- package/dist/components/QuestionsContainer/QuestionsContainer.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/Statistics/StatisticsPage.esm.js +13 -0
- package/dist/components/Statistics/StatisticsPage.esm.js.map +1 -0
- package/dist/components/Statistics/TopRankingUsersCard.esm.js +163 -0
- package/dist/components/Statistics/TopRankingUsersCard.esm.js.map +1 -0
- package/dist/components/Statistics/TrophyIcon.esm.js +19 -0
- package/dist/components/Statistics/TrophyIcon.esm.js.map +1 -0
- package/dist/components/Statistics/styles.esm.js +23 -0
- package/dist/components/Statistics/styles.esm.js.map +1 -0
- package/dist/components/TagPage/TagPage.esm.js +16 -0
- package/dist/components/TagPage/TagPage.esm.js.map +1 -0
- package/dist/components/TagPage/TagsContainer.esm.js +63 -0
- package/dist/components/TagPage/TagsContainer.esm.js.map +1 -0
- package/dist/components/UserPage/UserPage.esm.js +24 -0
- package/dist/components/UserPage/UserPage.esm.js.map +1 -0
- package/dist/index.esm.js +9 -32
- package/dist/index.esm.js.map +1 -1
- package/dist/plugin.esm.js +60 -0
- package/dist/plugin.esm.js.map +1 -0
- package/dist/utils/hooks.esm.js +283 -0
- package/dist/utils/hooks.esm.js.map +1 -0
- package/dist/utils/utils.esm.js +31 -0
- package/dist/utils/utils.esm.js.map +1 -0
- package/package.json +15 -15
- package/dist/esm/index-C7A2tOkT.esm.js +0 -33
- package/dist/esm/index-C7A2tOkT.esm.js.map +0 -1
- package/dist/esm/index-CFNWBJNR.esm.js +0 -2412
- package/dist/esm/index-CFNWBJNR.esm.js.map +0 -1
- package/dist/esm/index-rSPV8dxK.esm.js +0 -1120
- package/dist/esm/index-rSPV8dxK.esm.js.map +0 -1
|
@@ -1,1120 +0,0 @@
|
|
|
1
|
-
import React, { useState, useEffect } from 'react';
|
|
2
|
-
import { Grid, makeStyles, createStyles, Tooltip, IconButton, Typography, Box, Modal, Backdrop, Button, Avatar, Divider, TextField, Card, CardContent, Container, FormControl, Select, Chip, List, ListSubheader, ListItem, ListItemText, Menu, MenuItem, ListItemIcon } from '@material-ui/core';
|
|
3
|
-
import { Content, ContentHeader, InfoCard, MarkdownContent, Link, WarningPanel, Progress, Page, Header } from '@backstage/core-components';
|
|
4
|
-
import { useParams, useSearchParams, useNavigate, Routes, Route } from 'react-router-dom';
|
|
5
|
-
import { B as BackToQuestionsButton, A as AskForm, q as qetaApiRef, u as useBasePath, a as useStyles$1, b as useEntityAuthor, R as RelativeTimeWithTooltip, U as UpdatedByLink, c as AuthorLink, T as TagsAndEntities, M as MarkdownEditor, d as AskAnonymouslyCheckbox, e as useQetaApi, f as AskQuestionButton, g as QuestionsContainer, S as StatisticsPage, h as useIdentityApi, i as TrophyIcon } from './index-CFNWBJNR.esm.js';
|
|
6
|
-
import { useEntityPresentation } from '@backstage/plugin-catalog-react';
|
|
7
|
-
import { filterTags, qetaCreateAnswerPermission } from '@drodil/backstage-plugin-qeta-common';
|
|
8
|
-
import ArrowDownward from '@material-ui/icons/ArrowDownward';
|
|
9
|
-
import ArrowUpward from '@material-ui/icons/ArrowUpward';
|
|
10
|
-
import Check from '@material-ui/icons/Check';
|
|
11
|
-
import { useAnalytics, useApi, useRouteRef, configApiRef } from '@backstage/core-plugin-api';
|
|
12
|
-
import { useSignal } from '@backstage/plugin-signals-react';
|
|
13
|
-
import { Alert, Skeleton } from '@material-ui/lab';
|
|
14
|
-
import DeleteIcon from '@material-ui/icons/Delete';
|
|
15
|
-
import EditIcon from '@material-ui/icons/Edit';
|
|
16
|
-
import StarIcon from '@material-ui/icons/Star';
|
|
17
|
-
import StarOutlineIcon from '@material-ui/icons/StarOutline';
|
|
18
|
-
import { useForm, Controller } from 'react-hook-form';
|
|
19
|
-
import { editQuestionRouteRef, tagRouteRef, questionRouteRef, askRouteRef, favoriteQuestionsRouteRef, tagsRouteRef, userRouteRef, statisticsRouteRef } from '@drodil/backstage-plugin-qeta-react';
|
|
20
|
-
import Link$1 from '@material-ui/icons/Link';
|
|
21
|
-
import { RequirePermission } from '@backstage/plugin-permission-react';
|
|
22
|
-
import LoyaltyOutlined from '@material-ui/icons/LoyaltyOutlined';
|
|
23
|
-
import Whatshot from '@material-ui/icons/Whatshot';
|
|
24
|
-
import MoreVertIcon from '@material-ui/icons/MoreVert';
|
|
25
|
-
import AccountBox from '@material-ui/icons/AccountBox';
|
|
26
|
-
import '@backstage/plugin-home-react';
|
|
27
|
-
import '@backstage/errors';
|
|
28
|
-
import 'lodash/omitBy';
|
|
29
|
-
import 'lodash/isEmpty';
|
|
30
|
-
import 'react-use/lib/useAsync';
|
|
31
|
-
import 'lodash';
|
|
32
|
-
import 'react-use/lib/useDebounce';
|
|
33
|
-
import '@backstage/catalog-model';
|
|
34
|
-
import 'dompurify';
|
|
35
|
-
import 'react-relative-time';
|
|
36
|
-
import '@material-ui/icons/HelpOutline';
|
|
37
|
-
import '@material-ui/icons/FilterList';
|
|
38
|
-
import 'react-mde';
|
|
39
|
-
import 'react-mde/lib/styles/css/react-mde.css';
|
|
40
|
-
import 'react-mde/lib/styles/css/react-mde-editor.css';
|
|
41
|
-
import 'react-mde/lib/styles/css/react-mde-toolbar.css';
|
|
42
|
-
import 'file-type';
|
|
43
|
-
import '@material-ui/icons/Refresh';
|
|
44
|
-
import '@material-ui/icons/HomeOutlined';
|
|
45
|
-
|
|
46
|
-
const AskPage = () => {
|
|
47
|
-
var _a;
|
|
48
|
-
const { id } = useParams();
|
|
49
|
-
const [searchParams] = useSearchParams();
|
|
50
|
-
const entity = (_a = searchParams.get("entity")) != null ? _a : void 0;
|
|
51
|
-
const entityPage = searchParams.get("entityPage") === "true";
|
|
52
|
-
const tags = filterTags(searchParams.get("tags"));
|
|
53
|
-
let title;
|
|
54
|
-
if (id) {
|
|
55
|
-
title = "Edit question";
|
|
56
|
-
} else if (entity) {
|
|
57
|
-
const representation = useEntityPresentation(entity);
|
|
58
|
-
title = `Ask a question about ${representation.primaryTitle}`;
|
|
59
|
-
} else {
|
|
60
|
-
title = "Ask question";
|
|
61
|
-
}
|
|
62
|
-
return /* @__PURE__ */ React.createElement(Content, { className: "qetaAskPage" }, /* @__PURE__ */ React.createElement(ContentHeader, { title }, /* @__PURE__ */ React.createElement(BackToQuestionsButton, { entityPage })), /* @__PURE__ */ React.createElement(Grid, { container: true, spacing: 3, direction: "column" }, /* @__PURE__ */ React.createElement(Grid, { item: true }, /* @__PURE__ */ React.createElement(InfoCard, null, /* @__PURE__ */ React.createElement(
|
|
63
|
-
AskForm,
|
|
64
|
-
{
|
|
65
|
-
id,
|
|
66
|
-
entity,
|
|
67
|
-
entityPage,
|
|
68
|
-
tags
|
|
69
|
-
}
|
|
70
|
-
)))));
|
|
71
|
-
};
|
|
72
|
-
|
|
73
|
-
const useStyles = makeStyles(
|
|
74
|
-
(theme) => createStyles({
|
|
75
|
-
qetaCorrectAnswerSelected: {
|
|
76
|
-
color: theme.palette.success.main
|
|
77
|
-
},
|
|
78
|
-
qetaCorrectAnswer: {
|
|
79
|
-
color: theme.palette.grey[500]
|
|
80
|
-
}
|
|
81
|
-
})
|
|
82
|
-
);
|
|
83
|
-
const VoteButtons = (props) => {
|
|
84
|
-
var _a, _b, _c, _d, _e, _f, _g;
|
|
85
|
-
const [entity, setEntity] = React.useState(
|
|
86
|
-
props.entity
|
|
87
|
-
);
|
|
88
|
-
const [ownVote, setOwnVote] = React.useState((_a = props.entity.ownVote) != null ? _a : 0);
|
|
89
|
-
const [correctAnswer, setCorrectAnswer] = useState(
|
|
90
|
-
"questionId" in props.entity ? props.entity.correct : false
|
|
91
|
-
);
|
|
92
|
-
const [score, setScore] = useState(entity.score);
|
|
93
|
-
const analytics = useAnalytics();
|
|
94
|
-
const qetaApi = useApi(qetaApiRef);
|
|
95
|
-
const isQuestion = "title" in entity;
|
|
96
|
-
const own = (_b = props.entity.own) != null ? _b : false;
|
|
97
|
-
const classes = useStyles();
|
|
98
|
-
const { lastSignal } = useSignal(
|
|
99
|
-
isQuestion ? `qeta:question_${entity.id}` : `qeta:answer_${entity.id}`
|
|
100
|
-
);
|
|
101
|
-
useEffect(() => {
|
|
102
|
-
if (entity) {
|
|
103
|
-
setScore(entity.score);
|
|
104
|
-
}
|
|
105
|
-
}, [entity]);
|
|
106
|
-
useEffect(() => {
|
|
107
|
-
if ((lastSignal == null ? void 0 : lastSignal.type) === "question_stats" || (lastSignal == null ? void 0 : lastSignal.type) === "answer_stats") {
|
|
108
|
-
setCorrectAnswer(lastSignal.correctAnswer);
|
|
109
|
-
setScore(lastSignal.score);
|
|
110
|
-
}
|
|
111
|
-
}, [lastSignal]);
|
|
112
|
-
const voteUp = () => {
|
|
113
|
-
if (isQuestion) {
|
|
114
|
-
qetaApi.voteQuestionUp(entity.id).then((response) => {
|
|
115
|
-
setOwnVote(1);
|
|
116
|
-
analytics.captureEvent("vote", "question", { value: 1 });
|
|
117
|
-
setEntity(response);
|
|
118
|
-
});
|
|
119
|
-
} else if ("questionId" in entity) {
|
|
120
|
-
qetaApi.voteAnswerUp(entity.questionId, entity.id).then((response) => {
|
|
121
|
-
setOwnVote(1);
|
|
122
|
-
analytics.captureEvent("vote", "answer", { value: 1 });
|
|
123
|
-
setEntity(response);
|
|
124
|
-
});
|
|
125
|
-
}
|
|
126
|
-
};
|
|
127
|
-
const voteDown = () => {
|
|
128
|
-
if (isQuestion) {
|
|
129
|
-
qetaApi.voteQuestionDown(entity.id).then((response) => {
|
|
130
|
-
setOwnVote(-1);
|
|
131
|
-
analytics.captureEvent("vote", "question", { value: -1 });
|
|
132
|
-
setEntity(response);
|
|
133
|
-
});
|
|
134
|
-
} else if ("questionId" in entity) {
|
|
135
|
-
qetaApi.voteAnswerDown(entity.questionId, entity.id).then((response) => {
|
|
136
|
-
setOwnVote(-1);
|
|
137
|
-
analytics.captureEvent("vote", "answer", { value: -1 });
|
|
138
|
-
setEntity(response);
|
|
139
|
-
});
|
|
140
|
-
}
|
|
141
|
-
};
|
|
142
|
-
let correctTooltip = correctAnswer ? "Mark answer as incorrect" : "Mark answer as correct";
|
|
143
|
-
if (!((_c = props.question) == null ? void 0 : _c.own)) {
|
|
144
|
-
correctTooltip = correctAnswer ? "This answer has been marked as correct" : "";
|
|
145
|
-
}
|
|
146
|
-
let voteUpTooltip = isQuestion ? "This question is good" : "This answer is good";
|
|
147
|
-
if (own) {
|
|
148
|
-
voteUpTooltip = isQuestion ? "You cannot vote your own question" : "You cannot vote your own answer";
|
|
149
|
-
}
|
|
150
|
-
let voteDownTooltip = isQuestion ? "This question is not good" : "This answer is not good";
|
|
151
|
-
if (own) {
|
|
152
|
-
voteDownTooltip = voteUpTooltip;
|
|
153
|
-
}
|
|
154
|
-
const toggleCorrectAnswer = () => {
|
|
155
|
-
if (!("questionId" in entity)) {
|
|
156
|
-
return;
|
|
157
|
-
}
|
|
158
|
-
if (correctAnswer) {
|
|
159
|
-
qetaApi.markAnswerIncorrect(entity.questionId, entity.id).then((response) => {
|
|
160
|
-
if (response) {
|
|
161
|
-
setCorrectAnswer(false);
|
|
162
|
-
}
|
|
163
|
-
});
|
|
164
|
-
} else {
|
|
165
|
-
qetaApi.markAnswerCorrect(entity.questionId, entity.id).then((response) => {
|
|
166
|
-
setCorrectAnswer(response);
|
|
167
|
-
});
|
|
168
|
-
}
|
|
169
|
-
};
|
|
170
|
-
return /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement(Tooltip, { title: voteUpTooltip }, /* @__PURE__ */ React.createElement("span", null, /* @__PURE__ */ React.createElement(
|
|
171
|
-
IconButton,
|
|
172
|
-
{
|
|
173
|
-
"aria-label": "vote up",
|
|
174
|
-
color: ownVote > 0 ? "primary" : "default",
|
|
175
|
-
className: ownVote > 0 ? "qetaVoteUpSelected" : "qetaVoteUp",
|
|
176
|
-
disabled: own,
|
|
177
|
-
size: "small",
|
|
178
|
-
onClick: voteUp
|
|
179
|
-
},
|
|
180
|
-
/* @__PURE__ */ React.createElement(ArrowUpward, null)
|
|
181
|
-
))), /* @__PURE__ */ React.createElement(Typography, { variant: "h6" }, score), /* @__PURE__ */ React.createElement(Tooltip, { title: voteDownTooltip }, /* @__PURE__ */ React.createElement("span", null, /* @__PURE__ */ React.createElement(
|
|
182
|
-
IconButton,
|
|
183
|
-
{
|
|
184
|
-
"aria-label": "vote down",
|
|
185
|
-
color: ownVote < 0 ? "primary" : "default",
|
|
186
|
-
className: ownVote < 0 ? "qetaVoteDownSelected" : "qetaVoteDown",
|
|
187
|
-
disabled: own,
|
|
188
|
-
size: "small",
|
|
189
|
-
onClick: voteDown
|
|
190
|
-
},
|
|
191
|
-
/* @__PURE__ */ React.createElement(ArrowDownward, null)
|
|
192
|
-
))), "correct" in props.entity && (((_d = props.question) == null ? void 0 : _d.own) || ((_e = props.question) == null ? void 0 : _e.canEdit) || correctAnswer) && /* @__PURE__ */ React.createElement(Box, null, /* @__PURE__ */ React.createElement(Tooltip, { title: correctTooltip }, /* @__PURE__ */ React.createElement("span", null, /* @__PURE__ */ React.createElement(
|
|
193
|
-
IconButton,
|
|
194
|
-
{
|
|
195
|
-
"aria-label": "mark correct",
|
|
196
|
-
size: "small",
|
|
197
|
-
onClick: ((_f = props.question) == null ? void 0 : _f.own) || ((_g = props.question) == null ? void 0 : _g.canEdit) ? toggleCorrectAnswer : void 0
|
|
198
|
-
},
|
|
199
|
-
/* @__PURE__ */ React.createElement(
|
|
200
|
-
Check,
|
|
201
|
-
{
|
|
202
|
-
className: correctAnswer ? classes.qetaCorrectAnswerSelected : classes.qetaCorrectAnswer
|
|
203
|
-
}
|
|
204
|
-
)
|
|
205
|
-
)))));
|
|
206
|
-
};
|
|
207
|
-
|
|
208
|
-
const DeleteModal = (props) => {
|
|
209
|
-
const qetaApi = useApi(qetaApiRef);
|
|
210
|
-
const base_path = useBasePath();
|
|
211
|
-
const navigate = useNavigate();
|
|
212
|
-
const { entity, open, question, onClose } = props;
|
|
213
|
-
const styles = useStyles$1();
|
|
214
|
-
const [error, setError] = React.useState(false);
|
|
215
|
-
const isQuestion = "title" in entity;
|
|
216
|
-
const title = isQuestion ? "Are you sure you want to delete this question?" : "Are you sure you want to delete this answer?";
|
|
217
|
-
const handleDelete = () => {
|
|
218
|
-
if (isQuestion) {
|
|
219
|
-
qetaApi.deleteQuestion(entity.id).catch((_) => setError(true)).then((ret) => {
|
|
220
|
-
if (ret) {
|
|
221
|
-
onClose();
|
|
222
|
-
navigate(`${base_path}/qeta`);
|
|
223
|
-
} else {
|
|
224
|
-
setError(true);
|
|
225
|
-
}
|
|
226
|
-
});
|
|
227
|
-
} else if (question) {
|
|
228
|
-
qetaApi.deleteAnswer(question.id, entity.id).catch((_) => setError(true)).then((ret) => {
|
|
229
|
-
if (ret) {
|
|
230
|
-
onClose();
|
|
231
|
-
window.location.reload();
|
|
232
|
-
} else {
|
|
233
|
-
setError(true);
|
|
234
|
-
}
|
|
235
|
-
});
|
|
236
|
-
}
|
|
237
|
-
};
|
|
238
|
-
return /* @__PURE__ */ React.createElement(
|
|
239
|
-
Modal,
|
|
240
|
-
{
|
|
241
|
-
open,
|
|
242
|
-
onClose,
|
|
243
|
-
className: "qetaDeleteModal",
|
|
244
|
-
"aria-labelledby": "modal-modal-title",
|
|
245
|
-
"aria-describedby": "modal-modal-description",
|
|
246
|
-
closeAfterTransition: true,
|
|
247
|
-
BackdropComponent: Backdrop,
|
|
248
|
-
BackdropProps: {
|
|
249
|
-
timeout: 500
|
|
250
|
-
}
|
|
251
|
-
},
|
|
252
|
-
/* @__PURE__ */ React.createElement(Box, { className: `qetaDeleteModalContent ${styles.deleteModal}` }, error && /* @__PURE__ */ React.createElement(Alert, { severity: "error" }, "Failed to delete"), /* @__PURE__ */ React.createElement(
|
|
253
|
-
Typography,
|
|
254
|
-
{
|
|
255
|
-
id: "modal-modal-title",
|
|
256
|
-
className: "qetaDeleteModalTitle",
|
|
257
|
-
variant: "h6",
|
|
258
|
-
component: "h2"
|
|
259
|
-
},
|
|
260
|
-
title
|
|
261
|
-
), /* @__PURE__ */ React.createElement(
|
|
262
|
-
Button,
|
|
263
|
-
{
|
|
264
|
-
onClick: handleDelete,
|
|
265
|
-
className: "qetaDeleteModalDeleteBtn",
|
|
266
|
-
startIcon: /* @__PURE__ */ React.createElement(DeleteIcon, null),
|
|
267
|
-
color: "secondary"
|
|
268
|
-
},
|
|
269
|
-
"Delete"
|
|
270
|
-
), /* @__PURE__ */ React.createElement(Button, { onClick: onClose, className: "qetaDeleteModalCancelBtn" }, "Cancel"))
|
|
271
|
-
);
|
|
272
|
-
};
|
|
273
|
-
|
|
274
|
-
const FavoriteButton = (props) => {
|
|
275
|
-
const [entity, setEntity] = React.useState(props.entity);
|
|
276
|
-
const qetaApi = useApi(qetaApiRef);
|
|
277
|
-
const favoriteQuestion = () => {
|
|
278
|
-
qetaApi.favoriteQuestion(entity.id).then((response) => {
|
|
279
|
-
setEntity(response);
|
|
280
|
-
});
|
|
281
|
-
};
|
|
282
|
-
const unfavoriteQuestion = () => {
|
|
283
|
-
qetaApi.unfavoriteQuestion(entity.id).then((response) => {
|
|
284
|
-
setEntity(response);
|
|
285
|
-
});
|
|
286
|
-
};
|
|
287
|
-
return /* @__PURE__ */ React.createElement(React.Fragment, null, entity.favorite ? /* @__PURE__ */ React.createElement(Tooltip, { title: "Remove this question from favorites" }, /* @__PURE__ */ React.createElement(
|
|
288
|
-
IconButton,
|
|
289
|
-
{
|
|
290
|
-
"aria-label": "unfavorite",
|
|
291
|
-
size: "small",
|
|
292
|
-
onClick: unfavoriteQuestion,
|
|
293
|
-
className: "qetaUnfavoriteBtn"
|
|
294
|
-
},
|
|
295
|
-
/* @__PURE__ */ React.createElement(StarIcon, null)
|
|
296
|
-
)) : /* @__PURE__ */ React.createElement(Tooltip, { title: "Mark this question as favorite" }, /* @__PURE__ */ React.createElement(
|
|
297
|
-
IconButton,
|
|
298
|
-
{
|
|
299
|
-
"aria-label": "favorite",
|
|
300
|
-
size: "small",
|
|
301
|
-
onClick: favoriteQuestion,
|
|
302
|
-
className: "qetaFavoriteBtn"
|
|
303
|
-
},
|
|
304
|
-
/* @__PURE__ */ React.createElement(StarOutlineIcon, null)
|
|
305
|
-
)));
|
|
306
|
-
};
|
|
307
|
-
|
|
308
|
-
const AuthorBox = (props) => {
|
|
309
|
-
var _a, _b;
|
|
310
|
-
const { entity } = props;
|
|
311
|
-
const styles = useStyles$1();
|
|
312
|
-
const { name, initials, user } = useEntityAuthor(entity);
|
|
313
|
-
return /* @__PURE__ */ React.createElement(Box, { className: `qetaAuthorBox ${styles.questionCardAuthor}` }, /* @__PURE__ */ React.createElement(Grid, { container: true, alignItems: "center" }, /* @__PURE__ */ React.createElement(Grid, { item: true, xs: 12, style: { paddingBottom: 0 } }, /* @__PURE__ */ React.createElement(Typography, { className: "qetaAuthorBoxCreated", variant: "caption" }, "Posted ", /* @__PURE__ */ React.createElement(RelativeTimeWithTooltip, { value: entity.created }))), entity.updated && entity.updatedBy && /* @__PURE__ */ React.createElement(Grid, { item: true, xs: 12, style: { paddingBottom: 0, paddingTop: 0 } }, /* @__PURE__ */ React.createElement(Typography, { className: "qetaAuthorBoxUpdated", variant: "caption" }, "Updated ", /* @__PURE__ */ React.createElement(RelativeTimeWithTooltip, { value: entity.updated }), " by", " ", /* @__PURE__ */ React.createElement(UpdatedByLink, { entity }))), /* @__PURE__ */ React.createElement(Grid, { item: true, xs: 2 }, /* @__PURE__ */ React.createElement(
|
|
314
|
-
Avatar,
|
|
315
|
-
{
|
|
316
|
-
src: (_b = (_a = user == null ? void 0 : user.spec) == null ? void 0 : _a.profile) == null ? void 0 : _b.picture,
|
|
317
|
-
className: "qetaAuthorBoxAvatar avatar",
|
|
318
|
-
alt: name,
|
|
319
|
-
variant: "rounded"
|
|
320
|
-
},
|
|
321
|
-
initials
|
|
322
|
-
)), /* @__PURE__ */ React.createElement(Grid, { item: true, xs: 10, className: styles.authorLink }, /* @__PURE__ */ React.createElement(Box, { style: { paddingLeft: "5px" } }, /* @__PURE__ */ React.createElement(AuthorLink, { entity })))));
|
|
323
|
-
};
|
|
324
|
-
|
|
325
|
-
const CommentList = (props) => {
|
|
326
|
-
var _a;
|
|
327
|
-
const { question, answer, onCommentDelete } = props;
|
|
328
|
-
const entity = answer != null ? answer : question;
|
|
329
|
-
const styles = useStyles$1();
|
|
330
|
-
const qetaApi = useApi(qetaApiRef);
|
|
331
|
-
const deleteComment = (id) => {
|
|
332
|
-
if (answer) {
|
|
333
|
-
qetaApi.deleteAnswerComment(question.id, answer.id, id).then((a) => {
|
|
334
|
-
onCommentDelete(question, a);
|
|
335
|
-
return;
|
|
336
|
-
});
|
|
337
|
-
}
|
|
338
|
-
qetaApi.deleteQuestionComment(question.id, id).then((q) => onCommentDelete(q));
|
|
339
|
-
};
|
|
340
|
-
return /* @__PURE__ */ React.createElement(React.Fragment, null, (_a = entity.comments) == null ? void 0 : _a.map((c) => {
|
|
341
|
-
return /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement(Box, { key: c.id, className: "qetaCommentBox" }, /* @__PURE__ */ React.createElement(
|
|
342
|
-
MarkdownContent,
|
|
343
|
-
{
|
|
344
|
-
dialect: "gfm",
|
|
345
|
-
content: c.content,
|
|
346
|
-
className: `${styles.markdownContent} inline`
|
|
347
|
-
}
|
|
348
|
-
), " \u2013 ", /* @__PURE__ */ React.createElement(AuthorLink, { entity: c }), " ", /* @__PURE__ */ React.createElement(Typography, { variant: "caption", className: "qetaCommentTime" }, /* @__PURE__ */ React.createElement(RelativeTimeWithTooltip, { value: c.created })), (c.own || c.canDelete) && /* @__PURE__ */ React.createElement(React.Fragment, null, " / ", /* @__PURE__ */ React.createElement(
|
|
349
|
-
Link,
|
|
350
|
-
{
|
|
351
|
-
underline: "none",
|
|
352
|
-
to: "#",
|
|
353
|
-
className: "qetaCommentDeleteBtn",
|
|
354
|
-
onClick: () => deleteComment(c.id)
|
|
355
|
-
},
|
|
356
|
-
"delete"
|
|
357
|
-
))), /* @__PURE__ */ React.createElement(Divider, null));
|
|
358
|
-
}));
|
|
359
|
-
};
|
|
360
|
-
|
|
361
|
-
const CommentSection = (props) => {
|
|
362
|
-
const { answer, question, onCommentPost, onCommentDelete } = props;
|
|
363
|
-
const analytics = useAnalytics();
|
|
364
|
-
const qetaApi = useApi(qetaApiRef);
|
|
365
|
-
const [posting, setPosting] = React.useState(false);
|
|
366
|
-
const [formVisible, setFormVisible] = useState(false);
|
|
367
|
-
const {
|
|
368
|
-
handleSubmit,
|
|
369
|
-
control,
|
|
370
|
-
formState: { errors },
|
|
371
|
-
reset
|
|
372
|
-
} = useForm({});
|
|
373
|
-
const postComment = (data) => {
|
|
374
|
-
setPosting(true);
|
|
375
|
-
if (answer) {
|
|
376
|
-
qetaApi.commentAnswer(question.id, answer.id, data.content).then((a) => {
|
|
377
|
-
setFormVisible(false);
|
|
378
|
-
analytics.captureEvent("comment", "answer");
|
|
379
|
-
reset();
|
|
380
|
-
setPosting(false);
|
|
381
|
-
onCommentPost(question, a);
|
|
382
|
-
});
|
|
383
|
-
return;
|
|
384
|
-
}
|
|
385
|
-
qetaApi.commentQuestion(question.id, data.content).then((q) => {
|
|
386
|
-
setFormVisible(false);
|
|
387
|
-
analytics.captureEvent("comment", "question");
|
|
388
|
-
reset();
|
|
389
|
-
setPosting(false);
|
|
390
|
-
onCommentPost(q);
|
|
391
|
-
});
|
|
392
|
-
};
|
|
393
|
-
return /* @__PURE__ */ React.createElement(Box, { marginLeft: 9, className: "qetaCommentSection" }, /* @__PURE__ */ React.createElement(
|
|
394
|
-
CommentList,
|
|
395
|
-
{
|
|
396
|
-
question,
|
|
397
|
-
answer,
|
|
398
|
-
onCommentDelete
|
|
399
|
-
}
|
|
400
|
-
), !formVisible && /* @__PURE__ */ React.createElement(
|
|
401
|
-
Link,
|
|
402
|
-
{
|
|
403
|
-
underline: "none",
|
|
404
|
-
to: "#",
|
|
405
|
-
className: "qetaAddCommentBtn",
|
|
406
|
-
onClick: () => setFormVisible(true)
|
|
407
|
-
},
|
|
408
|
-
"Add comment"
|
|
409
|
-
), formVisible && /* @__PURE__ */ React.createElement("form", { onSubmit: handleSubmit(postComment), className: "qetaCommentForm" }, /* @__PURE__ */ React.createElement(Grid, { container: true }, /* @__PURE__ */ React.createElement(Grid, { item: true, xs: 11 }, /* @__PURE__ */ React.createElement(
|
|
410
|
-
Controller,
|
|
411
|
-
{
|
|
412
|
-
control,
|
|
413
|
-
defaultValue: "",
|
|
414
|
-
rules: {
|
|
415
|
-
required: true
|
|
416
|
-
},
|
|
417
|
-
render: ({ field: { onChange, value } }) => /* @__PURE__ */ React.createElement(
|
|
418
|
-
TextField,
|
|
419
|
-
{
|
|
420
|
-
id: "comment",
|
|
421
|
-
multiline: true,
|
|
422
|
-
minRows: 2,
|
|
423
|
-
fullWidth: true,
|
|
424
|
-
className: "qetaCommentInput",
|
|
425
|
-
value,
|
|
426
|
-
placeholder: "Your commment",
|
|
427
|
-
onChange,
|
|
428
|
-
variant: "outlined",
|
|
429
|
-
error: "content" in errors
|
|
430
|
-
}
|
|
431
|
-
),
|
|
432
|
-
name: "content"
|
|
433
|
-
}
|
|
434
|
-
)), /* @__PURE__ */ React.createElement(Grid, { item: true, xs: 1 }, /* @__PURE__ */ React.createElement(
|
|
435
|
-
Button,
|
|
436
|
-
{
|
|
437
|
-
variant: "contained",
|
|
438
|
-
size: "small",
|
|
439
|
-
className: "qetaCommentBtn",
|
|
440
|
-
type: "submit",
|
|
441
|
-
color: "primary",
|
|
442
|
-
disabled: posting
|
|
443
|
-
},
|
|
444
|
-
"Post"
|
|
445
|
-
)))));
|
|
446
|
-
};
|
|
447
|
-
|
|
448
|
-
const LinkButton = (props) => {
|
|
449
|
-
const isQuestion = "title" in props.entity;
|
|
450
|
-
const copyToClipboard = () => {
|
|
451
|
-
const url = new URL(window.location.href);
|
|
452
|
-
if (!isQuestion) {
|
|
453
|
-
url.hash = `#answer_${props.entity.id}`;
|
|
454
|
-
}
|
|
455
|
-
window.navigator.clipboard.writeText(url.toString());
|
|
456
|
-
};
|
|
457
|
-
return /* @__PURE__ */ React.createElement(
|
|
458
|
-
Tooltip,
|
|
459
|
-
{
|
|
460
|
-
title: `Copy link to this ${isQuestion ? "question" : "answer"} to clipboard`
|
|
461
|
-
},
|
|
462
|
-
/* @__PURE__ */ React.createElement(
|
|
463
|
-
IconButton,
|
|
464
|
-
{
|
|
465
|
-
"aria-label": "copy link to clipboard",
|
|
466
|
-
size: "small",
|
|
467
|
-
onClick: copyToClipboard
|
|
468
|
-
},
|
|
469
|
-
/* @__PURE__ */ React.createElement(Link$1, null)
|
|
470
|
-
)
|
|
471
|
-
);
|
|
472
|
-
};
|
|
473
|
-
|
|
474
|
-
const QuestionCard = (props) => {
|
|
475
|
-
var _a;
|
|
476
|
-
const { question } = props;
|
|
477
|
-
const styles = useStyles$1();
|
|
478
|
-
const editQuestionRoute = useRouteRef(editQuestionRouteRef);
|
|
479
|
-
const [deleteModalOpen, setDeleteModalOpen] = React.useState(false);
|
|
480
|
-
const [questionEntity, setQuestionEntity] = React.useState(question);
|
|
481
|
-
const handleDeleteModalOpen = () => setDeleteModalOpen(true);
|
|
482
|
-
const handleDeleteModalClose = () => setDeleteModalOpen(false);
|
|
483
|
-
const onCommentAction = (q, _) => {
|
|
484
|
-
setQuestionEntity(q);
|
|
485
|
-
};
|
|
486
|
-
const highlightedAnswer = (_a = window.location.hash.slice(1)) != null ? _a : void 0;
|
|
487
|
-
useEffect(() => {
|
|
488
|
-
if (highlightedAnswer) {
|
|
489
|
-
const element = document.querySelector(`#${highlightedAnswer}`);
|
|
490
|
-
if (element) {
|
|
491
|
-
element.scrollIntoView();
|
|
492
|
-
}
|
|
493
|
-
}
|
|
494
|
-
}, [highlightedAnswer]);
|
|
495
|
-
return /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement(
|
|
496
|
-
Card,
|
|
497
|
-
{
|
|
498
|
-
variant: "outlined",
|
|
499
|
-
className: `qetaQuestionCard ${styles.questionCard}`
|
|
500
|
-
},
|
|
501
|
-
/* @__PURE__ */ React.createElement(CardContent, null, /* @__PURE__ */ React.createElement("div", { className: styles.questionCardVote }, /* @__PURE__ */ React.createElement(VoteButtons, { entity: questionEntity }), /* @__PURE__ */ React.createElement(FavoriteButton, { entity: questionEntity }), /* @__PURE__ */ React.createElement(LinkButton, { entity: questionEntity })), /* @__PURE__ */ React.createElement("div", { className: styles.questionCardContent }, /* @__PURE__ */ React.createElement(Typography, { variant: "body1", gutterBottom: true }, /* @__PURE__ */ React.createElement(
|
|
502
|
-
MarkdownContent,
|
|
503
|
-
{
|
|
504
|
-
content: questionEntity.content,
|
|
505
|
-
dialect: "gfm",
|
|
506
|
-
className: styles.markdownContent
|
|
507
|
-
}
|
|
508
|
-
)), /* @__PURE__ */ React.createElement(
|
|
509
|
-
Grid,
|
|
510
|
-
{
|
|
511
|
-
container: true,
|
|
512
|
-
item: true,
|
|
513
|
-
justifyContent: "space-around",
|
|
514
|
-
className: styles.questionCardMetadata
|
|
515
|
-
},
|
|
516
|
-
/* @__PURE__ */ React.createElement(Grid, { item: true, xs: 9, style: { alignSelf: "flex-end" } }, /* @__PURE__ */ React.createElement(TagsAndEntities, { question: questionEntity }), (question.own || question.canEdit || question.canDelete) && /* @__PURE__ */ React.createElement(Box, { className: styles.questionCardActions }, (question.own || question.canDelete) && /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement(
|
|
517
|
-
Button,
|
|
518
|
-
{
|
|
519
|
-
variant: "outlined",
|
|
520
|
-
size: "small",
|
|
521
|
-
color: "secondary",
|
|
522
|
-
onClick: handleDeleteModalOpen,
|
|
523
|
-
className: `${styles.marginRight} qetaQuestionCardDeleteBtn`,
|
|
524
|
-
startIcon: /* @__PURE__ */ React.createElement(DeleteIcon, null)
|
|
525
|
-
},
|
|
526
|
-
"Delete"
|
|
527
|
-
), /* @__PURE__ */ React.createElement(
|
|
528
|
-
DeleteModal,
|
|
529
|
-
{
|
|
530
|
-
open: deleteModalOpen,
|
|
531
|
-
onClose: handleDeleteModalClose,
|
|
532
|
-
entity: questionEntity
|
|
533
|
-
}
|
|
534
|
-
)), (question.own || question.canEdit) && /* @__PURE__ */ React.createElement(
|
|
535
|
-
Button,
|
|
536
|
-
{
|
|
537
|
-
variant: "outlined",
|
|
538
|
-
size: "small",
|
|
539
|
-
startIcon: /* @__PURE__ */ React.createElement(EditIcon, null),
|
|
540
|
-
href: editQuestionRoute({
|
|
541
|
-
id: question.id.toString(10)
|
|
542
|
-
}),
|
|
543
|
-
className: "qetaQuestionCardEditBtn"
|
|
544
|
-
},
|
|
545
|
-
"Edit"
|
|
546
|
-
))),
|
|
547
|
-
/* @__PURE__ */ React.createElement(Grid, { item: true, xs: 3, className: styles.noPadding }, /* @__PURE__ */ React.createElement(AuthorBox, { entity: questionEntity }))
|
|
548
|
-
)))
|
|
549
|
-
), /* @__PURE__ */ React.createElement(
|
|
550
|
-
CommentSection,
|
|
551
|
-
{
|
|
552
|
-
question: questionEntity,
|
|
553
|
-
onCommentDelete: onCommentAction,
|
|
554
|
-
onCommentPost: onCommentAction
|
|
555
|
-
}
|
|
556
|
-
));
|
|
557
|
-
};
|
|
558
|
-
|
|
559
|
-
const getDefaultValues = (questionId) => {
|
|
560
|
-
return { questionId, answer: "" };
|
|
561
|
-
};
|
|
562
|
-
const AnswerForm = (props) => {
|
|
563
|
-
const { question, onPost, id } = props;
|
|
564
|
-
const [values, setValues] = React.useState(getDefaultValues(question.id));
|
|
565
|
-
const analytics = useAnalytics();
|
|
566
|
-
const [error, setError] = React.useState(false);
|
|
567
|
-
const [images, setImages] = React.useState([]);
|
|
568
|
-
const qetaApi = useApi(qetaApiRef);
|
|
569
|
-
const styles = useStyles$1();
|
|
570
|
-
const configApi = useApi(configApiRef);
|
|
571
|
-
const allowAnonymouns = configApi.getOptionalBoolean("qeta.allowAnonymous");
|
|
572
|
-
const {
|
|
573
|
-
handleSubmit,
|
|
574
|
-
control,
|
|
575
|
-
formState: { errors },
|
|
576
|
-
reset
|
|
577
|
-
} = useForm({
|
|
578
|
-
values,
|
|
579
|
-
defaultValues: getDefaultValues(question.id)
|
|
580
|
-
});
|
|
581
|
-
const postAnswer = (data) => {
|
|
582
|
-
if (id) {
|
|
583
|
-
qetaApi.updateAnswer(id, {
|
|
584
|
-
questionId: question.id,
|
|
585
|
-
answer: data.answer,
|
|
586
|
-
images
|
|
587
|
-
}).then((a) => {
|
|
588
|
-
if (!a || !("id" in a)) {
|
|
589
|
-
setError(true);
|
|
590
|
-
return;
|
|
591
|
-
}
|
|
592
|
-
analytics.captureEvent("edit", "answer");
|
|
593
|
-
reset();
|
|
594
|
-
onPost(a);
|
|
595
|
-
}).catch((_e) => setError(true));
|
|
596
|
-
return;
|
|
597
|
-
}
|
|
598
|
-
qetaApi.postAnswer({
|
|
599
|
-
questionId: question.id,
|
|
600
|
-
answer: data.answer,
|
|
601
|
-
images,
|
|
602
|
-
anonymous: data.anonymous
|
|
603
|
-
}).then((a) => {
|
|
604
|
-
if (!a || !("id" in a)) {
|
|
605
|
-
setError(true);
|
|
606
|
-
return;
|
|
607
|
-
}
|
|
608
|
-
analytics.captureEvent("post", "answer");
|
|
609
|
-
reset();
|
|
610
|
-
onPost(a);
|
|
611
|
-
}).catch((_e) => setError(true));
|
|
612
|
-
};
|
|
613
|
-
useEffect(() => {
|
|
614
|
-
if (id) {
|
|
615
|
-
qetaApi.getAnswer(question.id, id).then((a) => {
|
|
616
|
-
if ("content" in a) {
|
|
617
|
-
setValues({ questionId: question.id, answer: a.content });
|
|
618
|
-
} else {
|
|
619
|
-
setError(true);
|
|
620
|
-
}
|
|
621
|
-
});
|
|
622
|
-
}
|
|
623
|
-
}, [id, question, qetaApi]);
|
|
624
|
-
useEffect(() => {
|
|
625
|
-
reset(values);
|
|
626
|
-
}, [values, reset]);
|
|
627
|
-
return /* @__PURE__ */ React.createElement(
|
|
628
|
-
RequirePermission,
|
|
629
|
-
{
|
|
630
|
-
permission: qetaCreateAnswerPermission,
|
|
631
|
-
errorPage: /* @__PURE__ */ React.createElement(React.Fragment, null)
|
|
632
|
-
},
|
|
633
|
-
/* @__PURE__ */ React.createElement("form", { onSubmit: handleSubmit(postAnswer), className: "qetaAnswerForm" }, /* @__PURE__ */ React.createElement(Typography, { variant: "h6" }, "Your answer"), error && /* @__PURE__ */ React.createElement(WarningPanel, { severity: "error", title: "Could not post answer" }), /* @__PURE__ */ React.createElement(
|
|
634
|
-
Controller,
|
|
635
|
-
{
|
|
636
|
-
control,
|
|
637
|
-
defaultValue: "",
|
|
638
|
-
rules: {
|
|
639
|
-
required: true
|
|
640
|
-
},
|
|
641
|
-
render: ({ field: { onChange, value } }) => /* @__PURE__ */ React.createElement(
|
|
642
|
-
MarkdownEditor,
|
|
643
|
-
{
|
|
644
|
-
value,
|
|
645
|
-
onChange,
|
|
646
|
-
height: 200,
|
|
647
|
-
error: "answer" in errors,
|
|
648
|
-
config: configApi,
|
|
649
|
-
onImageUpload: (imageId) => {
|
|
650
|
-
setImages((prevImages) => [...prevImages, imageId]);
|
|
651
|
-
}
|
|
652
|
-
}
|
|
653
|
-
),
|
|
654
|
-
name: "answer"
|
|
655
|
-
}
|
|
656
|
-
), allowAnonymouns && !id && /* @__PURE__ */ React.createElement(
|
|
657
|
-
AskAnonymouslyCheckbox,
|
|
658
|
-
{
|
|
659
|
-
control,
|
|
660
|
-
label: "Answer anonymously"
|
|
661
|
-
}
|
|
662
|
-
), /* @__PURE__ */ React.createElement(
|
|
663
|
-
Button,
|
|
664
|
-
{
|
|
665
|
-
variant: "outlined",
|
|
666
|
-
type: "submit",
|
|
667
|
-
color: "primary",
|
|
668
|
-
className: `qetaAnswerFormPostBtn ${styles.postButton}`
|
|
669
|
-
},
|
|
670
|
-
id ? "Save" : "Post"
|
|
671
|
-
))
|
|
672
|
-
);
|
|
673
|
-
};
|
|
674
|
-
|
|
675
|
-
const AnswerCard = (props) => {
|
|
676
|
-
const { answer, question } = props;
|
|
677
|
-
const styles = useStyles$1();
|
|
678
|
-
const [editMode, setEditMode] = React.useState(false);
|
|
679
|
-
const [answerEntity, setAnswerEntity] = React.useState(answer);
|
|
680
|
-
const [deleteModalOpen, setDeleteModalOpen] = React.useState(false);
|
|
681
|
-
const handleDeleteModalOpen = () => setDeleteModalOpen(true);
|
|
682
|
-
const handleDeleteModalClose = () => setDeleteModalOpen(false);
|
|
683
|
-
const highlightedAnswer = window.location.hash.slice(1) === `answer_${answer.id}`;
|
|
684
|
-
const onAnswerEdit = (a) => {
|
|
685
|
-
setEditMode(false);
|
|
686
|
-
setAnswerEntity(a);
|
|
687
|
-
};
|
|
688
|
-
const onCommentAction = (_, a) => {
|
|
689
|
-
if (a) {
|
|
690
|
-
setAnswerEntity(a);
|
|
691
|
-
}
|
|
692
|
-
};
|
|
693
|
-
return /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement(
|
|
694
|
-
Card,
|
|
695
|
-
{
|
|
696
|
-
id: `answer_${answer.id}`,
|
|
697
|
-
className: `qetaAnswerCard ${styles.questionCard} ${highlightedAnswer ? styles.highlight : ""}`
|
|
698
|
-
},
|
|
699
|
-
/* @__PURE__ */ React.createElement(CardContent, null, /* @__PURE__ */ React.createElement("div", { className: styles.questionCardVote }, /* @__PURE__ */ React.createElement(VoteButtons, { entity: answerEntity, question }), /* @__PURE__ */ React.createElement(LinkButton, { entity: answerEntity })), /* @__PURE__ */ React.createElement("div", { className: styles.answerCardContent }, editMode ? /* @__PURE__ */ React.createElement(
|
|
700
|
-
AnswerForm,
|
|
701
|
-
{
|
|
702
|
-
question,
|
|
703
|
-
onPost: onAnswerEdit,
|
|
704
|
-
id: answerEntity.id
|
|
705
|
-
}
|
|
706
|
-
) : /* @__PURE__ */ React.createElement(Grid, { container: true }, /* @__PURE__ */ React.createElement(Grid, { item: true, xs: 12 }, /* @__PURE__ */ React.createElement(Typography, { variant: "body1", gutterBottom: true }, /* @__PURE__ */ React.createElement(
|
|
707
|
-
MarkdownContent,
|
|
708
|
-
{
|
|
709
|
-
className: `qetaAndwerCardAnswerContent ${styles.markdownContent}`,
|
|
710
|
-
content: answerEntity.content,
|
|
711
|
-
dialect: "gfm"
|
|
712
|
-
}
|
|
713
|
-
))), /* @__PURE__ */ React.createElement(Grid, { item: true, container: true, justifyContent: "space-around" }, /* @__PURE__ */ React.createElement(Grid, { item: true, xs: 9, style: { alignSelf: "flex-end" } }, (answerEntity.own || answerEntity.canDelete || answerEntity.canEdit) && /* @__PURE__ */ React.createElement(
|
|
714
|
-
Box,
|
|
715
|
-
{
|
|
716
|
-
className: `qetaAnswerCardActions ${styles.questionCardActions}`
|
|
717
|
-
},
|
|
718
|
-
!answerEntity.correct && (answerEntity.own || answerEntity.canDelete) && /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement(
|
|
719
|
-
Button,
|
|
720
|
-
{
|
|
721
|
-
variant: "outlined",
|
|
722
|
-
size: "small",
|
|
723
|
-
color: "secondary",
|
|
724
|
-
onClick: handleDeleteModalOpen,
|
|
725
|
-
className: `${styles.marginRight} qetaAnswerCardDeleteBtn`,
|
|
726
|
-
startIcon: /* @__PURE__ */ React.createElement(DeleteIcon, null)
|
|
727
|
-
},
|
|
728
|
-
"Delete"
|
|
729
|
-
), /* @__PURE__ */ React.createElement(
|
|
730
|
-
DeleteModal,
|
|
731
|
-
{
|
|
732
|
-
open: deleteModalOpen,
|
|
733
|
-
onClose: handleDeleteModalClose,
|
|
734
|
-
entity: answerEntity,
|
|
735
|
-
question
|
|
736
|
-
}
|
|
737
|
-
)),
|
|
738
|
-
(answerEntity.own || answerEntity.canEdit) && /* @__PURE__ */ React.createElement(
|
|
739
|
-
Button,
|
|
740
|
-
{
|
|
741
|
-
variant: "outlined",
|
|
742
|
-
size: "small",
|
|
743
|
-
startIcon: /* @__PURE__ */ React.createElement(EditIcon, null),
|
|
744
|
-
onClick: () => setEditMode(true),
|
|
745
|
-
className: "qetaAnswerCardEditBtn"
|
|
746
|
-
},
|
|
747
|
-
"Edit"
|
|
748
|
-
)
|
|
749
|
-
)), /* @__PURE__ */ React.createElement(Grid, { item: true, xs: 3, className: styles.noPadding }, /* @__PURE__ */ React.createElement(AuthorBox, { entity: answerEntity }))))))
|
|
750
|
-
), /* @__PURE__ */ React.createElement(
|
|
751
|
-
CommentSection,
|
|
752
|
-
{
|
|
753
|
-
question,
|
|
754
|
-
answer: answerEntity,
|
|
755
|
-
onCommentPost: onCommentAction,
|
|
756
|
-
onCommentDelete: onCommentAction
|
|
757
|
-
}
|
|
758
|
-
));
|
|
759
|
-
};
|
|
760
|
-
|
|
761
|
-
const QuestionPage = () => {
|
|
762
|
-
var _a;
|
|
763
|
-
const { id } = useParams();
|
|
764
|
-
const styles = useStyles$1();
|
|
765
|
-
const [newAnswers, setNewAnswers] = React.useState([]);
|
|
766
|
-
const [answerSort, setAnswerSort] = React.useState("default");
|
|
767
|
-
const [searchParams] = useSearchParams();
|
|
768
|
-
const [answersCount, setAnswersCount] = useState(0);
|
|
769
|
-
const [views, setViews] = useState(0);
|
|
770
|
-
const { lastSignal } = useSignal(`qeta:question_${id}`);
|
|
771
|
-
const {
|
|
772
|
-
value: question,
|
|
773
|
-
loading,
|
|
774
|
-
error
|
|
775
|
-
} = useQetaApi((api) => api.getQuestion(id), [id]);
|
|
776
|
-
useEffect(() => {
|
|
777
|
-
if (question) {
|
|
778
|
-
setAnswersCount(question.answersCount);
|
|
779
|
-
setViews(question.views);
|
|
780
|
-
}
|
|
781
|
-
}, [question]);
|
|
782
|
-
useEffect(() => {
|
|
783
|
-
if ((lastSignal == null ? void 0 : lastSignal.type) === "question_stats") {
|
|
784
|
-
setAnswersCount(lastSignal.answersCount);
|
|
785
|
-
setViews(lastSignal.views);
|
|
786
|
-
}
|
|
787
|
-
}, [lastSignal]);
|
|
788
|
-
const onAnswerPost = (answer) => {
|
|
789
|
-
setNewAnswers(newAnswers.concat([answer]));
|
|
790
|
-
};
|
|
791
|
-
const getDescription = (q) => {
|
|
792
|
-
return /* @__PURE__ */ React.createElement("span", null, "Asked", " ", /* @__PURE__ */ React.createElement(Box, { fontWeight: "fontWeightMedium", display: "inline", sx: { mr: 2 } }, /* @__PURE__ */ React.createElement(RelativeTimeWithTooltip, { value: q.created })), q.updated && /* @__PURE__ */ React.createElement(React.Fragment, null, "Updated", " ", /* @__PURE__ */ React.createElement(Box, { fontWeight: "fontWeightMedium", display: "inline", sx: { mr: 2 } }, /* @__PURE__ */ React.createElement(RelativeTimeWithTooltip, { value: q.updated }), " by", " ", /* @__PURE__ */ React.createElement(UpdatedByLink, { entity: q }))), "Viewed", " ", /* @__PURE__ */ React.createElement(Box, { fontWeight: "fontWeightMedium", display: "inline" }, views, " times"));
|
|
793
|
-
};
|
|
794
|
-
if (loading) {
|
|
795
|
-
return /* @__PURE__ */ React.createElement(Skeleton, { variant: "rect", height: 200 });
|
|
796
|
-
}
|
|
797
|
-
if (error || question === void 0) {
|
|
798
|
-
return /* @__PURE__ */ React.createElement(WarningPanel, { severity: "error", title: "Could not load question." }, error == null ? void 0 : error.message);
|
|
799
|
-
}
|
|
800
|
-
const sortAnswers = (a, b) => {
|
|
801
|
-
var _a2, _b, _c, _d, _e, _f;
|
|
802
|
-
if (answerSort === "default") {
|
|
803
|
-
return 1;
|
|
804
|
-
}
|
|
805
|
-
const parts = answerSort.split("_");
|
|
806
|
-
const field = parts[0];
|
|
807
|
-
const order = parts[1];
|
|
808
|
-
let ret = -1;
|
|
809
|
-
switch (field) {
|
|
810
|
-
case "created":
|
|
811
|
-
ret = a.created > b.created ? -1 : 1;
|
|
812
|
-
break;
|
|
813
|
-
case "score":
|
|
814
|
-
ret = a.score > b.score ? -1 : 1;
|
|
815
|
-
break;
|
|
816
|
-
case "author":
|
|
817
|
-
ret = a.author > b.author ? -1 : 1;
|
|
818
|
-
break;
|
|
819
|
-
case "comments":
|
|
820
|
-
ret = ((_b = (_a2 = a.comments) == null ? void 0 : _a2.length) != null ? _b : 0) > ((_d = (_c = b.comments) == null ? void 0 : _c.length) != null ? _d : 0) ? -1 : 1;
|
|
821
|
-
break;
|
|
822
|
-
case "updated":
|
|
823
|
-
ret = ((_e = a.updated) != null ? _e : a.created) > ((_f = b.updated) != null ? _f : b.created) ? -1 : 1;
|
|
824
|
-
break;
|
|
825
|
-
default:
|
|
826
|
-
return 1;
|
|
827
|
-
}
|
|
828
|
-
if (order === "desc") {
|
|
829
|
-
ret *= -1;
|
|
830
|
-
}
|
|
831
|
-
return ret;
|
|
832
|
-
};
|
|
833
|
-
const allAnswers = ((_a = question.answers) != null ? _a : []).concat(newAnswers);
|
|
834
|
-
return /* @__PURE__ */ React.createElement(Content, null, /* @__PURE__ */ React.createElement(Container, { maxWidth: "lg" }, /* @__PURE__ */ React.createElement(
|
|
835
|
-
ContentHeader,
|
|
836
|
-
{
|
|
837
|
-
title: question.title,
|
|
838
|
-
description: getDescription(question)
|
|
839
|
-
},
|
|
840
|
-
/* @__PURE__ */ React.createElement(
|
|
841
|
-
BackToQuestionsButton,
|
|
842
|
-
{
|
|
843
|
-
entityPage: searchParams.get("entityPage") === "true"
|
|
844
|
-
}
|
|
845
|
-
),
|
|
846
|
-
/* @__PURE__ */ React.createElement(AskQuestionButton, null)
|
|
847
|
-
), /* @__PURE__ */ React.createElement(QuestionCard, { question }), /* @__PURE__ */ React.createElement(Box, { sx: { mt: 3, mb: 2 } }, /* @__PURE__ */ React.createElement(Grid, { container: true, justifyContent: "space-between", alignItems: "center" }, /* @__PURE__ */ React.createElement(Grid, { item: true }, /* @__PURE__ */ React.createElement(Typography, { variant: "h6" }, answersCount + newAnswers.length, " answers")), allAnswers.length > 1 && /* @__PURE__ */ React.createElement(Grid, { item: true }, /* @__PURE__ */ React.createElement(FormControl, null, /* @__PURE__ */ React.createElement(
|
|
848
|
-
Select,
|
|
849
|
-
{
|
|
850
|
-
native: true,
|
|
851
|
-
label: "Sort answers",
|
|
852
|
-
value: answerSort,
|
|
853
|
-
onChange: (val) => setAnswerSort(val.target.value),
|
|
854
|
-
inputProps: {
|
|
855
|
-
name: "sortAnswers",
|
|
856
|
-
id: "sort-answers"
|
|
857
|
-
}
|
|
858
|
-
},
|
|
859
|
-
/* @__PURE__ */ React.createElement("option", { value: "default" }, "Default"),
|
|
860
|
-
/* @__PURE__ */ React.createElement("option", { value: "created_desc" }, "Created (desc)"),
|
|
861
|
-
/* @__PURE__ */ React.createElement("option", { value: "created_asc" }, "Created (asc)"),
|
|
862
|
-
/* @__PURE__ */ React.createElement("option", { value: "score_desc" }, "Score (desc)"),
|
|
863
|
-
/* @__PURE__ */ React.createElement("option", { value: "score_asc" }, "Score (asc)"),
|
|
864
|
-
/* @__PURE__ */ React.createElement("option", { value: "comments_desc" }, "Comments (desc)"),
|
|
865
|
-
/* @__PURE__ */ React.createElement("option", { value: "comments_asc" }, "Comments (asc)"),
|
|
866
|
-
/* @__PURE__ */ React.createElement("option", { value: "author_desc" }, "Author (desc)"),
|
|
867
|
-
/* @__PURE__ */ React.createElement("option", { value: "author_asc" }, "Author (asc)"),
|
|
868
|
-
/* @__PURE__ */ React.createElement("option", { value: "updated_desc" }, "Updated (desc)"),
|
|
869
|
-
/* @__PURE__ */ React.createElement("option", { value: "updated_asc" }, "Updated (asc)")
|
|
870
|
-
))))), allAnswers.sort(sortAnswers).map((a) => {
|
|
871
|
-
return /* @__PURE__ */ React.createElement(React.Fragment, { key: a.id }, /* @__PURE__ */ React.createElement(Divider, { className: styles.questionDivider }), /* @__PURE__ */ React.createElement(Box, { key: a.id, sx: { mb: 1 } }, /* @__PURE__ */ React.createElement(AnswerCard, { answer: a, question })));
|
|
872
|
-
}), /* @__PURE__ */ React.createElement(Divider, { className: styles.questionDivider }), /* @__PURE__ */ React.createElement(AnswerForm, { question, onPost: onAnswerPost })));
|
|
873
|
-
};
|
|
874
|
-
|
|
875
|
-
const TagsContainer = () => {
|
|
876
|
-
const [searchQuery, setSearchQuery] = React.useState("");
|
|
877
|
-
const tagRoute = useRouteRef(tagRouteRef);
|
|
878
|
-
const {
|
|
879
|
-
value: response,
|
|
880
|
-
loading,
|
|
881
|
-
error
|
|
882
|
-
} = useQetaApi((api) => api.getTags(), []);
|
|
883
|
-
if (loading) {
|
|
884
|
-
return /* @__PURE__ */ React.createElement(Progress, null);
|
|
885
|
-
}
|
|
886
|
-
if (error || response === void 0) {
|
|
887
|
-
return /* @__PURE__ */ React.createElement(WarningPanel, { severity: "error", title: "Could not load tags." }, error == null ? void 0 : error.message);
|
|
888
|
-
}
|
|
889
|
-
const filterData = (query, data) => {
|
|
890
|
-
if (!query) {
|
|
891
|
-
return data;
|
|
892
|
-
}
|
|
893
|
-
return data.filter((t) => t.tag.toLowerCase().includes(query));
|
|
894
|
-
};
|
|
895
|
-
const tags = filterData(searchQuery, response);
|
|
896
|
-
return /* @__PURE__ */ React.createElement(Grid, { container: true, className: "qetaTagsContainer" }, /* @__PURE__ */ React.createElement(Grid, { item: true, xs: 12 }, /* @__PURE__ */ React.createElement(
|
|
897
|
-
TextField,
|
|
898
|
-
{
|
|
899
|
-
id: "search-bar",
|
|
900
|
-
className: "text qetaTagsContainerSearchInput",
|
|
901
|
-
onChange: (event) => setSearchQuery(event.target.value),
|
|
902
|
-
label: "Search tag",
|
|
903
|
-
variant: "outlined",
|
|
904
|
-
placeholder: "Search...",
|
|
905
|
-
size: "small"
|
|
906
|
-
}
|
|
907
|
-
), /* @__PURE__ */ React.createElement(IconButton, { type: "submit", "aria-label": "search" })), /* @__PURE__ */ React.createElement(Grid, { item: true, xs: 12 }, /* @__PURE__ */ React.createElement(
|
|
908
|
-
Typography,
|
|
909
|
-
{
|
|
910
|
-
variant: "h6",
|
|
911
|
-
className: "qetaTagsContainerTitle"
|
|
912
|
-
},
|
|
913
|
-
`Showing ${tags.length} tags`
|
|
914
|
-
)), /* @__PURE__ */ React.createElement(Grid, { item: true }, tags.map((tag) => /* @__PURE__ */ React.createElement(
|
|
915
|
-
Chip,
|
|
916
|
-
{
|
|
917
|
-
key: tag.tag,
|
|
918
|
-
variant: "outlined",
|
|
919
|
-
avatar: /* @__PURE__ */ React.createElement(Avatar, null, tag.questionsCount),
|
|
920
|
-
label: tag.tag,
|
|
921
|
-
className: "qetaTagsContainerChip",
|
|
922
|
-
component: "a",
|
|
923
|
-
clickable: true,
|
|
924
|
-
href: tagRoute({ tag: tag.tag })
|
|
925
|
-
}
|
|
926
|
-
))));
|
|
927
|
-
};
|
|
928
|
-
|
|
929
|
-
const TagPage = () => {
|
|
930
|
-
const { tag } = useParams();
|
|
931
|
-
return /* @__PURE__ */ React.createElement(Content, null, /* @__PURE__ */ React.createElement(Container, { maxWidth: "lg" }, /* @__PURE__ */ React.createElement(ContentHeader, { title: tag ? `Questions tagged [${tag}]` : "Tags" }, /* @__PURE__ */ React.createElement(BackToQuestionsButton, null), /* @__PURE__ */ React.createElement(AskQuestionButton, { tags: tag ? [tag] : void 0 })), tag ? /* @__PURE__ */ React.createElement(QuestionsContainer, { tags: [tag != null ? tag : ""] }) : /* @__PURE__ */ React.createElement(TagsContainer, null)));
|
|
932
|
-
};
|
|
933
|
-
|
|
934
|
-
const UserPage = () => {
|
|
935
|
-
var _a;
|
|
936
|
-
const identity = (_a = useParams()["*"]) != null ? _a : "unknown";
|
|
937
|
-
const presentation = useEntityPresentation(identity);
|
|
938
|
-
return /* @__PURE__ */ React.createElement(Content, null, /* @__PURE__ */ React.createElement(Container, { maxWidth: "lg" }, /* @__PURE__ */ React.createElement(ContentHeader, { title: `Questions by ${presentation.primaryTitle}` }, /* @__PURE__ */ React.createElement(BackToQuestionsButton, null), /* @__PURE__ */ React.createElement(AskQuestionButton, null)), /* @__PURE__ */ React.createElement(
|
|
939
|
-
QuestionsContainer,
|
|
940
|
-
{
|
|
941
|
-
author: identity != null ? identity : "",
|
|
942
|
-
showNoQuestionsBtn: false
|
|
943
|
-
}
|
|
944
|
-
)));
|
|
945
|
-
};
|
|
946
|
-
|
|
947
|
-
const QuestionHighlightList = (props) => {
|
|
948
|
-
var _a;
|
|
949
|
-
const {
|
|
950
|
-
value: response,
|
|
951
|
-
loading,
|
|
952
|
-
error
|
|
953
|
-
} = useQetaApi((api) => api.getQuestionsList(props.type), []);
|
|
954
|
-
const classes = useStyles$1();
|
|
955
|
-
const questionRoute = useRouteRef(questionRouteRef);
|
|
956
|
-
const questions = (_a = response == null ? void 0 : response.questions) != null ? _a : [];
|
|
957
|
-
return /* @__PURE__ */ React.createElement(
|
|
958
|
-
Box,
|
|
959
|
-
{
|
|
960
|
-
className: `qetaQuestionHighlightList ${classes.questionHighlightList}`,
|
|
961
|
-
display: { md: "none", lg: "block" }
|
|
962
|
-
},
|
|
963
|
-
/* @__PURE__ */ React.createElement(
|
|
964
|
-
List,
|
|
965
|
-
{
|
|
966
|
-
component: "nav",
|
|
967
|
-
"aria-labelledby": "nested-list-subheader",
|
|
968
|
-
className: "qetaQuestionHighlightListList",
|
|
969
|
-
subheader: /* @__PURE__ */ React.createElement(
|
|
970
|
-
ListSubheader,
|
|
971
|
-
{
|
|
972
|
-
disableSticky: true,
|
|
973
|
-
component: "div",
|
|
974
|
-
id: "nested-list-subheader",
|
|
975
|
-
color: "primary"
|
|
976
|
-
},
|
|
977
|
-
props.title,
|
|
978
|
-
props.icon
|
|
979
|
-
)
|
|
980
|
-
},
|
|
981
|
-
loading && /* @__PURE__ */ React.createElement(ListItem, null, /* @__PURE__ */ React.createElement(Skeleton, { variant: "rect" })),
|
|
982
|
-
error && /* @__PURE__ */ React.createElement(ListItem, null, /* @__PURE__ */ React.createElement(ListItemText, null, "Failed to load questions")),
|
|
983
|
-
!error && questions.length === 0 && /* @__PURE__ */ React.createElement(ListItem, null, /* @__PURE__ */ React.createElement(ListItemText, null, props.noQuestionsLabel)),
|
|
984
|
-
!error && questions.map((q) => /* @__PURE__ */ React.createElement(React.Fragment, { key: q.id }, /* @__PURE__ */ React.createElement(Divider, null), /* @__PURE__ */ React.createElement(
|
|
985
|
-
ListItem,
|
|
986
|
-
{
|
|
987
|
-
className: "qetaQuestionHighlightListListItem",
|
|
988
|
-
button: true,
|
|
989
|
-
dense: true,
|
|
990
|
-
component: "a",
|
|
991
|
-
href: questionRoute({ id: q.id.toString(10) })
|
|
992
|
-
},
|
|
993
|
-
/* @__PURE__ */ React.createElement(ListItemText, null, q.title)
|
|
994
|
-
)))
|
|
995
|
-
)
|
|
996
|
-
);
|
|
997
|
-
};
|
|
998
|
-
|
|
999
|
-
const FavoritePage = () => {
|
|
1000
|
-
return /* @__PURE__ */ React.createElement(Content, { className: "qetaFavoritePage" }, /* @__PURE__ */ React.createElement(Container, { maxWidth: "lg" }, /* @__PURE__ */ React.createElement(ContentHeader, { title: "Your favorite questions" }, /* @__PURE__ */ React.createElement(BackToQuestionsButton, null), /* @__PURE__ */ React.createElement(AskQuestionButton, null)), /* @__PURE__ */ React.createElement(QuestionsContainer, { favorite: true })));
|
|
1001
|
-
};
|
|
1002
|
-
|
|
1003
|
-
const MoreMenu = () => {
|
|
1004
|
-
const [anchorEl, setAnchorEl] = React.useState(null);
|
|
1005
|
-
const tagsRoute = useRouteRef(tagsRouteRef);
|
|
1006
|
-
const favoritesRoute = useRouteRef(favoriteQuestionsRouteRef);
|
|
1007
|
-
const statisticsRoute = useRouteRef(statisticsRouteRef);
|
|
1008
|
-
const userRoute = useRouteRef(userRouteRef);
|
|
1009
|
-
const open = Boolean(anchorEl);
|
|
1010
|
-
const styles = useStyles$1();
|
|
1011
|
-
const {
|
|
1012
|
-
value: user,
|
|
1013
|
-
loading: loadingUser,
|
|
1014
|
-
error: userError
|
|
1015
|
-
} = useIdentityApi((api) => api.getBackstageIdentity(), []);
|
|
1016
|
-
const handleMenuOpen = (event) => {
|
|
1017
|
-
setAnchorEl(event.currentTarget);
|
|
1018
|
-
};
|
|
1019
|
-
const handleMenuClose = () => {
|
|
1020
|
-
setAnchorEl(null);
|
|
1021
|
-
};
|
|
1022
|
-
return /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement(Tooltip, { arrow: true, title: "More" }, /* @__PURE__ */ React.createElement(
|
|
1023
|
-
IconButton,
|
|
1024
|
-
{
|
|
1025
|
-
"aria-label": "more",
|
|
1026
|
-
"aria-controls": "long-menu",
|
|
1027
|
-
"aria-haspopup": "true",
|
|
1028
|
-
onClick: handleMenuOpen
|
|
1029
|
-
},
|
|
1030
|
-
/* @__PURE__ */ React.createElement(MoreVertIcon, null)
|
|
1031
|
-
)), /* @__PURE__ */ React.createElement(
|
|
1032
|
-
Menu,
|
|
1033
|
-
{
|
|
1034
|
-
id: "long-menu",
|
|
1035
|
-
anchorEl,
|
|
1036
|
-
keepMounted: true,
|
|
1037
|
-
open,
|
|
1038
|
-
getContentAnchorEl: null,
|
|
1039
|
-
anchorOrigin: {
|
|
1040
|
-
vertical: "bottom",
|
|
1041
|
-
horizontal: "center"
|
|
1042
|
-
},
|
|
1043
|
-
transformOrigin: {
|
|
1044
|
-
vertical: "top",
|
|
1045
|
-
horizontal: "center"
|
|
1046
|
-
},
|
|
1047
|
-
onClose: handleMenuClose
|
|
1048
|
-
},
|
|
1049
|
-
/* @__PURE__ */ React.createElement(MenuItem, { component: "a", href: tagsRoute() }, /* @__PURE__ */ React.createElement(ListItemIcon, { className: styles.menuIcon }, /* @__PURE__ */ React.createElement(LoyaltyOutlined, { fontSize: "small" })), "Tags"),
|
|
1050
|
-
user && !loadingUser && !userError && /* @__PURE__ */ React.createElement(MenuItem, { component: "a", href: `${userRoute()}/${user.userEntityRef}` }, /* @__PURE__ */ React.createElement(ListItemIcon, { className: styles.menuIcon }, /* @__PURE__ */ React.createElement(AccountBox, { fontSize: "small" })), "My questions"),
|
|
1051
|
-
/* @__PURE__ */ React.createElement(MenuItem, { component: "a", href: favoritesRoute() }, /* @__PURE__ */ React.createElement(ListItemIcon, { className: styles.menuIcon }, /* @__PURE__ */ React.createElement(StarIcon, { fontSize: "small" })), "Favorite questions"),
|
|
1052
|
-
/* @__PURE__ */ React.createElement(MenuItem, { component: "a", href: statisticsRoute() }, /* @__PURE__ */ React.createElement(ListItemIcon, { className: styles.menuIcon }, /* @__PURE__ */ React.createElement(TrophyIcon, null)), "Statistics")
|
|
1053
|
-
));
|
|
1054
|
-
};
|
|
1055
|
-
const HomePageContent = () => {
|
|
1056
|
-
const [searchParams] = useSearchParams();
|
|
1057
|
-
const [entityRef, setEntityRef] = React.useState(
|
|
1058
|
-
void 0
|
|
1059
|
-
);
|
|
1060
|
-
const [tags, setTags] = React.useState(void 0);
|
|
1061
|
-
useEffect(() => {
|
|
1062
|
-
var _a;
|
|
1063
|
-
setEntityRef((_a = searchParams.get("entity")) != null ? _a : void 0);
|
|
1064
|
-
setTags(filterTags(searchParams.get("tags")));
|
|
1065
|
-
}, [searchParams, setEntityRef]);
|
|
1066
|
-
return /* @__PURE__ */ React.createElement(Content, { className: "qetaHomePage" }, /* @__PURE__ */ React.createElement(Container, { maxWidth: "lg" }, /* @__PURE__ */ React.createElement(Grid, { container: true, spacing: 3 }, /* @__PURE__ */ React.createElement(Grid, { item: true, xs: 12, lg: 9, xl: 10 }, /* @__PURE__ */ React.createElement(ContentHeader, { title: "All questions" }, /* @__PURE__ */ React.createElement(MoreMenu, null), /* @__PURE__ */ React.createElement(AskQuestionButton, { entity: entityRef, tags })), /* @__PURE__ */ React.createElement(QuestionsContainer, { entity: entityRef, tags })), /* @__PURE__ */ React.createElement(Grid, { item: true, lg: 3, xl: 2 }, /* @__PURE__ */ React.createElement(
|
|
1067
|
-
QuestionHighlightList,
|
|
1068
|
-
{
|
|
1069
|
-
type: "hot",
|
|
1070
|
-
title: "Hot questions",
|
|
1071
|
-
noQuestionsLabel: "No questions",
|
|
1072
|
-
icon: /* @__PURE__ */ React.createElement(Whatshot, { fontSize: "small" })
|
|
1073
|
-
}
|
|
1074
|
-
), /* @__PURE__ */ React.createElement(
|
|
1075
|
-
QuestionHighlightList,
|
|
1076
|
-
{
|
|
1077
|
-
type: "unanswered",
|
|
1078
|
-
title: "Unanswered questions",
|
|
1079
|
-
noQuestionsLabel: "No unanswered questions"
|
|
1080
|
-
}
|
|
1081
|
-
), /* @__PURE__ */ React.createElement(
|
|
1082
|
-
QuestionHighlightList,
|
|
1083
|
-
{
|
|
1084
|
-
type: "incorrect",
|
|
1085
|
-
title: "Questions without correct answer",
|
|
1086
|
-
noQuestionsLabel: "No questions without correct answers"
|
|
1087
|
-
}
|
|
1088
|
-
)))));
|
|
1089
|
-
};
|
|
1090
|
-
const HomePage = (props) => {
|
|
1091
|
-
const {
|
|
1092
|
-
title = "Q&A",
|
|
1093
|
-
subtitle,
|
|
1094
|
-
headerElements,
|
|
1095
|
-
themeId = "tool",
|
|
1096
|
-
headerTooltip,
|
|
1097
|
-
headerType,
|
|
1098
|
-
headerTypeLink
|
|
1099
|
-
} = props != null ? props : {};
|
|
1100
|
-
return /* @__PURE__ */ React.createElement(Page, { themeId }, /* @__PURE__ */ React.createElement(
|
|
1101
|
-
Header,
|
|
1102
|
-
{
|
|
1103
|
-
title,
|
|
1104
|
-
subtitle,
|
|
1105
|
-
type: headerType,
|
|
1106
|
-
typeLink: headerTypeLink,
|
|
1107
|
-
tooltip: headerTooltip
|
|
1108
|
-
},
|
|
1109
|
-
headerElements
|
|
1110
|
-
), /* @__PURE__ */ React.createElement(Routes, null, /* @__PURE__ */ React.createElement(Route, { path: "/", element: /* @__PURE__ */ React.createElement(HomePageContent, null) }), /* @__PURE__ */ React.createElement(Route, { path: askRouteRef.path, element: /* @__PURE__ */ React.createElement(AskPage, null) }), /* @__PURE__ */ React.createElement(
|
|
1111
|
-
Route,
|
|
1112
|
-
{
|
|
1113
|
-
path: favoriteQuestionsRouteRef.path,
|
|
1114
|
-
element: /* @__PURE__ */ React.createElement(FavoritePage, null)
|
|
1115
|
-
}
|
|
1116
|
-
), /* @__PURE__ */ React.createElement(Route, { path: editQuestionRouteRef.path, element: /* @__PURE__ */ React.createElement(AskPage, null) }), /* @__PURE__ */ React.createElement(Route, { path: questionRouteRef.path, element: /* @__PURE__ */ React.createElement(QuestionPage, null) }), /* @__PURE__ */ React.createElement(Route, { path: tagsRouteRef.path, element: /* @__PURE__ */ React.createElement(TagPage, null) }), /* @__PURE__ */ React.createElement(Route, { path: tagRouteRef.path, element: /* @__PURE__ */ React.createElement(TagPage, null) }), /* @__PURE__ */ React.createElement(Route, { path: userRouteRef.path, element: /* @__PURE__ */ React.createElement(UserPage, null) }), /* @__PURE__ */ React.createElement(Route, { path: statisticsRouteRef.path, element: /* @__PURE__ */ React.createElement(StatisticsPage, null) })));
|
|
1117
|
-
};
|
|
1118
|
-
|
|
1119
|
-
export { HomePage };
|
|
1120
|
-
//# sourceMappingURL=index-rSPV8dxK.esm.js.map
|