[ADD] JS functions to the AA framework

This commit is contained in:
Peter Pfeufer 2025-08-08 18:36:30 +02:00
parent e68793f363
commit 18e9453fed
No known key found for this signature in database
5 changed files with 326 additions and 0 deletions

View File

@ -0,0 +1,219 @@
/* jshint -W097 */
'use strict';
/**
* Checks if the given item is an array.
*
* @usage
* ```javascript
* if (isArray(someVariable)) {
* console.log('This is an array');
* } else {
* console.log('This is not an array');
* }
* ```
*
* @param {*} item - The item to check.
* @returns {boolean} True if the item is an array, false otherwise.
*/
const isArray = (item) => {
return Array.isArray(item);
};
/**
* Checks if the given item is a plain object, excluding arrays and dates.
*
* @usage
* ```javascript
* if (isObject(someVariable)) {
* console.log('This is a plain object');
* } else {
* console.log('This is not a plain object');
* }
* ```
*
* @param {*} item - The item to check.
* @returns {boolean} True if the item is a plain object, false otherwise.
*/
const isObject = (item) => {
return (
item && typeof item === 'object' && !isArray(item) && !(item instanceof Date)
);
};
/**
* Fetch data from an ajax URL
*
* Do not call this function directly, use `fetchGet` or `fetchPost` instead.
*
* @param {string} url The URL to fetch data from
* @param {string} method The HTTP method to use for the request (default: 'get')
* @param {string|null} csrfToken The CSRF token to include in the request headers (default: null)
* @param {string|null} payload The payload (JSON|Object) to send with the request (default: null)
* @param {boolean} responseIsJson Whether the response is expected to be JSON or not (default: true)
* @returns {Promise<string>} The fetched data
* @throws {Error} Throws an error when:
* - The method is not valid (only `get` and `post` are allowed).
* - The CSRF token is required but not provided for POST requests.
* - The payload is not an object when using POST method.
* - The response status is not OK (HTTP 200-299).
* - There is a network error or if the response cannot be parsed as JSON.
*/
const _fetchAjaxData = async ({
url,
method = 'get',
csrfToken = null,
payload = null,
responseIsJson = true
}) => {
const normalizedMethod = method.toLowerCase();
// Validate the method
const validMethods = ['get', 'post'];
if (!validMethods.includes(normalizedMethod)) {
throw new Error(`Invalid method: ${method}. Valid methods are: get, post`);
}
const headers = {};
// Set headers based on response type
if (responseIsJson) {
headers['Accept'] = 'application/json'; // jshint ignore:line
headers['Content-Type'] = 'application/json';
}
let requestUrl = url;
let body = null;
if (normalizedMethod === 'post') {
if (!csrfToken) {
throw new Error('CSRF token is required for POST requests');
}
headers['X-CSRFToken'] = csrfToken;
if (payload !== null && !isObject(payload)) {
throw new Error('Payload must be an object when using POST method');
}
body = payload ? JSON.stringify(payload) : null;
} else if (normalizedMethod === 'get' && payload) {
const queryParams = new URLSearchParams(payload).toString(); // jshint ignore:line
requestUrl += (url.includes('?') ? '&' : '?') + queryParams;
}
/**
* Throws an error with a formatted message.
*
* @param {Response} response The error object containing the message to throw.
*/
const throwHTTPStatusError = (response) => {
throw new Error(`Error: ${response.status} - ${response.statusText}`);
};
try {
const response = await fetch(requestUrl, {
method: method.toUpperCase(),
headers: headers,
body: body
});
/**
* Throws an error if the response status is not OK (HTTP 200-299).
* This is used to handle HTTP errors gracefully.
*/
if (!response.ok) {
throwHTTPStatusError(response);
}
return responseIsJson ? await response.json() : await response.text();
} catch (error) {
// Log the error message to the console
console.log(`Error: ${error.message}`);
throw error;
}
};
/**
* Fetch data from an ajax URL using the GET method.
* This function is a wrapper around _fetchAjaxData to simplify GET requests.
*
* @usage
* ```javascript
* fetchGet({
* url: url,
* responseIsJson: false
* }).then((data) => {
* // Process the fetched data
* }).catch((error) => {
* console.error(`Error: ${error.message}`);
*
* // Handle the error appropriately
* });
* ```
*
* @param {string} url The URL to fetch data from
* @param {string|null} payload The payload (JSON) to send with the request (default: null)
* @param {boolean} responseIsJson Whether the response is expected to be JSON or not (default: true)
* @return {Promise<string>} The fetched data
*/
const fetchGet = ({
url,
payload = null,
responseIsJson = true
}) => {
return _fetchAjaxData({
url: url,
method: 'get',
payload: payload,
responseIsJson: responseIsJson
});
};
/**
* Fetch data from an ajax URL using the POST method.
* This function is a wrapper around _fetchAjaxData to simplify POST requests.
* It requires a CSRF token for security purposes.
*
* @usage
* ```javascript
* fetchPost({
* url: url,
* csrfToken: csrfToken,
* payload: {
* key: 'value',
* anotherKey: 'anotherValue'
* },
* responseIsJson: true
* }).then((data) => {
* // Process the fetched data
* }).catch((error) => {
* console.error(`Error: ${error.message}`);
*
* // Handle the error appropriately
* });
* ```
*
* @param {string} url The URL to fetch data from
* @param {string|null} csrfToken The CSRF token to include in the request headers (default: null)
* @param {string|null} payload The payload (JSON) to send with the request (default: null)
* @param {boolean} responseIsJson Whether the response is expected to be JSON or not (default: true)
* @return {Promise<string>} The fetched data
*/
const fetchPost = ({
url,
csrfToken,
payload = null,
responseIsJson = true
}) => {
return _fetchAjaxData({
url: url,
method: 'post',
csrfToken: csrfToken,
payload: payload,
responseIsJson: responseIsJson
});
};

