Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ jobs:
echo "RELEASE_TYPE=${RELEASE_TYPE}" >> $GITHUB_ENV

- name: Create Release 🎉
uses: ncipollo/release-action@v1.20.0
uses: ncipollo/release-action@v1
if: github.ref_type == 'tag'
with:
artifacts: semantic-workshop.zip,semantic-workshop.tar.gz
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ jobs:
uses: actions/checkout@v6

- name: node 20 ❇️
uses: actions/setup-node@v6.1.0
uses: actions/setup-node@v6
with:
node-version: 24

Expand Down
5 changes: 4 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
## 0.1.5 (December 28, 2025)
* Use correct Danish language code (da) instead of country code (dk).

## 0.1.4 (November 8, 2025)
* Fix for Get Changes CSV output missing data.

## 0.1.3 (November 7, 2025)
* Added map to Get Geographic Coverage Area.

Expand Down
699 changes: 319 additions & 380 deletions package-lock.json

Large diffs are not rendered by default.

13 changes: 11 additions & 2 deletions src/App.svelte
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
<script lang="ts">
import './app.css';
import { Button, Heading, Helper, Label, P, Select } from 'flowbite-svelte';
import { SvelteMap } from 'svelte/reactivity';
import { onMount } from 'svelte';

import DarkMode from './components/DarkMode.svelte';
Expand Down Expand Up @@ -36,8 +37,8 @@

const defaultRootServerURL = apiBaseUrl || 'https://bmlt.wszf.org/main_server/';
const allLanguages = [
{ value: 'da', name: 'Dansk' },
{ value: 'de', name: 'Deutsch' },
{ value: 'dk', name: 'Dansk' },
{ value: 'en', name: 'English' },
{ value: 'es', name: 'Español' },
{ value: 'fa', name: 'فارسی' },
Expand Down Expand Up @@ -119,7 +120,15 @@
serverLangs = serverInfo ? serverInfo[0].langs.split(',') : [];
serviceBodies = await getData('GetServiceBodies');
serviceBodies.sort((a, b) => a.name.localeCompare(b.name));
availableFields = await getData('GetFieldKeys');
const fields = await getData('GetFieldKeys');
// Deduplicate by key in case server returns duplicates
const fieldMap = new SvelteMap<string, { key: string; description: string }>();
for (const field of fields) {
if (!fieldMap.has(field.key)) {
fieldMap.set(field.key, field);
}
}
availableFields = Array.from(fieldMap.values());
availableFields.sort((a, b) => a.description.localeCompare(b.description));
formats = await getData('GetFormats');
formats.sort((a, b) => a.key_string.localeCompare(b.key_string));
Expand Down
4 changes: 1 addition & 3 deletions src/components/GetChanges.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
let changesMeetingId: string = $state('');
let badChangesMeetingId: boolean = $state(false);
let changesServiceBodyId: string = $state('all');
let serviceBodyOptions = $derived([{ value: 'all', name: $translations.allServiceBodies }, ...serviceBodies.map((b: { name: string; id: string }) => ({ name: b.name, value: b.id }))]);

function computeParameters() {
badChangesMeetingId = /[^\d]/.test(changesMeetingId);
Expand All @@ -37,9 +38,6 @@
return '';
}
}

const bodies: { name: string; value: string }[] = serviceBodies.map((b: { name: string; id: string }) => ({ name: b.name, value: b.id }));
const serviceBodyOptions = [{ value: 'all', name: $translations.allServiceBodies }].concat(bodies);
onMount(() => (parameters = ''));
</script>

Expand Down
2 changes: 1 addition & 1 deletion src/components/GetFieldValues.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@

let { availableFields, parameters = $bindable() }: Props = $props();
let keyForGetFieldValues: string | undefined = $state();
const fieldOptions: { name: string; value: string }[] = availableFields.map((f: { key: string; description: string }) => ({ name: f.description, value: f.key }));
let fieldOptions = $derived(availableFields.map((f: { key: string; description: string }) => ({ name: f.description, value: f.key })));

// If keyForGetFieldValues is null, no field has been selected and so we should not have a response URL yet.
// Set parameters to null in computeParameters and onMount to indicate this.
Expand Down
6 changes: 3 additions & 3 deletions src/components/GetFormats.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@
let excludeFormatIds: boolean[] = $state([]);
let includeKeyStrings: boolean[] = $state([]);

