From 8d3631a12c34837ffb3e8f7a73419f91da09a60e Mon Sep 17 00:00:00 2001 From: feederbox826 <144178721+feederbox826@users.noreply.github.com> Date: Mon, 3 Jun 2024 17:01:42 -0400 Subject: [PATCH] add JSDoc and README for cs-ui-lib (#323) Co-authored-by: feederbox826 --- plugins/CommunityScriptsUILibrary/README.md | 70 ++++++++++++++++++ .../CommunityScriptsUILibrary/cs-ui-lib.js | 72 +++++++++++++++++-- 2 files changed, 137 insertions(+), 5 deletions(-) create mode 100644 plugins/CommunityScriptsUILibrary/README.md diff --git a/plugins/CommunityScriptsUILibrary/README.md b/plugins/CommunityScriptsUILibrary/README.md new file mode 100644 index 00000000..b03c56b3 --- /dev/null +++ b/plugins/CommunityScriptsUILibrary/README.md @@ -0,0 +1,70 @@ +# CommunityScripts UI Plugin library + +This is a set of slimmed down functions from StashUserscriptLibrary, targeting CommunityScripts originally introduced in [#319](https://github.com/stashapp/CommunityScripts/pull/319) + + +## functions +All the following functions are exposed under `window.csLib` and `csLib` + +## callGQL +```js +/** + * This is a wrapped GraphQL (GQL) query caller + * @param {...Object} reqData + * @param {Object} reqData.query - GraphQL query + * @param {Object}= reqData.variables - GraphQL variables + * @returns {Object} - GQL response data with the `data` wrapper removed + * + * @example + * // fetch the count of organized scenes + * const filter = { organized: true }; + * const query = `query findScenes($filter: SceneFilter) { findScenes(filter: $filter) { count } }`; + * const variables = { filter }; + * const response = await callGQL({ query, variables }); + * // response = { findScenes: { count: 3 } } + */ +``` + +## getConfiguration +```js +/** + * Get configuration of a plugin from the server via GraphQL + * @param {string} pluginId - The ID of the plugin as it is registered in the server + * @param {*}= fallback - Fallback value if the configuration is not found. Defaults to an empty object + * @returns {Object} - The configuration object of the plugin as it is stored in the server + * + * @example + * // set default config + * const defaultConfig = { enabled: true, theme: 'light' }; + * // fetch config from the server + * const config = await getConfiguration('CommunityScriptsUIPlugin', defaultConfig); + * // config = { theme: 'dark' } + * // merge fetched with default config + * const pluginConfig = { + * ...defaultConfig + * ...config + * }; + * // pluginConfig = { enabled: true, theme: 'dark' } + * } + */ +``` + +## waitForElement +```js + /** + * Waits for an element to be available in the DOM and runs the callback function once it is + * @param {string} selector - The CSS selector of the element to wait for + * @param {function} callback - The function to be called once the element is available (with the element as an argument) + * @returns + * + * @example + * // wait for the element with the class 'my-element' to be available + * // and change its color to red + * function myCallback(el) { + * el.style.color = 'red'; + * }; + * waitForElement('.my-element', myCallback); + */ +``` + +## pathElementListener \ No newline at end of file diff --git a/plugins/CommunityScriptsUILibrary/cs-ui-lib.js b/plugins/CommunityScriptsUILibrary/cs-ui-lib.js index a403b6c0..90902142 100644 --- a/plugins/CommunityScriptsUILibrary/cs-ui-lib.js +++ b/plugins/CommunityScriptsUILibrary/cs-ui-lib.js @@ -4,7 +4,21 @@ // get base URL for graphQL queries const baseURL = document.querySelector("base")?.getAttribute("href") ?? "/"; - // call GQL query, returns data without `data` wrapper + /** + * This is a wrapped GraphQL (GQL) query caller + * @param {...Object} reqData + * @param {Object} reqData.query - GraphQL query + * @param {Object}= reqData.variables - GraphQL variables + * @returns {Object} - GQL response data with the `data` wrapper removed + * + * @example + * // fetch the count of organized scenes + * const filter = { organized: true }; + * const query = `query findScenes($filter: SceneFilter) { findScenes(filter: $filter) { count } }`; + * const variables = { filter }; + * const response = await callGQL({ query, variables }); + * // response = { findScenes: { count: 3 } } + */ const callGQL = (reqData) => fetch(`${baseURL}graphql`, { method: "POST", @@ -14,21 +28,68 @@ .then((res) => res.json()) .then((res) => res.data); - // get configuration via GQL - const getConfiguration = async (pluginId, fallback) => { + /** + * Get configuration of a plugin from the server via GraphQL + * @param {string} pluginId - The ID of the plugin as it is registered in the server + * @param {*}= fallback - Fallback value if the configuration is not found. Defaults to an empty object + * @returns {Object} - The configuration object of the plugin as it is stored in the server + * + * @example + * // set default config + * const defaultConfig = { enabled: true, theme: 'light' }; + * // fetch config from the server + * const config = await getConfiguration('CommunityScriptsUIPlugin', defaultConfig); + * // config = { theme: 'dark' } + * // merge fetched with default config + * const pluginConfig = { + * ...defaultConfig + * ...config + * }; + * // pluginConfig = { enabled: true, theme: 'dark' } + * } + */ + const getConfiguration = async (pluginId, fallback = {}) => { const query = `query Configuration { configuration { plugins }}`; const response = await callGQL({ query }); return response.configuration.plugins?.[pluginId] ?? fallback; }; - // wait for key elements + /** + * Waits for an element to be available in the DOM and runs the callback function once it is + * @param {string} selector - The CSS selector of the element to wait for + * @param {function} callback - The function to be called once the element is available (with the element as an argument) + * @returns + * + * @example + * // wait for the element with the class 'my-element' to be available + * // and change its color to red + * function myCallback(el) { + * el.style.color = 'red'; + * }; + * waitForElement('.my-element', myCallback); + */ function waitForElement(selector, callback) { var el = document.querySelector(selector); if (el) return callback(el); setTimeout(waitForElement, 100, selector, callback); } - // wait for a path match, then for key elements + /** + * Wait for a specific element to be available on a specific path + * This combines the `waitForElement` and `PluginApi.Event.addEventListener` functions to only trigger on certain pages + * + * @param {string} path - The path to listen for + * @param {string} element - The CSS selector of the element to wait for + * @param {function} callback - The function to be called once the element is available (with the element as an argument) + * + * @example + * // wait for the element with the class 'my-element' to be available, but only on the `/scene/#` path + * function myCallback(el) { + * el.style.color = 'red'; + * }; + * PathElementListener('/scene/', '.my-element', myCallback); + * // this will only trigger the callback function when the user is on the `/scene/` path AND the element is available + */ const PathElementListener = (path, element, callback) => { // startup location if (window.location.pathname.startsWith(path)) @@ -41,6 +102,7 @@ // export to window window.csLib = { + baseURL, callGQL, getConfiguration, waitForElement,