View File

@ -21,6 +21,7 @@
{% theme_css %}
{% include 'bundles/fontawesome.html' %}
{% include 'bundles/auth-framework-js.html' %}
{% include 'bundles/auth-framework-css.html' %}
<style>

View File

@ -0,0 +1,3 @@
{% load sri %}
{% sri_static 'allianceauth/framework/js/auth-framework.js' %}

View File

@ -13,5 +13,6 @@ The Alliance Auth framework is split into several submodules, each of which is d
framework/api
framework/css
framework/js
framework/templates
:::

View File

@ -0,0 +1,102 @@
# JavaScript Framework
This contains some simple JavaScript functions that are used throughout Alliance Auth,
so they can be used by community app developers as well.
The JS file is already loaded in the base template, so it is globally available.
## Functions
The following functions are available in the JavaScript framework:
### `isArray()`
Checks if the given value is an array.
Usage:
```javascript
/* global isArray */
if (isArray(someVariable)) {
console.log('This is an array');
} else {
console.log('This is not an array');
}
```
### `isObject()`
Checks if the given value is an object.
Usage:
```javascript
/* global isObject */
if (isObject(someVariable)) {
console.log('This is a plain object');
} else {
console.log('This is not a plain object');
}
```
### `fetchGet()`
Performs a GET request to the given URL and returns a Promise that resolves with the response data.
Usage:
```javascript
/* global fetchGet */
fetchGet({
url: url,
responseIsJson: false
}).then((data) => {
// Process the fetched data
}).catch((error) => {
console.error(`Error: ${error.message}`);
// Handle the error appropriately
});
```
#### `fetchGet()` Parameters
- `url`: The URL to fetch data from.
- `payload`: Optional data to send with the request. Can be an object or a string.
- `responseIsJson`: Optional boolean indicating if the response should be parsed as JSON (default is `true`).
### `fetchPost()`
Performs a POST request to the given URL with the provided data and returns a Promise that resolves with the response data.
Usage:
```javascript
/* global fetchPost */
fetchPost({
url: url,
csrfToken: csrfToken,
payload: {
key: 'value',
anotherKey: 'anotherValue'
},
responseIsJson: true
}).then((data) => {
// Process the fetched data
}).catch((error) => {
console.error(`Error: ${error.message}`);
// Handle the error appropriately
});
```
#### `fetchPost()` Parameters
- `url`: The URL to send the POST request to.
- `csrfToken`: The CSRF token to include in the request headers.
- `payload`: The data as JS object to send with the request.
- `responseIsJson`: Optional boolean indicating if the response should be parsed as JSON (default is `true`).