Skip to content

Commit

Permalink
add JSDoc and README for cs-ui-lib (#323)
Browse files Browse the repository at this point in the history
Co-authored-by: feederbox826 <[email protected]>
  • Loading branch information
feederbox826 and feederbox826 authored Jun 3, 2024
1 parent 7eb37b4 commit 8d3631a
Show file tree
Hide file tree
Showing 2 changed files with 137 additions and 5 deletions.
70 changes: 70 additions & 0 deletions plugins/CommunityScriptsUILibrary/README.md
Original file line number Diff line number Diff line change
@@ -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
72 changes: 67 additions & 5 deletions plugins/CommunityScriptsUILibrary/cs-ui-lib.js
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand All @@ -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))
Expand All @@ -41,6 +102,7 @@

// export to window
window.csLib = {
baseURL,
callGQL,
getConfiguration,
waitForElement,
Expand Down

0 comments on commit 8d3631a

Please sign in to comment.