@drodil/backstage-plugin-qeta 1.20.0 → 1.21.1
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/esm/{index-ba15a52c.esm.js → index-05d845fb.esm.js} +145 -57
- package/dist/esm/index-05d845fb.esm.js.map +1 -0
- package/dist/esm/{index-0917d370.esm.js → index-3bec4f6e.esm.js} +8 -34
- package/dist/esm/index-3bec4f6e.esm.js.map +1 -0
- package/dist/esm/{index-a1512692.esm.js → index-db684599.esm.js} +2 -2
- package/dist/esm/index-db684599.esm.js.map +1 -0
- package/dist/index.esm.js +1 -1
- package/package.json +3 -3
- package/dist/esm/index-0917d370.esm.js.map +0 -1
- package/dist/esm/index-a1512692.esm.js.map +0 -1
- package/dist/esm/index-ba15a52c.esm.js.map +0 -1
|
@@ -5,11 +5,11 @@ import omitBy from 'lodash/omitBy';
|
|
|
5
5
|
import isEmpty from 'lodash/isEmpty';
|
|
6
6
|
import { qetaRouteRef, tagRouteRef, questionRouteRef, userRouteRef, askRouteRef } from '@drodil/backstage-plugin-qeta-react';
|
|
7
7
|
import useAsync from 'react-use/lib/useAsync';
|
|
8
|
-
import { makeStyles, Box, Grid, FormGroup, FormControlLabel, Checkbox, FormControl, FormLabel, RadioGroup, TextField, Radio, Tooltip, Chip, useTheme, Card, CardContent, Typography, Divider, Select, MenuItem, Button, Collapse, TableRow, TableCell, ButtonGroup, TableContainer, Table, TableHead, TableBody, TablePagination, SvgIcon, ListItem, ListItemAvatar,
|
|
9
|
-
import { catalogApiRef,
|
|
8
|
+
import { makeStyles, Box, Grid, FormGroup, FormControlLabel, Checkbox, FormControl, FormLabel, RadioGroup, TextField, Radio, Tooltip, Chip, useTheme, Card, CardContent, Typography, Avatar, Divider, Select, MenuItem, Button, Collapse, TableRow, TableCell, ButtonGroup, TableContainer, Table, TableHead, TableBody, TablePagination, SvgIcon, ListItem, ListItemAvatar, ListItemText, List, Container } from '@material-ui/core';
|
|
9
|
+
import { catalogApiRef, useEntityPresentation, entityRouteRef, EntityRefLink } from '@backstage/plugin-catalog-react';
|
|
10
10
|
import { trimEnd, compact } from 'lodash';
|
|
11
11
|
import { useSearchParams, useNavigate } from 'react-router-dom';
|
|
12
|
-
import React, { useEffect, useMemo } from 'react';
|
|
12
|
+
import React, { useEffect, useRef, useState, useMemo } from 'react';
|
|
13
13
|
import useDebounce from 'react-use/lib/useDebounce';
|
|
14
14
|
import { Autocomplete, Pagination, Alert } from '@material-ui/lab';
|
|
15
15
|
import { stringifyEntityRef, getCompoundEntityRef, parseEntityRef } from '@backstage/catalog-model';
|
|
@@ -469,7 +469,7 @@ const qetaPlugin = createPlugin({
|
|
|
469
469
|
const QetaPage = qetaPlugin.provide(
|
|
470
470
|
createRoutableExtension({
|
|
471
471
|
name: "QetaPage",
|
|
472
|
-
component: () => import('./index-
|
|
472
|
+
component: () => import('./index-3bec4f6e.esm.js').then((m) => m.HomePage),
|
|
473
473
|
mountPoint: qetaRouteRef
|
|
474
474
|
})
|
|
475
475
|
);
|
|
@@ -478,7 +478,7 @@ const QuestionTableCard = qetaPlugin.provide(
|
|
|
478
478
|
name: "QuestionsTableCard",
|
|
479
479
|
title: "Q&A",
|
|
480
480
|
description: "Shows Q&A questions",
|
|
481
|
-
components: () => import('./index-
|
|
481
|
+
components: () => import('./index-db684599.esm.js'),
|
|
482
482
|
layout: {
|
|
483
483
|
height: { minRows: 6 },
|
|
484
484
|
width: { minColumns: 6 }
|
|
@@ -606,6 +606,29 @@ const useStyles$1 = makeStyles((theme) => {
|
|
|
606
606
|
width: "calc(100% - 70px)",
|
|
607
607
|
minHeight: "160px"
|
|
608
608
|
},
|
|
609
|
+
questionListItemStats: {
|
|
610
|
+
width: "80px",
|
|
611
|
+
textAlign: "right",
|
|
612
|
+
marginRight: "26px",
|
|
613
|
+
display: "inline-block",
|
|
614
|
+
verticalAlign: "top",
|
|
615
|
+
paddingTop: "10px"
|
|
616
|
+
},
|
|
617
|
+
questionListItemContent: {
|
|
618
|
+
display: "inline-block",
|
|
619
|
+
width: "calc(100% - 120px)"
|
|
620
|
+
},
|
|
621
|
+
questionListItemAuthor: {
|
|
622
|
+
display: "inline",
|
|
623
|
+
float: "right"
|
|
624
|
+
},
|
|
625
|
+
questionListItemAvatar: {
|
|
626
|
+
display: "inline-flex",
|
|
627
|
+
marginRight: "0.25rem",
|
|
628
|
+
fontSize: "1rem",
|
|
629
|
+
maxWidth: "1rem",
|
|
630
|
+
maxHeight: "1rem"
|
|
631
|
+
},
|
|
609
632
|
answerCardContent: {
|
|
610
633
|
display: "inline-block",
|
|
611
634
|
width: "calc(100% - 70px)"
|
|
@@ -713,6 +736,43 @@ const useBasePath = () => {
|
|
|
713
736
|
const { pathname } = new URL(url, base);
|
|
714
737
|
return trimEnd(pathname, "/");
|
|
715
738
|
};
|
|
739
|
+
const useEntityAuthor = (entity) => {
|
|
740
|
+
var _a;
|
|
741
|
+
const catalogApi = useApi(catalogApiRef);
|
|
742
|
+
const identityApi = useApi(identityApiRef);
|
|
743
|
+
const [name, setName] = React.useState(void 0);
|
|
744
|
+
const [user, setUser] = React.useState(null);
|
|
745
|
+
const [initials, setInitials] = React.useState(null);
|
|
746
|
+
const [currentUser, setCurrentUser] = React.useState(null);
|
|
747
|
+
const anonymous = (_a = entity.anonymous) != null ? _a : false;
|
|
748
|
+
const { primaryTitle: userName } = useEntityPresentation(entity.author);
|
|
749
|
+
useEffect(() => {
|
|
750
|
+
if (!anonymous) {
|
|
751
|
+
catalogApi.getEntityByRef(entity.author).catch((_) => setUser(null)).then((data) => data ? setUser(data) : setUser(null));
|
|
752
|
+
}
|
|
753
|
+
}, [catalogApi, entity, anonymous]);
|
|
754
|
+
useEffect(() => {
|
|
755
|
+
identityApi.getBackstageIdentity().then((res) => {
|
|
756
|
+
var _a2;
|
|
757
|
+
setCurrentUser((_a2 = res.userEntityRef) != null ? _a2 : "user:default/guest");
|
|
758
|
+
});
|
|
759
|
+
}, [identityApi]);
|
|
760
|
+
useEffect(() => {
|
|
761
|
+
let displayName = userName;
|
|
762
|
+
if (entity.author === currentUser) {
|
|
763
|
+
displayName = "You";
|
|
764
|
+
if (anonymous) {
|
|
765
|
+
displayName += " (anonymous)";
|
|
766
|
+
}
|
|
767
|
+
}
|
|
768
|
+
setName(displayName);
|
|
769
|
+
}, [entity.author, anonymous, currentUser, userName]);
|
|
770
|
+
useEffect(() => {
|
|
771
|
+
const init = (name != null ? name : "").split(" ").map((p) => p[0]).join("").substring(0, 2).toUpperCase();
|
|
772
|
+
setInitials(init);
|
|
773
|
+
}, [name]);
|
|
774
|
+
return { name, initials, user };
|
|
775
|
+
};
|
|
716
776
|
|
|
717
777
|
const formatEntityName = (username) => {
|
|
718
778
|
if (!username) {
|
|
@@ -1013,12 +1073,44 @@ const RelativeTimeWithTooltip = (props) => {
|
|
|
1013
1073
|
};
|
|
1014
1074
|
|
|
1015
1075
|
const QuestionListItem = (props) => {
|
|
1076
|
+
var _a, _b;
|
|
1016
1077
|
const { question, entity } = props;
|
|
1017
1078
|
const questionRoute = useRouteRef(questionRouteRef);
|
|
1018
1079
|
const userRoute = useRouteRef(userRouteRef);
|
|
1019
|
-
const { primaryTitle: userName } = useEntityPresentation(question.author);
|
|
1020
1080
|
const theme = useTheme();
|
|
1021
|
-
|
|
1081
|
+
const styles = useStyles$1();
|
|
1082
|
+
const { name, initials, user } = useEntityAuthor(question);
|
|
1083
|
+
return /* @__PURE__ */ React.createElement(Card, { className: "qetaQuestionListItem" }, /* @__PURE__ */ React.createElement(CardContent, null, /* @__PURE__ */ React.createElement(Box, { className: styles.questionListItemStats }, /* @__PURE__ */ React.createElement(
|
|
1084
|
+
Typography,
|
|
1085
|
+
{
|
|
1086
|
+
display: "block",
|
|
1087
|
+
variant: "caption",
|
|
1088
|
+
className: "qetaQuestionListItemScore"
|
|
1089
|
+
},
|
|
1090
|
+
question.score,
|
|
1091
|
+
" score"
|
|
1092
|
+
), /* @__PURE__ */ React.createElement(
|
|
1093
|
+
Typography,
|
|
1094
|
+
{
|
|
1095
|
+
variant: "caption",
|
|
1096
|
+
display: "block",
|
|
1097
|
+
className: `qetaQuestionListItemAnswers ${question.correctAnswer ? "qetaQuestionListItemCorrectAnswer" : "quetaQuestionListItemNoCorrectAnswer"}`,
|
|
1098
|
+
style: {
|
|
1099
|
+
color: question.correctAnswer ? theme.palette.success.main : void 0
|
|
1100
|
+
}
|
|
1101
|
+
},
|
|
1102
|
+
question.answersCount,
|
|
1103
|
+
" answers"
|
|
1104
|
+
), /* @__PURE__ */ React.createElement(
|
|
1105
|
+
Typography,
|
|
1106
|
+
{
|
|
1107
|
+
display: "block",
|
|
1108
|
+
variant: "caption",
|
|
1109
|
+
className: "qetaQuestionListItemViews"
|
|
1110
|
+
},
|
|
1111
|
+
question.views,
|
|
1112
|
+
" views"
|
|
1113
|
+
)), /* @__PURE__ */ React.createElement(Box, { className: styles.questionListItemContent }, /* @__PURE__ */ React.createElement(Typography, { variant: "h5", component: "div" }, /* @__PURE__ */ React.createElement(
|
|
1022
1114
|
Link,
|
|
1023
1115
|
{
|
|
1024
1116
|
to: entity ? `${questionRoute({
|
|
@@ -1027,66 +1119,49 @@ const QuestionListItem = (props) => {
|
|
|
1027
1119
|
className: "qetaQuestionListItemQuestionBtn"
|
|
1028
1120
|
},
|
|
1029
1121
|
question.title
|
|
1030
|
-
))
|
|
1122
|
+
)), /* @__PURE__ */ React.createElement(
|
|
1031
1123
|
Typography,
|
|
1032
1124
|
{
|
|
1033
1125
|
variant: "caption",
|
|
1034
1126
|
noWrap: true,
|
|
1035
1127
|
component: "div",
|
|
1036
|
-
className: "qetaQuestionListItemContent"
|
|
1128
|
+
className: "qetaQuestionListItemContent",
|
|
1129
|
+
style: { marginBottom: "5px" }
|
|
1037
1130
|
},
|
|
1038
1131
|
DOMPurify.sanitize(
|
|
1039
1132
|
truncate(removeMarkdownFormatting(question.content), 150)
|
|
1040
1133
|
)
|
|
1041
|
-
)
|
|
1042
|
-
Typography,
|
|
1043
|
-
{
|
|
1044
|
-
variant: "body2",
|
|
1045
|
-
display: "block",
|
|
1046
|
-
className: "qetaQuestionListItemAuthor"
|
|
1047
|
-
},
|
|
1048
|
-
"By",
|
|
1049
|
-
" ",
|
|
1050
|
-
question.author === "anonymous" ? "Anonymous" : /* @__PURE__ */ React.createElement(Link, { to: `${userRoute()}/${question.author}` }, userName),
|
|
1051
|
-
" ",
|
|
1052
|
-
/* @__PURE__ */ React.createElement(RelativeTimeWithTooltip, { value: question.created })
|
|
1053
|
-
), /* @__PURE__ */ React.createElement(
|
|
1134
|
+
), /* @__PURE__ */ React.createElement(TagsAndEntities, { question }), /* @__PURE__ */ React.createElement(
|
|
1054
1135
|
Typography,
|
|
1055
1136
|
{
|
|
1056
1137
|
variant: "caption",
|
|
1057
1138
|
display: "inline",
|
|
1058
|
-
|
|
1059
|
-
className: "qetaQuestionListItemScore"
|
|
1139
|
+
className: `${styles.questionListItemAuthor} qetaQuestionListItemAuthor`
|
|
1060
1140
|
},
|
|
1061
|
-
|
|
1062
|
-
|
|
1141
|
+
/* @__PURE__ */ React.createElement(
|
|
1142
|
+
Avatar,
|
|
1143
|
+
{
|
|
1144
|
+
src: (_b = (_a = user == null ? void 0 : user.spec) == null ? void 0 : _a.profile) == null ? void 0 : _b.picture,
|
|
1145
|
+
className: styles.questionListItemAvatar,
|
|
1146
|
+
alt: name,
|
|
1147
|
+
variant: "rounded"
|
|
1148
|
+
},
|
|
1149
|
+
initials
|
|
1150
|
+
),
|
|
1151
|
+
question.author === "anonymous" ? "Anonymous" : /* @__PURE__ */ React.createElement(Link, { to: `${userRoute()}/${question.author}` }, name),
|
|
1063
1152
|
" ",
|
|
1064
|
-
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
color: question.correctAnswer ? theme.palette.success.main : void 0
|
|
1153
|
+
/* @__PURE__ */ React.createElement(
|
|
1154
|
+
Link,
|
|
1155
|
+
{
|
|
1156
|
+
to: entity ? `${questionRoute({
|
|
1157
|
+
id: question.id.toString(10)
|
|
1158
|
+
})}?entity=${entity}` : questionRoute({ id: question.id.toString(10) }),
|
|
1159
|
+
className: "qetaQuestionListItemQuestionBtn"
|
|
1072
1160
|
},
|
|
1073
|
-
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
question.answersCount
|
|
1078
|
-
), /* @__PURE__ */ React.createElement(
|
|
1079
|
-
Typography,
|
|
1080
|
-
{
|
|
1081
|
-
variant: "caption",
|
|
1082
|
-
display: "inline",
|
|
1083
|
-
gutterBottom: true,
|
|
1084
|
-
className: "qetaQuestionListItemViews"
|
|
1085
|
-
},
|
|
1086
|
-
" | ",
|
|
1087
|
-
" Views: ",
|
|
1088
|
-
question.views
|
|
1089
|
-
)), /* @__PURE__ */ React.createElement(Grid, { item: true }, /* @__PURE__ */ React.createElement(TagsAndEntities, { question })))));
|
|
1161
|
+
"asked ",
|
|
1162
|
+
/* @__PURE__ */ React.createElement(RelativeTimeWithTooltip, { value: question.created })
|
|
1163
|
+
)
|
|
1164
|
+
))));
|
|
1090
1165
|
};
|
|
1091
1166
|
|
|
1092
1167
|
const NoQuestionsCard = (props) => {
|
|
@@ -1135,19 +1210,32 @@ const QuestionList = (props) => {
|
|
|
1135
1210
|
entityPage
|
|
1136
1211
|
} = props;
|
|
1137
1212
|
const styles = useStyles$1();
|
|
1213
|
+
const listRef = useRef(null);
|
|
1214
|
+
const [initialLoad, setInitialLoad] = useState(true);
|
|
1215
|
+
useEffect(() => {
|
|
1216
|
+
if (!initialLoad) {
|
|
1217
|
+
setInitialLoad(false);
|
|
1218
|
+
}
|
|
1219
|
+
}, [initialLoad, loading]);
|
|
1138
1220
|
const handlePageChange = (_event, value) => {
|
|
1221
|
+
if (listRef.current) {
|
|
1222
|
+
listRef.current.scrollIntoView();
|
|
1223
|
+
}
|
|
1139
1224
|
onPageChange(value);
|
|
1140
1225
|
};
|
|
1141
1226
|
const handlePageSizeChange = (event) => {
|
|
1227
|
+
if (listRef.current) {
|
|
1228
|
+
listRef.current.scrollIntoView();
|
|
1229
|
+
}
|
|
1142
1230
|
onPageSizeChange(Number.parseInt(event.target.value, 10));
|
|
1143
1231
|
};
|
|
1144
|
-
if (loading) {
|
|
1232
|
+
if (loading && initialLoad) {
|
|
1145
1233
|
return /* @__PURE__ */ React.createElement(Progress, null);
|
|
1146
1234
|
}
|
|
1147
1235
|
if (error || response === void 0) {
|
|
1148
1236
|
return /* @__PURE__ */ React.createElement(WarningPanel, { severity: "error", title: "Could not load questions." }, error == null ? void 0 : error.message);
|
|
1149
1237
|
}
|
|
1150
|
-
if (!response.questions || response.questions.length === 0) {
|
|
1238
|
+
if (initialLoad && (!response.questions || response.questions.length === 0)) {
|
|
1151
1239
|
return /* @__PURE__ */ React.createElement(
|
|
1152
1240
|
NoQuestionsCard,
|
|
1153
1241
|
{
|
|
@@ -1158,7 +1246,7 @@ const QuestionList = (props) => {
|
|
|
1158
1246
|
);
|
|
1159
1247
|
}
|
|
1160
1248
|
const pageCount = response.total < props.pageSize ? 1 : Math.ceil(response.total / props.pageSize);
|
|
1161
|
-
return /* @__PURE__ */ React.createElement(Box, { sx: { mt: 2 }, className: "qetaQuestionList" }, /* @__PURE__ */ React.createElement(Grid, { container: true, spacing: 2, className: "qetaQuestionListGrid" }, response.questions.map((question) => {
|
|
1249
|
+
return /* @__PURE__ */ React.createElement("div", { ref: listRef }, /* @__PURE__ */ React.createElement(Box, { sx: { mt: 2 }, className: "qetaQuestionList" }, /* @__PURE__ */ React.createElement(Grid, { container: true, spacing: 2, className: "qetaQuestionListGrid" }, response.questions.map((question) => {
|
|
1162
1250
|
return /* @__PURE__ */ React.createElement(Grid, { item: true, xs: 12, key: question.id }, /* @__PURE__ */ React.createElement(QuestionListItem, { question, entity }), /* @__PURE__ */ React.createElement(Divider, null));
|
|
1163
1251
|
})), /* @__PURE__ */ React.createElement(
|
|
1164
1252
|
Grid,
|
|
@@ -1196,7 +1284,7 @@ const QuestionList = (props) => {
|
|
|
1196
1284
|
showLastButton: true
|
|
1197
1285
|
}
|
|
1198
1286
|
)
|
|
1199
|
-
));
|
|
1287
|
+
)));
|
|
1200
1288
|
};
|
|
1201
1289
|
|
|
1202
1290
|
const AskQuestionButton = (props) => {
|
|
@@ -2266,5 +2354,5 @@ const StatisticsPage = () => {
|
|
|
2266
2354
|
return /* @__PURE__ */ React.createElement(Content$1, { className: "qetaStatisticsPage" }, /* @__PURE__ */ React.createElement(Container, { maxWidth: "lg" }, /* @__PURE__ */ React.createElement(ContentHeader, { title: "Statistics" }, /* @__PURE__ */ React.createElement(BackToQuestionsButton, null), /* @__PURE__ */ React.createElement(AskQuestionButton, null)), /* @__PURE__ */ React.createElement(TopRankingUsers, { limit: 10 })));
|
|
2267
2355
|
};
|
|
2268
2356
|
|
|
2269
|
-
export { AskForm as A, BackToQuestionsButton as B, Content as C, MarkdownEditor as M, QuestionsContainer as Q, RelativeTimeWithTooltip as R, StatisticsPage as S, TagsAndEntities as T, UpdatedByLink as U, useStyles$1 as a,
|
|
2270
|
-
//# sourceMappingURL=index-
|
|
2357
|
+
export { AskForm as A, BackToQuestionsButton as B, Content as C, MarkdownEditor as M, QuestionsContainer as Q, RelativeTimeWithTooltip as R, StatisticsPage as S, TagsAndEntities as T, UpdatedByLink as U, useStyles$1 as a, useEntityAuthor as b, AuthorLink as c, AskAnonymouslyCheckbox as d, useQetaApi as e, AskQuestionButton as f, useIdentityApi as g, TrophyIcon as h, QuestionsTable as i, qetaPlugin as j, QetaPage as k, QuestionTableCard as l, RankingRow as m, RankingCard as n, TopRankingUsers as o, QetaClient as p, qetaApiRef as q, useBasePath as u };
|
|
2358
|
+
//# sourceMappingURL=index-05d845fb.esm.js.map
|