let filteredLangs = $derived(allLanguages.filter((x: { value: string; name: string }) => serverLangs.includes(x.value)));
let formatLanguageOptions = $derived([{ value: 'servLang', name: 'Server language' }].concat(filteredLangs));

// Initialize arrays when formats change
$effect(() => {
const formatCount = formats ? formats.length : 0;
Expand Down Expand Up @@ -80,9 +83,6 @@

parameters = languagePart + showAllPart + formatIdsPart + keyStringsPart;
}

const filteredLangs = allLanguages.filter((x: { value: string; name: string }) => serverLangs.includes(x.value));
const formatLanguageOptions = [{ value: 'servLang', name: 'Server language' }].concat(filteredLangs);
onMount(() => (parameters = ''));
</script>

Expand Down
96 changes: 85 additions & 11 deletions src/components/GetMeetingSearchResults.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,9 @@
let notOnWeekdays: boolean[] = $state(new Array(7).fill(false));
let hasVenueType: boolean[] = $state(new Array(3).fill(false));
let doesNotHaveVenueType: boolean[] = $state(new Array(3).fill(false));
let hasFormat: boolean[] = $state(new Array(formats.length).fill(false));
let hasFormat: boolean[] = $state<boolean[]>([]);
let formatsComparisonOperator: string = $state('AND');
let doesNotHaveFormat: boolean[] = $state(new Array(formats.length).fill(false));
let doesNotHaveFormat: boolean[] = $state<boolean[]>([]);
let keyForMeetingKeyValue: string = $state('');
let meetingKeyValues: { name: string; value: string }[] = $state([]);
let meetingFieldValue = $state('');
Expand All @@ -37,6 +37,24 @@
let searchType = $state('general');
let textSearchRadius = $state('');
let fieldOptions: { name: string; value: string }[] = $derived(availableFields.map((f: { key: string; description: string }) => ({ name: f.description, value: f.key })));

// Initialize/resize arrays when props change
// Using $effect (not $derived) because these arrays need to be mutable for user interaction
$effect(() => {
if (hasFormat.length !== formats.length) {
hasFormat = new Array(formats.length).fill(false);
}
if (doesNotHaveFormat.length !== formats.length) {
doesNotHaveFormat = new Array(formats.length).fill(false);
}
if (selectedFields.length !== availableFields.length) {
selectedFields = new Array(availableFields.length).fill(false);
}
if (sortOrder.length !== availableFields.length) {
sortOrder = new Array(availableFields.length).fill('0');
}
});

let startsAfter = $state('');
let startsBefore = $state('');
let endsBefore = $state('');
Expand All @@ -54,11 +72,11 @@
let badTime = $derived(!validTime(startsAfter) || !validTime(startsBefore) || !validTime(endsBefore) || !validTime(minDuration) || !validTime(maxDuration));
let badMeetingIds = $derived(!validMeetingIds(meetingIds) || !validMeetingIds(excludeMeetingIds));
let badPagination = $derived(!validPositiveInteger(pageSize) || !validPositiveInteger(pageNumber));
let selectedFields = $state(Array(availableFields.length).fill(false));
let selectedFields: boolean[] = $state<boolean[]>([]);
// sortOrder[i] gives the sort order for availableFields[i], where a value of '1' means it's the first field to be used in the sort,
// '2' means it's the second, etc. '0' means that field isn't in the sort order. Annoyingly, the flowbite-svelte version of Select
// seems to want the values to be strings only, so the code is constantly converting between strings and ints for this array.
let sortOrder: string[] = $state(new Array(availableFields.length).fill('0'));
let sortOrder: string[] = $state<string[]>([]);

// return true if s represents a valid number (either integer or float is ok). An empty string is also OK -- this indicates an entry
// hasn't been made yet, but we don't want to fire off an error message in this case.
Expand Down Expand Up @@ -367,7 +385,15 @@
{#each $translations.weekdays as day, i}
<div class="flex items-center space-x-2">
<Label class="mt-4 flex text-sm dark:text-white">
<Checkbox bind:checked={onWeekdays[i]} onchange={computeParameters} class="me-1" />
<Checkbox
checked={onWeekdays[i] || false}
onchange={(e) => {
const target = e.target as HTMLInputElement;
onWeekdays[i] = target.checked;
computeParameters();
}}
class="me-1"
/>
{day}
</Label>
</div>
Expand All @@ -383,7 +409,15 @@
{#each $translations.weekdays as day, i}
<div class="flex items-center space-x-2">
<Label class="mt-4 flex text-sm dark:text-white">
<Checkbox bind:checked={notOnWeekdays[i]} onchange={computeParameters} class="me-1" />
<Checkbox
checked={notOnWeekdays[i] || false}
onchange={(e) => {
const target = e.target as HTMLInputElement;
notOnWeekdays[i] = target.checked;
computeParameters();
}}
class="me-1"
/>
{day}
</Label>
</div>
Expand All @@ -398,7 +432,15 @@
{#each $translations.venueTypes as vt, i}
<div class="flex items-center space-x-2">
<Label class="mt-4 flex text-sm dark:text-white">
<Checkbox bind:checked={hasVenueType[i]} onchange={computeParameters} class="me-1" />
<Checkbox
checked={hasVenueType[i] || false}
onchange={(e) => {
const target = e.target as HTMLInputElement;
hasVenueType[i] = target.checked;
computeParameters();
}}
class="me-1"
/>
{vt}
</Label>
</div>
Expand All @@ -414,7 +456,15 @@
{#each $translations.venueTypes as vt, i}
<div class="flex items-center space-x-2">
<Label class="mt-4 flex text-sm dark:text-white">
<Checkbox bind:checked={doesNotHaveVenueType[i]} onchange={computeParameters} class="me-1" />
<Checkbox
checked={doesNotHaveVenueType[i] || false}
onchange={(e) => {
const target = e.target as HTMLInputElement;
doesNotHaveVenueType[i] = target.checked;
computeParameters();
}}
class="me-1"
/>
{vt}
</Label>
</div>
Expand Down Expand Up @@ -480,7 +530,15 @@
{#each formats as f, i}
<div class="flex items-center space-x-2">
<Label class="mt-4 flex text-sm dark:text-white">
<Checkbox bind:checked={hasFormat[i]} onchange={computeParameters} class="me-1" />
<Checkbox
checked={hasFormat[i] || false}
onchange={(e) => {
const target = e.target as HTMLInputElement;
hasFormat[i] = target.checked;
computeParameters();
}}
class="me-1"
/>
{f.key_string}
</Label>
</div>
Expand All @@ -507,7 +565,15 @@
{#each formats as f, i}
<div class="flex items-center space-x-2">
<Label class="mt-4 flex text-sm dark:text-white">
<Checkbox bind:checked={doesNotHaveFormat[i]} onchange={computeParameters} class="me-1" />
<Checkbox
checked={doesNotHaveFormat[i] || false}
onchange={(e) => {
const target = e.target as HTMLInputElement;
doesNotHaveFormat[i] = target.checked;
computeParameters();
}}
class="me-1"
/>
{f.key_string}
</Label>
</div>
Expand Down Expand Up @@ -754,7 +820,15 @@
{#each fieldOptions as f, i}
<div class="flex items-center space-x-2">
<Label class="flex text-sm dark:text-white">
<Checkbox class="me-2" bind:checked={selectedFields[i]} onchange={computeParameters} />
<Checkbox
class="me-2"
checked={selectedFields[i] || false}
onchange={(e) => {
const target = e.target as HTMLInputElement;
selectedFields[i] = target.checked;
computeParameters();
}}
/>
{f.name}
</Label>
</div>
Expand Down
2 changes: 1 addition & 1 deletion src/components/GetNAWSDump.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@

let { serviceBodies, parameters = $bindable() }: Props = $props();
let nawsDumpServiceBodyId: string | undefined = $state();
const serviceBodyOptions: { name: string; value: string }[] = serviceBodies.map((b: { name: string; id: string }) => ({ name: b.name, value: b.id }));
let serviceBodyOptions = $derived(serviceBodies.map((b: { name: string; id: string }) => ({ name: b.name, value: b.id })));

// If nawsDumpServiceBodyId is null, no service body has been selected and so we should not have a response URL yet.
// Set parameters to null in computeParameters and onMount to indicate this.
Expand Down