From 783dd4002aab31028241c627c1f468268e1b5314 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20N=C3=A9grier?= Date: Thu, 5 Feb 2026 17:17:04 +0100 Subject: [PATCH 1/3] Code and UI refactoring - Moving duplicated HTML code in Mustache partials - Adding a "Publish now" button right on the first page and another "Configure publishing" button - Moving the module to ESM - Fixing path in self-hosted single-domain mode --- package.json | 7 +- public/assets/js/index.js | 69 ++- public/assets/views/index.html | 64 +-- public/assets/views/partials/error-popup.html | 43 ++ public/assets/views/partials/footer.html | 48 +++ .../background-fade-selfhosted.html | 7 + .../head-scripts/background-fade.html | 8 + .../views/partials/head-scripts/index.html | 8 + .../head-scripts/selfhosted-maps.html | 102 +++++ public/assets/views/partials/head.html | 13 + public/assets/views/partials/header.html | 29 ++ public/assets/views/step1-git.html | 71 +--- public/assets/views/step2-hosting.html | 69 +-- .../assets/views/step3-steps-selfhosted.html | 371 ++++------------ public/assets/views/step3-steps.html | 401 ++++-------------- .../views/step4-validated-selfhosted.html | 135 +----- public/assets/views/step4-validated.html | 53 +-- public/styles/styles.css | 137 ++++++ src/controllers/FrontController.ts | 127 +++++- src/controllers/UploaderController.ts | 39 -- src/server.ts | 4 +- vite.config.ts | 6 +- 22 files changed, 803 insertions(+), 1008 deletions(-) create mode 100644 public/assets/views/partials/error-popup.html create mode 100644 public/assets/views/partials/footer.html create mode 100644 public/assets/views/partials/head-scripts/background-fade-selfhosted.html create mode 100644 public/assets/views/partials/head-scripts/background-fade.html create mode 100644 public/assets/views/partials/head-scripts/index.html create mode 100644 public/assets/views/partials/head-scripts/selfhosted-maps.html create mode 100644 public/assets/views/partials/head.html create mode 100644 public/assets/views/partials/header.html diff --git a/package.json b/package.json index 6ad8802..ec403de 100644 --- a/package.json +++ b/package.json @@ -2,6 +2,7 @@ "name": "@workadventure/map-starter-kit-core", "version": "1.1.0", "description": "Core app, HTML pages and static assets for the WorkAdventure Map Starter Kit. Update this package to get new UI and server features without touching your maps or config.", + "type": "module", "main": "dist/server.js", "types": "dist/server.d.ts", "scripts": { @@ -35,13 +36,11 @@ "exports": { ".": { "types": "./dist/server.d.ts", - "import": "./dist/server.js", - "require": "./dist/server.js" + "import": "./dist/server.js" }, "./dist/server.js": { "types": "./dist/server.d.ts", - "import": "./dist/server.js", - "require": "./dist/server.js" + "import": "./dist/server.js" } }, "dependencies": { diff --git a/public/assets/js/index.js b/public/assets/js/index.js index cf6c999..190d7d1 100644 --- a/public/assets/js/index.js +++ b/public/assets/js/index.js @@ -162,4 +162,71 @@ async function loadTMJ() { } } -export { getMapsList, getImagesList, createBackgroundImageFade, loadTMJ }; +async function setupPublishingActions() { + const publishButton = document.getElementById('publishNowButton'); + if (!publishButton) return; + const isInitiallyEnabled = !publishButton.disabled; + + publishButton.addEventListener('click', async () => { + if (publishButton.disabled) { + return; + } + const defaultLabel = publishButton.textContent; + publishButton.disabled = true; + publishButton.setAttribute('aria-disabled', 'true'); + publishButton.setAttribute('aria-busy', 'true'); + publishButton.textContent = 'Publishing...'; + const startTime = Date.now(); + const minDuration = 2000; + const mapStorageInput = document.getElementById('mapStorageURL'); + const mapStorageUrl = mapStorageInput && 'value' in mapStorageInput + ? mapStorageInput.value + : ''; + + if (typeof window.showLoadingOverlay === 'function') { + window.showLoadingOverlay('Publishing your map...'); + } + + try { + const response = await fetch('/uploader/upload', { + method: 'POST', + headers: { + 'Content-Type': 'application/json' + } + }); + + if (!response.ok) { + const errorData = await response.json().catch(() => ({})); + const errorMessage = errorData.message || errorData.error || 'Failed to publish maps. Please try again.'; + throw new Error(errorMessage); + } + + const elapsed = Date.now() - startTime; + if (elapsed < minDuration) { + await new Promise(resolve => setTimeout(resolve, minDuration - elapsed)); + } + + const redirectUrl = typeof window.getPostPublishRedirect === 'function' + ? window.getPostPublishRedirect(mapStorageUrl) + : '/step4-validated'; + window.location.href = redirectUrl; + } catch (error) { + console.error('Error publishing maps:', error); + if (typeof window.hideLoadingOverlay === 'function') { + window.hideLoadingOverlay(); + } + const errorMessage = error instanceof Error ? error.message : 'An error occurred while publishing maps.'; + if (typeof window.showErrorPopup === 'function') { + window.showErrorPopup(errorMessage); + } else { + window.alert(errorMessage); + } + publishButton.textContent = defaultLabel; + publishButton.removeAttribute('aria-busy'); + publishButton.disabled = !isInitiallyEnabled; + publishButton.setAttribute('aria-disabled', String(!isInitiallyEnabled)); + } + }); +} + +export { getMapsList, getImagesList, createBackgroundImageFade, loadTMJ, setupPublishingActions }; diff --git a/public/assets/views/index.html b/public/assets/views/index.html index 188781b..f551e05 100644 --- a/public/assets/views/index.html +++ b/public/assets/views/index.html @@ -1,71 +1,29 @@ - - - - - - - - - - WorkAdventure build your map - - - +{{> head}}
-
- -
- - -
+ {{> header}}
+ -
+{{> footer}} - \ No newline at end of file + diff --git a/public/assets/views/partials/error-popup.html b/public/assets/views/partials/error-popup.html new file mode 100644 index 0000000..a217ab5 --- /dev/null +++ b/public/assets/views/partials/error-popup.html @@ -0,0 +1,43 @@ + + diff --git a/public/assets/views/partials/footer.html b/public/assets/views/partials/footer.html new file mode 100644 index 0000000..112debb --- /dev/null +++ b/public/assets/views/partials/footer.html @@ -0,0 +1,48 @@ +
+{{> error-popup}} + + diff --git a/public/assets/views/partials/head-scripts/background-fade-selfhosted.html b/public/assets/views/partials/head-scripts/background-fade-selfhosted.html new file mode 100644 index 0000000..47a86dd --- /dev/null +++ b/public/assets/views/partials/head-scripts/background-fade-selfhosted.html @@ -0,0 +1,7 @@ + diff --git a/public/assets/views/partials/head-scripts/background-fade.html b/public/assets/views/partials/head-scripts/background-fade.html new file mode 100644 index 0000000..8af533d --- /dev/null +++ b/public/assets/views/partials/head-scripts/background-fade.html @@ -0,0 +1,8 @@ + diff --git a/public/assets/views/partials/head-scripts/index.html b/public/assets/views/partials/head-scripts/index.html new file mode 100644 index 0000000..e9aed15 --- /dev/null +++ b/public/assets/views/partials/head-scripts/index.html @@ -0,0 +1,8 @@ + diff --git a/public/assets/views/partials/head-scripts/selfhosted-maps.html b/public/assets/views/partials/head-scripts/selfhosted-maps.html new file mode 100644 index 0000000..8df431d --- /dev/null +++ b/public/assets/views/partials/head-scripts/selfhosted-maps.html @@ -0,0 +1,102 @@ + diff --git a/public/assets/views/partials/head.html b/public/assets/views/partials/head.html new file mode 100644 index 0000000..94519cf --- /dev/null +++ b/public/assets/views/partials/head.html @@ -0,0 +1,13 @@ + + + + + + + + + + {{pageTitle}} + + {{{headScripts}}} + diff --git a/public/assets/views/partials/header.html b/public/assets/views/partials/header.html new file mode 100644 index 0000000..579553c --- /dev/null +++ b/public/assets/views/partials/header.html @@ -0,0 +1,29 @@ +
+ +
+ + +
diff --git a/public/assets/views/step1-git.html b/public/assets/views/step1-git.html index ab7d637..c904c41 100644 --- a/public/assets/views/step1-git.html +++ b/public/assets/views/step1-git.html @@ -1,58 +1,11 @@ - - - - - - - - - - WorkAdventure build your map - - - +{{> head}}
-
- -
- - -
+ {{> header}}

@@ -63,34 +16,36 @@

@@ -113,7 +68,7 @@

-
+{{> footer}} - + {{> header}}

Which version of WorkAdventure do you use?

- Choose the setup that matches how your WorkAdventure instance is running. This will help us adapt the publishing process to your setup. + Choose the setup that matches how you use WorkAdventure. This will help us adapt the publishing process.
@@ -86,11 +39,11 @@

- I use SaaS version + I'm self-hosting WorkAdventure

- Your map is published on the WorkAdventure platform. - We handle hosting, updates, and infrastructure for you. + Your map is published on your own WorkAdventure server. + You manage the hosting, configuration, and updates yourself.
@@ -113,7 +66,7 @@

-
+{{> footer}} - +{{> head}}
-
- -
- - -
+ {{> header}}
1
-

Open your WorkAdventure self-hosted .env file

+

Gather your WorkAdventure credentials

- In your WorkAdventure self-hosted installation directory, open the .env file. You will need the values of PUBLIC_MAP_STORAGE_URL and MAP_STORAGE_API_TOKEN from this file for the next steps. +

You will need help from your WorkAdventure administrator for this step. Please ask them to provide you + with the URL and API token of your map storage service.

+ +
    +
  • + If your WorkAdventure instance was deployed with docker-compose, the URL is + most often https://[your-server-url]/map-storage/, and the API token can be found in + the .env file under the variable MAP_STORAGE_API_TOKEN. +
  • +
  • + If your WorkAdventure instance was deployed using the Kubernetes Helm chart, the URL is + most often https://[your-server-url]/map-storage/ + (or https://map-storage.[your-server-url]/) if you are using singleDomain: false in your values.yaml file. + The API token can be found in values.yaml under the key commonSecretEnv.MAP_STORAGE_API_TOKEN. +
  • +
- +
2
-

Copy your PUBLIC_MAP_STORAGE_URL

+

Copy your Map storage URL

- In your .env file, find the line PUBLIC_MAP_STORAGE_URL. Copy the value (the URL of your map storage service) and paste it below. + Refer to the instructions in step 1 to find the URL of your map storage service.
- +
3
-

Copy your MAP_STORAGE_API_TOKEN

+

Copy your Map storage API token

- In the same .env file, find the line MAP_STORAGE_API_TOKEN. Copy the token value and paste it below. + Refer to the instructions in step 1 to find the API token of your map storage service. It is a long + string of letters and numbers that serves as a password to authenticate your uploads.
@@ -101,38 +72,26 @@

Copy your MAP_STORAGE_API_TOKEN

4
-

Choose a name / directory for your world

+

Choose a name / directory for your maps

- You can use an existing directory or create a new one. This is the directory where your maps will be stored on your map storage. +

The maps you upload will be stored in this directory in our map storage.

+ +
+
+ Anything in this directory will be overwritten when you upload, so be careful to choose a + unique name or a name that matches the world you want to update if you already have one. +
+
+ +

The directory be visible in the URL of your maps.

- +
- - - -
-
+{{> footer}} - \ No newline at end of file + diff --git a/public/assets/views/step4-validated-selfhosted.html b/public/assets/views/step4-validated-selfhosted.html index 55264c4..9156b8e 100644 --- a/public/assets/views/step4-validated-selfhosted.html +++ b/public/assets/views/step4-validated-selfhosted.html @@ -1,140 +1,11 @@ - - - - - - - - - - Your maps - Self-hosted - - - +{{> head}}
-
- -
- - -
+ {{> header}}
Success @@ -170,7 +41,7 @@

-
+{{> footer}}