From a5bb3fe60f3110c6c7d87fae84b8125778314030 Mon Sep 17 00:00:00 2001 From: Staples1010 Date: Fri, 9 Aug 2024 21:11:39 +0100 Subject: [PATCH] Created minimal config for Linkwarden --- docs/widgets/services/linkwarden.md | 44 ------ src/widgets/linkwarden/component.jsx | 227 +-------------------------- src/widgets/linkwarden/widget.js | 3 - 3 files changed, 8 insertions(+), 266 deletions(-) diff --git a/docs/widgets/services/linkwarden.md b/docs/widgets/services/linkwarden.md index d5a9fb27..bef196a9 100644 --- a/docs/widgets/services/linkwarden.md +++ b/docs/widgets/services/linkwarden.md @@ -13,47 +13,3 @@ widget: url: http://linkwarden.host.or.ip key: myApiKeyHere # On your Linkwarden install, go to Settings > Access Tokens. Generate a token. ``` - -Use `mode` to show a list of recent bookmarks. - -```yaml -widget: - type: linkwarden - url: http://linkwarden.host.or.ip - key: myApiKeyHere - mode: ["recent"] -``` - -Use `params` to set which collections and/or tags to display links from. - -Examples: - -```yaml -params: - collectionIds: ["8", "13", "6"] # ID's of collections -``` - -or - -```yaml -params: - tagIds: ["84", "66", "88", "69"] # ID's of tags -``` - -or - -```yaml -params: - collectionIds: ["8", "13", "6"] # ID's of collections - tagIds: ["84", "66", "88", "69"] # ID's of tags -``` - -```yaml -widget: - type: linkwarden - url: http://linkwarden.host.or.ip - key: myApiKeyHere - params: - collectionIds: ["8", "13", "6"] # ID's of collections - tagIds: ["84", "66", "88", "69"] # ID's of tags -``` diff --git a/src/widgets/linkwarden/component.jsx b/src/widgets/linkwarden/component.jsx index b11e9b14..657d8b11 100644 --- a/src/widgets/linkwarden/component.jsx +++ b/src/widgets/linkwarden/component.jsx @@ -1,4 +1,4 @@ -import React, { useState, useEffect, useMemo, useCallback } from "react"; +import React, { useState, useEffect } from "react"; import Container from "components/services/widget/container"; import Block from "components/services/widget/block"; @@ -7,39 +7,13 @@ import useWidgetAPI from "utils/proxy/use-widget-api"; export default function Component({ service }) { const { widget } = service; - // Assign icons. Assign recent/collections/tags to query by id(s) - const bookmarkTypes = useMemo( - () => ({ - recent: { ids: widget.mode?.includes("recent") ? ["0"] : [] }, // "0" Is a made-up number used to allow looping in processBookmarks() - collection: { - ids: widget.params?.collectionIds ? widget.params.collectionIds : [], - }, - tag: { ids: widget.params?.tagIds ? widget.params.tagIds : [] }, - }), - [widget], - ); - // State to hold Stats const [stats, setStats] = useState({ totalLinks: null, - collections: { list: null, total: null }, - tags: { list: null, total: null }, + collections: { total: null }, + tags: { total: null }, }); - // State to hold Recent/Collection/Tag Bookmarks - const [bookmarks, setBookmarks] = useState({ - recent: { icon: "📚️", data: {} }, - collection: { icon: "📁", data: {} }, - tag: { icon: "🏷️", data: {} }, - }); - - const [fetchingMore, setFetchingMore] = useState({ - recent: {}, - collection: {}, - tag: {}, - }); - const [error, setError] = useState(null); - const { data: collectionsStatsData, error: collectionsStatsError } = useWidgetAPI(widget, "collections"); // Fetch Collection Stats const { data: tagsStatsData, error: tagsStatsError } = useWidgetAPI(widget, "tags"); // Fetch Tag Stats @@ -50,11 +24,9 @@ export default function Component({ service }) { setStats({ totalLinks: collectionsStatsData.response.reduce((sum, collection) => sum + (collection._count?.links || 0), 0), collections: { - list: collectionsStatsData.response, total: collectionsStatsData.response.length, }, tags: { - list: tagsStatsData.response, total: tagsStatsData.response.length, }, }); @@ -62,199 +34,16 @@ export default function Component({ service }) { } }, [collectionsStatsData, tagsStatsData]); - // Reusable function to fetch bookmarks based on ids.recent/ids.collection/ids.tag and type - const fetchBookmarks = useCallback(async (ids, type, cursor, currentWidget) => { - try { - const promises = ids.map(async (id) => { - const baseQuery = { sort: 0, cursor: cursor || "" }; - const query = type === "recent" ? baseQuery : { ...baseQuery, [`${type}Id`]: id }; - - const queryParams = new URLSearchParams({ - group: currentWidget.service_group, - service: currentWidget.service_name, - endpoint: "links", - query: JSON.stringify(query), - }); - - const response = await fetch(`/api/services/proxy?${queryParams}`); - if (!response.ok) { - if (response.status === 401) { - setError("Unauthorized access. Please log in again."); - } else { - setError(`HTTP error! Status: ${response.status}`); - } - throw new Error(`HTTP error! Status: ${response.status}`); - } - return { id, bookmarks: await response.json() }; - }); - - return await Promise.all(promises); - } catch (fetchError) { - setError("An error occurred while fetching bookmarks."); - return []; - } - }, []); - - const processBookmarks = useCallback( - async (ids, type, cursor, currentWidget, currentStats, updateBookmarks, append = false) => { - try { - const fetchedBookmarks = await fetchBookmarks(ids, type, cursor, currentWidget); - updateBookmarks((prev) => { - const newBookmarks = fetchedBookmarks.map((item) => ({ - id: item.id, - title: - type === "recent" - ? "Recent Bookmarks" - : currentStats[`${type}s`]?.list?.find((statItem) => statItem.id.toString() === item.id)?.name || - item.id, - url: `${currentWidget.url}${type === "recent" ? "/links/" : `/${type}s/${item.id}/`}`, - /* eslint-disable no-underscore-dangle */ - total: - type === "recent" - ? currentStats.totalLinks - : currentStats[`${type}s`]?.list?.find((foundStatItem) => foundStatItem.id.toString() === item.id) - ?._count?.links || 0, - /* eslint-enable no-underscore-dangle */ - cursor: item.bookmarks.response.length - ? item.bookmarks.response[item.bookmarks.response.length - 1]?.id - : "end", - bookmarks: append - ? [...(prev[type].data[item.id]?.bookmarks || []), ...item.bookmarks.response] - : item.bookmarks.response, - })); - - return { - ...prev, - [type]: { - ...prev[type], - data: { - ...prev[type].data, - ...Object.fromEntries(newBookmarks.map((bookmark) => [bookmark.id, bookmark])), - }, - }, - }; - }); - } catch (processError) { - const errorMessage = `Error setting ${type} bookmarks: ${processError.message}`; - setError(errorMessage); - } - }, - [fetchBookmarks], - ); - - // Effect to fetch and update Recent/Collection/Tag Bookmarks - useEffect(() => { - if (error) return; // Stop fetching if there's an error - - const fetchAndProcessBookmarks = async () => { - try { - const bookmarkFetchPromises = Object.entries(bookmarkTypes) - .filter(([type, { ids }]) => ids.length > 0 && Object.keys(bookmarks[type].data).length === 0) - .map(async ([type, { ids }]) => { - // Process bookmarks for each type - await processBookmarks(ids, type, null, widget, stats, setBookmarks); - }); - - await Promise.all(bookmarkFetchPromises); - } catch (fetchError) { - setError(`Error processing bookmarks: ${fetchError.message}`); - } - }; - - fetchAndProcessBookmarks(); - }, [bookmarkTypes, processBookmarks, widget, stats, bookmarks, error]); - - const handleScroll = async (event, id, type, cursor) => { - const { scrollTop, scrollHeight, clientHeight } = event.target; - if (scrollHeight - scrollTop <= clientHeight + 1 && cursor !== "end") { - if (!fetchingMore[type][id]) { - setFetchingMore((prev) => ({ - ...prev, - [type]: { ...prev[type], [id]: true }, - })); - try { - await processBookmarks([id], type, cursor, widget, stats, setBookmarks, true); - } finally { - setFetchingMore((prev) => ({ - ...prev, - [type]: { ...prev[type], [id]: false }, - })); - } - } - } - }; - - // Handle errors - if (error) { - return ; - } if (collectionsStatsError || tagsStatsError) { return ; } // Render when data is available return ( - <> - - - - - - - {Object.keys(bookmarks).map((type) => { - const dataAvailable = Object.keys(bookmarks[type].data).length > 0; - - return dataAvailable ? ( -
- {Object.values(bookmarks[type].data).map((bookmarkList) => ( -
- -
    handleScroll(e, bookmarkList.id, type, bookmarkList.cursor)} - > - {Object.values(bookmarkList.bookmarks).map(({ id, url, name, description }) => ( -
  • - - 🔗 -
    -
    - {name || description} -
    -
    - {url} -
    -
    -
    -
  • - ))} - {fetchingMore[type][bookmarkList.id] && ( -
  • - Loading more... -
  • - )} -
-
- ))} -
- ) : null; // Render nothing if there's no data - })} - + + + + + ); } diff --git a/src/widgets/linkwarden/widget.js b/src/widgets/linkwarden/widget.js index 7ca05e21..decc726e 100644 --- a/src/widgets/linkwarden/widget.js +++ b/src/widgets/linkwarden/widget.js @@ -11,9 +11,6 @@ const widget = { tags: { endpoint: "tags", }, - links: { - endpoint: "links", - }, }, };