@drodil/backstage-plugin-qeta-react 3.52.6 → 3.53.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/AIAnswerCard/AIAnswerCard.esm.js +11 -11
- package/dist/components/AIAnswerCard/AIAnswerCard.esm.js.map +1 -1
- package/dist/components/AnswerForm/AnswerForm.esm.js +5 -0
- package/dist/components/AnswerForm/AnswerForm.esm.js.map +1 -1
- package/dist/components/AnswersContainer/AnswerListItem.esm.js +4 -2
- package/dist/components/AnswersContainer/AnswerListItem.esm.js.map +1 -1
- package/dist/components/AnswersContainer/AnswersContainer.esm.js +59 -231
- package/dist/components/AnswersContainer/AnswersContainer.esm.js.map +1 -1
- package/dist/components/AnswersContainer/AnswersGridItem.esm.js +167 -0
- package/dist/components/AnswersContainer/AnswersGridItem.esm.js.map +1 -0
- package/dist/components/ArticleContent/ArticleButtons.esm.js +14 -1
- package/dist/components/ArticleContent/ArticleButtons.esm.js.map +1 -1
- package/dist/components/Badges/UserBadges.esm.js +7 -2
- package/dist/components/Badges/UserBadges.esm.js.map +1 -1
- package/dist/components/Buttons/AddToCollectionButton.esm.js +7 -2
- package/dist/components/Buttons/AddToCollectionButton.esm.js.map +1 -1
- package/dist/components/Buttons/EntityFollowButton.esm.js +7 -2
- package/dist/components/Buttons/EntityFollowButton.esm.js.map +1 -1
- package/dist/components/Buttons/RankingButtons.esm.js +94 -0
- package/dist/components/Buttons/RankingButtons.esm.js.map +1 -0
- package/dist/components/Buttons/TagFollowButton.esm.js +8 -3
- package/dist/components/Buttons/TagFollowButton.esm.js.map +1 -1
- package/dist/components/Buttons/UserFollowButton.esm.js +7 -2
- package/dist/components/Buttons/UserFollowButton.esm.js.map +1 -1
- package/dist/components/Buttons/VoteButtons.esm.js +12 -1
- package/dist/components/Buttons/VoteButtons.esm.js.map +1 -1
- package/dist/components/CollectionsContainer/CollectionListItem.esm.js +143 -0
- package/dist/components/CollectionsContainer/CollectionListItem.esm.js.map +1 -0
- package/dist/components/CollectionsContainer/CollectionsContainer.esm.js +45 -0
- package/dist/components/CollectionsContainer/CollectionsContainer.esm.js.map +1 -0
- package/dist/components/CollectionsContainer/CollectionsGridItem.esm.js.map +1 -0
- package/dist/components/ContentHeader/ContentHeader.esm.js +6 -0
- package/dist/components/ContentHeader/ContentHeader.esm.js.map +1 -1
- package/dist/components/EntitiesContainer/EntitiesContainer.esm.js +44 -0
- package/dist/components/EntitiesContainer/EntitiesContainer.esm.js.map +1 -0
- package/dist/components/{EntitiesGrid → EntitiesContainer}/EntitiesGridItem.esm.js +18 -26
- package/dist/components/EntitiesContainer/EntitiesGridItem.esm.js.map +1 -0
- package/dist/components/EntitiesContainer/EntityListItem.esm.js +102 -0
- package/dist/components/EntitiesContainer/EntityListItem.esm.js.map +1 -0
- package/dist/components/FilterPanel/FilterPanel.esm.js +2 -2
- package/dist/components/FilterPanel/FilterPanel.esm.js.map +1 -1
- package/dist/components/FollowedLists/FollowedEntitiesList.esm.js +7 -3
- package/dist/components/FollowedLists/FollowedEntitiesList.esm.js.map +1 -1
- package/dist/components/FollowedLists/FollowedTagsList.esm.js +8 -4
- package/dist/components/FollowedLists/FollowedTagsList.esm.js.map +1 -1
- package/dist/components/FollowedLists/FollowedUsersList.esm.js +7 -3
- package/dist/components/FollowedLists/FollowedUsersList.esm.js.map +1 -1
- package/dist/components/HomePageCards/ImpactCard.esm.js +7 -2
- package/dist/components/HomePageCards/ImpactCard.esm.js.map +1 -1
- package/dist/components/HomePageCards/PostsCard.esm.js +23 -15
- package/dist/components/HomePageCards/PostsCard.esm.js.map +1 -1
- package/dist/components/LeftMenu/LeftMenu.esm.js +15 -16
- package/dist/components/LeftMenu/LeftMenu.esm.js.map +1 -1
- package/dist/components/LinkCard/LinkCard.esm.js +4 -0
- package/dist/components/LinkCard/LinkCard.esm.js.map +1 -1
- package/dist/components/Links/Links.esm.js +11 -1
- package/dist/components/Links/Links.esm.js.map +1 -1
- package/dist/components/PostForm/EntitiesInput.esm.js +229 -226
- package/dist/components/PostForm/EntitiesInput.esm.js.map +1 -1
- package/dist/components/PostForm/PostForm.esm.js +13 -10
- package/dist/components/PostForm/PostForm.esm.js.map +1 -1
- package/dist/components/PostForm/TagInput.esm.js +4 -3
- package/dist/components/PostForm/TagInput.esm.js.map +1 -1
- package/dist/components/PostHighlightList/PostHighlightList.esm.js +6 -2
- package/dist/components/PostHighlightList/PostHighlightList.esm.js.map +1 -1
- package/dist/components/PostsContainer/PostListItem.esm.js +58 -19
- package/dist/components/PostsContainer/PostListItem.esm.js.map +1 -1
- package/dist/components/PostsContainer/PostsContainer.esm.js +137 -128
- package/dist/components/PostsContainer/PostsContainer.esm.js.map +1 -1
- package/dist/components/{PostsGrid → PostsContainer}/PostsGridItem.esm.js +29 -53
- package/dist/components/PostsContainer/PostsGridItem.esm.js.map +1 -0
- package/dist/components/PostsTable/PostsTable.esm.js +7 -2
- package/dist/components/PostsTable/PostsTable.esm.js.map +1 -1
- package/dist/components/QetaEntityContainer/QetaEntityContainer.esm.js +178 -0
- package/dist/components/QetaEntityContainer/QetaEntityContainer.esm.js.map +1 -0
- package/dist/components/QuestionCard/QuestionCard.esm.js +100 -88
- package/dist/components/QuestionCard/QuestionCard.esm.js.map +1 -1
- package/dist/components/SuggestionsCard/SuggestionsCard.esm.js +7 -3
- package/dist/components/SuggestionsCard/SuggestionsCard.esm.js.map +1 -1
- package/dist/components/TagsAndEntities/EntityChip.esm.js +6 -2
- package/dist/components/TagsAndEntities/EntityChip.esm.js.map +1 -1
- package/dist/components/TagsAndEntities/TagChip.esm.js +6 -2
- package/dist/components/TagsAndEntities/TagChip.esm.js.map +1 -1
- package/dist/components/TagsAndEntities/UserChip.esm.js +7 -3
- package/dist/components/TagsAndEntities/UserChip.esm.js.map +1 -1
- package/dist/components/TagsContainer/CreateTagModal.esm.js.map +1 -0
- package/dist/components/TagsContainer/EditTagModal.esm.js.map +1 -0
- package/dist/components/{TagsGrid → TagsContainer}/TagGridItem.esm.js +3 -3
- package/dist/components/TagsContainer/TagGridItem.esm.js.map +1 -0
- package/dist/components/TagsContainer/TagListItem.esm.js +243 -0
- package/dist/components/TagsContainer/TagListItem.esm.js.map +1 -0
- package/dist/components/TagsContainer/TagsContainer.esm.js +86 -0
- package/dist/components/TagsContainer/TagsContainer.esm.js.map +1 -0
- package/dist/components/TemplateList/TemplateForm.esm.js +7 -2
- package/dist/components/TemplateList/TemplateForm.esm.js.map +1 -1
- package/dist/components/TemplateList/TemplateList.esm.js +7 -3
- package/dist/components/TemplateList/TemplateList.esm.js.map +1 -1
- package/dist/components/Timeline/TimelineItem.esm.js +4 -0
- package/dist/components/Timeline/TimelineItem.esm.js.map +1 -1
- package/dist/components/TopRankingUsersCard/TopRankingUsersCard.esm.js +7 -2
- package/dist/components/TopRankingUsersCard/TopRankingUsersCard.esm.js.map +1 -1
- package/dist/components/UsersContainer/UserListItem.esm.js +133 -0
- package/dist/components/UsersContainer/UserListItem.esm.js.map +1 -0
- package/dist/components/UsersContainer/UsersContainer.esm.js +44 -0
- package/dist/components/UsersContainer/UsersContainer.esm.js.map +1 -0
- package/dist/components/{UsersGrid → UsersContainer}/UsersGridItem.esm.js +35 -38
- package/dist/components/UsersContainer/UsersGridItem.esm.js.map +1 -0
- package/dist/components/Utility/QetaGridHeader.esm.js +15 -11
- package/dist/components/Utility/QetaGridHeader.esm.js.map +1 -1
- package/dist/components/Utility/QetaPagination.esm.js +69 -0
- package/dist/components/Utility/QetaPagination.esm.js.map +1 -0
- package/dist/hooks/useEntityAuthor.esm.js +3 -1
- package/dist/hooks/useEntityAuthor.esm.js.map +1 -1
- package/dist/hooks/useListItemStyles.esm.js +22 -0
- package/dist/hooks/useListItemStyles.esm.js.map +1 -0
- package/dist/hooks/{usePaginatedPosts.esm.js → useQetaEntities.esm.js} +59 -86
- package/dist/hooks/useQetaEntities.esm.js.map +1 -0
- package/dist/hooks/useUserSettings.esm.js +83 -0
- package/dist/hooks/useUserSettings.esm.js.map +1 -0
- package/dist/index.d.ts +211 -58
- package/dist/index.esm.js +21 -8
- package/dist/index.esm.js.map +1 -1
- package/dist/routes.esm.js +6 -1
- package/dist/routes.esm.js.map +1 -1
- package/dist/translation.esm.js +49 -0
- package/dist/translation.esm.js.map +1 -1
- package/package.json +2 -2
- package/dist/components/AnswersContainer/AnswerList.esm.js +0 -54
- package/dist/components/AnswersContainer/AnswerList.esm.js.map +0 -1
- package/dist/components/CollectionsGrid/CollectionsGrid.esm.js +0 -204
- package/dist/components/CollectionsGrid/CollectionsGrid.esm.js.map +0 -1
- package/dist/components/CollectionsGrid/CollectionsGridContent.esm.js +0 -55
- package/dist/components/CollectionsGrid/CollectionsGridContent.esm.js.map +0 -1
- package/dist/components/CollectionsGrid/CollectionsGridItem.esm.js.map +0 -1
- package/dist/components/CollectionsGrid/NoCollectionsCard.esm.js +0 -21
- package/dist/components/CollectionsGrid/NoCollectionsCard.esm.js.map +0 -1
- package/dist/components/EntitiesGrid/EntitiesGrid.esm.js +0 -136
- package/dist/components/EntitiesGrid/EntitiesGrid.esm.js.map +0 -1
- package/dist/components/EntitiesGrid/EntitiesGridContent.esm.js +0 -46
- package/dist/components/EntitiesGrid/EntitiesGridContent.esm.js.map +0 -1
- package/dist/components/EntitiesGrid/EntitiesGridItem.esm.js.map +0 -1
- package/dist/components/EntitiesGrid/NoEntitiesCard.esm.js +0 -21
- package/dist/components/EntitiesGrid/NoEntitiesCard.esm.js.map +0 -1
- package/dist/components/PostsContainer/PostList.esm.js +0 -83
- package/dist/components/PostsContainer/PostList.esm.js.map +0 -1
- package/dist/components/PostsGrid/PostsGrid.esm.js +0 -197
- package/dist/components/PostsGrid/PostsGrid.esm.js.map +0 -1
- package/dist/components/PostsGrid/PostsGridContent.esm.js +0 -90
- package/dist/components/PostsGrid/PostsGridContent.esm.js.map +0 -1
- package/dist/components/PostsGrid/PostsGridItem.esm.js.map +0 -1
- package/dist/components/TagsGrid/CreateTagModal.esm.js.map +0 -1
- package/dist/components/TagsGrid/EditTagModal.esm.js.map +0 -1
- package/dist/components/TagsGrid/NoTagsCard.esm.js +0 -21
- package/dist/components/TagsGrid/NoTagsCard.esm.js.map +0 -1
- package/dist/components/TagsGrid/TagGridItem.esm.js.map +0 -1
- package/dist/components/TagsGrid/TagsGrid.esm.js +0 -190
- package/dist/components/TagsGrid/TagsGrid.esm.js.map +0 -1
- package/dist/components/TagsGrid/TagsGridContent.esm.js +0 -62
- package/dist/components/TagsGrid/TagsGridContent.esm.js.map +0 -1
- package/dist/components/UsersGrid/NoUsersCard.esm.js +0 -21
- package/dist/components/UsersGrid/NoUsersCard.esm.js.map +0 -1
- package/dist/components/UsersGrid/UsersGrid.esm.js +0 -137
- package/dist/components/UsersGrid/UsersGrid.esm.js.map +0 -1
- package/dist/components/UsersGrid/UsersGridContent.esm.js +0 -46
- package/dist/components/UsersGrid/UsersGridContent.esm.js.map +0 -1
- package/dist/components/UsersGrid/UsersGridItem.esm.js.map +0 -1
- package/dist/hooks/usePaginatedPosts.esm.js.map +0 -1
- /package/dist/components/{CollectionsGrid → CollectionsContainer}/CollectionsGridItem.esm.js +0 -0
- /package/dist/components/{TagsGrid → TagsContainer}/CreateTagModal.esm.js +0 -0
- /package/dist/components/{TagsGrid → TagsContainer}/EditTagModal.esm.js +0 -0
|
@@ -38,6 +38,7 @@ const useUserInfo = (entityRef, anonymous) => {
|
|
|
38
38
|
const identityApi = useApi(identityApiRef);
|
|
39
39
|
const { t } = useTranslationRef(qetaTranslationRef);
|
|
40
40
|
const [name, setName] = useState("");
|
|
41
|
+
const [isCurrentUser, setIsCurrentUser] = useState(false);
|
|
41
42
|
const [user, setUser] = useState(null);
|
|
42
43
|
const [initials, setInitials] = useState(null);
|
|
43
44
|
const [currentUser, setCurrentUser] = useState(null);
|
|
@@ -80,6 +81,7 @@ const useUserInfo = (entityRef, anonymous) => {
|
|
|
80
81
|
});
|
|
81
82
|
const userRef = parseEntityRef(ref, { defaultKind: "user" });
|
|
82
83
|
if (currentUserRef.name === userRef.name && currentUserRef.namespace === userRef.namespace) {
|
|
84
|
+
setIsCurrentUser(true);
|
|
83
85
|
displayName = `${t("userLink.you")}${anonymous ? ` (${t("userLink.anonymous").toLocaleLowerCase("en-US")})` : ""}`;
|
|
84
86
|
} else if (anonymous) {
|
|
85
87
|
displayName = t("userLink.anonymous");
|
|
@@ -93,7 +95,7 @@ const useUserInfo = (entityRef, anonymous) => {
|
|
|
93
95
|
const init = (name ?? "").replace(/[^a-zA-Z]/g, "").split(" ").map((p) => p[0]).join("").substring(0, 2).toUpperCase();
|
|
94
96
|
setInitials(init);
|
|
95
97
|
}, [name]);
|
|
96
|
-
return { name, initials, user, secondaryTitle, Icon };
|
|
98
|
+
return { name, initials, user, secondaryTitle, Icon, isCurrentUser };
|
|
97
99
|
};
|
|
98
100
|
const useEntityAuthor = (entity) => {
|
|
99
101
|
const anonymous = "anonymous" in entity ? entity.anonymous ?? false : false;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useEntityAuthor.esm.js","sources":["../../src/hooks/useEntityAuthor.ts"],"sourcesContent":["import {\n parseEntityRef,\n stringifyEntityRef,\n UserEntity,\n} from '@backstage/catalog-model';\nimport { CatalogApi } from '@backstage/catalog-client';\nimport DataLoader from 'dataloader';\nimport { identityApiRef, useApi } from '@backstage/core-plugin-api';\nimport {\n catalogApiRef,\n useEntityPresentation,\n} from '@backstage/plugin-catalog-react';\nimport { useEffect, useState } from 'react';\nimport {\n AnswerResponse,\n CollectionResponse,\n PostResponse,\n UserResponse,\n} from '@drodil/backstage-plugin-qeta-common';\nimport { useTranslationRef } from '@backstage/core-plugin-api/alpha';\nimport { qetaTranslationRef } from '../translation.ts';\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 useUserInfo = (entityRef: string, anonymous?: boolean) => {\n const catalogApi = useApi(catalogApiRef);\n const identityApi = useApi(identityApiRef);\n const { t } = useTranslationRef(qetaTranslationRef);\n const [name, setName] = useState<string>('');\n const [user, setUser] = useState<UserEntity | null>(null);\n const [initials, setInitials] = useState<string | null>(null);\n const [currentUser, setCurrentUser] = useState<string | null>(null);\n const ref = stringifyEntityRef(\n parseEntityRef(entityRef, { defaultKind: 'user' }),\n );\n\n const {\n primaryTitle: userName,\n secondaryTitle,\n Icon,\n } = useEntityPresentation(ref, { defaultKind: 'user' });\n\n useEffect(() => {\n if (anonymous) {\n return;\n }\n\n if (userCache.get(ref)) {\n setUser(userCache.get(ref) as UserEntity);\n return;\n }\n\n dataLoaderFactory(catalogApi)\n .load(ref)\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, ref, 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 (currentUser) {\n const currentUserRef = parseEntityRef(currentUser, {\n defaultKind: 'user',\n });\n const userRef = parseEntityRef(ref, { defaultKind: 'user' });\n if (\n currentUserRef.name === userRef.name &&\n currentUserRef.namespace === userRef.namespace\n ) {\n displayName = `${t('userLink.you')}${\n anonymous\n ? ` (${t('userLink.anonymous').toLocaleLowerCase('en-US')})`\n : ''\n }`;\n } else if (anonymous) {\n displayName = t('userLink.anonymous');\n }\n } else if (anonymous) {\n displayName = t('userLink.anonymous');\n }\n setName(displayName);\n }, [ref, anonymous, currentUser, userName, t]);\n\n useEffect(() => {\n const init = (name ?? '')\n .replace(/[^a-zA-Z]/g, '')\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, secondaryTitle, Icon };\n};\n\nexport const useEntityAuthor = (\n entity: PostResponse | AnswerResponse | CollectionResponse | UserResponse,\n) => {\n const anonymous = 'anonymous' in entity ? entity.anonymous ?? false : false;\n const author =\n // eslint-disable-next-line no-nested-ternary\n 'author' in entity\n ? entity.author\n : 'userRef' in entity\n ? entity.userRef\n : entity.owner;\n return useUserInfo(author, anonymous);\n};\n"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"useEntityAuthor.esm.js","sources":["../../src/hooks/useEntityAuthor.ts"],"sourcesContent":["import {\n parseEntityRef,\n stringifyEntityRef,\n UserEntity,\n} from '@backstage/catalog-model';\nimport { CatalogApi } from '@backstage/catalog-client';\nimport DataLoader from 'dataloader';\nimport { identityApiRef, useApi } from '@backstage/core-plugin-api';\nimport {\n catalogApiRef,\n useEntityPresentation,\n} from '@backstage/plugin-catalog-react';\nimport { useEffect, useState } from 'react';\nimport {\n AnswerResponse,\n CollectionResponse,\n PostResponse,\n UserResponse,\n} from '@drodil/backstage-plugin-qeta-common';\nimport { useTranslationRef } from '@backstage/core-plugin-api/alpha';\nimport { qetaTranslationRef } from '../translation.ts';\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 useUserInfo = (entityRef: string, anonymous?: boolean) => {\n const catalogApi = useApi(catalogApiRef);\n const identityApi = useApi(identityApiRef);\n const { t } = useTranslationRef(qetaTranslationRef);\n const [name, setName] = useState<string>('');\n const [isCurrentUser, setIsCurrentUser] = useState<boolean>(false);\n const [user, setUser] = useState<UserEntity | null>(null);\n const [initials, setInitials] = useState<string | null>(null);\n const [currentUser, setCurrentUser] = useState<string | null>(null);\n const ref = stringifyEntityRef(\n parseEntityRef(entityRef, { defaultKind: 'user' }),\n );\n\n const {\n primaryTitle: userName,\n secondaryTitle,\n Icon,\n } = useEntityPresentation(ref, { defaultKind: 'user' });\n\n useEffect(() => {\n if (anonymous) {\n return;\n }\n\n if (userCache.get(ref)) {\n setUser(userCache.get(ref) as UserEntity);\n return;\n }\n\n dataLoaderFactory(catalogApi)\n .load(ref)\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, ref, 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 (currentUser) {\n const currentUserRef = parseEntityRef(currentUser, {\n defaultKind: 'user',\n });\n const userRef = parseEntityRef(ref, { defaultKind: 'user' });\n if (\n currentUserRef.name === userRef.name &&\n currentUserRef.namespace === userRef.namespace\n ) {\n setIsCurrentUser(true);\n displayName = `${t('userLink.you')}${\n anonymous\n ? ` (${t('userLink.anonymous').toLocaleLowerCase('en-US')})`\n : ''\n }`;\n } else if (anonymous) {\n displayName = t('userLink.anonymous');\n }\n } else if (anonymous) {\n displayName = t('userLink.anonymous');\n }\n setName(displayName);\n }, [ref, anonymous, currentUser, userName, t]);\n\n useEffect(() => {\n const init = (name ?? '')\n .replace(/[^a-zA-Z]/g, '')\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, secondaryTitle, Icon, isCurrentUser };\n};\n\nexport const useEntityAuthor = (\n entity: PostResponse | AnswerResponse | CollectionResponse | UserResponse,\n) => {\n const anonymous = 'anonymous' in entity ? entity.anonymous ?? false : false;\n const author =\n // eslint-disable-next-line no-nested-ternary\n 'author' in entity\n ? entity.author\n : 'userRef' in entity\n ? entity.userRef\n : entity.owner;\n return useUserInfo(author, anonymous);\n};\n"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { makeStyles } from '@material-ui/core';
|
|
2
|
+
|
|
3
|
+
const useListItemStyles = makeStyles((theme) => ({
|
|
4
|
+
root: {
|
|
5
|
+
display: "flex",
|
|
6
|
+
flexDirection: "row",
|
|
7
|
+
alignItems: "center",
|
|
8
|
+
padding: theme.spacing(1, 2),
|
|
9
|
+
"&:hover": {
|
|
10
|
+
backgroundColor: theme.palette.action.hover
|
|
11
|
+
},
|
|
12
|
+
textDecoration: "none",
|
|
13
|
+
color: "inherit",
|
|
14
|
+
width: "100%",
|
|
15
|
+
"&:first-child": {
|
|
16
|
+
paddingTop: theme.spacing(2)
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
}));
|
|
20
|
+
|
|
21
|
+
export { useListItemStyles };
|
|
22
|
+
//# sourceMappingURL=useListItemStyles.esm.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useListItemStyles.esm.js","sources":["../../src/hooks/useListItemStyles.ts"],"sourcesContent":["import { makeStyles } from '@material-ui/core';\n\nexport const useListItemStyles = makeStyles(theme => ({\n root: {\n display: 'flex',\n flexDirection: 'row',\n alignItems: 'center',\n padding: theme.spacing(1, 2),\n '&:hover': {\n backgroundColor: theme.palette.action.hover,\n },\n textDecoration: 'none',\n color: 'inherit',\n width: '100%',\n '&:first-child': {\n paddingTop: theme.spacing(2),\n },\n },\n}));\n"],"names":[],"mappings":";;AAEa,MAAA,iBAAA,GAAoB,WAAW,CAAU,KAAA,MAAA;AAAA,EACpD,IAAM,EAAA;AAAA,IACJ,OAAS,EAAA,MAAA;AAAA,IACT,aAAe,EAAA,KAAA;AAAA,IACf,UAAY,EAAA,QAAA;AAAA,IACZ,OAAS,EAAA,KAAA,CAAM,OAAQ,CAAA,CAAA,EAAG,CAAC,CAAA;AAAA,IAC3B,SAAW,EAAA;AAAA,MACT,eAAA,EAAiB,KAAM,CAAA,OAAA,CAAQ,MAAO,CAAA;AAAA,KACxC;AAAA,IACA,cAAgB,EAAA,MAAA;AAAA,IAChB,KAAO,EAAA,SAAA;AAAA,IACP,KAAO,EAAA,MAAA;AAAA,IACP,eAAiB,EAAA;AAAA,MACf,UAAA,EAAY,KAAM,CAAA,OAAA,CAAQ,CAAC;AAAA;AAC7B;AAEJ,CAAE,CAAA;;;;"}
|
|
@@ -1,68 +1,48 @@
|
|
|
1
1
|
import { useAnalytics } from '@backstage/core-plugin-api';
|
|
2
2
|
import { useState, useEffect } from 'react';
|
|
3
3
|
import { useSearchParams } from 'react-router-dom';
|
|
4
|
-
import { filterKeys } from '../components/FilterPanel/FilterPanel.esm.js';
|
|
5
4
|
import useDebounce from 'react-use/lib/useDebounce';
|
|
6
|
-
import { getFiltersWithDateRange } from '../utils/utils.esm.js';
|
|
7
|
-
import { filterTags } from '@drodil/backstage-plugin-qeta-common';
|
|
8
5
|
import { useQetaApi } from './useQetaApi.esm.js';
|
|
6
|
+
import { filterKeys } from '../components/FilterPanel/FilterPanel.esm.js';
|
|
7
|
+
import { filterTags } from '@drodil/backstage-plugin-qeta-common';
|
|
8
|
+
import { useUserSettings } from './useUserSettings.esm.js';
|
|
9
9
|
|
|
10
|
-
|
|
11
|
-
function usePaginatedPosts(props) {
|
|
10
|
+
function useQetaEntities(props) {
|
|
12
11
|
const {
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
12
|
+
fetch,
|
|
13
|
+
initialFilters,
|
|
14
|
+
prefix,
|
|
15
|
+
defaultPageSize,
|
|
16
|
+
filterKeys: filterKeys$1,
|
|
17
|
+
fetchDeps,
|
|
18
|
+
getKey,
|
|
19
|
+
usePagination
|
|
21
20
|
} = props;
|
|
22
21
|
const analytics = useAnalytics();
|
|
23
22
|
const [page, setPage] = useState(1);
|
|
24
|
-
const
|
|
25
|
-
const
|
|
23
|
+
const [pageSize, setPageSize] = useState(defaultPageSize ?? 24);
|
|
24
|
+
const { getSetting, setSetting } = useUserSettings();
|
|
26
25
|
const [showFilterPanel, setShowFilterPanel] = useState(
|
|
27
|
-
|
|
26
|
+
getSetting("filterPanelExpanded")[prefix] ?? false
|
|
28
27
|
);
|
|
29
28
|
const [searchParams, setSearchParams] = useSearchParams();
|
|
30
29
|
const [searchQuery, setSearchQuery] = useState("");
|
|
31
|
-
const [filters, setFilters] = useState(
|
|
32
|
-
|
|
33
|
-
orderBy: props.orderBy ?? "created",
|
|
34
|
-
noAnswers: props.noAnswers ?? "false",
|
|
35
|
-
noCorrectAnswer: props.noCorrectAnswer ?? "false",
|
|
36
|
-
noVotes: props.noVotes ?? "false",
|
|
37
|
-
searchQuery: props.searchQuery ?? "",
|
|
38
|
-
entities: entities ?? (entity ? [entity] : void 0),
|
|
39
|
-
tags,
|
|
40
|
-
dateRange: "",
|
|
41
|
-
collectionId: props.collectionId,
|
|
42
|
-
status,
|
|
43
|
-
type
|
|
44
|
-
});
|
|
45
|
-
const [posts, setPosts] = useState([]);
|
|
30
|
+
const [filters, setFilters] = useState(initialFilters);
|
|
31
|
+
const [items, setItems] = useState([]);
|
|
46
32
|
const [hasMore, setHasMore] = useState(true);
|
|
47
33
|
const [total, setTotal] = useState(0);
|
|
48
34
|
useEffect(() => {
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
}, [showFilterPanel]);
|
|
35
|
+
if (defaultPageSize) {
|
|
36
|
+
setPageSize(defaultPageSize);
|
|
37
|
+
}
|
|
38
|
+
}, [defaultPageSize]);
|
|
54
39
|
useEffect(() => {
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
collectionId: props.collectionId
|
|
62
|
-
}));
|
|
63
|
-
setPage(1);
|
|
64
|
-
setPosts([]);
|
|
65
|
-
}, [tags, entities, entity, type, status, props.collectionId]);
|
|
40
|
+
const currentExpanded = getSetting("filterPanelExpanded");
|
|
41
|
+
setSetting("filterPanelExpanded", {
|
|
42
|
+
...currentExpanded,
|
|
43
|
+
[prefix]: showFilterPanel
|
|
44
|
+
});
|
|
45
|
+
}, [showFilterPanel, prefix, getSetting, setSetting]);
|
|
66
46
|
const onPageChange = (value) => {
|
|
67
47
|
setPage(value);
|
|
68
48
|
setSearchParams((prev) => {
|
|
@@ -77,7 +57,6 @@ function usePaginatedPosts(props) {
|
|
|
77
57
|
const onFilterChange = (changes) => {
|
|
78
58
|
const changesArray = Array.isArray(changes) ? changes : [changes];
|
|
79
59
|
setPage(1);
|
|
80
|
-
setPosts([]);
|
|
81
60
|
setFilters((prev) => {
|
|
82
61
|
const newValue = { ...prev };
|
|
83
62
|
for (const { key, value } of changesArray) {
|
|
@@ -88,7 +67,8 @@ function usePaginatedPosts(props) {
|
|
|
88
67
|
setSearchParams((prev) => {
|
|
89
68
|
const newValue = prev;
|
|
90
69
|
for (const { key, value } of changesArray) {
|
|
91
|
-
|
|
70
|
+
const allowedKeys = filterKeys$1 ?? filterKeys;
|
|
71
|
+
if (!allowedKeys.includes(key)) {
|
|
92
72
|
continue;
|
|
93
73
|
}
|
|
94
74
|
if (!value || value === "false") {
|
|
@@ -112,17 +92,14 @@ function usePaginatedPosts(props) {
|
|
|
112
92
|
};
|
|
113
93
|
const onSearchQueryChange = (query) => {
|
|
114
94
|
onPageChange(1);
|
|
115
|
-
setPosts([]);
|
|
116
95
|
if (query) {
|
|
117
|
-
analytics.captureEvent(
|
|
96
|
+
analytics.captureEvent(`qeta_search_${prefix}`, query);
|
|
118
97
|
}
|
|
119
98
|
setSearchQuery(query);
|
|
120
99
|
};
|
|
121
100
|
useDebounce(
|
|
122
101
|
() => {
|
|
123
102
|
if (filters.searchQuery !== searchQuery) {
|
|
124
|
-
setPage(1);
|
|
125
|
-
setPosts([]);
|
|
126
103
|
setFilters({ ...filters, searchQuery });
|
|
127
104
|
}
|
|
128
105
|
},
|
|
@@ -139,12 +116,12 @@ function usePaginatedPosts(props) {
|
|
|
139
116
|
setPage(pv);
|
|
140
117
|
} else {
|
|
141
118
|
setPage(1);
|
|
142
|
-
|
|
119
|
+
setItems([]);
|
|
143
120
|
}
|
|
144
|
-
} else if (key ===
|
|
121
|
+
} else if (key === `${prefix}PerPage`) {
|
|
145
122
|
const qpp = Number.parseInt(value, 10);
|
|
146
|
-
if (qpp > 0)
|
|
147
|
-
} else if (filterKeys.includes(key)) {
|
|
123
|
+
if (qpp > 0) setPageSize(qpp);
|
|
124
|
+
} else if ((filterKeys$1 ?? filterKeys).includes(key)) {
|
|
148
125
|
filtersApplied = true;
|
|
149
126
|
if (key === "tags") {
|
|
150
127
|
filters.tags = filterTags(value.split(",")) ?? [];
|
|
@@ -161,7 +138,7 @@ function usePaginatedPosts(props) {
|
|
|
161
138
|
if (filtersApplied) {
|
|
162
139
|
setShowFilterPanel(true);
|
|
163
140
|
}
|
|
164
|
-
}, [searchParams,
|
|
141
|
+
}, [searchParams, filterKeys$1, prefix]);
|
|
165
142
|
const {
|
|
166
143
|
value: response,
|
|
167
144
|
loading,
|
|
@@ -169,34 +146,31 @@ function usePaginatedPosts(props) {
|
|
|
169
146
|
retry
|
|
170
147
|
} = useQetaApi(
|
|
171
148
|
(api) => {
|
|
172
|
-
return api
|
|
173
|
-
type,
|
|
174
|
-
limit: postsPerPage,
|
|
175
|
-
offset: (page - 1) * postsPerPage,
|
|
176
|
-
includeEntities: true,
|
|
177
|
-
includeAnswers: false,
|
|
178
|
-
includeComments: false,
|
|
179
|
-
includeAttachments: false,
|
|
180
|
-
includeExperts: false,
|
|
181
|
-
author,
|
|
182
|
-
favorite,
|
|
183
|
-
status,
|
|
184
|
-
...getFiltersWithDateRange(filters)
|
|
185
|
-
});
|
|
149
|
+
return fetch(api, pageSize, (page - 1) * pageSize, filters);
|
|
186
150
|
},
|
|
187
|
-
[
|
|
151
|
+
[page, filters, pageSize, ...fetchDeps ?? []]
|
|
188
152
|
);
|
|
189
153
|
useEffect(() => {
|
|
190
154
|
if (response) {
|
|
191
|
-
if (page === 1) {
|
|
192
|
-
|
|
155
|
+
if (page === 1 || usePagination) {
|
|
156
|
+
setItems(response.items);
|
|
193
157
|
} else {
|
|
194
|
-
|
|
158
|
+
setItems((prev) => {
|
|
159
|
+
const newItems = response.items.filter(
|
|
160
|
+
(newItem) => !prev.some((prevItem) => {
|
|
161
|
+
if (getKey) {
|
|
162
|
+
return getKey(prevItem) === getKey(newItem);
|
|
163
|
+
}
|
|
164
|
+
return prevItem.id === newItem.id;
|
|
165
|
+
})
|
|
166
|
+
);
|
|
167
|
+
return [...prev, ...newItems];
|
|
168
|
+
});
|
|
195
169
|
}
|
|
196
|
-
setHasMore((response.
|
|
170
|
+
setHasMore((response.items ?? []).length >= pageSize);
|
|
197
171
|
setTotal(response.total);
|
|
198
172
|
}
|
|
199
|
-
}, [response, page,
|
|
173
|
+
}, [response, page, pageSize, getKey, usePagination]);
|
|
200
174
|
const onPageSizeChange = (value) => {
|
|
201
175
|
if (response) {
|
|
202
176
|
let newPage = page;
|
|
@@ -205,18 +179,18 @@ function usePaginatedPosts(props) {
|
|
|
205
179
|
}
|
|
206
180
|
onPageChange(Math.max(1, newPage));
|
|
207
181
|
}
|
|
208
|
-
|
|
182
|
+
setPageSize(value);
|
|
209
183
|
setSearchParams((prev) => {
|
|
210
184
|
const newValue = prev;
|
|
211
|
-
newValue.set(
|
|
185
|
+
newValue.set(`${prefix}PerPage`, String(value));
|
|
212
186
|
return newValue;
|
|
213
187
|
});
|
|
214
188
|
};
|
|
215
189
|
return {
|
|
216
190
|
page,
|
|
217
191
|
setPage,
|
|
218
|
-
|
|
219
|
-
|
|
192
|
+
pageSize,
|
|
193
|
+
setPageSize,
|
|
220
194
|
showFilterPanel,
|
|
221
195
|
setShowFilterPanel,
|
|
222
196
|
searchParams,
|
|
@@ -230,17 +204,16 @@ function usePaginatedPosts(props) {
|
|
|
230
204
|
onFilterChange,
|
|
231
205
|
onSearchQueryChange,
|
|
232
206
|
response,
|
|
233
|
-
|
|
207
|
+
items: (page === 1 || usePagination) && !loading && response ? response.items : items,
|
|
234
208
|
hasMore,
|
|
235
209
|
total,
|
|
236
210
|
loading,
|
|
237
211
|
error,
|
|
238
212
|
loadNextPage,
|
|
239
|
-
pageCount,
|
|
240
213
|
retry,
|
|
241
214
|
fetchNextPage: loadNextPage
|
|
242
215
|
};
|
|
243
216
|
}
|
|
244
217
|
|
|
245
|
-
export {
|
|
246
|
-
//# sourceMappingURL=
|
|
218
|
+
export { useQetaEntities };
|
|
219
|
+
//# sourceMappingURL=useQetaEntities.esm.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useQetaEntities.esm.js","sources":["../../src/hooks/useQetaEntities.ts"],"sourcesContent":["import { useAnalytics } from '@backstage/core-plugin-api';\nimport { useEffect, useState } from 'react';\nimport { useSearchParams } from 'react-router-dom';\nimport useDebounce from 'react-use/lib/useDebounce';\nimport { useQetaApi } from './useQetaApi';\nimport { QetaApi } from '@drodil/backstage-plugin-qeta-common';\nimport { filterKeys as globalFilterKeys } from '../components/FilterPanel/FilterPanel';\nimport { filterTags } from '@drodil/backstage-plugin-qeta-common';\nimport { useUserSettings } from './useUserSettings';\n\nexport type QetaEntitiesProps<T, F> = {\n fetch: (\n api: QetaApi,\n limit: number,\n offset: number,\n filters: F,\n ) => Promise<{ items: T[]; total: number }>;\n initialFilters: F;\n prefix: string;\n defaultPageSize?: number;\n filterKeys?: string[];\n fetchDeps?: any[];\n getKey?: (item: T) => string | number;\n usePagination?: boolean;\n};\n\nexport type FilterChange<F> = {\n key: keyof F;\n value?: F[keyof F] | string | string[];\n};\n\nexport function useQetaEntities<T, F>(props: QetaEntitiesProps<T, F>) {\n const {\n fetch,\n initialFilters,\n prefix,\n defaultPageSize,\n filterKeys,\n fetchDeps,\n getKey,\n usePagination,\n } = props;\n const analytics = useAnalytics();\n const [page, setPage] = useState(1);\n const [pageSize, setPageSize] = useState(defaultPageSize ?? 24);\n const { getSetting, setSetting } = useUserSettings();\n const [showFilterPanel, setShowFilterPanel] = useState(\n getSetting('filterPanelExpanded')[prefix] ?? false,\n );\n const [searchParams, setSearchParams] = useSearchParams();\n const [searchQuery, setSearchQuery] = useState('');\n const [filters, setFilters] = useState<F>(initialFilters);\n\n const [items, setItems] = useState<T[]>([]);\n const [hasMore, setHasMore] = useState(true);\n const [total, setTotal] = useState(0);\n\n useEffect(() => {\n if (defaultPageSize) {\n setPageSize(defaultPageSize);\n }\n }, [defaultPageSize]);\n\n useEffect(() => {\n const currentExpanded = getSetting('filterPanelExpanded');\n setSetting('filterPanelExpanded', {\n ...currentExpanded,\n [prefix]: showFilterPanel,\n });\n }, [showFilterPanel, prefix, getSetting, setSetting]);\n\n const onPageChange = (value: number) => {\n setPage(value);\n setSearchParams(prev => {\n const newValue = prev;\n newValue.set('page', String(value));\n return newValue;\n });\n };\n\n const loadNextPage = () => {\n setPage(prev => prev + 1);\n };\n\n const onFilterChange = (changes: FilterChange<F> | FilterChange<F>[]) => {\n const changesArray = Array.isArray(changes) ? changes : [changes];\n setPage(1);\n setFilters(prev => {\n const newValue = { ...prev };\n for (const { key, value } of changesArray) {\n (newValue as any)[key] = value;\n }\n return newValue;\n });\n setSearchParams(prev => {\n const newValue = prev;\n for (const { key, value } of changesArray) {\n const allowedKeys = filterKeys ?? globalFilterKeys;\n if (!allowedKeys.includes(key as any)) {\n continue;\n }\n if (!value || value === 'false') {\n newValue.delete(key as string);\n } else if (Array.isArray(value)) {\n if (value.length === 0) {\n newValue.delete(key as string);\n } else {\n newValue.set(key as string, value.join(','));\n }\n } else if (typeof value === 'number') {\n newValue.set(key as string, String(value));\n } else if ((value as any).length > 0) {\n newValue.set(key as string, value as any);\n } else {\n newValue.delete(key as string);\n }\n }\n return newValue;\n });\n };\n\n const onSearchQueryChange = (query: string) => {\n onPageChange(1);\n if (query) {\n analytics.captureEvent(`qeta_search_${prefix}`, query);\n }\n setSearchQuery(query);\n };\n\n useDebounce(\n () => {\n if ((filters as any).searchQuery !== searchQuery) {\n setFilters({ ...filters, searchQuery: searchQuery });\n }\n },\n 400,\n [searchQuery],\n );\n\n useEffect(() => {\n let filtersApplied = false;\n searchParams.forEach((value, key) => {\n try {\n if (key === 'page') {\n const pv = Number.parseInt(value, 10);\n if (pv > 0) {\n setPage(pv);\n } else {\n setPage(1);\n setItems([]);\n }\n } else if (key === `${prefix}PerPage`) {\n const qpp = Number.parseInt(value, 10);\n if (qpp > 0) setPageSize(qpp);\n } else if ((filterKeys ?? globalFilterKeys).includes(key as any)) {\n filtersApplied = true;\n if (key === 'tags') {\n (filters as any).tags = filterTags(value.split(',')) ?? [];\n } else if (key === 'entities') {\n (filters as any).entities = value.split(',');\n } else {\n (filters as any)[key] = value;\n }\n }\n } catch (_e) {\n // NOOP\n }\n });\n setFilters(filters);\n if (filtersApplied) {\n setShowFilterPanel(true);\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [searchParams, filterKeys, prefix]);\n\n const {\n value: response,\n loading,\n error,\n retry,\n } = useQetaApi(\n api => {\n return fetch(api, pageSize, (page - 1) * pageSize, filters);\n },\n [page, filters, pageSize, ...(fetchDeps ?? [])],\n );\n\n useEffect(() => {\n if (response) {\n if (page === 1 || usePagination) {\n setItems(response.items);\n } else {\n setItems(prev => {\n const newItems = response.items.filter(\n newItem =>\n !prev.some(prevItem => {\n if (getKey) {\n return getKey(prevItem) === getKey(newItem);\n }\n return (prevItem as any).id === (newItem as any).id;\n }),\n );\n return [...prev, ...newItems];\n });\n }\n setHasMore((response.items ?? []).length >= pageSize);\n setTotal(response.total);\n }\n }, [response, page, pageSize, getKey, usePagination]);\n\n const onPageSizeChange = (value: number) => {\n if (response) {\n let newPage = page;\n while (newPage * value > response.total) {\n newPage -= 1;\n }\n onPageChange(Math.max(1, newPage));\n }\n setPageSize(value);\n setSearchParams(prev => {\n const newValue = prev;\n newValue.set(`${prefix}PerPage`, String(value));\n return newValue;\n });\n };\n\n return {\n page,\n setPage,\n pageSize,\n setPageSize,\n showFilterPanel,\n setShowFilterPanel,\n searchParams,\n setSearchParams,\n searchQuery,\n setSearchQuery,\n filters,\n setFilters,\n onPageChange,\n onPageSizeChange,\n onFilterChange,\n onSearchQueryChange,\n response,\n items:\n (page === 1 || usePagination) && !loading && response\n ? response.items\n : items,\n hasMore,\n total,\n loading,\n error,\n loadNextPage,\n retry,\n fetchNextPage: loadNextPage,\n };\n}\n"],"names":["filterKeys","globalFilterKeys"],"mappings":";;;;;;;;;AA+BO,SAAS,gBAAsB,KAAgC,EAAA;AACpE,EAAM,MAAA;AAAA,IACJ,KAAA;AAAA,IACA,cAAA;AAAA,IACA,MAAA;AAAA,IACA,eAAA;AAAA,gBACAA,YAAA;AAAA,IACA,SAAA;AAAA,IACA,MAAA;AAAA,IACA;AAAA,GACE,GAAA,KAAA;AACJ,EAAA,MAAM,YAAY,YAAa,EAAA;AAC/B,EAAA,MAAM,CAAC,IAAA,EAAM,OAAO,CAAA,GAAI,SAAS,CAAC,CAAA;AAClC,EAAA,MAAM,CAAC,QAAU,EAAA,WAAW,CAAI,GAAA,QAAA,CAAS,mBAAmB,EAAE,CAAA;AAC9D,EAAA,MAAM,EAAE,UAAA,EAAY,UAAW,EAAA,GAAI,eAAgB,EAAA;AACnD,EAAM,MAAA,CAAC,eAAiB,EAAA,kBAAkB,CAAI,GAAA,QAAA;AAAA,IAC5C,UAAW,CAAA,qBAAqB,CAAE,CAAA,MAAM,CAAK,IAAA;AAAA,GAC/C;AACA,EAAA,MAAM,CAAC,YAAA,EAAc,eAAe,CAAA,GAAI,eAAgB,EAAA;AACxD,EAAA,MAAM,CAAC,WAAA,EAAa,cAAc,CAAA,GAAI,SAAS,EAAE,CAAA;AACjD,EAAA,MAAM,CAAC,OAAA,EAAS,UAAU,CAAA,GAAI,SAAY,cAAc,CAAA;AAExD,EAAA,MAAM,CAAC,KAAO,EAAA,QAAQ,CAAI,GAAA,QAAA,CAAc,EAAE,CAAA;AAC1C,EAAA,MAAM,CAAC,OAAA,EAAS,UAAU,CAAA,GAAI,SAAS,IAAI,CAAA;AAC3C,EAAA,MAAM,CAAC,KAAA,EAAO,QAAQ,CAAA,GAAI,SAAS,CAAC,CAAA;AAEpC,EAAA,SAAA,CAAU,MAAM;AACd,IAAA,IAAI,eAAiB,EAAA;AACnB,MAAA,WAAA,CAAY,eAAe,CAAA;AAAA;AAC7B,GACF,EAAG,CAAC,eAAe,CAAC,CAAA;AAEpB,EAAA,SAAA,CAAU,MAAM;AACd,IAAM,MAAA,eAAA,GAAkB,WAAW,qBAAqB,CAAA;AACxD,IAAA,UAAA,CAAW,qBAAuB,EAAA;AAAA,MAChC,GAAG,eAAA;AAAA,MACH,CAAC,MAAM,GAAG;AAAA,KACX,CAAA;AAAA,KACA,CAAC,eAAA,EAAiB,MAAQ,EAAA,UAAA,EAAY,UAAU,CAAC,CAAA;AAEpD,EAAM,MAAA,YAAA,GAAe,CAAC,KAAkB,KAAA;AACtC,IAAA,OAAA,CAAQ,KAAK,CAAA;AACb,IAAA,eAAA,CAAgB,CAAQ,IAAA,KAAA;AACtB,MAAA,MAAM,QAAW,GAAA,IAAA;AACjB,MAAA,QAAA,CAAS,GAAI,CAAA,MAAA,EAAQ,MAAO,CAAA,KAAK,CAAC,CAAA;AAClC,MAAO,OAAA,QAAA;AAAA,KACR,CAAA;AAAA,GACH;AAEA,EAAA,MAAM,eAAe,MAAM;AACzB,IAAQ,OAAA,CAAA,CAAA,IAAA,KAAQ,OAAO,CAAC,CAAA;AAAA,GAC1B;AAEA,EAAM,MAAA,cAAA,GAAiB,CAAC,OAAiD,KAAA;AACvE,IAAA,MAAM,eAAe,KAAM,CAAA,OAAA,CAAQ,OAAO,CAAI,GAAA,OAAA,GAAU,CAAC,OAAO,CAAA;AAChE,IAAA,OAAA,CAAQ,CAAC,CAAA;AACT,IAAA,UAAA,CAAW,CAAQ,IAAA,KAAA;AACjB,MAAM,MAAA,QAAA,GAAW,EAAE,GAAG,IAAK,EAAA;AAC3B,MAAA,KAAA,MAAW,EAAE,GAAA,EAAK,KAAM,EAAA,IAAK,YAAc,EAAA;AACzC,QAAC,QAAA,CAAiB,GAAG,CAAI,GAAA,KAAA;AAAA;AAE3B,MAAO,OAAA,QAAA;AAAA,KACR,CAAA;AACD,IAAA,eAAA,CAAgB,CAAQ,IAAA,KAAA;AACtB,MAAA,MAAM,QAAW,GAAA,IAAA;AACjB,MAAA,KAAA,MAAW,EAAE,GAAA,EAAK,KAAM,EAAA,IAAK,YAAc,EAAA;AACzC,QAAA,MAAM,cAAcA,YAAc,IAAAC,UAAA;AAClC,QAAA,IAAI,CAAC,WAAA,CAAY,QAAS,CAAA,GAAU,CAAG,EAAA;AACrC,UAAA;AAAA;AAEF,QAAI,IAAA,CAAC,KAAS,IAAA,KAAA,KAAU,OAAS,EAAA;AAC/B,UAAA,QAAA,CAAS,OAAO,GAAa,CAAA;AAAA,SACpB,MAAA,IAAA,KAAA,CAAM,OAAQ,CAAA,KAAK,CAAG,EAAA;AAC/B,UAAI,IAAA,KAAA,CAAM,WAAW,CAAG,EAAA;AACtB,YAAA,QAAA,CAAS,OAAO,GAAa,CAAA;AAAA,WACxB,MAAA;AACL,YAAA,QAAA,CAAS,GAAI,CAAA,GAAA,EAAe,KAAM,CAAA,IAAA,CAAK,GAAG,CAAC,CAAA;AAAA;AAC7C,SACF,MAAA,IAAW,OAAO,KAAA,KAAU,QAAU,EAAA;AACpC,UAAA,QAAA,CAAS,GAAI,CAAA,GAAA,EAAe,MAAO,CAAA,KAAK,CAAC,CAAA;AAAA,SAC3C,MAAA,IAAY,KAAc,CAAA,MAAA,GAAS,CAAG,EAAA;AACpC,UAAS,QAAA,CAAA,GAAA,CAAI,KAAe,KAAY,CAAA;AAAA,SACnC,MAAA;AACL,UAAA,QAAA,CAAS,OAAO,GAAa,CAAA;AAAA;AAC/B;AAEF,MAAO,OAAA,QAAA;AAAA,KACR,CAAA;AAAA,GACH;AAEA,EAAM,MAAA,mBAAA,GAAsB,CAAC,KAAkB,KAAA;AAC7C,IAAA,YAAA,CAAa,CAAC,CAAA;AACd,IAAA,IAAI,KAAO,EAAA;AACT,MAAA,SAAA,CAAU,YAAa,CAAA,CAAA,YAAA,EAAe,MAAM,CAAA,CAAA,EAAI,KAAK,CAAA;AAAA;AAEvD,IAAA,cAAA,CAAe,KAAK,CAAA;AAAA,GACtB;AAEA,EAAA,WAAA;AAAA,IACE,MAAM;AACJ,MAAK,IAAA,OAAA,CAAgB,gBAAgB,WAAa,EAAA;AAChD,QAAA,UAAA,CAAW,EAAE,GAAG,OAAS,EAAA,WAAA,EAA0B,CAAA;AAAA;AACrD,KACF;AAAA,IACA,GAAA;AAAA,IACA,CAAC,WAAW;AAAA,GACd;AAEA,EAAA,SAAA,CAAU,MAAM;AACd,IAAA,IAAI,cAAiB,GAAA,KAAA;AACrB,IAAa,YAAA,CAAA,OAAA,CAAQ,CAAC,KAAA,EAAO,GAAQ,KAAA;AACnC,MAAI,IAAA;AACF,QAAA,IAAI,QAAQ,MAAQ,EAAA;AAClB,UAAA,MAAM,EAAK,GAAA,MAAA,CAAO,QAAS,CAAA,KAAA,EAAO,EAAE,CAAA;AACpC,UAAA,IAAI,KAAK,CAAG,EAAA;AACV,YAAA,OAAA,CAAQ,EAAE,CAAA;AAAA,WACL,MAAA;AACL,YAAA,OAAA,CAAQ,CAAC,CAAA;AACT,YAAA,QAAA,CAAS,EAAE,CAAA;AAAA;AACb,SACS,MAAA,IAAA,GAAA,KAAQ,CAAG,EAAA,MAAM,CAAW,OAAA,CAAA,EAAA;AACrC,UAAA,MAAM,GAAM,GAAA,MAAA,CAAO,QAAS,CAAA,KAAA,EAAO,EAAE,CAAA;AACrC,UAAI,IAAA,GAAA,GAAM,CAAG,EAAA,WAAA,CAAY,GAAG,CAAA;AAAA,SAClB,MAAA,IAAA,CAAAD,YAAA,IAAcC,UAAkB,EAAA,QAAA,CAAS,GAAU,CAAG,EAAA;AAChE,UAAiB,cAAA,GAAA,IAAA;AACjB,UAAA,IAAI,QAAQ,MAAQ,EAAA;AAClB,YAAC,OAAA,CAAgB,OAAO,UAAW,CAAA,KAAA,CAAM,MAAM,GAAG,CAAC,KAAK,EAAC;AAAA,WAC3D,MAAA,IAAW,QAAQ,UAAY,EAAA;AAC7B,YAAC,OAAgB,CAAA,QAAA,GAAW,KAAM,CAAA,KAAA,CAAM,GAAG,CAAA;AAAA,WACtC,MAAA;AACL,YAAC,OAAA,CAAgB,GAAG,CAAI,GAAA,KAAA;AAAA;AAC1B;AACF,eACO,EAAI,EAAA;AAAA;AAEb,KACD,CAAA;AACD,IAAA,UAAA,CAAW,OAAO,CAAA;AAClB,IAAA,IAAI,cAAgB,EAAA;AAClB,MAAA,kBAAA,CAAmB,IAAI,CAAA;AAAA;AACzB,GAEC,EAAA,CAAC,YAAc,EAAAD,YAAA,EAAY,MAAM,CAAC,CAAA;AAErC,EAAM,MAAA;AAAA,IACJ,KAAO,EAAA,QAAA;AAAA,IACP,OAAA;AAAA,IACA,KAAA;AAAA,IACA;AAAA,GACE,GAAA,UAAA;AAAA,IACF,CAAO,GAAA,KAAA;AACL,MAAA,OAAO,MAAM,GAAK,EAAA,QAAA,EAAA,CAAW,IAAO,GAAA,CAAA,IAAK,UAAU,OAAO,CAAA;AAAA,KAC5D;AAAA,IACA,CAAC,IAAM,EAAA,OAAA,EAAS,UAAU,GAAI,SAAA,IAAa,EAAG;AAAA,GAChD;AAEA,EAAA,SAAA,CAAU,MAAM;AACd,IAAA,IAAI,QAAU,EAAA;AACZ,MAAI,IAAA,IAAA,KAAS,KAAK,aAAe,EAAA;AAC/B,QAAA,QAAA,CAAS,SAAS,KAAK,CAAA;AAAA,OAClB,MAAA;AACL,QAAA,QAAA,CAAS,CAAQ,IAAA,KAAA;AACf,UAAM,MAAA,QAAA,GAAW,SAAS,KAAM,CAAA,MAAA;AAAA,YAC9B,CACE,OAAA,KAAA,CAAC,IAAK,CAAA,IAAA,CAAK,CAAY,QAAA,KAAA;AACrB,cAAA,IAAI,MAAQ,EAAA;AACV,gBAAA,OAAO,MAAO,CAAA,QAAQ,CAAM,KAAA,MAAA,CAAO,OAAO,CAAA;AAAA;AAE5C,cAAQ,OAAA,QAAA,CAAiB,OAAQ,OAAgB,CAAA,EAAA;AAAA,aAClD;AAAA,WACL;AACA,UAAA,OAAO,CAAC,GAAG,IAAM,EAAA,GAAG,QAAQ,CAAA;AAAA,SAC7B,CAAA;AAAA;AAEH,MAAA,UAAA,CAAA,CAAY,QAAS,CAAA,KAAA,IAAS,EAAC,EAAG,UAAU,QAAQ,CAAA;AACpD,MAAA,QAAA,CAAS,SAAS,KAAK,CAAA;AAAA;AACzB,KACC,CAAC,QAAA,EAAU,MAAM,QAAU,EAAA,MAAA,EAAQ,aAAa,CAAC,CAAA;AAEpD,EAAM,MAAA,gBAAA,GAAmB,CAAC,KAAkB,KAAA;AAC1C,IAAA,IAAI,QAAU,EAAA;AACZ,MAAA,IAAI,OAAU,GAAA,IAAA;AACd,MAAO,OAAA,OAAA,GAAU,KAAQ,GAAA,QAAA,CAAS,KAAO,EAAA;AACvC,QAAW,OAAA,IAAA,CAAA;AAAA;AAEb,MAAA,YAAA,CAAa,IAAK,CAAA,GAAA,CAAI,CAAG,EAAA,OAAO,CAAC,CAAA;AAAA;AAEnC,IAAA,WAAA,CAAY,KAAK,CAAA;AACjB,IAAA,eAAA,CAAgB,CAAQ,IAAA,KAAA;AACtB,MAAA,MAAM,QAAW,GAAA,IAAA;AACjB,MAAA,QAAA,CAAS,IAAI,CAAG,EAAA,MAAM,CAAW,OAAA,CAAA,EAAA,MAAA,CAAO,KAAK,CAAC,CAAA;AAC9C,MAAO,OAAA,QAAA;AAAA,KACR,CAAA;AAAA,GACH;AAEA,EAAO,OAAA;AAAA,IACL,IAAA;AAAA,IACA,OAAA;AAAA,IACA,QAAA;AAAA,IACA,WAAA;AAAA,IACA,eAAA;AAAA,IACA,kBAAA;AAAA,IACA,YAAA;AAAA,IACA,eAAA;AAAA,IACA,WAAA;AAAA,IACA,cAAA;AAAA,IACA,OAAA;AAAA,IACA,UAAA;AAAA,IACA,YAAA;AAAA,IACA,gBAAA;AAAA,IACA,cAAA;AAAA,IACA,mBAAA;AAAA,IACA,QAAA;AAAA,IACA,KAAA,EAAA,CACG,SAAS,CAAK,IAAA,aAAA,KAAkB,CAAC,OAAW,IAAA,QAAA,GACzC,SAAS,KACT,GAAA,KAAA;AAAA,IACN,OAAA;AAAA,IACA,KAAA;AAAA,IACA,OAAA;AAAA,IACA,KAAA;AAAA,IACA,YAAA;AAAA,IACA,KAAA;AAAA,IACA,aAAe,EAAA;AAAA,GACjB;AACF;;;;"}
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import { useApi, storageApiRef } from '@backstage/core-plugin-api';
|
|
2
|
+
import { useState, useRef, useEffect, useCallback } from 'react';
|
|
3
|
+
|
|
4
|
+
const DEFAULT_SETTINGS = {
|
|
5
|
+
autoSaveEnabled: false,
|
|
6
|
+
filterPanelExpanded: {},
|
|
7
|
+
viewType: {},
|
|
8
|
+
aiAnswerExpanded: false,
|
|
9
|
+
usePagination: false
|
|
10
|
+
};
|
|
11
|
+
const BUCKET_KEY = "qeta";
|
|
12
|
+
const STORAGE_KEY = "qeta-user-settings";
|
|
13
|
+
const useUserSettings = () => {
|
|
14
|
+
const storageApi = useApi(storageApiRef);
|
|
15
|
+
const [settings, setSettings] = useState(DEFAULT_SETTINGS);
|
|
16
|
+
const [isLoaded, setIsLoaded] = useState(false);
|
|
17
|
+
const settingsRef = useRef(DEFAULT_SETTINGS);
|
|
18
|
+
useEffect(() => {
|
|
19
|
+
settingsRef.current = settings;
|
|
20
|
+
}, [settings]);
|
|
21
|
+
useEffect(() => {
|
|
22
|
+
const bucket = storageApi.forBucket(BUCKET_KEY);
|
|
23
|
+
const snapshot = bucket.snapshot(STORAGE_KEY);
|
|
24
|
+
const stored = snapshot.value;
|
|
25
|
+
if (stored) {
|
|
26
|
+
setSettings(stored);
|
|
27
|
+
}
|
|
28
|
+
setIsLoaded(true);
|
|
29
|
+
const subscription = bucket.observe$(STORAGE_KEY).subscribe({
|
|
30
|
+
next: (newSnapshot) => {
|
|
31
|
+
const value = newSnapshot.value;
|
|
32
|
+
if (value) {
|
|
33
|
+
setSettings(value);
|
|
34
|
+
} else {
|
|
35
|
+
setSettings(DEFAULT_SETTINGS);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
});
|
|
39
|
+
return () => {
|
|
40
|
+
subscription.unsubscribe();
|
|
41
|
+
};
|
|
42
|
+
}, [storageApi]);
|
|
43
|
+
const updateSettings = useCallback(
|
|
44
|
+
async (updates) => {
|
|
45
|
+
const bucket = storageApi.forBucket(BUCKET_KEY);
|
|
46
|
+
const snapshot = bucket.snapshot(STORAGE_KEY);
|
|
47
|
+
const currentSettings = snapshot.value || DEFAULT_SETTINGS;
|
|
48
|
+
const newSettings = {
|
|
49
|
+
...currentSettings,
|
|
50
|
+
...updates
|
|
51
|
+
};
|
|
52
|
+
await bucket.set(STORAGE_KEY, newSettings);
|
|
53
|
+
},
|
|
54
|
+
[storageApi]
|
|
55
|
+
);
|
|
56
|
+
const getSetting = useCallback(
|
|
57
|
+
(key) => {
|
|
58
|
+
return settingsRef.current[key];
|
|
59
|
+
},
|
|
60
|
+
[]
|
|
61
|
+
);
|
|
62
|
+
const setSetting = useCallback(
|
|
63
|
+
async (key, value) => {
|
|
64
|
+
await updateSettings({ [key]: value });
|
|
65
|
+
},
|
|
66
|
+
[updateSettings]
|
|
67
|
+
);
|
|
68
|
+
const resetSettings = useCallback(async () => {
|
|
69
|
+
const bucket = storageApi.forBucket("qeta");
|
|
70
|
+
await bucket.set(STORAGE_KEY, DEFAULT_SETTINGS);
|
|
71
|
+
}, [storageApi]);
|
|
72
|
+
return {
|
|
73
|
+
settings,
|
|
74
|
+
updateSettings,
|
|
75
|
+
getSetting,
|
|
76
|
+
setSetting,
|
|
77
|
+
resetSettings,
|
|
78
|
+
isLoaded
|
|
79
|
+
};
|
|
80
|
+
};
|
|
81
|
+
|
|
82
|
+
export { useUserSettings };
|
|
83
|
+
//# sourceMappingURL=useUserSettings.esm.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useUserSettings.esm.js","sources":["../../src/hooks/useUserSettings.ts"],"sourcesContent":["import { useApi } from '@backstage/core-plugin-api';\nimport { storageApiRef } from '@backstage/core-plugin-api';\nimport { useCallback, useEffect, useRef, useState } from 'react';\nimport { ViewType } from '../components/ViewToggle/ViewToggle';\n\nexport type UserSettings = {\n autoSaveEnabled: boolean;\n filterPanelExpanded: Record<string, boolean>;\n viewType: Record<string, ViewType>;\n aiAnswerExpanded: boolean;\n usePagination: boolean;\n};\n\nconst DEFAULT_SETTINGS: UserSettings = {\n autoSaveEnabled: false,\n filterPanelExpanded: {},\n viewType: {},\n aiAnswerExpanded: false,\n usePagination: false,\n};\n\nconst BUCKET_KEY = 'qeta';\nconst STORAGE_KEY = 'qeta-user-settings';\n\nexport const useUserSettings = () => {\n const storageApi = useApi(storageApiRef);\n const [settings, setSettings] = useState<UserSettings>(DEFAULT_SETTINGS);\n const [isLoaded, setIsLoaded] = useState(false);\n const settingsRef = useRef<UserSettings>(DEFAULT_SETTINGS);\n\n useEffect(() => {\n settingsRef.current = settings;\n }, [settings]);\n\n useEffect(() => {\n const bucket = storageApi.forBucket(BUCKET_KEY);\n const snapshot = bucket.snapshot(STORAGE_KEY);\n const stored = snapshot.value as UserSettings | undefined;\n\n if (stored) {\n setSettings(stored);\n }\n\n setIsLoaded(true);\n\n const subscription = bucket.observe$<UserSettings>(STORAGE_KEY).subscribe({\n next: newSnapshot => {\n const value = newSnapshot.value as UserSettings | undefined;\n if (value) {\n setSettings(value);\n } else {\n setSettings(DEFAULT_SETTINGS);\n }\n },\n });\n\n return () => {\n subscription.unsubscribe();\n };\n }, [storageApi]);\n\n const updateSettings = useCallback(\n async (updates: Partial<UserSettings>) => {\n const bucket = storageApi.forBucket(BUCKET_KEY);\n const snapshot = bucket.snapshot(STORAGE_KEY);\n const currentSettings =\n (snapshot.value as UserSettings) || DEFAULT_SETTINGS;\n const newSettings = {\n ...currentSettings,\n ...(updates as Partial<UserSettings>),\n };\n await bucket.set(STORAGE_KEY, newSettings);\n },\n [storageApi],\n );\n\n const getSetting = useCallback(\n <K extends keyof UserSettings>(key: K): UserSettings[K] => {\n return settingsRef.current[key];\n },\n [],\n );\n\n const setSetting = useCallback(\n async <K extends keyof UserSettings>(\n key: K,\n value: UserSettings[K],\n ): Promise<void> => {\n await updateSettings({ [key]: value } as Partial<UserSettings>);\n },\n [updateSettings],\n );\n\n const resetSettings = useCallback(async () => {\n const bucket = storageApi.forBucket('qeta');\n await bucket.set(STORAGE_KEY, DEFAULT_SETTINGS);\n }, [storageApi]);\n\n return {\n settings,\n updateSettings,\n getSetting,\n setSetting,\n resetSettings,\n isLoaded,\n };\n};\n"],"names":[],"mappings":"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"}
|