Compare commits

...

18 Commits

Author SHA1 Message Date
Daniel Waxweiler 2889edcb4c parse events 2024-04-02 23:30:56 +02:00
Daniel Waxweiler 48fa50ab85 clean up a bit 2024-04-02 23:17:16 +02:00
Daniel Waxweiler c27d0760ea wip 2024-04-02 23:14:08 +02:00
Daniel Waxweiler a442da042f Merge branch 'main' into requests-in-php 2024-04-02 22:18:36 +02:00
Daniel Waxweiler 3269ccca1a add missing readme changelog entry 2024-04-02 22:13:20 +02:00
Daniel Waxweiler 2d91350cc9 prepare next release 2024-04-02 22:09:58 +02:00
Daniel Waxweiler e7fd47a346 release version 0.11.5 2024-04-02 22:09:20 +02:00
Daniel Waxweiler 8d4e81878e confirm compatibility with WordPress 6.5 2024-04-02 22:02:55 +02:00
Daniel Waxweiler 418dc829d0 document after-release step 2024-04-02 22:01:53 +02:00
Daniel Waxweiler 78e30411f1 document after-release step 2024-04-02 21:58:39 +02:00
Daniel Waxweiler 1af1e62301 Merge branch 'main' into requests-in-php 2023-11-11 20:44:15 +01:00
Daniel Waxweiler a75d3a3915 prepare next release 2023-11-11 20:43:50 +01:00
Daniel Waxweiler d2fb67b5bc release version 0.11.4 2023-11-11 20:39:06 +01:00
Daniel Waxweiler a9f5205d78 remove Qodana Github action 2023-11-11 20:31:50 +01:00
Daniel Waxweiler 25c76e4998 increase Node version number in Github action 2023-11-11 20:30:22 +01:00
Daniel Waxweiler 6157cf3988 update dependencies 2023-11-11 20:28:16 +01:00
Daniel Waxweiler 8644a7103c confirm compatibility with WordPress 6.4 2023-11-11 20:24:59 +01:00
Daniel Waxweiler 761b1d1c46 wip 2023-11-11 20:12:30 +01:00
15 changed files with 3892 additions and 3072 deletions

View File

@ -1,23 +0,0 @@
name: Qodana
on:
workflow_dispatch:
pull_request:
push:
branches:
- main
- 'releases/*'
jobs:
qodana:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
with:
fetch-depth: 0
- name: 'Qodana Scan'
uses: JetBrains/qodana-action@v2022.3.2
env:
QODANA_TOKEN: ${{ secrets.QODANA_TOKEN }}
- uses: github/codeql-action/upload-sarif@v2
with:
sarif_file: ${{ runner.temp }}/qodana/results/qodana.sarif.json

View File

@ -15,7 +15,7 @@ jobs:
strategy: strategy:
matrix: matrix:
node-version: [16.x] node-version: [18.x]
# See supported Node.js release schedule at https://nodejs.org/en/about/releases/ # See supported Node.js release schedule at https://nodejs.org/en/about/releases/
steps: steps:

View File

