@drodil/backstage-plugin-qeta 2.6.0 → 2.7.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/components/AnswersContainer/AnswerListItem.esm.js +1 -1
- package/dist/components/AnswersContainer/AnswerListItem.esm.js.map +1 -1
- package/dist/components/AskForm/AskForm.esm.js +74 -51
- package/dist/components/AskForm/AskForm.esm.js.map +1 -1
- package/dist/components/AskForm/EntitiesInput.esm.js +1 -0
- package/dist/components/AskForm/EntitiesInput.esm.js.map +1 -1
- package/dist/components/CommentSection/CommentSection.esm.js +52 -35
- package/dist/components/CommentSection/CommentSection.esm.js.map +1 -1
- package/dist/components/QuestionPage/AnswerForm.esm.js +58 -37
- package/dist/components/QuestionPage/AnswerForm.esm.js.map +1 -1
- package/dist/components/QuestionsContainer/QuestionListItem.esm.js +1 -1
- package/dist/components/QuestionsContainer/QuestionListItem.esm.js.map +1 -1
- package/dist/components/UserPage/UserPage.esm.js +2 -1
- package/dist/components/UserPage/UserPage.esm.js.map +1 -1
- package/dist/utils/hooks.esm.js +9 -3
- package/dist/utils/hooks.esm.js.map +1 -1
- package/dist/utils/utils.esm.js +13 -15
- package/dist/utils/utils.esm.js.map +1 -1
- package/package.json +3 -3
|
@@ -2,7 +2,7 @@ import { Card, CardContent, Box, Typography, Avatar } from '@material-ui/core';
|
|
|
2
2
|
import { Link } from '@backstage/core-components';
|
|
3
3
|
import React from 'react';
|
|
4
4
|
import DOMPurify from 'dompurify';
|
|
5
|
-
import { truncate, removeMarkdownFormatting } from '
|
|
5
|
+
import { truncate, removeMarkdownFormatting } from '@drodil/backstage-plugin-qeta-common';
|
|
6
6
|
import { useRouteRef } from '@backstage/core-plugin-api';
|
|
7
7
|
import { questionRouteRef, userRouteRef } from '@drodil/backstage-plugin-qeta-react';
|
|
8
8
|
import { RelativeTimeWithTooltip } from '../RelativeTimeWithTooltip/RelativeTimeWithTooltip.esm.js';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AnswerListItem.esm.js","sources":["../../../src/components/AnswersContainer/AnswerListItem.tsx"],"sourcesContent":["import { Avatar, Box, Card, CardContent, Typography } from '@material-ui/core';\nimport { Link } from '@backstage/core-components';\nimport React from 'react';\nimport DOMPurify from 'dompurify';\nimport {
|
|
1
|
+
{"version":3,"file":"AnswerListItem.esm.js","sources":["../../../src/components/AnswersContainer/AnswerListItem.tsx"],"sourcesContent":["import { Avatar, Box, Card, CardContent, Typography } from '@material-ui/core';\nimport { Link } from '@backstage/core-components';\nimport React from 'react';\nimport DOMPurify from 'dompurify';\nimport {\n AnswerResponse,\n removeMarkdownFormatting,\n truncate,\n} from '@drodil/backstage-plugin-qeta-common';\nimport { useRouteRef } from '@backstage/core-plugin-api';\nimport {\n questionRouteRef,\n userRouteRef,\n} from '@drodil/backstage-plugin-qeta-react';\nimport { RelativeTimeWithTooltip } from '../RelativeTimeWithTooltip/RelativeTimeWithTooltip';\nimport { useEntityAuthor, useStyles, useTranslation } from '../../utils/hooks';\nimport { TagsAndEntities } from '../QuestionPage/TagsAndEntities';\n\nexport interface AnswerListItemProps {\n answer: AnswerResponse;\n entity?: string;\n}\n\nexport const AnswerListItem = (props: AnswerListItemProps) => {\n const { answer, entity } = props;\n\n const questionRoute = useRouteRef(questionRouteRef);\n const userRoute = useRouteRef(userRouteRef);\n const styles = useStyles();\n const { name, initials, user } = useEntityAuthor(answer);\n const { t } = useTranslation();\n\n const getAnswerLink = () => {\n return entity\n ? `${questionRoute({\n id: answer.questionId.toString(10),\n })}?entity=${entity}#answer_${answer.id}`\n : `${questionRoute({\n id: answer.questionId.toString(10),\n })}/#answer_${answer.id}`;\n };\n\n return (\n <Card className=\"qetaQuestionListItem\">\n <CardContent>\n <Box className={styles.questionListItemStats}>\n <Typography\n display=\"block\"\n variant=\"caption\"\n className=\"qetaQuestionListItemScore\"\n >\n {t('common.score', { score: answer.score.toString(10) })}\n </Typography>\n </Box>\n <Box className={styles.questionListItemContent}>\n <Typography variant=\"h5\" component=\"div\">\n <Link\n to={getAnswerLink()}\n className=\"qetaAnswerListItemQuestionBtn\"\n >\n {t('answer.questionTitle', {\n question: answer.question?.title ?? '',\n })}\n </Link>\n </Typography>\n <Typography\n variant=\"caption\"\n noWrap\n component=\"div\"\n className=\"qetaQuestionListItemContent\"\n style={{ marginBottom: '5px' }}\n >\n {DOMPurify.sanitize(\n truncate(removeMarkdownFormatting(answer.content), 150),\n )}\n </Typography>\n {answer.question && <TagsAndEntities question={answer.question} />}\n <Typography\n variant=\"caption\"\n display=\"inline\"\n className={`${styles.questionListItemAuthor} qetaAnswerListItemAuthor`}\n >\n <Avatar\n src={user?.spec?.profile?.picture}\n className={styles.questionListItemAvatar}\n alt={name}\n variant=\"rounded\"\n >\n {initials}\n </Avatar>\n {answer.author === 'anonymous' ? (\n t('common.anonymousAuthor')\n ) : (\n <Link to={`${userRoute()}/${answer.author}`}>{name}</Link>\n )}{' '}\n <Link\n to={getAnswerLink()}\n className=\"qetaQuestionListItemQuestionBtn\"\n >\n {`${t('answer.answeredTime')} `}\n <RelativeTimeWithTooltip value={answer.created} />\n </Link>\n </Typography>\n </Box>\n </CardContent>\n </Card>\n );\n};\n"],"names":[],"mappings":"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"}
|
|
@@ -14,6 +14,7 @@ import { EntitiesInput } from './EntitiesInput.esm.js';
|
|
|
14
14
|
import { questionRouteRef } from '@drodil/backstage-plugin-qeta-react';
|
|
15
15
|
import { AskAnonymouslyCheckbox } from '../AskAnonymouslyCheckbox/AskAnonymouslyCheckbox.esm.js';
|
|
16
16
|
import { qetaApiRef } from '../../api/QetaClient.esm.js';
|
|
17
|
+
import { confirmNavigationIfEdited } from '../../utils/utils.esm.js';
|
|
17
18
|
|
|
18
19
|
const formToRequest = (form, images) => {
|
|
19
20
|
return {
|
|
@@ -60,6 +61,7 @@ const AskForm = (props) => {
|
|
|
60
61
|
const [posting, setPosting] = React.useState(false);
|
|
61
62
|
const [values, setValues] = React.useState(getDefaultValues(props));
|
|
62
63
|
const [error, setError] = React.useState(false);
|
|
64
|
+
const [edited, setEdited] = React.useState(false);
|
|
63
65
|
const [images, setImages] = React.useState([]);
|
|
64
66
|
const [searchParams, _setSearchParams] = useSearchParams();
|
|
65
67
|
const { t } = useTranslation();
|
|
@@ -93,6 +95,7 @@ const AskForm = (props) => {
|
|
|
93
95
|
setError(true);
|
|
94
96
|
return;
|
|
95
97
|
}
|
|
98
|
+
setEdited(false);
|
|
96
99
|
reset();
|
|
97
100
|
analytics.captureEvent("edit", "question");
|
|
98
101
|
if (onPost) {
|
|
@@ -117,6 +120,7 @@ const AskForm = (props) => {
|
|
|
117
120
|
setError(true);
|
|
118
121
|
return;
|
|
119
122
|
}
|
|
123
|
+
setEdited(false);
|
|
120
124
|
analytics.captureEvent("post", "question");
|
|
121
125
|
reset();
|
|
122
126
|
if (entity) {
|
|
@@ -162,60 +166,79 @@ const AskForm = (props) => {
|
|
|
162
166
|
useEffect(() => {
|
|
163
167
|
reset(values);
|
|
164
168
|
}, [values, reset]);
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
required: true,
|
|
171
|
-
fullWidth: true,
|
|
172
|
-
error: "title" in errors,
|
|
173
|
-
margin: "normal",
|
|
174
|
-
variant: "outlined",
|
|
175
|
-
helperText: t("askForm.titleInput.helperText"),
|
|
176
|
-
// @ts-ignore
|
|
177
|
-
...register("title", { required: true, maxLength: 255 })
|
|
178
|
-
}
|
|
179
|
-
), /* @__PURE__ */ React.createElement(
|
|
180
|
-
Controller,
|
|
169
|
+
useEffect(() => {
|
|
170
|
+
return confirmNavigationIfEdited(edited);
|
|
171
|
+
}, [edited]);
|
|
172
|
+
return /* @__PURE__ */ React.createElement(
|
|
173
|
+
"form",
|
|
181
174
|
{
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
175
|
+
onSubmit: handleSubmit(postQuestion),
|
|
176
|
+
onChange: () => {
|
|
177
|
+
setEdited(true);
|
|
185
178
|
},
|
|
186
|
-
|
|
187
|
-
MarkdownEditor,
|
|
188
|
-
{
|
|
189
|
-
value,
|
|
190
|
-
onChange,
|
|
191
|
-
height: 400,
|
|
192
|
-
error: "content" in errors,
|
|
193
|
-
placeholder: t("askForm.contentInput.placeholder"),
|
|
194
|
-
config: configApi,
|
|
195
|
-
onImageUpload: (imageId) => {
|
|
196
|
-
setImages((prevImages) => [...prevImages, imageId]);
|
|
197
|
-
}
|
|
198
|
-
}
|
|
199
|
-
),
|
|
200
|
-
name: "content"
|
|
201
|
-
}
|
|
202
|
-
), /* @__PURE__ */ React.createElement(TagInput, { control }), /* @__PURE__ */ React.createElement(EntitiesInput, { control, entityRef }), allowAnonymouns && !id && /* @__PURE__ */ React.createElement(
|
|
203
|
-
AskAnonymouslyCheckbox,
|
|
204
|
-
{
|
|
205
|
-
control,
|
|
206
|
-
label: t("anonymousCheckbox.askAnonymously")
|
|
207
|
-
}
|
|
208
|
-
), /* @__PURE__ */ React.createElement(
|
|
209
|
-
Button,
|
|
210
|
-
{
|
|
211
|
-
color: "primary",
|
|
212
|
-
type: "submit",
|
|
213
|
-
variant: "contained",
|
|
214
|
-
disabled: posting,
|
|
215
|
-
className: `qetaAskFormSubmitBtn ${styles.postButton}`
|
|
179
|
+
className: "qetaAskForm"
|
|
216
180
|
},
|
|
217
|
-
|
|
218
|
-
|
|
181
|
+
error && /* @__PURE__ */ React.createElement(Alert, { severity: "error" }, t("askForm.errorPosting")),
|
|
182
|
+
/* @__PURE__ */ React.createElement(
|
|
183
|
+
TextField,
|
|
184
|
+
{
|
|
185
|
+
label: "Title",
|
|
186
|
+
className: "qetaAskFormTitle",
|
|
187
|
+
required: true,
|
|
188
|
+
fullWidth: true,
|
|
189
|
+
error: "title" in errors,
|
|
190
|
+
margin: "normal",
|
|
191
|
+
variant: "outlined",
|
|
192
|
+
helperText: t("askForm.titleInput.helperText"),
|
|
193
|
+
// @ts-ignore
|
|
194
|
+
...register("title", { required: true, maxLength: 255 })
|
|
195
|
+
}
|
|
196
|
+
),
|
|
197
|
+
/* @__PURE__ */ React.createElement(
|
|
198
|
+
Controller,
|
|
199
|
+
{
|
|
200
|
+
control,
|
|
201
|
+
rules: {
|
|
202
|
+
required: true
|
|
203
|
+
},
|
|
204
|
+
render: ({ field: { onChange, value } }) => /* @__PURE__ */ React.createElement(
|
|
205
|
+
MarkdownEditor,
|
|
206
|
+
{
|
|
207
|
+
value,
|
|
208
|
+
onChange,
|
|
209
|
+
height: 400,
|
|
210
|
+
error: "content" in errors,
|
|
211
|
+
placeholder: t("askForm.contentInput.placeholder"),
|
|
212
|
+
config: configApi,
|
|
213
|
+
onImageUpload: (imageId) => {
|
|
214
|
+
setImages((prevImages) => [...prevImages, imageId]);
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
),
|
|
218
|
+
name: "content"
|
|
219
|
+
}
|
|
220
|
+
),
|
|
221
|
+
/* @__PURE__ */ React.createElement(TagInput, { control }),
|
|
222
|
+
/* @__PURE__ */ React.createElement(EntitiesInput, { control, entityRef }),
|
|
223
|
+
allowAnonymouns && !id && /* @__PURE__ */ React.createElement(
|
|
224
|
+
AskAnonymouslyCheckbox,
|
|
225
|
+
{
|
|
226
|
+
control,
|
|
227
|
+
label: t("anonymousCheckbox.askAnonymously")
|
|
228
|
+
}
|
|
229
|
+
),
|
|
230
|
+
/* @__PURE__ */ React.createElement(
|
|
231
|
+
Button,
|
|
232
|
+
{
|
|
233
|
+
color: "primary",
|
|
234
|
+
type: "submit",
|
|
235
|
+
variant: "contained",
|
|
236
|
+
disabled: posting,
|
|
237
|
+
className: `qetaAskFormSubmitBtn ${styles.postButton}`
|
|
238
|
+
},
|
|
239
|
+
id ? t("askForm.submit.existingQuestion") : t("askForm.submit.newQuestion")
|
|
240
|
+
)
|
|
241
|
+
);
|
|
219
242
|
};
|
|
220
243
|
|
|
221
244
|
export { AskForm };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AskForm.esm.js","sources":["../../../src/components/AskForm/AskForm.tsx"],"sourcesContent":["import {\n configApiRef,\n useAnalytics,\n useApi,\n useRouteRef,\n} from '@backstage/core-plugin-api';\nimport { Button, TextField } from '@material-ui/core';\nimport { Alert } from '@material-ui/lab';\nimport React, { useEffect } from 'react';\nimport { Controller, useForm } from 'react-hook-form';\nimport { useNavigate, useSearchParams } from 'react-router-dom';\nimport {\n QuestionRequest,\n QuestionResponse,\n} from '@drodil/backstage-plugin-qeta-common';\nimport { useStyles, useTranslation } from '../../utils/hooks';\nimport { MarkdownEditor } from '../MarkdownEditor/MarkdownEditor';\nimport { catalogApiRef } from '@backstage/plugin-catalog-react';\nimport { stringifyEntityRef } from '@backstage/catalog-model';\nimport { CatalogApi } from '@backstage/catalog-client';\nimport { compact } from 'lodash';\nimport { TagInput } from './TagInput';\nimport { QuestionForm } from './types';\nimport { EntitiesInput } from './EntitiesInput';\nimport { questionRouteRef } from '@drodil/backstage-plugin-qeta-react';\nimport { AskAnonymouslyCheckbox } from '../AskAnonymouslyCheckbox/AskAnonymouslyCheckbox';\nimport { QetaApi, qetaApiRef } from '../../api';\n\nconst formToRequest = (\n form: QuestionForm,\n images: number[],\n): QuestionRequest => {\n return {\n ...form,\n entities: form.entities?.map(stringifyEntityRef),\n images,\n };\n};\n\nexport type AskFormProps = {\n id?: string;\n entity?: string;\n tags?: string[];\n onPost?: (question: QuestionResponse) => void;\n entityPage?: boolean;\n};\n\nconst getDefaultValues = (props: AskFormProps): QuestionForm => {\n return {\n title: '',\n content: '',\n tags: props.tags ?? [],\n entities: [],\n };\n};\n\nconst getValues = async (\n api: QetaApi,\n catalogApi: CatalogApi,\n id?: string,\n): Promise<QuestionForm> => {\n if (!id) {\n return getDefaultValues({});\n }\n\n const question = await api.getQuestion(id);\n const entities =\n question.entities && question.entities.length > 0\n ? await catalogApi.getEntitiesByRefs({\n entityRefs: question.entities,\n fields: [\n 'kind',\n 'metadata.name',\n 'metadata.namespace',\n 'metadata.title',\n ],\n })\n : [];\n return {\n title: question.title,\n content: question.content,\n tags: question.tags ?? [],\n entities: 'items' in entities ? compact(entities.items) : [],\n };\n};\n\nexport const AskForm = (props: AskFormProps) => {\n const { id, entity, onPost, entityPage } = props;\n const questionRoute = useRouteRef(questionRouteRef);\n const navigate = useNavigate();\n const analytics = useAnalytics();\n const [entityRef, setEntityRef] = React.useState(entity);\n const [posting, setPosting] = React.useState(false);\n const [values, setValues] = React.useState(getDefaultValues(props));\n const [error, setError] = React.useState(false);\n\n const [images, setImages] = React.useState<number[]>([]);\n const [searchParams, _setSearchParams] = useSearchParams();\n const { t } = useTranslation();\n\n const qetaApi = useApi(qetaApiRef);\n const catalogApi = useApi(catalogApiRef);\n const configApi = useApi(configApiRef);\n const allowAnonymouns = configApi.getOptionalBoolean('qeta.allowAnonymous');\n const styles = useStyles();\n const {\n register,\n handleSubmit,\n control,\n reset,\n formState: { errors },\n } = useForm<QuestionForm>({\n values,\n defaultValues: getDefaultValues(props),\n });\n\n const postQuestion = (data: QuestionForm) => {\n setPosting(true);\n\n const queryParams = new URLSearchParams();\n if (entity) {\n queryParams.set('entity', entity);\n }\n if (entityPage) {\n queryParams.set('entityPage', 'true');\n }\n\n if (id) {\n qetaApi\n .updateQuestion(id, formToRequest(data, images))\n .then(q => {\n if (!q || !q.id) {\n setError(true);\n return;\n }\n reset();\n analytics.captureEvent('edit', 'question');\n if (onPost) {\n onPost(q);\n } else if (entity) {\n navigate(\n `${questionRoute({\n id: q.id.toString(10),\n })}?${queryParams.toString()}`,\n );\n } else {\n navigate(questionRoute({ id: q.id.toString(10) }));\n }\n })\n .catch(_e => {\n setError(true);\n setPosting(false);\n });\n return;\n }\n qetaApi\n .postQuestion(formToRequest(data, images))\n .then(q => {\n if (!q || !q.id) {\n setError(true);\n return;\n }\n analytics.captureEvent('post', 'question');\n reset();\n if (entity) {\n navigate(\n `${questionRoute({\n id: q.id.toString(10),\n })}?${queryParams.toString()}`,\n );\n } else {\n navigate(questionRoute({ id: q.id.toString(10) }));\n }\n })\n .catch(_e => {\n setError(true);\n setPosting(false);\n });\n };\n\n useEffect(() => {\n if (!entityRef) {\n const e = searchParams.get('entity');\n if (e) {\n setEntityRef(e);\n }\n }\n }, [entityRef, searchParams]);\n\n useEffect(() => {\n if (id) {\n getValues(qetaApi, catalogApi, id).then(data => {\n setValues(data);\n });\n }\n }, [qetaApi, catalogApi, id]);\n\n useEffect(() => {\n if (entityRef) {\n catalogApi.getEntityByRef(entityRef).then(data => {\n if (data) {\n setValues(v => {\n return { ...v, entities: [data] };\n });\n }\n });\n }\n }, [catalogApi, entityRef]);\n\n useEffect(() => {\n reset(values);\n }, [values, reset]);\n\n return (\n <form onSubmit={handleSubmit(postQuestion)} className=\"qetaAskForm\">\n {error && <Alert severity=\"error\">{t('askForm.errorPosting')}</Alert>}\n <TextField\n label=\"Title\"\n className=\"qetaAskFormTitle\"\n required\n fullWidth\n error={'title' in errors}\n margin=\"normal\"\n variant=\"outlined\"\n helperText={t('askForm.titleInput.helperText')}\n {\n // @ts-ignore\n ...register('title', { required: true, maxLength: 255 })\n }\n />\n <Controller\n control={control}\n rules={{\n required: true,\n }}\n render={({ field: { onChange, value } }) => (\n <MarkdownEditor\n value={value}\n onChange={onChange}\n height={400}\n error={'content' in errors}\n placeholder={t('askForm.contentInput.placeholder')}\n config={configApi}\n onImageUpload={(imageId: number) => {\n setImages(prevImages => [...prevImages, imageId]);\n }}\n />\n )}\n name=\"content\"\n />\n <TagInput control={control} />\n <EntitiesInput control={control} entityRef={entityRef} />\n {allowAnonymouns && !id && (\n <AskAnonymouslyCheckbox\n control={control}\n label={t('anonymousCheckbox.askAnonymously')}\n />\n )}\n <Button\n color=\"primary\"\n type=\"submit\"\n variant=\"contained\"\n disabled={posting}\n className={`qetaAskFormSubmitBtn ${styles.postButton}`}\n >\n {id\n ? t('askForm.submit.existingQuestion')\n : t('askForm.submit.newQuestion')}\n </Button>\n </form>\n );\n};\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"AskForm.esm.js","sources":["../../../src/components/AskForm/AskForm.tsx"],"sourcesContent":["import {\n configApiRef,\n useAnalytics,\n useApi,\n useRouteRef,\n} from '@backstage/core-plugin-api';\nimport { Button, TextField } from '@material-ui/core';\nimport { Alert } from '@material-ui/lab';\nimport React, { useEffect } from 'react';\nimport { Controller, useForm } from 'react-hook-form';\nimport { useNavigate, useSearchParams } from 'react-router-dom';\nimport {\n QuestionRequest,\n QuestionResponse,\n} from '@drodil/backstage-plugin-qeta-common';\nimport { useStyles, useTranslation } from '../../utils/hooks';\nimport { MarkdownEditor } from '../MarkdownEditor/MarkdownEditor';\nimport { catalogApiRef } from '@backstage/plugin-catalog-react';\nimport { stringifyEntityRef } from '@backstage/catalog-model';\nimport { CatalogApi } from '@backstage/catalog-client';\nimport { compact } from 'lodash';\nimport { TagInput } from './TagInput';\nimport { QuestionForm } from './types';\nimport { EntitiesInput } from './EntitiesInput';\nimport { questionRouteRef } from '@drodil/backstage-plugin-qeta-react';\nimport { AskAnonymouslyCheckbox } from '../AskAnonymouslyCheckbox/AskAnonymouslyCheckbox';\nimport { QetaApi, qetaApiRef } from '../../api';\nimport { confirmNavigationIfEdited } from '../../utils/utils';\n\nconst formToRequest = (\n form: QuestionForm,\n images: number[],\n): QuestionRequest => {\n return {\n ...form,\n entities: form.entities?.map(stringifyEntityRef),\n images,\n };\n};\n\nexport type AskFormProps = {\n id?: string;\n entity?: string;\n tags?: string[];\n onPost?: (question: QuestionResponse) => void;\n entityPage?: boolean;\n};\n\nconst getDefaultValues = (props: AskFormProps): QuestionForm => {\n return {\n title: '',\n content: '',\n tags: props.tags ?? [],\n entities: [],\n };\n};\n\nconst getValues = async (\n api: QetaApi,\n catalogApi: CatalogApi,\n id?: string,\n): Promise<QuestionForm> => {\n if (!id) {\n return getDefaultValues({});\n }\n\n const question = await api.getQuestion(id);\n const entities =\n question.entities && question.entities.length > 0\n ? await catalogApi.getEntitiesByRefs({\n entityRefs: question.entities,\n fields: [\n 'kind',\n 'metadata.name',\n 'metadata.namespace',\n 'metadata.title',\n ],\n })\n : [];\n return {\n title: question.title,\n content: question.content,\n tags: question.tags ?? [],\n entities: 'items' in entities ? compact(entities.items) : [],\n };\n};\n\nexport const AskForm = (props: AskFormProps) => {\n const { id, entity, onPost, entityPage } = props;\n const questionRoute = useRouteRef(questionRouteRef);\n const navigate = useNavigate();\n const analytics = useAnalytics();\n const [entityRef, setEntityRef] = React.useState(entity);\n const [posting, setPosting] = React.useState(false);\n const [values, setValues] = React.useState(getDefaultValues(props));\n const [error, setError] = React.useState(false);\n const [edited, setEdited] = React.useState(false);\n\n const [images, setImages] = React.useState<number[]>([]);\n const [searchParams, _setSearchParams] = useSearchParams();\n const { t } = useTranslation();\n\n const qetaApi = useApi(qetaApiRef);\n const catalogApi = useApi(catalogApiRef);\n const configApi = useApi(configApiRef);\n const allowAnonymouns = configApi.getOptionalBoolean('qeta.allowAnonymous');\n const styles = useStyles();\n const {\n register,\n handleSubmit,\n control,\n reset,\n formState: { errors },\n } = useForm<QuestionForm>({\n values,\n defaultValues: getDefaultValues(props),\n });\n\n const postQuestion = (data: QuestionForm) => {\n setPosting(true);\n\n const queryParams = new URLSearchParams();\n if (entity) {\n queryParams.set('entity', entity);\n }\n if (entityPage) {\n queryParams.set('entityPage', 'true');\n }\n\n if (id) {\n qetaApi\n .updateQuestion(id, formToRequest(data, images))\n .then(q => {\n if (!q || !q.id) {\n setError(true);\n return;\n }\n setEdited(false);\n reset();\n analytics.captureEvent('edit', 'question');\n if (onPost) {\n onPost(q);\n } else if (entity) {\n navigate(\n `${questionRoute({\n id: q.id.toString(10),\n })}?${queryParams.toString()}`,\n );\n } else {\n navigate(questionRoute({ id: q.id.toString(10) }));\n }\n })\n .catch(_e => {\n setError(true);\n setPosting(false);\n });\n return;\n }\n qetaApi\n .postQuestion(formToRequest(data, images))\n .then(q => {\n if (!q || !q.id) {\n setError(true);\n return;\n }\n setEdited(false);\n analytics.captureEvent('post', 'question');\n reset();\n if (entity) {\n navigate(\n `${questionRoute({\n id: q.id.toString(10),\n })}?${queryParams.toString()}`,\n );\n } else {\n navigate(questionRoute({ id: q.id.toString(10) }));\n }\n })\n .catch(_e => {\n setError(true);\n setPosting(false);\n });\n };\n\n useEffect(() => {\n if (!entityRef) {\n const e = searchParams.get('entity');\n if (e) {\n setEntityRef(e);\n }\n }\n }, [entityRef, searchParams]);\n\n useEffect(() => {\n if (id) {\n getValues(qetaApi, catalogApi, id).then(data => {\n setValues(data);\n });\n }\n }, [qetaApi, catalogApi, id]);\n\n useEffect(() => {\n if (entityRef) {\n catalogApi.getEntityByRef(entityRef).then(data => {\n if (data) {\n setValues(v => {\n return { ...v, entities: [data] };\n });\n }\n });\n }\n }, [catalogApi, entityRef]);\n\n useEffect(() => {\n reset(values);\n }, [values, reset]);\n\n useEffect(() => {\n return confirmNavigationIfEdited(edited);\n }, [edited]);\n\n return (\n <form\n onSubmit={handleSubmit(postQuestion)}\n onChange={() => {\n setEdited(true);\n }}\n className=\"qetaAskForm\"\n >\n {error && <Alert severity=\"error\">{t('askForm.errorPosting')}</Alert>}\n <TextField\n label=\"Title\"\n className=\"qetaAskFormTitle\"\n required\n fullWidth\n error={'title' in errors}\n margin=\"normal\"\n variant=\"outlined\"\n helperText={t('askForm.titleInput.helperText')}\n {\n // @ts-ignore\n ...register('title', { required: true, maxLength: 255 })\n }\n />\n <Controller\n control={control}\n rules={{\n required: true,\n }}\n render={({ field: { onChange, value } }) => (\n <MarkdownEditor\n value={value}\n onChange={onChange}\n height={400}\n error={'content' in errors}\n placeholder={t('askForm.contentInput.placeholder')}\n config={configApi}\n onImageUpload={(imageId: number) => {\n setImages(prevImages => [...prevImages, imageId]);\n }}\n />\n )}\n name=\"content\"\n />\n <TagInput control={control} />\n <EntitiesInput control={control} entityRef={entityRef} />\n {allowAnonymouns && !id && (\n <AskAnonymouslyCheckbox\n control={control}\n label={t('anonymousCheckbox.askAnonymously')}\n />\n )}\n <Button\n color=\"primary\"\n type=\"submit\"\n variant=\"contained\"\n disabled={posting}\n className={`qetaAskFormSubmitBtn ${styles.postButton}`}\n >\n {id\n ? t('askForm.submit.existingQuestion')\n : t('askForm.submit.newQuestion')}\n </Button>\n </form>\n );\n};\n"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"EntitiesInput.esm.js","sources":["../../../src/components/AskForm/EntitiesInput.tsx"],"sourcesContent":["import { Control, Controller } from 'react-hook-form';\nimport { QuestionForm } from './types';\nimport { Autocomplete } from '@material-ui/lab';\nimport { getEntityTitle } from '../../utils/utils';\nimport { Entity, stringifyEntityRef } from '@backstage/catalog-model';\nimport { TextField } from '@material-ui/core';\nimport React, { useEffect, useMemo } from 'react';\nimport { configApiRef, useApi } from '@backstage/core-plugin-api';\nimport { catalogApiRef } from '@backstage/plugin-catalog-react';\nimport { useTranslation } from '../../utils/hooks';\n\nexport const EntitiesInput = (props: {\n control: Control<QuestionForm>;\n entityRef?: string;\n}) => {\n const { control, entityRef } = props;\n const configApi = useApi(configApiRef);\n const catalogApi = useApi(catalogApiRef);\n const [availableEntities, setAvailableEntities] = React.useState<\n Entity[] | null\n >([]);\n const { t } = useTranslation();\n\n const entityKinds: string[] = useMemo(() => {\n let kinds = configApi.getOptionalStringArray('qeta.entityKinds');\n if (!kinds) {\n kinds = configApi.getOptionalStringArray('qeta.entities.kinds');\n }\n return kinds || ['Component', 'System'];\n }, [configApi]);\n const max = useMemo(\n () => configApi.getOptionalNumber('qeta.entities.max') ?? 3,\n [configApi],\n );\n\n useEffect(() => {\n if (entityRef) {\n catalogApi.getEntityByRef(entityRef).then(data => {\n if (data) {\n setAvailableEntities([data]);\n }\n });\n }\n }, [catalogApi, entityRef]);\n\n useEffect(() => {\n if (entityRef) {\n return;\n }\n\n if (entityKinds && entityKinds.length > 0) {\n catalogApi\n .getEntities({\n filter: { kind: entityKinds },\n fields: [\n 'kind',\n 'metadata.name',\n 'metadata.namespace',\n 'metadata.title',\n ],\n })\n .catch(_ => setAvailableEntities(null))\n .then(data =>\n data ? setAvailableEntities(data.items) : setAvailableEntities(null),\n );\n }\n }, [catalogApi, entityRef, configApi, entityKinds]);\n\n if (!availableEntities || availableEntities.length === 0) {\n return null;\n }\n\n return (\n <Controller\n control={control}\n render={({ field: { onChange, value } }) => (\n <Autocomplete\n multiple\n className=\"qetaAskFormEntities\"\n value={value}\n groupBy={entityKinds.length > 1 ? option => option.kind : undefined}\n id=\"entities-select\"\n options={availableEntities}\n getOptionLabel={getEntityTitle}\n getOptionSelected={(o, v) =>\n stringifyEntityRef(o) === stringifyEntityRef(v)\n }\n onChange={(_e, newValue) => {\n if (!value || value.length < max) {\n onChange(newValue);\n }\n }}\n renderInput={params => (\n <TextField\n {...params}\n variant=\"outlined\"\n margin=\"normal\"\n label={t('entitiesInput.label')}\n placeholder={t('entitiesInput.placeholder')}\n helperText={t('entitiesInput.helperText', {\n max: max.toString(10),\n })}\n />\n )}\n />\n )}\n name=\"entities\"\n />\n );\n};\n"],"names":[],"mappings":";;;;;;;;;;AAWa,MAAA,aAAA,GAAgB,CAAC,KAGxB,KAAA;AACJ,EAAM,MAAA,EAAE,OAAS,EAAA,SAAA,EAAc,GAAA,KAAA,CAAA;AAC/B,EAAM,MAAA,SAAA,GAAY,OAAO,YAAY,CAAA,CAAA;AACrC,EAAM,MAAA,UAAA,GAAa,OAAO,aAAa,CAAA,CAAA;AACvC,EAAA,MAAM,CAAC,iBAAmB,EAAA,oBAAoB,IAAI,KAAM,CAAA,QAAA,CAEtD,EAAE,CAAA,CAAA;AACJ,EAAM,MAAA,EAAE,CAAE,EAAA,GAAI,cAAe,EAAA,CAAA;AAE7B,EAAM,MAAA,WAAA,GAAwB,QAAQ,MAAM;AAC1C,IAAI,IAAA,KAAA,GAAQ,SAAU,CAAA,sBAAA,CAAuB,kBAAkB,CAAA,CAAA;AAC/D,IAAA,IAAI,CAAC,KAAO,EAAA;AACV,MAAQ,KAAA,GAAA,SAAA,CAAU,uBAAuB,qBAAqB,CAAA,CAAA;AAAA,KAChE;AACA,IAAO,OAAA,KAAA,IAAS,CAAC,WAAA,EAAa,QAAQ,CAAA,CAAA;AAAA,GACxC,EAAG,CAAC,SAAS,CAAC,CAAA,CAAA;AACd,EAAA,MAAM,GAAM,GAAA,OAAA;AAAA,IACV,MAAM,SAAA,CAAU,iBAAkB,CAAA,mBAAmB,CAAK,IAAA,CAAA;AAAA,IAC1D,CAAC,SAAS,CAAA;AAAA,GACZ,CAAA;AAEA,EAAA,SAAA,CAAU,MAAM;AACd,IAAA,IAAI,SAAW,EAAA;AACb,MAAA,UAAA,CAAW,cAAe,CAAA,SAAS,CAAE,CAAA,IAAA,CAAK,CAAQ,IAAA,KAAA;AAChD,QAAA,IAAI,IAAM,EAAA;AACR,UAAqB,oBAAA,CAAA,CAAC,IAAI,CAAC,CAAA,CAAA;AAAA,SAC7B;AAAA,OACD,CAAA,CAAA;AAAA,KACH;AAAA,GACC,EAAA,CAAC,UAAY,EAAA,SAAS,CAAC,CAAA,CAAA;AAE1B,EAAA,SAAA,CAAU,MAAM;AACd,IAAA,IAAI,SAAW,EAAA;AACb,MAAA,OAAA;AAAA,KACF;AAEA,IAAI,IAAA,WAAA,IAAe,WAAY,CAAA,MAAA,GAAS,CAAG,EAAA;AACzC,MAAA,UAAA,CACG,WAAY,CAAA;AAAA,QACX,MAAA,EAAQ,EAAE,IAAA,EAAM,WAAY,EAAA;AAAA,QAC5B,MAAQ,EAAA;AAAA,UACN,MAAA;AAAA,UACA,eAAA;AAAA,UACA,oBAAA;AAAA,UACA,gBAAA;AAAA,SACF;AAAA,OACD,CACA,CAAA,KAAA,CAAM,OAAK,oBAAqB,CAAA,IAAI,CAAC,CACrC,CAAA,IAAA;AAAA,QAAK,UACJ,IAAO,GAAA,oBAAA,CAAqB,KAAK,KAAK,CAAA,GAAI,qBAAqB,IAAI,CAAA;AAAA,OACrE,CAAA;AAAA,KACJ;AAAA,KACC,CAAC,UAAA,EAAY,SAAW,EAAA,SAAA,EAAW,WAAW,CAAC,CAAA,CAAA;AAElD,EAAA,IAAI,CAAC,iBAAA,IAAqB,iBAAkB,CAAA,MAAA,KAAW,CAAG,EAAA;AACxD,IAAO,OAAA,IAAA,CAAA;AAAA,GACT;AAEA,EACE,uBAAA,KAAA,CAAA,aAAA;AAAA,IAAC,UAAA;AAAA,IAAA;AAAA,MACC,OAAA;AAAA,MACA,MAAA,EAAQ,CAAC,EAAE,KAAA,EAAO,EAAE,QAAU,EAAA,KAAA,IAC5B,qBAAA,KAAA,CAAA,aAAA;AAAA,QAAC,YAAA;AAAA,QAAA;AAAA,UACC,QAAQ,EAAA,IAAA;AAAA,UACR,SAAU,EAAA,qBAAA;AAAA,UACV,KAAA;AAAA,UACA,SAAS,WAAY,CAAA,MAAA,GAAS,CAAI,GAAA,CAAA,MAAA,KAAU,OAAO,IAAO,GAAA,KAAA,CAAA;AAAA,UAC1D,EAAG,EAAA,iBAAA;AAAA,UACH,OAAS,EAAA,iBAAA;AAAA,UACT,cAAgB,EAAA,cAAA;AAAA,UAChB,iBAAA,EAAmB,CAAC,CAAG,EAAA,CAAA,KACrB,mBAAmB,CAAC,CAAA,KAAM,mBAAmB,CAAC,CAAA;AAAA,UAEhD,QAAA,EAAU,CAAC,EAAA,EAAI,QAAa,KAAA;AAC1B,YAAA,IAAI,CAAC,KAAA,IAAS,KAAM,CAAA,MAAA,GAAS,GAAK,EAAA;AAChC,cAAA,QAAA,CAAS,QAAQ,CAAA,CAAA;AAAA,aACnB;AAAA,WACF;AAAA,UACA,aAAa,CACX,MAAA,qBAAA,KAAA,CAAA,aAAA;AAAA,YAAC,SAAA;AAAA,YAAA;AAAA,cACE,GAAG,MAAA;AAAA,cACJ,OAAQ,EAAA,UAAA;AAAA,cACR,MAAO,EAAA,QAAA;AAAA,cACP,KAAA,EAAO,EAAE,qBAAqB,CAAA;AAAA,cAC9B,WAAA,EAAa,EAAE,2BAA2B,CAAA;AAAA,cAC1C,UAAA,EAAY,EAAE,0BAA4B,EAAA;AAAA,gBACxC,GAAA,EAAK,GAAI,CAAA,QAAA,CAAS,EAAE,CAAA;AAAA,eACrB,CAAA;AAAA,aAAA;AAAA,WACH;AAAA,SAAA;AAAA,OAEJ;AAAA,MAEF,IAAK,EAAA,UAAA;AAAA,KAAA;AAAA,GACP,CAAA;AAEJ;;;;"}
|
|
1
|
+
{"version":3,"file":"EntitiesInput.esm.js","sources":["../../../src/components/AskForm/EntitiesInput.tsx"],"sourcesContent":["import { Control, Controller } from 'react-hook-form';\nimport { QuestionForm } from './types';\nimport { Autocomplete } from '@material-ui/lab';\nimport { getEntityTitle } from '../../utils/utils';\nimport { Entity, stringifyEntityRef } from '@backstage/catalog-model';\nimport { TextField } from '@material-ui/core';\nimport React, { useEffect, useMemo } from 'react';\nimport { configApiRef, useApi } from '@backstage/core-plugin-api';\nimport { catalogApiRef } from '@backstage/plugin-catalog-react';\nimport { useTranslation } from '../../utils/hooks';\n\nexport const EntitiesInput = (props: {\n control: Control<QuestionForm>;\n entityRef?: string;\n}) => {\n const { control, entityRef } = props;\n const configApi = useApi(configApiRef);\n const catalogApi = useApi(catalogApiRef);\n const [availableEntities, setAvailableEntities] = React.useState<\n Entity[] | null\n >([]);\n const { t } = useTranslation();\n\n const entityKinds: string[] = useMemo(() => {\n let kinds = configApi.getOptionalStringArray('qeta.entityKinds');\n if (!kinds) {\n kinds = configApi.getOptionalStringArray('qeta.entities.kinds');\n }\n return kinds || ['Component', 'System'];\n }, [configApi]);\n const max = useMemo(\n () => configApi.getOptionalNumber('qeta.entities.max') ?? 3,\n [configApi],\n );\n\n useEffect(() => {\n if (entityRef) {\n catalogApi.getEntityByRef(entityRef).then(data => {\n if (data) {\n setAvailableEntities([data]);\n }\n });\n }\n }, [catalogApi, entityRef]);\n\n useEffect(() => {\n if (entityRef) {\n return;\n }\n\n if (entityKinds && entityKinds.length > 0) {\n catalogApi\n .getEntities({\n order: { field: 'kind', order: 'asc' },\n filter: { kind: entityKinds },\n fields: [\n 'kind',\n 'metadata.name',\n 'metadata.namespace',\n 'metadata.title',\n ],\n })\n .catch(_ => setAvailableEntities(null))\n .then(data =>\n data ? setAvailableEntities(data.items) : setAvailableEntities(null),\n );\n }\n }, [catalogApi, entityRef, configApi, entityKinds]);\n\n if (!availableEntities || availableEntities.length === 0) {\n return null;\n }\n\n return (\n <Controller\n control={control}\n render={({ field: { onChange, value } }) => (\n <Autocomplete\n multiple\n className=\"qetaAskFormEntities\"\n value={value}\n groupBy={entityKinds.length > 1 ? option => option.kind : undefined}\n id=\"entities-select\"\n options={availableEntities}\n getOptionLabel={getEntityTitle}\n getOptionSelected={(o, v) =>\n stringifyEntityRef(o) === stringifyEntityRef(v)\n }\n onChange={(_e, newValue) => {\n if (!value || value.length < max) {\n onChange(newValue);\n }\n }}\n renderInput={params => (\n <TextField\n {...params}\n variant=\"outlined\"\n margin=\"normal\"\n label={t('entitiesInput.label')}\n placeholder={t('entitiesInput.placeholder')}\n helperText={t('entitiesInput.helperText', {\n max: max.toString(10),\n })}\n />\n )}\n />\n )}\n name=\"entities\"\n />\n );\n};\n"],"names":[],"mappings":"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"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import React, { useState } from 'react';
|
|
1
|
+
import React, { useState, useEffect } from 'react';
|
|
2
2
|
import { Box, Grid, TextField, Button } from '@material-ui/core';
|
|
3
3
|
import { Link } from '@backstage/core-components';
|
|
4
4
|
import { useForm, Controller } from 'react-hook-form';
|
|
@@ -6,6 +6,7 @@ import { useAnalytics, useApi } from '@backstage/core-plugin-api';
|
|
|
6
6
|
import { CommentList } from './CommentList.esm.js';
|
|
7
7
|
import { qetaApiRef } from '../../api/QetaClient.esm.js';
|
|
8
8
|
import { useTranslation } from '../../utils/hooks.esm.js';
|
|
9
|
+
import { confirmNavigationIfEdited } from '../../utils/utils.esm.js';
|
|
9
10
|
|
|
10
11
|
const CommentSection = (props) => {
|
|
11
12
|
const { answer, question, onCommentPost, onCommentDelete } = props;
|
|
@@ -13,6 +14,7 @@ const CommentSection = (props) => {
|
|
|
13
14
|
const qetaApi = useApi(qetaApiRef);
|
|
14
15
|
const [posting, setPosting] = React.useState(false);
|
|
15
16
|
const [formVisible, setFormVisible] = useState(false);
|
|
17
|
+
const [edited, setEdited] = React.useState(false);
|
|
16
18
|
const { t } = useTranslation();
|
|
17
19
|
const {
|
|
18
20
|
handleSubmit,
|
|
@@ -28,6 +30,7 @@ const CommentSection = (props) => {
|
|
|
28
30
|
analytics.captureEvent("comment", "answer");
|
|
29
31
|
reset();
|
|
30
32
|
setPosting(false);
|
|
33
|
+
setEdited(false);
|
|
31
34
|
onCommentPost(question, a);
|
|
32
35
|
});
|
|
33
36
|
return;
|
|
@@ -37,9 +40,13 @@ const CommentSection = (props) => {
|
|
|
37
40
|
analytics.captureEvent("comment", "question");
|
|
38
41
|
reset();
|
|
39
42
|
setPosting(false);
|
|
43
|
+
setEdited(false);
|
|
40
44
|
onCommentPost(q);
|
|
41
45
|
});
|
|
42
46
|
};
|
|
47
|
+
useEffect(() => {
|
|
48
|
+
return confirmNavigationIfEdited(edited);
|
|
49
|
+
}, [edited]);
|
|
43
50
|
return /* @__PURE__ */ React.createElement(Box, { marginLeft: 9, className: "qetaCommentSection" }, /* @__PURE__ */ React.createElement(
|
|
44
51
|
CommentList,
|
|
45
52
|
{
|
|
@@ -56,43 +63,53 @@ const CommentSection = (props) => {
|
|
|
56
63
|
onClick: () => setFormVisible(true)
|
|
57
64
|
},
|
|
58
65
|
t("commentSection.addComment")
|
|
59
|
-
), formVisible && /* @__PURE__ */ React.createElement(
|
|
60
|
-
|
|
66
|
+
), formVisible && /* @__PURE__ */ React.createElement(
|
|
67
|
+
"form",
|
|
61
68
|
{
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
required: true
|
|
69
|
+
onSubmit: handleSubmit(postComment),
|
|
70
|
+
onChange: () => {
|
|
71
|
+
setEdited(true);
|
|
66
72
|
},
|
|
67
|
-
|
|
68
|
-
TextField,
|
|
69
|
-
{
|
|
70
|
-
id: "comment",
|
|
71
|
-
multiline: true,
|
|
72
|
-
minRows: 2,
|
|
73
|
-
fullWidth: true,
|
|
74
|
-
className: "qetaCommentInput",
|
|
75
|
-
value,
|
|
76
|
-
placeholder: t("commentSection.input.placeholder"),
|
|
77
|
-
onChange,
|
|
78
|
-
variant: "outlined",
|
|
79
|
-
error: "content" in errors
|
|
80
|
-
}
|
|
81
|
-
),
|
|
82
|
-
name: "content"
|
|
83
|
-
}
|
|
84
|
-
)), /* @__PURE__ */ React.createElement(Grid, { item: true, xs: 1 }, /* @__PURE__ */ React.createElement(
|
|
85
|
-
Button,
|
|
86
|
-
{
|
|
87
|
-
variant: "contained",
|
|
88
|
-
size: "small",
|
|
89
|
-
className: "qetaCommentBtn",
|
|
90
|
-
type: "submit",
|
|
91
|
-
color: "primary",
|
|
92
|
-
disabled: posting
|
|
73
|
+
className: "qetaCommentForm"
|
|
93
74
|
},
|
|
94
|
-
|
|
95
|
-
|
|
75
|
+
/* @__PURE__ */ React.createElement(Grid, { container: true }, /* @__PURE__ */ React.createElement(Grid, { item: true, xs: 11 }, /* @__PURE__ */ React.createElement(
|
|
76
|
+
Controller,
|
|
77
|
+
{
|
|
78
|
+
control,
|
|
79
|
+
defaultValue: "",
|
|
80
|
+
rules: {
|
|
81
|
+
required: true
|
|
82
|
+
},
|
|
83
|
+
render: ({ field: { onChange, value } }) => /* @__PURE__ */ React.createElement(
|
|
84
|
+
TextField,
|
|
85
|
+
{
|
|
86
|
+
id: "comment",
|
|
87
|
+
multiline: true,
|
|
88
|
+
minRows: 2,
|
|
89
|
+
fullWidth: true,
|
|
90
|
+
className: "qetaCommentInput",
|
|
91
|
+
value,
|
|
92
|
+
placeholder: t("commentSection.input.placeholder"),
|
|
93
|
+
onChange,
|
|
94
|
+
variant: "outlined",
|
|
95
|
+
error: "content" in errors
|
|
96
|
+
}
|
|
97
|
+
),
|
|
98
|
+
name: "content"
|
|
99
|
+
}
|
|
100
|
+
)), /* @__PURE__ */ React.createElement(Grid, { item: true, xs: 1 }, /* @__PURE__ */ React.createElement(
|
|
101
|
+
Button,
|
|
102
|
+
{
|
|
103
|
+
variant: "contained",
|
|
104
|
+
size: "small",
|
|
105
|
+
className: "qetaCommentBtn",
|
|
106
|
+
type: "submit",
|
|
107
|
+
color: "primary",
|
|
108
|
+
disabled: posting
|
|
109
|
+
},
|
|
110
|
+
t("commentSection.post")
|
|
111
|
+
)))
|
|
112
|
+
));
|
|
96
113
|
};
|
|
97
114
|
|
|
98
115
|
export { CommentSection };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CommentSection.esm.js","sources":["../../../src/components/CommentSection/CommentSection.tsx"],"sourcesContent":["import React, { useState } from 'react';\nimport { Box, Button, Grid, TextField } from '@material-ui/core';\nimport { Link } from '@backstage/core-components';\nimport {\n AnswerResponse,\n QuestionResponse,\n} from '@drodil/backstage-plugin-qeta-common';\nimport { Controller, useForm } from 'react-hook-form';\nimport { useAnalytics, useApi } from '@backstage/core-plugin-api';\nimport { CommentList } from './CommentList';\nimport { qetaApiRef } from '../../api';\nimport { useTranslation } from '../../utils/hooks';\n\nexport const CommentSection = (props: {\n onCommentPost: (question: QuestionResponse, answer?: AnswerResponse) => void;\n onCommentDelete: (\n question: QuestionResponse,\n answer?: AnswerResponse,\n ) => void;\n question: QuestionResponse;\n answer?: AnswerResponse;\n}) => {\n const { answer, question, onCommentPost, onCommentDelete } = props;\n const analytics = useAnalytics();\n const qetaApi = useApi(qetaApiRef);\n const [posting, setPosting] = React.useState(false);\n const [formVisible, setFormVisible] = useState(false);\n const { t } = useTranslation();\n const {\n handleSubmit,\n control,\n formState: { errors },\n reset,\n } = useForm<{ content: string }>({});\n\n const postComment = (data: { content: string }) => {\n setPosting(true);\n if (answer) {\n qetaApi.commentAnswer(question.id, answer.id, data.content).then(a => {\n setFormVisible(false);\n analytics.captureEvent('comment', 'answer');\n reset();\n setPosting(false);\n onCommentPost(question, a);\n });\n return;\n }\n\n qetaApi.commentQuestion(question.id, data.content).then(q => {\n setFormVisible(false);\n analytics.captureEvent('comment', 'question');\n reset();\n setPosting(false);\n onCommentPost(q);\n });\n };\n\n return (\n <Box marginLeft={9} className=\"qetaCommentSection\">\n <CommentList\n question={question}\n answer={answer}\n onCommentDelete={onCommentDelete}\n />\n {!formVisible && (\n <Link\n underline=\"none\"\n to=\"#\"\n className=\"qetaAddCommentBtn\"\n onClick={() => setFormVisible(true)}\n >\n {t('commentSection.addComment')}\n </Link>\n )}\n {formVisible && (\n <form
|
|
1
|
+
{"version":3,"file":"CommentSection.esm.js","sources":["../../../src/components/CommentSection/CommentSection.tsx"],"sourcesContent":["import React, { useEffect, useState } from 'react';\nimport { Box, Button, Grid, TextField } from '@material-ui/core';\nimport { Link } from '@backstage/core-components';\nimport {\n AnswerResponse,\n QuestionResponse,\n} from '@drodil/backstage-plugin-qeta-common';\nimport { Controller, useForm } from 'react-hook-form';\nimport { useAnalytics, useApi } from '@backstage/core-plugin-api';\nimport { CommentList } from './CommentList';\nimport { qetaApiRef } from '../../api';\nimport { useTranslation } from '../../utils/hooks';\nimport { confirmNavigationIfEdited } from '../../utils/utils';\n\nexport const CommentSection = (props: {\n onCommentPost: (question: QuestionResponse, answer?: AnswerResponse) => void;\n onCommentDelete: (\n question: QuestionResponse,\n answer?: AnswerResponse,\n ) => void;\n question: QuestionResponse;\n answer?: AnswerResponse;\n}) => {\n const { answer, question, onCommentPost, onCommentDelete } = props;\n const analytics = useAnalytics();\n const qetaApi = useApi(qetaApiRef);\n const [posting, setPosting] = React.useState(false);\n const [formVisible, setFormVisible] = useState(false);\n const [edited, setEdited] = React.useState(false);\n const { t } = useTranslation();\n const {\n handleSubmit,\n control,\n formState: { errors },\n reset,\n } = useForm<{ content: string }>({});\n\n const postComment = (data: { content: string }) => {\n setPosting(true);\n if (answer) {\n qetaApi.commentAnswer(question.id, answer.id, data.content).then(a => {\n setFormVisible(false);\n analytics.captureEvent('comment', 'answer');\n reset();\n setPosting(false);\n setEdited(false);\n onCommentPost(question, a);\n });\n return;\n }\n\n qetaApi.commentQuestion(question.id, data.content).then(q => {\n setFormVisible(false);\n analytics.captureEvent('comment', 'question');\n reset();\n setPosting(false);\n setEdited(false);\n onCommentPost(q);\n });\n };\n\n useEffect(() => {\n return confirmNavigationIfEdited(edited);\n }, [edited]);\n\n return (\n <Box marginLeft={9} className=\"qetaCommentSection\">\n <CommentList\n question={question}\n answer={answer}\n onCommentDelete={onCommentDelete}\n />\n {!formVisible && (\n <Link\n underline=\"none\"\n to=\"#\"\n className=\"qetaAddCommentBtn\"\n onClick={() => setFormVisible(true)}\n >\n {t('commentSection.addComment')}\n </Link>\n )}\n {formVisible && (\n <form\n onSubmit={handleSubmit(postComment)}\n onChange={() => {\n setEdited(true);\n }}\n className=\"qetaCommentForm\"\n >\n <Grid container>\n <Grid item xs={11}>\n <Controller\n control={control}\n defaultValue=\"\"\n rules={{\n required: true,\n }}\n render={({ field: { onChange, value } }) => (\n <TextField\n id=\"comment\"\n multiline\n minRows={2}\n fullWidth\n className=\"qetaCommentInput\"\n value={value}\n placeholder={t('commentSection.input.placeholder')}\n onChange={onChange}\n variant=\"outlined\"\n error={'content' in errors}\n />\n )}\n name=\"content\"\n />\n </Grid>\n <Grid item xs={1}>\n <Button\n variant=\"contained\"\n size=\"small\"\n className=\"qetaCommentBtn\"\n type=\"submit\"\n color=\"primary\"\n disabled={posting}\n >\n {t('commentSection.post')}\n </Button>\n </Grid>\n </Grid>\n </form>\n )}\n </Box>\n );\n};\n"],"names":[],"mappings":"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"}
|
|
@@ -9,6 +9,7 @@ import { MarkdownEditor } from '../MarkdownEditor/MarkdownEditor.esm.js';
|
|
|
9
9
|
import { RequirePermission } from '@backstage/plugin-permission-react';
|
|
10
10
|
import { AskAnonymouslyCheckbox } from '../AskAnonymouslyCheckbox/AskAnonymouslyCheckbox.esm.js';
|
|
11
11
|
import { qetaApiRef } from '../../api/QetaClient.esm.js';
|
|
12
|
+
import { confirmNavigationIfEdited } from '../../utils/utils.esm.js';
|
|
12
13
|
|
|
13
14
|
const getDefaultValues = (questionId) => {
|
|
14
15
|
return { questionId, answer: "" };
|
|
@@ -19,6 +20,7 @@ const AnswerForm = (props) => {
|
|
|
19
20
|
const analytics = useAnalytics();
|
|
20
21
|
const [error, setError] = React.useState(false);
|
|
21
22
|
const [images, setImages] = React.useState([]);
|
|
23
|
+
const [edited, setEdited] = React.useState(false);
|
|
22
24
|
const qetaApi = useApi(qetaApiRef);
|
|
23
25
|
const styles = useStyles();
|
|
24
26
|
const configApi = useApi(configApiRef);
|
|
@@ -44,6 +46,7 @@ const AnswerForm = (props) => {
|
|
|
44
46
|
setError(true);
|
|
45
47
|
return;
|
|
46
48
|
}
|
|
49
|
+
setEdited(false);
|
|
47
50
|
analytics.captureEvent("edit", "answer");
|
|
48
51
|
reset();
|
|
49
52
|
onPost(a);
|
|
@@ -60,6 +63,7 @@ const AnswerForm = (props) => {
|
|
|
60
63
|
setError(true);
|
|
61
64
|
return;
|
|
62
65
|
}
|
|
66
|
+
setEdited(false);
|
|
63
67
|
analytics.captureEvent("post", "answer");
|
|
64
68
|
reset();
|
|
65
69
|
onPost(a);
|
|
@@ -79,52 +83,69 @@ const AnswerForm = (props) => {
|
|
|
79
83
|
useEffect(() => {
|
|
80
84
|
reset(values);
|
|
81
85
|
}, [values, reset]);
|
|
86
|
+
useEffect(() => {
|
|
87
|
+
return confirmNavigationIfEdited(edited);
|
|
88
|
+
}, [edited]);
|
|
82
89
|
return /* @__PURE__ */ React.createElement(
|
|
83
90
|
RequirePermission,
|
|
84
91
|
{
|
|
85
92
|
permission: qetaCreateAnswerPermission,
|
|
86
93
|
errorPage: /* @__PURE__ */ React.createElement(React.Fragment, null)
|
|
87
94
|
},
|
|
88
|
-
/* @__PURE__ */ React.createElement(
|
|
89
|
-
|
|
95
|
+
/* @__PURE__ */ React.createElement(
|
|
96
|
+
"form",
|
|
90
97
|
{
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
required: true
|
|
98
|
+
onSubmit: handleSubmit(postAnswer),
|
|
99
|
+
onChange: () => {
|
|
100
|
+
setEdited(true);
|
|
95
101
|
},
|
|
96
|
-
|
|
97
|
-
MarkdownEditor,
|
|
98
|
-
{
|
|
99
|
-
value,
|
|
100
|
-
onChange,
|
|
101
|
-
height: 200,
|
|
102
|
-
error: "answer" in errors,
|
|
103
|
-
config: configApi,
|
|
104
|
-
placeholder: t("answerForm.contentInput.placeholder"),
|
|
105
|
-
onImageUpload: (imageId) => {
|
|
106
|
-
setImages((prevImages) => [...prevImages, imageId]);
|
|
107
|
-
}
|
|
108
|
-
}
|
|
109
|
-
),
|
|
110
|
-
name: "answer"
|
|
111
|
-
}
|
|
112
|
-
), allowAnonymouns && !id && /* @__PURE__ */ React.createElement(
|
|
113
|
-
AskAnonymouslyCheckbox,
|
|
114
|
-
{
|
|
115
|
-
control,
|
|
116
|
-
label: t("anonymousCheckbox.answerAnonymously")
|
|
117
|
-
}
|
|
118
|
-
), /* @__PURE__ */ React.createElement(
|
|
119
|
-
Button,
|
|
120
|
-
{
|
|
121
|
-
variant: "outlined",
|
|
122
|
-
type: "submit",
|
|
123
|
-
color: "primary",
|
|
124
|
-
className: `qetaAnswerFormPostBtn ${styles.postButton}`
|
|
102
|
+
className: "qetaAnswerForm"
|
|
125
103
|
},
|
|
126
|
-
|
|
127
|
-
|
|
104
|
+
/* @__PURE__ */ React.createElement(Typography, { variant: "h6" }, "Your answer"),
|
|
105
|
+
error && /* @__PURE__ */ React.createElement(WarningPanel, { severity: "error", title: t("answerForm.errorPosting") }),
|
|
106
|
+
/* @__PURE__ */ React.createElement(
|
|
107
|
+
Controller,
|
|
108
|
+
{
|
|
109
|
+
control,
|
|
110
|
+
defaultValue: "",
|
|
111
|
+
rules: {
|
|
112
|
+
required: true
|
|
113
|
+
},
|
|
114
|
+
render: ({ field: { onChange, value } }) => /* @__PURE__ */ React.createElement(
|
|
115
|
+
MarkdownEditor,
|
|
116
|
+
{
|
|
117
|
+
value,
|
|
118
|
+
onChange,
|
|
119
|
+
height: 200,
|
|
120
|
+
error: "answer" in errors,
|
|
121
|
+
config: configApi,
|
|
122
|
+
placeholder: t("answerForm.contentInput.placeholder"),
|
|
123
|
+
onImageUpload: (imageId) => {
|
|
124
|
+
setImages((prevImages) => [...prevImages, imageId]);
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
),
|
|
128
|
+
name: "answer"
|
|
129
|
+
}
|
|
130
|
+
),
|
|
131
|
+
allowAnonymouns && !id && /* @__PURE__ */ React.createElement(
|
|
132
|
+
AskAnonymouslyCheckbox,
|
|
133
|
+
{
|
|
134
|
+
control,
|
|
135
|
+
label: t("anonymousCheckbox.answerAnonymously")
|
|
136
|
+
}
|
|
137
|
+
),
|
|
138
|
+
/* @__PURE__ */ React.createElement(
|
|
139
|
+
Button,
|
|
140
|
+
{
|
|
141
|
+
variant: "outlined",
|
|
142
|
+
type: "submit",
|
|
143
|
+
color: "primary",
|
|
144
|
+
className: `qetaAnswerFormPostBtn ${styles.postButton}`
|
|
145
|
+
},
|
|
146
|
+
id ? t("answerForm.submit.existingAnswer") : t("answerForm.submit.newAnswer")
|
|
147
|
+
)
|
|
148
|
+
)
|
|
128
149
|
);
|
|
129
150
|
};
|
|
130
151
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AnswerForm.esm.js","sources":["../../../src/components/QuestionPage/AnswerForm.tsx"],"sourcesContent":["import { WarningPanel } from '@backstage/core-components';\nimport { Button, Typography } from '@material-ui/core';\nimport React, { useEffect } from 'react';\nimport { configApiRef, useAnalytics, useApi } from '@backstage/core-plugin-api';\nimport {\n AnswerRequest,\n AnswerResponse,\n qetaCreateAnswerPermission,\n QuestionResponse,\n} from '@drodil/backstage-plugin-qeta-common';\nimport { useStyles, useTranslation } from '../../utils/hooks';\nimport { Controller, useForm } from 'react-hook-form';\nimport { MarkdownEditor } from '../MarkdownEditor/MarkdownEditor';\nimport { RequirePermission } from '@backstage/plugin-permission-react';\nimport { AskAnonymouslyCheckbox } from '../AskAnonymouslyCheckbox/AskAnonymouslyCheckbox';\nimport { qetaApiRef } from '../../api';\n\nconst getDefaultValues = (questionId: number) => {\n return { questionId, answer: '' };\n};\n\nexport const AnswerForm = (props: {\n question: QuestionResponse;\n onPost: (answer: AnswerResponse) => void;\n id?: number;\n}) => {\n const { question, onPost, id } = props;\n const [values, setValues] = React.useState(getDefaultValues(question.id));\n const analytics = useAnalytics();\n const [error, setError] = React.useState(false);\n const [images, setImages] = React.useState<number[]>([]);\n const qetaApi = useApi(qetaApiRef);\n const styles = useStyles();\n const configApi = useApi(configApiRef);\n const allowAnonymouns = configApi.getOptionalBoolean('qeta.allowAnonymous');\n const { t } = useTranslation();\n\n const {\n handleSubmit,\n control,\n formState: { errors },\n reset,\n } = useForm<AnswerRequest>({\n values,\n defaultValues: getDefaultValues(question.id),\n });\n\n const postAnswer = (data: AnswerRequest) => {\n if (id) {\n qetaApi\n .updateAnswer(id, {\n questionId: question.id,\n answer: data.answer,\n images,\n })\n .then(a => {\n if (!a || !('id' in a)) {\n setError(true);\n return;\n }\n analytics.captureEvent('edit', 'answer');\n reset();\n onPost(a);\n })\n .catch(_e => setError(true));\n return;\n }\n // http://localhost:7007/api/qeta/attachments/36e551b1-3be7-479a-8942-b7018434e710\n qetaApi\n .postAnswer({\n questionId: question.id,\n answer: data.answer,\n images,\n anonymous: data.anonymous,\n })\n .then(a => {\n if (!a || !('id' in a)) {\n setError(true);\n return;\n }\n analytics.captureEvent('post', 'answer');\n reset();\n onPost(a);\n })\n .catch(_e => setError(true));\n };\n\n useEffect(() => {\n if (id) {\n qetaApi.getAnswer(question.id, id).then(a => {\n if ('content' in a) {\n setValues({ questionId: question.id, answer: a.content });\n } else {\n setError(true);\n }\n });\n }\n }, [id, question, qetaApi]);\n\n useEffect(() => {\n reset(values);\n }, [values, reset]);\n\n return (\n <RequirePermission\n permission={qetaCreateAnswerPermission}\n errorPage={<></>}\n >\n <form
|
|
1
|
+
{"version":3,"file":"AnswerForm.esm.js","sources":["../../../src/components/QuestionPage/AnswerForm.tsx"],"sourcesContent":["import { WarningPanel } from '@backstage/core-components';\nimport { Button, Typography } from '@material-ui/core';\nimport React, { useEffect } from 'react';\nimport { configApiRef, useAnalytics, useApi } from '@backstage/core-plugin-api';\nimport {\n AnswerRequest,\n AnswerResponse,\n qetaCreateAnswerPermission,\n QuestionResponse,\n} from '@drodil/backstage-plugin-qeta-common';\nimport { useStyles, useTranslation } from '../../utils/hooks';\nimport { Controller, useForm } from 'react-hook-form';\nimport { MarkdownEditor } from '../MarkdownEditor/MarkdownEditor';\nimport { RequirePermission } from '@backstage/plugin-permission-react';\nimport { AskAnonymouslyCheckbox } from '../AskAnonymouslyCheckbox/AskAnonymouslyCheckbox';\nimport { qetaApiRef } from '../../api';\nimport { confirmNavigationIfEdited } from '../../utils/utils';\n\nconst getDefaultValues = (questionId: number) => {\n return { questionId, answer: '' };\n};\n\nexport const AnswerForm = (props: {\n question: QuestionResponse;\n onPost: (answer: AnswerResponse) => void;\n id?: number;\n}) => {\n const { question, onPost, id } = props;\n const [values, setValues] = React.useState(getDefaultValues(question.id));\n const analytics = useAnalytics();\n const [error, setError] = React.useState(false);\n const [images, setImages] = React.useState<number[]>([]);\n const [edited, setEdited] = React.useState(false);\n const qetaApi = useApi(qetaApiRef);\n const styles = useStyles();\n const configApi = useApi(configApiRef);\n const allowAnonymouns = configApi.getOptionalBoolean('qeta.allowAnonymous');\n const { t } = useTranslation();\n\n const {\n handleSubmit,\n control,\n formState: { errors },\n reset,\n } = useForm<AnswerRequest>({\n values,\n defaultValues: getDefaultValues(question.id),\n });\n\n const postAnswer = (data: AnswerRequest) => {\n if (id) {\n qetaApi\n .updateAnswer(id, {\n questionId: question.id,\n answer: data.answer,\n images,\n })\n .then(a => {\n if (!a || !('id' in a)) {\n setError(true);\n return;\n }\n setEdited(false);\n analytics.captureEvent('edit', 'answer');\n reset();\n onPost(a);\n })\n .catch(_e => setError(true));\n return;\n }\n // http://localhost:7007/api/qeta/attachments/36e551b1-3be7-479a-8942-b7018434e710\n qetaApi\n .postAnswer({\n questionId: question.id,\n answer: data.answer,\n images,\n anonymous: data.anonymous,\n })\n .then(a => {\n if (!a || !('id' in a)) {\n setError(true);\n return;\n }\n setEdited(false);\n analytics.captureEvent('post', 'answer');\n reset();\n onPost(a);\n })\n .catch(_e => setError(true));\n };\n\n useEffect(() => {\n if (id) {\n qetaApi.getAnswer(question.id, id).then(a => {\n if ('content' in a) {\n setValues({ questionId: question.id, answer: a.content });\n } else {\n setError(true);\n }\n });\n }\n }, [id, question, qetaApi]);\n\n useEffect(() => {\n reset(values);\n }, [values, reset]);\n\n useEffect(() => {\n return confirmNavigationIfEdited(edited);\n }, [edited]);\n\n return (\n <RequirePermission\n permission={qetaCreateAnswerPermission}\n errorPage={<></>}\n >\n <form\n onSubmit={handleSubmit(postAnswer)}\n onChange={() => {\n setEdited(true);\n }}\n className=\"qetaAnswerForm\"\n >\n <Typography variant=\"h6\">Your answer</Typography>\n {error && (\n <WarningPanel severity=\"error\" title={t('answerForm.errorPosting')} />\n )}\n <Controller\n control={control}\n defaultValue=\"\"\n rules={{\n required: true,\n }}\n render={({ field: { onChange, value } }) => (\n <MarkdownEditor\n value={value}\n onChange={onChange}\n height={200}\n error={'answer' in errors}\n config={configApi}\n placeholder={t('answerForm.contentInput.placeholder')}\n onImageUpload={(imageId: number) => {\n setImages(prevImages => [...prevImages, imageId]);\n }}\n />\n )}\n name=\"answer\"\n />\n {allowAnonymouns && !id && (\n <AskAnonymouslyCheckbox\n control={control}\n label={t('anonymousCheckbox.answerAnonymously')}\n />\n )}\n <Button\n variant=\"outlined\"\n type=\"submit\"\n color=\"primary\"\n className={`qetaAnswerFormPostBtn ${styles.postButton}`}\n >\n {id\n ? t('answerForm.submit.existingAnswer')\n : t('answerForm.submit.newAnswer')}\n </Button>\n </form>\n </RequirePermission>\n );\n};\n"],"names":[],"mappings":"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"}
|
|
@@ -2,7 +2,7 @@ import { useTheme, Card, CardContent, Box, Typography, Avatar } from '@material-
|
|
|
2
2
|
import { Link } from '@backstage/core-components';
|
|
3
3
|
import React, { useState, useEffect } from 'react';
|
|
4
4
|
import DOMPurify from 'dompurify';
|
|
5
|
-
import { truncate, removeMarkdownFormatting } from '
|
|
5
|
+
import { truncate, removeMarkdownFormatting } from '@drodil/backstage-plugin-qeta-common';
|
|
6
6
|
import { TagsAndEntities } from '../QuestionPage/TagsAndEntities.esm.js';
|
|
7
7
|
import { useRouteRef } from '@backstage/core-plugin-api';
|
|
8
8
|
import { questionRouteRef, userRouteRef } from '@drodil/backstage-plugin-qeta-react';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"QuestionListItem.esm.js","sources":["../../../src/components/QuestionsContainer/QuestionListItem.tsx"],"sourcesContent":["import {\n Avatar,\n Box,\n Card,\n CardContent,\n Typography,\n useTheme,\n} from '@material-ui/core';\nimport { Link } from '@backstage/core-components';\nimport React, { useEffect, useState } from 'react';\nimport DOMPurify from 'dompurify';\nimport {
|
|
1
|
+
{"version":3,"file":"QuestionListItem.esm.js","sources":["../../../src/components/QuestionsContainer/QuestionListItem.tsx"],"sourcesContent":["import {\n Avatar,\n Box,\n Card,\n CardContent,\n Typography,\n useTheme,\n} from '@material-ui/core';\nimport { Link } from '@backstage/core-components';\nimport React, { useEffect, useState } from 'react';\nimport DOMPurify from 'dompurify';\nimport {\n QetaSignal,\n QuestionResponse,\n removeMarkdownFormatting,\n truncate,\n} from '@drodil/backstage-plugin-qeta-common';\nimport { TagsAndEntities } from '../QuestionPage/TagsAndEntities';\nimport { useRouteRef } from '@backstage/core-plugin-api';\nimport {\n questionRouteRef,\n userRouteRef,\n} from '@drodil/backstage-plugin-qeta-react';\nimport { RelativeTimeWithTooltip } from '../RelativeTimeWithTooltip/RelativeTimeWithTooltip';\nimport { useEntityAuthor, useStyles, useTranslation } from '../../utils/hooks';\nimport { useSignal } from '@backstage/plugin-signals-react';\n\nexport interface QuestionListItemProps {\n question: QuestionResponse;\n entity?: string;\n}\n\nexport const QuestionListItem = (props: QuestionListItemProps) => {\n const { question, entity } = props;\n\n const [correctAnswer, setCorrectAnswer] = useState(question.correctAnswer);\n const [answersCount, setAnswersCount] = useState(question.answersCount);\n const [score, setScore] = useState(question.score);\n const [views, setViews] = useState(question.views);\n const { t } = useTranslation();\n\n const { lastSignal } = useSignal<QetaSignal>(`qeta:question_${question.id}`);\n\n useEffect(() => {\n if (lastSignal?.type === 'question_stats') {\n setCorrectAnswer(lastSignal.correctAnswer);\n setAnswersCount(lastSignal.answersCount);\n setScore(lastSignal.score);\n setViews(lastSignal.views);\n }\n }, [lastSignal]);\n\n const questionRoute = useRouteRef(questionRouteRef);\n const userRoute = useRouteRef(userRouteRef);\n const theme = useTheme();\n const styles = useStyles();\n const { name, initials, user } = useEntityAuthor(question);\n\n return (\n <Card className=\"qetaQuestionListItem\">\n <CardContent>\n <Box className={styles.questionListItemStats}>\n <Typography\n display=\"block\"\n variant=\"caption\"\n className=\"qetaQuestionListItemScore\"\n >\n {t('common.score', { score: score.toString(10) })}\n </Typography>\n <Typography\n variant=\"caption\"\n display=\"block\"\n className={`qetaQuestionListItemAnswers ${\n correctAnswer\n ? 'qetaQuestionListItemCorrectAnswer'\n : 'quetaQuestionListItemNoCorrectAnswer'\n }`}\n style={{\n color: correctAnswer ? theme.palette.success.main : undefined,\n }}\n >\n {t('common.answers', {\n count: answersCount,\n })}\n </Typography>\n <Typography\n display=\"block\"\n variant=\"caption\"\n className=\"qetaQuestionListItemViews\"\n >\n {t('common.viewsShort', {\n count: views,\n })}\n </Typography>\n </Box>\n <Box className={styles.questionListItemContent}>\n <Typography variant=\"h5\" component=\"div\">\n <Link\n to={\n entity\n ? `${questionRoute({\n id: question.id.toString(10),\n })}?entity=${entity}`\n : questionRoute({ id: question.id.toString(10) })\n }\n className=\"qetaQuestionListItemQuestionBtn\"\n >\n {question.title}\n </Link>\n </Typography>\n <Typography\n variant=\"caption\"\n noWrap\n component=\"div\"\n className=\"qetaQuestionListItemContent\"\n style={{ marginBottom: '5px' }}\n >\n {DOMPurify.sanitize(\n truncate(removeMarkdownFormatting(question.content), 150),\n )}\n </Typography>\n <TagsAndEntities question={question} />\n <Typography\n variant=\"caption\"\n display=\"inline\"\n className={`${styles.questionListItemAuthor} qetaQuestionListItemAuthor`}\n >\n <Avatar\n src={user?.spec?.profile?.picture}\n className={styles.questionListItemAvatar}\n alt={name}\n variant=\"rounded\"\n >\n {initials}\n </Avatar>\n {question.author === 'anonymous' ? (\n t('common.anonymousAuthor')\n ) : (\n <Link to={`${userRoute()}/${question.author}`}>{name}</Link>\n )}{' '}\n <Link\n to={\n entity\n ? `${questionRoute({\n id: question.id.toString(10),\n })}?entity=${entity}`\n : questionRoute({ id: question.id.toString(10) })\n }\n className=\"qetaQuestionListItemQuestionBtn\"\n >\n {t('authorBox.askedAtTime')}{' '}\n <RelativeTimeWithTooltip value={question.created} />\n </Link>\n </Typography>\n </Box>\n </CardContent>\n </Card>\n );\n};\n"],"names":[],"mappings":"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"}
|
|
@@ -9,11 +9,12 @@ import { useEntityPresentation } from '@backstage/plugin-catalog-react';
|
|
|
9
9
|
import { TabContext, TabList, TabPanel } from '@material-ui/lab';
|
|
10
10
|
import { useTranslation } from '../../utils/hooks.esm.js';
|
|
11
11
|
import 'dompurify';
|
|
12
|
-
import '@backstage
|
|
12
|
+
import '@drodil/backstage-plugin-qeta-common';
|
|
13
13
|
import '@backstage/core-plugin-api';
|
|
14
14
|
import '@drodil/backstage-plugin-qeta-react';
|
|
15
15
|
import 'react-relative-time';
|
|
16
16
|
import 'lodash';
|
|
17
|
+
import '@backstage/catalog-model';
|
|
17
18
|
import { AnswersContainer } from '../AnswersContainer/AnswersContainer.esm.js';
|
|
18
19
|
|
|
19
20
|
const UserPage = () => {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"UserPage.esm.js","sources":["../../../src/components/UserPage/UserPage.tsx"],"sourcesContent":["import React, { useState } from 'react';\nimport { Content, ContentHeader } from '@backstage/core-components';\nimport { useParams, useSearchParams } from 'react-router-dom';\nimport { QuestionsContainer } from '../QuestionsContainer';\nimport { AskQuestionButton } from '../Buttons/AskQuestionButton';\nimport { Box, Container, Tab } from '@material-ui/core';\nimport { BackToQuestionsButton } from '../Buttons/BackToQuestionsButton';\nimport { useEntityPresentation } from '@backstage/plugin-catalog-react';\nimport { TabContext, TabList, TabPanel } from '@material-ui/lab';\nimport { AnswersContainer } from '../AnswersContainer';\nimport { useTranslation } from '../../utils/hooks';\n\nexport const UserPage = () => {\n const identity = useParams()['*'] ?? 'unknown';\n const presentation = useEntityPresentation(identity);\n const [tab, setTab] = useState('questions');\n const { t } = useTranslation();\n const [_searchParams, setSearchParams] = useSearchParams();\n\n const handleChange = (_event: React.ChangeEvent<{}>, newValue: string) => {\n setSearchParams({});\n setTab(newValue);\n };\n return (\n <Content>\n <Container maxWidth=\"lg\">\n <ContentHeader title={`${presentation.primaryTitle}`}>\n <BackToQuestionsButton />\n <AskQuestionButton />\n </ContentHeader>\n <TabContext value={tab}>\n <Box sx={{ borderBottom: 1, borderColor: 'divider' }}>\n <TabList\n onChange={handleChange}\n aria-label={t('userPage.profileTab')}\n >\n <Tab label={t('userPage.questions')} value=\"questions\" />\n <Tab label={t('userPage.answers')} value=\"answers\" />\n </TabList>\n </Box>\n <TabPanel value=\"questions\">\n <QuestionsContainer\n author={identity ?? ''}\n showNoQuestionsBtn={false}\n />\n </TabPanel>\n <TabPanel value=\"answers\">\n <AnswersContainer\n author={identity ?? ''}\n title={t('userPage.answers')}\n />\n </TabPanel>\n </TabContext>\n </Container>\n </Content>\n );\n};\n"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"UserPage.esm.js","sources":["../../../src/components/UserPage/UserPage.tsx"],"sourcesContent":["import React, { useState } from 'react';\nimport { Content, ContentHeader } from '@backstage/core-components';\nimport { useParams, useSearchParams } from 'react-router-dom';\nimport { QuestionsContainer } from '../QuestionsContainer';\nimport { AskQuestionButton } from '../Buttons/AskQuestionButton';\nimport { Box, Container, Tab } from '@material-ui/core';\nimport { BackToQuestionsButton } from '../Buttons/BackToQuestionsButton';\nimport { useEntityPresentation } from '@backstage/plugin-catalog-react';\nimport { TabContext, TabList, TabPanel } from '@material-ui/lab';\nimport { AnswersContainer } from '../AnswersContainer';\nimport { useTranslation } from '../../utils/hooks';\n\nexport const UserPage = () => {\n const identity = useParams()['*'] ?? 'unknown';\n const presentation = useEntityPresentation(identity);\n const [tab, setTab] = useState('questions');\n const { t } = useTranslation();\n const [_searchParams, setSearchParams] = useSearchParams();\n\n const handleChange = (_event: React.ChangeEvent<{}>, newValue: string) => {\n setSearchParams({});\n setTab(newValue);\n };\n return (\n <Content>\n <Container maxWidth=\"lg\">\n <ContentHeader title={`${presentation.primaryTitle}`}>\n <BackToQuestionsButton />\n <AskQuestionButton />\n </ContentHeader>\n <TabContext value={tab}>\n <Box sx={{ borderBottom: 1, borderColor: 'divider' }}>\n <TabList\n onChange={handleChange}\n aria-label={t('userPage.profileTab')}\n >\n <Tab label={t('userPage.questions')} value=\"questions\" />\n <Tab label={t('userPage.answers')} value=\"answers\" />\n </TabList>\n </Box>\n <TabPanel value=\"questions\">\n <QuestionsContainer\n author={identity ?? ''}\n showNoQuestionsBtn={false}\n />\n </TabPanel>\n <TabPanel value=\"answers\">\n <AnswersContainer\n author={identity ?? ''}\n title={t('userPage.answers')}\n />\n </TabPanel>\n </TabContext>\n </Container>\n </Content>\n );\n};\n"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;AAYO,MAAM,WAAW,MAAM;AAC5B,EAAA,MAAM,QAAW,GAAA,SAAA,EAAY,CAAA,GAAG,CAAK,IAAA,SAAA,CAAA;AACrC,EAAM,MAAA,YAAA,GAAe,sBAAsB,QAAQ,CAAA,CAAA;AACnD,EAAA,MAAM,CAAC,GAAA,EAAK,MAAM,CAAA,GAAI,SAAS,WAAW,CAAA,CAAA;AAC1C,EAAM,MAAA,EAAE,CAAE,EAAA,GAAI,cAAe,EAAA,CAAA;AAC7B,EAAA,MAAM,CAAC,aAAA,EAAe,eAAe,CAAA,GAAI,eAAgB,EAAA,CAAA;AAEzD,EAAM,MAAA,YAAA,GAAe,CAAC,MAAA,EAA+B,QAAqB,KAAA;AACxE,IAAA,eAAA,CAAgB,EAAE,CAAA,CAAA;AAClB,IAAA,MAAA,CAAO,QAAQ,CAAA,CAAA;AAAA,GACjB,CAAA;AACA,EAAA,uBACG,KAAA,CAAA,aAAA,CAAA,OAAA,EAAA,IAAA,kBACE,KAAA,CAAA,aAAA,CAAA,SAAA,EAAA,EAAU,UAAS,IAClB,EAAA,kBAAA,KAAA,CAAA,aAAA,CAAC,aAAc,EAAA,EAAA,KAAA,EAAO,CAAG,EAAA,YAAA,CAAa,YAAY,CAAA,CAAA,EAAA,sCAC/C,qBAAsB,EAAA,IAAA,CAAA,kBACtB,KAAA,CAAA,aAAA,CAAA,iBAAA,EAAA,IAAkB,CACrB,CAAA,kBACC,KAAA,CAAA,aAAA,CAAA,UAAA,EAAA,EAAW,OAAO,GACjB,EAAA,kBAAA,KAAA,CAAA,aAAA,CAAC,GAAI,EAAA,EAAA,EAAA,EAAI,EAAE,YAAA,EAAc,CAAG,EAAA,WAAA,EAAa,WACvC,EAAA,kBAAA,KAAA,CAAA,aAAA;AAAA,IAAC,OAAA;AAAA,IAAA;AAAA,MACC,QAAU,EAAA,YAAA;AAAA,MACV,YAAA,EAAY,EAAE,qBAAqB,CAAA;AAAA,KAAA;AAAA,wCAElC,GAAI,EAAA,EAAA,KAAA,EAAO,EAAE,oBAAoB,CAAA,EAAG,OAAM,WAAY,EAAA,CAAA;AAAA,wCACtD,GAAI,EAAA,EAAA,KAAA,EAAO,EAAE,kBAAkB,CAAA,EAAG,OAAM,SAAU,EAAA,CAAA;AAAA,GAEvD,CAAA,kBACC,KAAA,CAAA,aAAA,CAAA,QAAA,EAAA,EAAS,OAAM,WACd,EAAA,kBAAA,KAAA,CAAA,aAAA;AAAA,IAAC,kBAAA;AAAA,IAAA;AAAA,MACC,QAAQ,QAAY,IAAA,EAAA;AAAA,MACpB,kBAAoB,EAAA,KAAA;AAAA,KAAA;AAAA,GAExB,CAAA,kBACC,KAAA,CAAA,aAAA,CAAA,QAAA,EAAA,EAAS,OAAM,SACd,EAAA,kBAAA,KAAA,CAAA,aAAA;AAAA,IAAC,gBAAA;AAAA,IAAA;AAAA,MACC,QAAQ,QAAY,IAAA,EAAA;AAAA,MACpB,KAAA,EAAO,EAAE,kBAAkB,CAAA;AAAA,KAAA;AAAA,GAE/B,CACF,CACF,CACF,CAAA,CAAA;AAEJ;;;;"}
|
package/dist/utils/hooks.esm.js
CHANGED
|
@@ -244,10 +244,16 @@ const useBasePath = () => {
|
|
|
244
244
|
return trimEnd(pathname, "/");
|
|
245
245
|
};
|
|
246
246
|
const userCache = /* @__PURE__ */ new Map();
|
|
247
|
-
const
|
|
247
|
+
const dataLoaderFactory = (catalogApi) => new DataLoader(
|
|
248
248
|
async (entityRefs) => {
|
|
249
|
-
const catalogApi = useApi(catalogApiRef);
|
|
250
249
|
const { items } = await catalogApi.getEntitiesByRefs({
|
|
250
|
+
fields: [
|
|
251
|
+
"kind",
|
|
252
|
+
"metadata.name",
|
|
253
|
+
"metadata.namespace",
|
|
254
|
+
"spec.profile.displayName",
|
|
255
|
+
"spec.profile.picture"
|
|
256
|
+
],
|
|
251
257
|
entityRefs
|
|
252
258
|
});
|
|
253
259
|
entityRefs.forEach((entityRef, index) => {
|
|
@@ -285,7 +291,7 @@ const useEntityAuthor = (entity) => {
|
|
|
285
291
|
setUser(userCache.get(author));
|
|
286
292
|
return;
|
|
287
293
|
}
|
|
288
|
-
|
|
294
|
+
dataLoaderFactory(catalogApi).load(author).then((data) => {
|
|
289
295
|
if (data) {
|
|
290
296
|
setUser(data);
|
|
291
297
|
} else {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"hooks.esm.js","sources":["../../src/utils/hooks.ts"],"sourcesContent":["import { QetaApi, qetaApiRef } from '../api';\nimport useAsync from 'react-use/lib/useAsync';\nimport {\n configApiRef,\n IdentityApi,\n identityApiRef,\n useApi,\n} from '@backstage/core-plugin-api';\nimport { makeStyles } from '@material-ui/core';\nimport { CatalogApi } from '@backstage/catalog-client';\nimport {\n catalogApiRef,\n useEntityPresentation,\n} from '@backstage/plugin-catalog-react';\nimport { trimEnd } from 'lodash';\nimport { useSearchParams } from 'react-router-dom';\nimport React, { useEffect } from 'react';\nimport { UserEntity } from '@backstage/catalog-model';\nimport {\n AnswerResponse,\n QuestionResponse,\n} from '@drodil/backstage-plugin-qeta-common';\nimport DataLoader from 'dataloader';\nimport { useTranslationRef } from '@backstage/core-plugin-api/alpha';\nimport { qetaTranslationRef } from '../translation';\n\nexport function useQetaApi<T>(\n f: (api: QetaApi) => Promise<T>,\n deps: any[] = [],\n) {\n const qetaApi = useApi(qetaApiRef);\n\n return useAsync(async () => {\n return await f(qetaApi);\n }, deps);\n}\n\nexport function useCatalogApi<T>(\n f: (api: CatalogApi) => Promise<T>,\n deps: any[] = [],\n) {\n const catalogApi = useApi(catalogApiRef);\n\n return useAsync(async () => {\n return await f(catalogApi);\n }, deps);\n}\n\nexport function useIdentityApi<T>(\n f: (api: IdentityApi) => Promise<T>,\n deps: any[] = [],\n) {\n const identityApi = useApi(identityApiRef);\n\n return useAsync(async () => {\n return await f(identityApi);\n }, deps);\n}\n\nexport function useEntityQueryParameter(entity?: string) {\n const [searchParams] = useSearchParams();\n const [entityRef, setEntityRef] = React.useState<string | undefined>(entity);\n\n useEffect(() => {\n setEntityRef(searchParams.get('entity') ?? undefined);\n }, [searchParams, setEntityRef]);\n\n return entityRef;\n}\n\nexport const useStyles = makeStyles(theme => {\n return {\n markdownEditor: {\n backgroundColor: 'initial',\n color: theme.palette.text.primary,\n border: `1px solid ${theme.palette.action.disabled}`,\n borderRadius: theme.shape.borderRadius,\n '&:hover': {\n borderColor: theme.palette.action.active,\n },\n '&:focus-within': {\n borderColor: theme.palette.primary.main,\n },\n '& .mde-header': {\n backgroundColor: 'initial',\n color: theme.palette.text.primary,\n borderBottom: `1px solid ${theme.palette.action.selected}`,\n '& .mde-tabs button, .mde-header-item > button': {\n color: `${theme.palette.text.primary} !important`,\n },\n },\n '& .mde-preview-content': {\n padding: '10px',\n },\n '& .mde-text, .mde-preview': {\n fontSize: theme.typography.body1.fontSize,\n fontFamily: theme.typography.body1.fontFamily,\n lineHeight: theme.typography.body1.lineHeight,\n },\n '& .mde-text': {\n backgroundColor: 'initial',\n color: theme.palette.text.primary,\n outline: 'none',\n },\n '& .image-tip': {\n color: theme.palette.text.primary,\n backgroundColor: 'initial',\n },\n },\n markdownEditorError: {\n border: `1px solid ${theme.palette.error.main} !important`,\n },\n markdownContent: {\n '& *': {\n wordBreak: 'break-word',\n },\n '&.inline': {\n display: 'inline-block',\n },\n '& > :first-child': {\n marginTop: '0px !important',\n },\n '& > :last-child': {\n marginBottom: '0px !important',\n },\n },\n successColor: {\n color: theme.palette.success.main,\n },\n questionDivider: {\n marginTop: theme.spacing(2),\n marginBottom: theme.spacing(2),\n },\n questionCard: {\n marginBottom: theme.spacing(1),\n position: 'relative',\n },\n questionCardVote: {\n textAlign: 'center',\n width: '32px',\n marginRight: '26px',\n display: 'inline-block',\n verticalAlign: 'top',\n },\n questionCardContent: {\n display: 'inline-block',\n width: 'calc(100% - 70px)',\n minHeight: '160px',\n },\n questionListItemStats: {\n width: '80px',\n textAlign: 'right',\n marginRight: '26px',\n display: 'inline-block',\n verticalAlign: 'top',\n paddingTop: '10px',\n },\n questionListItemContent: {\n display: 'inline-block',\n width: 'calc(100% - 120px)',\n },\n questionListItemAuthor: {\n display: 'inline',\n float: 'right',\n },\n questionListItemAvatar: {\n display: 'inline-flex',\n marginRight: '0.25rem',\n fontSize: '1rem',\n maxWidth: '1rem',\n maxHeight: '1rem',\n },\n answerCardContent: {\n display: 'inline-block',\n width: 'calc(100% - 70px)',\n },\n questionCardAuthor: {\n padding: theme.spacing(1),\n float: 'right',\n maxWidth: '200px',\n border: `1px solid ${theme.palette.action.selected}`,\n '& .avatar': {\n width: theme.spacing(3),\n height: theme.spacing(3),\n fontSize: '1rem',\n },\n },\n questionListPagination: {\n marginTop: theme.spacing(2),\n },\n postButton: {\n marginTop: theme.spacing(1),\n marginBottom: theme.spacing(1),\n },\n questionsPerPageInput: {\n paddingTop: '10px',\n },\n questionsPerPage: {\n marginRight: theme.spacing(3),\n },\n questionHighlightList: {\n width: '100%',\n border: `1px solid ${theme.palette.action.selected}`,\n borderRadius: theme.shape.borderRadius,\n '&:not(:first-child)': {\n marginTop: theme.spacing(2),\n },\n },\n filterPanel: {\n border: `1px solid ${theme.palette.action.selected}`,\n borderRadius: theme.shape.borderRadius,\n padding: theme.spacing(3),\n },\n questionCardMetadata: {\n marginTop: theme.spacing(3),\n },\n marginRight: {\n marginRight: theme.spacing(1),\n },\n questionCardActions: {\n marginTop: theme.spacing(2),\n '& a': {\n marginRight: theme.spacing(1),\n },\n },\n noPadding: {\n padding: `0 !important`,\n },\n menuIcon: {\n minWidth: '26px',\n },\n deleteModal: {\n position: 'absolute',\n top: '20%',\n left: '50%',\n transform: 'translate(-50%, -50%)',\n width: 400,\n backgroundColor: theme.palette.background.default,\n border: `1px solid ${theme.palette.action.selected}`,\n borderRadius: theme.shape.borderRadius,\n padding: theme.spacing(2),\n '& button': {\n marginTop: theme.spacing(2),\n float: 'right',\n },\n },\n authorLink: {\n textOverflow: 'ellipsis',\n overflow: 'hidden',\n whiteSpace: 'nowrap',\n },\n highlight: {\n animation: '$highlight 2s',\n },\n '@keyframes highlight': {\n '0%': {\n boxShadow: `0px 0px 0px 3px ${theme.palette.secondary.light}`,\n },\n '100%': {\n boxShadow: 'none',\n },\n },\n dateFilter: {\n minWidth: '200px',\n marginTop: theme.spacing(2),\n marginBottom: theme.spacing(2),\n },\n };\n});\n\n// Url resolving logic from https://github.com/backstage/backstage/blob/master/packages/core-components/src/components/Link/Link.tsx\n\n/**\n * Returns the app base url that could be empty if the Config API is not properly implemented.\n * The only cases there would be no Config API are in tests and in storybook stories, and in those cases, it's unlikely that callers would rely on this subpath behavior.\n */\nexport const useBaseUrl = () => {\n try {\n const config = useApi(configApiRef);\n return config.getOptionalString('app.baseUrl');\n } catch {\n return undefined;\n }\n};\n\nexport const useBasePath = () => {\n // baseUrl can be specified as just a path\n const base = 'http://sample.dev';\n const url = useBaseUrl() ?? '/';\n const { pathname } = new URL(url, base);\n return trimEnd(pathname, '/');\n};\n\nconst userCache: Map<string, UserEntity> = new Map();\nconst dataLoader = new DataLoader(\n async (entityRefs: readonly string[]) => {\n const catalogApi = useApi(catalogApiRef);\n const { items } = await catalogApi.getEntitiesByRefs({\n entityRefs: entityRefs as string[],\n });\n\n entityRefs.forEach((entityRef, index) => {\n userCache.set(entityRef, items[index] as UserEntity);\n });\n return items;\n },\n {\n name: 'EntityAuthorLoader',\n cacheMap: new Map(),\n maxBatchSize: 100,\n batchScheduleFn: callback => {\n setTimeout(callback, 50);\n },\n },\n);\n\nexport const useEntityAuthor = (entity: QuestionResponse | AnswerResponse) => {\n const catalogApi = useApi(catalogApiRef);\n const identityApi = useApi(identityApiRef);\n const [name, setName] = React.useState<string | undefined>(undefined);\n const [user, setUser] = React.useState<UserEntity | null>(null);\n const [initials, setInitials] = React.useState<string | null>(null);\n const [currentUser, setCurrentUser] = React.useState<string | null>(null);\n const anonymous = entity.anonymous ?? false;\n let author = entity.author;\n if (!author.startsWith('user:')) {\n author = `user:${author}`;\n }\n\n const { primaryTitle: userName } = useEntityPresentation(author);\n\n useEffect(() => {\n if (anonymous) {\n return;\n }\n\n if (userCache.get(author)) {\n setUser(userCache.get(author) as UserEntity);\n return;\n }\n\n dataLoader\n .load(author)\n .then(data => {\n if (data) {\n setUser(data as UserEntity);\n } else {\n setUser(null);\n }\n })\n .catch(() => {\n setUser(null);\n });\n }, [catalogApi, author, anonymous]);\n\n useEffect(() => {\n identityApi.getBackstageIdentity().then(res => {\n setCurrentUser(res.userEntityRef ?? 'user:default/guest');\n });\n }, [identityApi]);\n\n useEffect(() => {\n let displayName = userName;\n if (entity.author === currentUser) {\n displayName = 'You';\n if (anonymous) {\n displayName += ' (anonymous)';\n }\n }\n setName(displayName);\n }, [entity.author, anonymous, currentUser, userName]);\n\n useEffect(() => {\n const init = (name ?? '')\n .split(' ')\n .map(p => p[0])\n .join('')\n .substring(0, 2)\n .toUpperCase();\n setInitials(init);\n }, [name]);\n\n return { name, initials, user };\n};\n\nexport const useTranslation = () => {\n return useTranslationRef(qetaTranslationRef);\n};\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"hooks.esm.js","sources":["../../src/utils/hooks.ts"],"sourcesContent":["import { QetaApi, qetaApiRef } from '../api';\nimport useAsync from 'react-use/lib/useAsync';\nimport {\n configApiRef,\n IdentityApi,\n identityApiRef,\n useApi,\n} from '@backstage/core-plugin-api';\nimport { makeStyles } from '@material-ui/core';\nimport { CatalogApi } from '@backstage/catalog-client';\nimport {\n catalogApiRef,\n useEntityPresentation,\n} from '@backstage/plugin-catalog-react';\nimport { trimEnd } from 'lodash';\nimport { useSearchParams } from 'react-router-dom';\nimport React, { useEffect } from 'react';\nimport { UserEntity } from '@backstage/catalog-model';\nimport {\n AnswerResponse,\n QuestionResponse,\n} from '@drodil/backstage-plugin-qeta-common';\nimport DataLoader from 'dataloader';\nimport { useTranslationRef } from '@backstage/core-plugin-api/alpha';\nimport { qetaTranslationRef } from '../translation';\n\nexport function useQetaApi<T>(\n f: (api: QetaApi) => Promise<T>,\n deps: any[] = [],\n) {\n const qetaApi = useApi(qetaApiRef);\n\n return useAsync(async () => {\n return await f(qetaApi);\n }, deps);\n}\n\nexport function useCatalogApi<T>(\n f: (api: CatalogApi) => Promise<T>,\n deps: any[] = [],\n) {\n const catalogApi = useApi(catalogApiRef);\n\n return useAsync(async () => {\n return await f(catalogApi);\n }, deps);\n}\n\nexport function useIdentityApi<T>(\n f: (api: IdentityApi) => Promise<T>,\n deps: any[] = [],\n) {\n const identityApi = useApi(identityApiRef);\n\n return useAsync(async () => {\n return await f(identityApi);\n }, deps);\n}\n\nexport function useEntityQueryParameter(entity?: string) {\n const [searchParams] = useSearchParams();\n const [entityRef, setEntityRef] = React.useState<string | undefined>(entity);\n\n useEffect(() => {\n setEntityRef(searchParams.get('entity') ?? undefined);\n }, [searchParams, setEntityRef]);\n\n return entityRef;\n}\n\nexport const useStyles = makeStyles(theme => {\n return {\n markdownEditor: {\n backgroundColor: 'initial',\n color: theme.palette.text.primary,\n border: `1px solid ${theme.palette.action.disabled}`,\n borderRadius: theme.shape.borderRadius,\n '&:hover': {\n borderColor: theme.palette.action.active,\n },\n '&:focus-within': {\n borderColor: theme.palette.primary.main,\n },\n '& .mde-header': {\n backgroundColor: 'initial',\n color: theme.palette.text.primary,\n borderBottom: `1px solid ${theme.palette.action.selected}`,\n '& .mde-tabs button, .mde-header-item > button': {\n color: `${theme.palette.text.primary} !important`,\n },\n },\n '& .mde-preview-content': {\n padding: '10px',\n },\n '& .mde-text, .mde-preview': {\n fontSize: theme.typography.body1.fontSize,\n fontFamily: theme.typography.body1.fontFamily,\n lineHeight: theme.typography.body1.lineHeight,\n },\n '& .mde-text': {\n backgroundColor: 'initial',\n color: theme.palette.text.primary,\n outline: 'none',\n },\n '& .image-tip': {\n color: theme.palette.text.primary,\n backgroundColor: 'initial',\n },\n },\n markdownEditorError: {\n border: `1px solid ${theme.palette.error.main} !important`,\n },\n markdownContent: {\n '& *': {\n wordBreak: 'break-word',\n },\n '&.inline': {\n display: 'inline-block',\n },\n '& > :first-child': {\n marginTop: '0px !important',\n },\n '& > :last-child': {\n marginBottom: '0px !important',\n },\n },\n successColor: {\n color: theme.palette.success.main,\n },\n questionDivider: {\n marginTop: theme.spacing(2),\n marginBottom: theme.spacing(2),\n },\n questionCard: {\n marginBottom: theme.spacing(1),\n position: 'relative',\n },\n questionCardVote: {\n textAlign: 'center',\n width: '32px',\n marginRight: '26px',\n display: 'inline-block',\n verticalAlign: 'top',\n },\n questionCardContent: {\n display: 'inline-block',\n width: 'calc(100% - 70px)',\n minHeight: '160px',\n },\n questionListItemStats: {\n width: '80px',\n textAlign: 'right',\n marginRight: '26px',\n display: 'inline-block',\n verticalAlign: 'top',\n paddingTop: '10px',\n },\n questionListItemContent: {\n display: 'inline-block',\n width: 'calc(100% - 120px)',\n },\n questionListItemAuthor: {\n display: 'inline',\n float: 'right',\n },\n questionListItemAvatar: {\n display: 'inline-flex',\n marginRight: '0.25rem',\n fontSize: '1rem',\n maxWidth: '1rem',\n maxHeight: '1rem',\n },\n answerCardContent: {\n display: 'inline-block',\n width: 'calc(100% - 70px)',\n },\n questionCardAuthor: {\n padding: theme.spacing(1),\n float: 'right',\n maxWidth: '200px',\n border: `1px solid ${theme.palette.action.selected}`,\n '& .avatar': {\n width: theme.spacing(3),\n height: theme.spacing(3),\n fontSize: '1rem',\n },\n },\n questionListPagination: {\n marginTop: theme.spacing(2),\n },\n postButton: {\n marginTop: theme.spacing(1),\n marginBottom: theme.spacing(1),\n },\n questionsPerPageInput: {\n paddingTop: '10px',\n },\n questionsPerPage: {\n marginRight: theme.spacing(3),\n },\n questionHighlightList: {\n width: '100%',\n border: `1px solid ${theme.palette.action.selected}`,\n borderRadius: theme.shape.borderRadius,\n '&:not(:first-child)': {\n marginTop: theme.spacing(2),\n },\n },\n filterPanel: {\n border: `1px solid ${theme.palette.action.selected}`,\n borderRadius: theme.shape.borderRadius,\n padding: theme.spacing(3),\n },\n questionCardMetadata: {\n marginTop: theme.spacing(3),\n },\n marginRight: {\n marginRight: theme.spacing(1),\n },\n questionCardActions: {\n marginTop: theme.spacing(2),\n '& a': {\n marginRight: theme.spacing(1),\n },\n },\n noPadding: {\n padding: `0 !important`,\n },\n menuIcon: {\n minWidth: '26px',\n },\n deleteModal: {\n position: 'absolute',\n top: '20%',\n left: '50%',\n transform: 'translate(-50%, -50%)',\n width: 400,\n backgroundColor: theme.palette.background.default,\n border: `1px solid ${theme.palette.action.selected}`,\n borderRadius: theme.shape.borderRadius,\n padding: theme.spacing(2),\n '& button': {\n marginTop: theme.spacing(2),\n float: 'right',\n },\n },\n authorLink: {\n textOverflow: 'ellipsis',\n overflow: 'hidden',\n whiteSpace: 'nowrap',\n },\n highlight: {\n animation: '$highlight 2s',\n },\n '@keyframes highlight': {\n '0%': {\n boxShadow: `0px 0px 0px 3px ${theme.palette.secondary.light}`,\n },\n '100%': {\n boxShadow: 'none',\n },\n },\n dateFilter: {\n minWidth: '200px',\n marginTop: theme.spacing(2),\n marginBottom: theme.spacing(2),\n },\n };\n});\n\n// Url resolving logic from https://github.com/backstage/backstage/blob/master/packages/core-components/src/components/Link/Link.tsx\n\n/**\n * Returns the app base url that could be empty if the Config API is not properly implemented.\n * The only cases there would be no Config API are in tests and in storybook stories, and in those cases, it's unlikely that callers would rely on this subpath behavior.\n */\nexport const useBaseUrl = () => {\n try {\n const config = useApi(configApiRef);\n return config.getOptionalString('app.baseUrl');\n } catch {\n return undefined;\n }\n};\n\nexport const useBasePath = () => {\n // baseUrl can be specified as just a path\n const base = 'http://sample.dev';\n const url = useBaseUrl() ?? '/';\n const { pathname } = new URL(url, base);\n return trimEnd(pathname, '/');\n};\n\nconst userCache: Map<string, UserEntity> = new Map();\nconst dataLoaderFactory = (catalogApi: CatalogApi) =>\n new DataLoader(\n async (entityRefs: readonly string[]) => {\n const { items } = await catalogApi.getEntitiesByRefs({\n fields: [\n 'kind',\n 'metadata.name',\n 'metadata.namespace',\n 'spec.profile.displayName',\n 'spec.profile.picture',\n ],\n entityRefs: entityRefs as string[],\n });\n\n entityRefs.forEach((entityRef, index) => {\n userCache.set(entityRef, items[index] as UserEntity);\n });\n return items;\n },\n {\n name: 'EntityAuthorLoader',\n cacheMap: new Map(),\n maxBatchSize: 100,\n batchScheduleFn: callback => {\n setTimeout(callback, 50);\n },\n },\n );\n\nexport const useEntityAuthor = (entity: QuestionResponse | AnswerResponse) => {\n const catalogApi = useApi(catalogApiRef);\n const identityApi = useApi(identityApiRef);\n const [name, setName] = React.useState<string | undefined>(undefined);\n const [user, setUser] = React.useState<UserEntity | null>(null);\n const [initials, setInitials] = React.useState<string | null>(null);\n const [currentUser, setCurrentUser] = React.useState<string | null>(null);\n const anonymous = entity.anonymous ?? false;\n let author = entity.author;\n if (!author.startsWith('user:')) {\n author = `user:${author}`;\n }\n\n const { primaryTitle: userName } = useEntityPresentation(author);\n\n useEffect(() => {\n if (anonymous) {\n return;\n }\n\n if (userCache.get(author)) {\n setUser(userCache.get(author) as UserEntity);\n return;\n }\n\n dataLoaderFactory(catalogApi)\n .load(author)\n .then(data => {\n if (data) {\n setUser(data as UserEntity);\n } else {\n setUser(null);\n }\n })\n .catch(() => {\n setUser(null);\n });\n }, [catalogApi, author, anonymous]);\n\n useEffect(() => {\n identityApi.getBackstageIdentity().then(res => {\n setCurrentUser(res.userEntityRef ?? 'user:default/guest');\n });\n }, [identityApi]);\n\n useEffect(() => {\n let displayName = userName;\n if (entity.author === currentUser) {\n displayName = 'You';\n if (anonymous) {\n displayName += ' (anonymous)';\n }\n }\n setName(displayName);\n }, [entity.author, anonymous, currentUser, userName]);\n\n useEffect(() => {\n const init = (name ?? '')\n .split(' ')\n .map(p => p[0])\n .join('')\n .substring(0, 2)\n .toUpperCase();\n setInitials(init);\n }, [name]);\n\n return { name, initials, user };\n};\n\nexport const useTranslation = () => {\n return useTranslationRef(qetaTranslationRef);\n};\n"],"names":[],"mappings":"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"}
|
package/dist/utils/utils.esm.js
CHANGED
|
@@ -11,20 +11,6 @@ const getEntityTitle = (entity) => {
|
|
|
11
11
|
const stringified = stringifyEntityRef(entity);
|
|
12
12
|
return formatEntityName(entity.metadata.title ?? stringified) ?? stringified;
|
|
13
13
|
};
|
|
14
|
-
const truncate = (str, n) => {
|
|
15
|
-
return str.length > n ? `${str.slice(0, n - 1)}...` : str;
|
|
16
|
-
};
|
|
17
|
-
const removeMarkdownFormatting = (text) => {
|
|
18
|
-
let fixed = text.replace(/^(-\s*?|\*\s*?|_\s*?){3,}\s*/gm, "");
|
|
19
|
-
fixed = text.replace(/<[^>]*>/g, "");
|
|
20
|
-
fixed = fixed.replace(/```[\s\S]*?```/g, (match) => {
|
|
21
|
-
return match.replace(/(^```[a-z]*\n)|(```$)/g, "").trim();
|
|
22
|
-
});
|
|
23
|
-
fixed = fixed.replace(/`{1,2}([^`]*)`{1,2}/g, "$1");
|
|
24
|
-
fixed = fixed.replace(/(?:\*\*|__)([^\n*]+)(?:\*\*|__)/g, "$1").replace(/(?:\*|_)([^\n*]+)(?:\*|_)/g, "$1").replace(/(?:~~)([^~]+)(?:~~)/g, "$1").replace(/^[>\t]{0,3}>+\s?/gm, "").replace(/\[\^.+?\](: .*?$)?/g, "").replace(/^([ \t]*)([*\-+]|\d+\.)\s+/gm, "").replace(/!\[([^\]]*)\]\([^)]*\)/g, "$1").replace(/\[([^\]]*)\]\([^)]*\)/g, "$1").replace(/^#{1,6}[ \t]+/gm, "").replace(/^[=-]{2,}\s*$/g, "").replace(/(?:\r\n|\r|\n)/g, " ").replace(/(^\s+|\s+$)/g, "");
|
|
25
|
-
fixed = fixed.replace(/<[^>]*>/g, "");
|
|
26
|
-
return fixed;
|
|
27
|
-
};
|
|
28
14
|
const formatDate = (localDate) => {
|
|
29
15
|
let date = localDate.getDate();
|
|
30
16
|
let month = localDate.getMonth() + 1;
|
|
@@ -69,6 +55,18 @@ const getFiltersWithDateRange = (filters) => {
|
|
|
69
55
|
}
|
|
70
56
|
return filters;
|
|
71
57
|
};
|
|
58
|
+
const confirmNavigationIfEdited = (edited) => {
|
|
59
|
+
const handleBeforeUnload = (event) => {
|
|
60
|
+
if (edited) {
|
|
61
|
+
event.preventDefault();
|
|
62
|
+
event.returnValue = "";
|
|
63
|
+
}
|
|
64
|
+
};
|
|
65
|
+
window.addEventListener("beforeunload", handleBeforeUnload);
|
|
66
|
+
return () => {
|
|
67
|
+
window.removeEventListener("beforeunload", handleBeforeUnload);
|
|
68
|
+
};
|
|
69
|
+
};
|
|
72
70
|
|
|
73
|
-
export { formatDate, formatEntityName, getEntityTitle, getFiltersWithDateRange
|
|
71
|
+
export { confirmNavigationIfEdited, formatDate, formatEntityName, getEntityTitle, getFiltersWithDateRange };
|
|
74
72
|
//# sourceMappingURL=utils.esm.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"utils.esm.js","sources":["../../src/utils/utils.ts"],"sourcesContent":["import { Entity, stringifyEntityRef } from '@backstage/catalog-model';\nimport { Filters } from '../components/QuestionsContainer/FilterPanel';\n\nexport const formatEntityName = (username?: string) => {\n if (!username) {\n return '';\n }\n const plainName = username.split(/[/:]+/).pop();\n return plainName\n ?.split(/[_.-]+/)\n .map(a => a.charAt(0).toUpperCase() + a.slice(1))\n .join(' ');\n};\n\nexport const getEntityTitle = (entity: Entity): string => {\n const stringified = stringifyEntityRef(entity);\n return formatEntityName(entity.metadata.title ?? stringified) ?? stringified;\n};\n\nexport const
|
|
1
|
+
{"version":3,"file":"utils.esm.js","sources":["../../src/utils/utils.ts"],"sourcesContent":["import { Entity, stringifyEntityRef } from '@backstage/catalog-model';\nimport { Filters } from '../components/QuestionsContainer/FilterPanel';\n\nexport const formatEntityName = (username?: string) => {\n if (!username) {\n return '';\n }\n const plainName = username.split(/[/:]+/).pop();\n return plainName\n ?.split(/[_.-]+/)\n .map(a => a.charAt(0).toUpperCase() + a.slice(1))\n .join(' ');\n};\n\nexport const getEntityTitle = (entity: Entity): string => {\n const stringified = stringifyEntityRef(entity);\n return formatEntityName(entity.metadata.title ?? stringified) ?? stringified;\n};\n\nexport const formatDate = (localDate: Date) => {\n let date: any = localDate.getDate();\n let month: any = localDate.getMonth() + 1;\n if (date < 10) {\n date = `0${date}`;\n }\n\n if (month < 10) {\n month = `0${month}`;\n }\n return `${localDate.getFullYear()}-${month}-${date}`;\n};\n\nexport type FiltersWithDateRange = Filters & {\n fromDate: string;\n toDate: string;\n};\n\nexport const getFiltersWithDateRange = (filters: Filters) => {\n let filtersWithDateRange: FiltersWithDateRange;\n const to = new Date();\n const from = new Date(to);\n if (filters.dateRange) {\n let fromDate = '';\n let toDate = '';\n\n switch (filters.dateRange) {\n case '7-days':\n toDate = formatDate(to);\n from.setDate(to.getDate() - 6);\n fromDate = formatDate(from);\n break;\n\n case '30-days':\n toDate = formatDate(to);\n from.setDate(to.getDate() - 29);\n fromDate = formatDate(from);\n break;\n default:\n if (filters.dateRange.indexOf('--') > 0) {\n fromDate = filters.dateRange.split('--')[0];\n toDate = filters.dateRange.split('--')[1];\n }\n break;\n }\n if (fromDate && toDate) {\n filtersWithDateRange = { ...filters, fromDate, toDate };\n delete filtersWithDateRange.dateRange;\n return filtersWithDateRange;\n }\n }\n return filters;\n};\n\nexport const confirmNavigationIfEdited = (edited: boolean) => {\n const handleBeforeUnload = (event: BeforeUnloadEvent) => {\n if (edited) {\n event.preventDefault();\n event.returnValue = ''; // Included for legacy support, e.g. Chrome/Edge < 119\n }\n };\n\n window.addEventListener('beforeunload', handleBeforeUnload);\n\n return () => {\n window.removeEventListener('beforeunload', handleBeforeUnload);\n };\n};\n"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
"frontend",
|
|
8
8
|
"backstage.io"
|
|
9
9
|
],
|
|
10
|
-
"version": "2.
|
|
10
|
+
"version": "2.7.1",
|
|
11
11
|
"main": "dist/index.esm.js",
|
|
12
12
|
"types": "dist/index.d.ts",
|
|
13
13
|
"prepublishOnly": "yarn tsc && yarn build",
|
|
@@ -57,8 +57,8 @@
|
|
|
57
57
|
"@backstage/plugin-home-react": "^0.1.16",
|
|
58
58
|
"@backstage/plugin-permission-react": "^0.4.25",
|
|
59
59
|
"@backstage/plugin-signals-react": "^0.0.4",
|
|
60
|
-
"@drodil/backstage-plugin-qeta-common": "^2.
|
|
61
|
-
"@drodil/backstage-plugin-qeta-react": "^2.
|
|
60
|
+
"@drodil/backstage-plugin-qeta-common": "^2.7.1",
|
|
61
|
+
"@drodil/backstage-plugin-qeta-react": "^2.7.1",
|
|
62
62
|
"@material-ui/core": "^4.12.2",
|
|
63
63
|
"@material-ui/icons": "^4.11.3",
|
|
64
64
|
"@material-ui/lab": "4.0.0-alpha.61",
|