@ -34,6 +34,9 @@ The current changelog can be found under [source/changelog.txt](source/changelog
11. Commit the new version in git with the same message. 11. Commit the new version in git with the same message.
12. Tag the new version: `git tag v<version>` 12. Tag the new version: `git tag v<version>`
13. Push the new tag to the repository: `git push --tags` 13. Push the new tag to the repository: `git push --tags`
14. Append `-next` to the version number in `package.json`.
15. Update the `package-lock.json`: `npm i --package-lock-only`
16. Commit: `git commit -am "prepare next release"`
### Other commands ### Other commands

View File

@ -15,7 +15,7 @@ function injectMetadata() {
FOLDER_BUILD + '/includes/Constants.php', FOLDER_BUILD + '/includes/Constants.php',
FOLDER_BUILD + '/readme.txt', FOLDER_BUILD + '/readme.txt',
], ],
{ base: './' } { base: './' },
) )
.pipe(replace('<wordpress-author-name>', PACKAGE.author.name)) .pipe(replace('<wordpress-author-name>', PACKAGE.author.name))
.pipe(replace('<wordpress-author-url>', PACKAGE.author.url)) .pipe(replace('<wordpress-author-url>', PACKAGE.author.url))
@ -25,22 +25,22 @@ function injectMetadata() {
.pipe( .pipe(
replace( replace(
'<wordpress-minimum-version>', '<wordpress-minimum-version>',
PACKAGE.additionalDetails.wordpressMinimumVersion PACKAGE.additionalDetails.wordpressMinimumVersion,
) ),
) )
.pipe(replace('<wordpress-name>', PACKAGE.name)) .pipe(replace('<wordpress-name>', PACKAGE.name))
.pipe(replace('<wordpress-nice-name>', PACKAGE.additionalDetails.niceName)) .pipe(replace('<wordpress-nice-name>', PACKAGE.additionalDetails.niceName))
.pipe( .pipe(
replace( replace(
'<wordpress-php-minimum-version>', '<wordpress-php-minimum-version>',
PACKAGE.additionalDetails.phpMinimumVersion PACKAGE.additionalDetails.phpMinimumVersion,
) ),
) )
.pipe( .pipe(
replace( replace(
'<wordpress-tested-up-to-version>', '<wordpress-tested-up-to-version>',
PACKAGE.additionalDetails.wordpressTestedUpToVersion PACKAGE.additionalDetails.wordpressTestedUpToVersion,
) ),
) )
.pipe(replace('<wordpress-version>', PACKAGE.version)) .pipe(replace('<wordpress-version>', PACKAGE.version))
.pipe(dest('.')) .pipe(dest('.'))

6705
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -1,6 +1,6 @@
{ {
"name": "connector-mobilizon", "name": "connector-mobilizon",
"version": "0.11.3", "version": "0.11.5-next",
"description": "Display Mobilizon events in WordPress.", "description": "Display Mobilizon events in WordPress.",
"private": true, "private": true,
"type": "module", "type": "module",
@ -24,34 +24,34 @@
}, },
"license": "Apache-2.0", "license": "Apache-2.0",
"dependencies": { "dependencies": {
"graphql": "16.7.1", "graphql": "16.8.1",
"graphql-request": "6.1.0", "graphql-request": "6.1.0",
"luxon": "3.3.0", "luxon": "3.4.3",
"object-hash": "3.0.0" "object-hash": "3.0.0"
}, },
"devDependencies": { "devDependencies": {
"@babel/core": "7.22.9", "@babel/core": "7.23.3",
"@babel/eslint-parser": "7.22.9", "@babel/eslint-parser": "7.23.3",
"@babel/preset-env": "7.22.9", "@babel/preset-env": "7.23.3",
"@babel/preset-react": "7.22.5", "@babel/preset-react": "7.23.3",
"@wordpress/eslint-plugin": "14.11.0", "@wordpress/eslint-plugin": "17.2.0",
"ava": "5.3.1", "ava": "5.3.1",
"babel-loader": "9.1.3", "babel-loader": "9.1.3",
"browser-env": "3.3.0", "browser-env": "3.3.0",
"c8": "8.0.1", "c8": "8.0.1",
"copy-webpack-plugin": "11.0.0", "copy-webpack-plugin": "11.0.0",
"eslint": "8.45.0", "eslint": "8.53.0",
"eslint-plugin-ava": "14.0.0", "eslint-plugin-ava": "14.0.0",
"eslint-plugin-jsx": "0.1.0", "eslint-plugin-jsx": "0.1.0",
"eslint-plugin-react": "7.33.0", "eslint-plugin-react": "7.33.2",
"esm": "3.2.25", "esm": "3.2.25",
"gulp": "4.0.2", "gulp": "4.0.2",
"gulp-replace": "1.1.4", "gulp-replace": "1.1.4",
"husky": "8.0.3", "husky": "8.0.3",
"lint-staged": "13.2.3", "lint-staged": "15.1.0",
"prettier": "3.0.0", "prettier": "3.0.3",
"rimraf": "5.0.1", "rimraf": "5.0.5",
"webpack": "5.88.2", "webpack": "5.89.0",
"webpack-cli": "5.1.4" "webpack-cli": "5.1.4"
}, },
"ava": { "ava": {
@ -63,7 +63,7 @@
"niceName": "Connector for Mobilizon", "niceName": "Connector for Mobilizon",
"phpMinimumVersion": 7.4, "phpMinimumVersion": 7.4,
"wordpressMinimumVersion": 5.6, "wordpressMinimumVersion": 5.6,
"wordpressTestedUpToVersion": "6.3" "wordpressTestedUpToVersion": "6.5"
}, },
"lint-staged": { "lint-staged": {
"source/**/*.js": "eslint", "source/**/*.js": "eslint",

View File

@ -8,6 +8,15 @@
#### Fixed #### Fixed
#### Security #### Security
### [0.11.5]
#### Changed
- Confirm compatibility with WordPress 6.5
### [0.11.4]
#### Changed
- Confirm compatibility with WordPress 6.4
- Update dependencies
### [0.11.3] ### [0.11.3]
#### Fixed #### Fixed
- Clean up distributed files - Clean up distributed files

View File

@ -13,6 +13,7 @@
require_once __DIR__ . '/includes/exceptions/GeneralException.php'; require_once __DIR__ . '/includes/exceptions/GeneralException.php';
require_once __DIR__ . '/includes/exceptions/GroupNotFoundException.php'; require_once __DIR__ . '/includes/exceptions/GroupNotFoundException.php';
require_once __DIR__ . '/includes/Constants.php'; require_once __DIR__ . '/includes/Constants.php';
require_once __DIR__ . '/includes/Api.php';
require_once __DIR__ . '/includes/EventsCache.php'; require_once __DIR__ . '/includes/EventsCache.php';
require_once __DIR__ . '/includes/Settings.php'; require_once __DIR__ . '/includes/Settings.php';
require_once __DIR__ . '/includes/DateTimeWrapper.php'; require_once __DIR__ . '/includes/DateTimeWrapper.php';
@ -30,6 +31,7 @@ if (!defined('ABSPATH')) {
final class Mobilizon_Connector { final class Mobilizon_Connector {
private function __construct() { private function __construct() {
add_action('init', [$this, 'register_api']);
add_action('init', [$this, 'register_blocks']); add_action('init', [$this, 'register_blocks']);
add_action('init', [$this, 'register_settings'], 1); // required for register_blocks add_action('init', [$this, 'register_settings'], 1); // required for register_blocks
add_action('init', [$this, 'register_shortcut']); add_action('init', [$this, 'register_shortcut']);
@ -54,12 +56,15 @@ final class Mobilizon_Connector {
$settings = array( $settings = array(
'isShortOffsetNameShown' => MobilizonConnector\Settings::isShortOffsetNameShown(), 'isShortOffsetNameShown' => MobilizonConnector\Settings::isShortOffsetNameShown(),
'locale' => str_replace('_', '-', get_locale()), 'locale' => str_replace('_', '-', get_locale()),
'timeZone' => wp_timezone_string(), 'timeZone' => wp_timezone_string()
'url' => MobilizonConnector\Settings::getUrl()
); );
wp_add_inline_script($scriptName, 'var MOBILIZON_CONNECTOR = ' . json_encode($settings), 'before'); wp_add_inline_script($scriptName, 'var MOBILIZON_CONNECTOR = ' . json_encode($settings), 'before');
} }
public function register_api() {
MobilizonConnector\Api::init();
}
public function register_blocks() { public function register_blocks() {
$scriptName = MobilizonConnector\EventsListBlock::initAndReturnScriptName(); $scriptName = MobilizonConnector\EventsListBlock::initAndReturnScriptName();
$this->load_settings_globally_before_script($scriptName); $this->load_settings_globally_before_script($scriptName);

View File

@ -1,5 +1,11 @@
/* eslint-disable @wordpress/i18n-ellipsis */ /* eslint-disable @wordpress/i18n-ellipsis */
import { loadEventList } from '../../events-loader.js' import {
clearEventsList,
displayErrorMessage,
displayEvents,
hideErrorMessages,
showLoadingIndicator,
} from '../../events-displayer.js'
const { InspectorControls, useBlockProps } = wp.blockEditor const { InspectorControls, useBlockProps } = wp.blockEditor
const { PanelBody } = wp.components const { PanelBody } = wp.components
@ -14,7 +20,7 @@ export default ({ attributes, setAttributes }) => {
const blockProps = useBlockProps({ const blockProps = useBlockProps({
className: NAME + '_events-list', className: NAME + '_events-list',
'data-maximum': attributes.eventsCount, 'data-maximum': attributes.eventsCount,
'data-group-name': attributes.groupName, 'data-group-name': attributes.groupName, // TODO still necessary?
}) })
function reloadEventList() { function reloadEventList() {
if (timer) { if (timer) {
@ -23,7 +29,25 @@ export default ({ attributes, setAttributes }) => {
timer = setTimeout(() => { timer = setTimeout(() => {
const container = document.getElementById(blockProps.id) const container = document.getElementById(blockProps.id)
if (container) { if (container) {
loadEventList(container) // TODO not using newest values yet, can get out of sync
hideErrorMessages(container)
clearEventsList(container)
showLoadingIndicator(container)
const eventsCount = attributes.eventsCount
const groupName = attributes.groupName
let url = `/wp-json/connector-mobilizon/v1/events?eventsCount=${eventsCount}`
if (groupName) {
url += `&groupName=${groupName}`
}
fetch(url)
.then((response) => response.text()) // TODO also handle response.ok being false
.then((data) => {
const events = JSON.parse(data)
displayEvents({ events, document, container })
})
.catch((data) => {
displayErrorMessage({ data, container })
})
} }
}, 500) }, 500)
} }
@ -37,6 +61,7 @@ export default ({ attributes, setAttributes }) => {
reloadEventList() reloadEventList()
} }
function updateGroupName(event) { function updateGroupName(event) {
// TODO not triggered on pasting only
setAttributes({ groupName: event.target.value }) setAttributes({ groupName: event.target.value })
reloadEventList() reloadEventList()
} }

View File

@ -40,24 +40,20 @@ test.beforeEach((t) => {
}) })
test('#displayEvents one event', (t) => { test('#displayEvents one event', (t) => {
const data = { const events = [
events: { {
elements: [ title: 'a',
{ url: 'b',
title: 'a', beginsOn: '2021-04-15T10:30:00Z',
url: 'b', endsOn: '2021-04-15T15:30:00Z',
beginsOn: '2021-04-15T10:30:00Z', physicalAddress: {
endsOn: '2021-04-15T15:30:00Z', description: 'c',
physicalAddress: { locality: 'd',
description: 'c', },
locality: 'd',
},
},
],
}, },
} ]
const container = t.context.container const container = t.context.container
displayEvents({ data, document, container }) displayEvents({ events, document, container })
const list = container.querySelector('ul') const list = container.querySelector('ul')
t.is(list.children[0].childNodes[0].tagName, 'A') t.is(list.children[0].childNodes[0].tagName, 'A')
t.is(list.children[0].childNodes[0].getAttribute('href'), 'b') t.is(list.children[0].childNodes[0].getAttribute('href'), 'b')

View File

@ -6,7 +6,7 @@ export function clearEventsList(container) {
list.replaceChildren() list.replaceChildren()
} }
export function displayEvents({ data, document, container }) { export function displayEvents({ events, document, container }) {
hideLoadingIndicator(container) hideLoadingIndicator(container)
const isShortOffsetNameShown = const isShortOffsetNameShown =
@ -15,9 +15,6 @@ export function displayEvents({ data, document, container }) {
const maxEventsCount = container.getAttribute('data-maximum') const maxEventsCount = container.getAttribute('data-maximum')
const timeZone = window.MOBILIZON_CONNECTOR.timeZone const timeZone = window.MOBILIZON_CONNECTOR.timeZone
const events = data.events
? data.events.elements
: data.group.organizedEvents.elements
const eventsCount = Math.min(maxEventsCount, events.length) const eventsCount = Math.min(maxEventsCount, events.length)
const list = container.querySelector('ul') const list = container.querySelector('ul')
for (let i = 0; i < eventsCount; i++) { for (let i = 0; i < eventsCount; i++) {
@ -84,7 +81,7 @@ export function showLoadingIndicator(container) {
indicator.style.display = 'block' indicator.style.display = 'block'
} }
function hideLoadingIndicator(container) { export function hideLoadingIndicator(container) {
const indicator = container.querySelector('.loading-indicator') const indicator = container.querySelector('.loading-indicator')
indicator.style.display = 'none' indicator.style.display = 'none'
} }

View File

@ -1,38 +0,0 @@
import {
clearEventsList,
displayEvents,
displayErrorMessage,
hideErrorMessages,
showLoadingIndicator,
} from './events-displayer.js'
import * as GraphqlWrapper from './graphql-wrapper.js'
const NAME = '<wordpress-name>'
const URL_SUFFIX = '/api'
document.addEventListener('DOMContentLoaded', loadEventLists)
function loadEventLists() {
const eventLists = document.getElementsByClassName(NAME + '_events-list')
for (const list of eventLists) {
loadEventList(list)
}
}
export function loadEventList(container) {
const url = MOBILIZON_CONNECTOR.url + URL_SUFFIX
const limit = parseInt(container.getAttribute('data-maximum'))
const groupName = container.getAttribute('data-group-name')
hideErrorMessages(container)
clearEventsList(container)
showLoadingIndicator(container)
if (groupName) {
GraphqlWrapper.getUpcomingEventsByGroupName({ url, limit, groupName })
.then((data) => displayEvents({ data, document, container }))
.catch((data) => displayErrorMessage({ data, container }))
} else {
GraphqlWrapper.getUpcomingEvents({ url, limit })
.then((data) => displayEvents({ data, document, container }))
.catch((data) => displayErrorMessage({ data, container }))
}
}

View File

@ -70,9 +70,9 @@ export function getUpcomingEventsByGroupName({ url, limit, groupName }) {
SessionCache.add( SessionCache.add(
sessionStorage, sessionStorage,
{ url, query, variables: { afterDatetime, groupName, limit } }, { url, query, variables: { afterDatetime, groupName, limit } },
data data,
) )
return Promise.resolve(data) return Promise.resolve(data)
} },
) )
} }

52
source/includes/Api.php Normal file
View File

@ -0,0 +1,52 @@
<?php
namespace MobilizonConnector;
class Api {
public static function init() {
add_action('rest_api_init', 'MobilizonConnector\Api::init_api');
}
public static function init_api() {
register_rest_route(
NAME . '/v1',
'/events',
[
'methods' => 'GET',
'callback' => 'MobilizonConnector\Api::get_events',
'args' => [
'eventsCount' => [
'required' => true,
'validate_callback' => function($param, $request, $key) {
return is_numeric($param) && $param > 0;
}
],
'groupName' => [
'validate_callback' => function($param, $request, $key) {
return !is_numeric($param);
}
]
]
]
);
}
public static function get_events($request) {
$eventsCount = $request['eventsCount'];
$groupName = isset($request['groupName']) ? $request['groupName'] : '';
$url = Settings::getUrl();
try {
if ($groupName) {
$events = GraphQlClient::get_upcoming_events_by_group_name($url, (int) $eventsCount, $groupName);
} else {
$events = GraphQlClient::get_upcoming_events($url, (int) $eventsCount);
}
return $events;
} catch (GeneralException $e) {
return 'The events could not be loaded!';
} catch (GroupNotFoundException $e) {
return sprintf('The group "%s" could not be found!', $groupName);
}
}
}

View File

@ -41,6 +41,15 @@ You have to use their username, e.g. `@nosliensvivants`, and append the name of
## Changelog ## Changelog
### [0.11.5]
#### Changed
- Confirm compatibility with WordPress 6.5
### [0.11.4]
#### Changed
- Confirm compatibility with WordPress 6.4
- Update dependencies
### [0.11.3] ### [0.11.3]
#### Fixed #### Fixed
- Clean up distributed files - Clean up distributed files