@workadventure/map-starter-kit-core 1.1.0 → 1.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (36) hide show
  1. package/README.md +165 -0
  2. package/dist/assets/js/index.js +164 -0
  3. package/dist/assets/views/index.html +71 -0
  4. package/dist/assets/views/step1-git.html +154 -0
  5. package/dist/assets/views/step2-hosting.html +153 -0
  6. package/dist/assets/views/step3-steps-selfhosted.html +502 -0
  7. package/dist/assets/views/step3-steps.html +549 -0
  8. package/dist/assets/views/step4-validated-selfhosted.html +188 -0
  9. package/dist/assets/views/step4-validated.html +80 -0
  10. package/dist/images/world-select.png +0 -0
  11. package/dist/server.js +4 -4
  12. package/dist/server.js.map +1 -1
  13. package/dist/styles/styles.css +1 -8
  14. package/package.json +3 -1
  15. package/public/assets/js/index.js +164 -0
  16. package/public/assets/views/index.html +71 -0
  17. package/public/assets/views/step1-git.html +154 -0
  18. package/public/assets/views/step2-hosting.html +153 -0
  19. package/public/assets/views/step3-steps-selfhosted.html +502 -0
  20. package/public/assets/views/step3-steps.html +549 -0
  21. package/public/assets/views/step4-validated-selfhosted.html +188 -0
  22. package/public/assets/views/step4-validated.html +80 -0
  23. package/public/images/badumtss.svg +12 -0
  24. package/public/images/brand-discord.svg +22 -0
  25. package/public/images/brand-github.svg +19 -0
  26. package/public/images/brand-linkedin.svg +23 -0
  27. package/public/images/brand-x.svg +20 -0
  28. package/public/images/brand-youtube.svg +20 -0
  29. package/public/images/favicon.svg +50 -0
  30. package/public/images/logo.svg +72 -0
  31. package/public/images/world-select.png +0 -0
  32. package/public/styles/styles.css +424 -0
  33. package/public/styles/styles.css.map +1 -0
  34. package/types/server.d.ts +5 -0
  35. package/dist/assets/index.js +0 -80
  36. /package/{dist/images/unknown-room-image copy.png → public/images/unknown-room-image.png} +0 -0
@@ -0,0 +1,164 @@
1
+ // Function to retrieve the list of maps from the API
2
+ async function getMapsList() {
3
+ try {
4
+ const response = await fetch('/maps/list');
5
+ if (!response.ok) {
6
+ throw new Error(`HTTP error! status: ${response.status}`);
7
+ }
8
+ const maps = await response.json();
9
+ return maps;
10
+ } catch (error) {
11
+ console.error('Error fetching maps list:', error);
12
+ return [];
13
+ }
14
+ }
15
+
16
+ // Function to get the list
17
+ async function getImagesList() {
18
+ try {
19
+ const response = await fetch('/images/list');
20
+ if (!response.ok) {
21
+ throw new Error(`HTTP error! status: ${response.status}`);
22
+ }
23
+ const images = await response.json();
24
+ return images;
25
+ } catch (error) {
26
+ console.error('Error fetching images list:', error);
27
+ return [];
28
+ }
29
+ }
30
+
31
+ // Function to create a background image fade for "bg" element
32
+ async function createBackgroundImageFade(images = null) {
33
+ // Get the list of images
34
+ if (images === null) {
35
+ const maps = await getMapsList();
36
+ images = maps.map(map => {
37
+ if (map.mapImage) {
38
+ return map.mapImage.startsWith('http') ? map.mapImage : `/${map.mapImage}`;
39
+ }
40
+ return null;
41
+ }).filter(img => img !== null);
42
+ if (images.length === 0) {
43
+ return;
44
+ }
45
+ }
46
+
47
+ // Get the "bg" element
48
+ const bgElement = document.querySelector('.bg');
49
+ if (!bgElement || images.length === 0) return;
50
+
51
+ // Create divs for each image with fade animation
52
+ bgElement.innerHTML = '';
53
+ images.forEach((imageUrl, index) => {
54
+ const imgDiv = document.createElement('div');
55
+ imgDiv.className = 'bg-image' + (index === 0 ? ' active' : '');
56
+ imgDiv.style.backgroundImage = `url('${imageUrl}')`;
57
+ bgElement.appendChild(imgDiv);
58
+ });
59
+
60
+ // Automatic fade between images
61
+ let currentIndex = 0;
62
+ setInterval(() => {
63
+ const imageElements = bgElement.querySelectorAll('.bg-image');
64
+ if (imageElements.length === 0) return;
65
+
66
+ // Remove the active class from the current image
67
+ imageElements[currentIndex].classList.remove('active');
68
+
69
+ // Move to the next image
70
+ currentIndex = (currentIndex + 1) % imageElements.length;
71
+
72
+ // Add the active class to the new image
73
+ imageElements[currentIndex].classList.add('active');
74
+ }, 5000); // Change image every 5 seconds
75
+ }
76
+
77
+ // Mustache template for a map card (rendered in loadTMJ)
78
+ const CARD_TEMPLATE = `
79
+ <div class="map-cover" style="background-image: url('{{mapImageUrl}}');"></div>
80
+ <div class="map-date">
81
+ Last edit: {{lastModifiedFormatted}}
82
+ </div>
83
+ <div class="map-name">
84
+ {{mapName}}
85
+ </div>
86
+ <div class="map-detail">
87
+ <div class="map-file">
88
+ <strong>{{filename}}</strong>.tmj
89
+ </div>
90
+ <div class="map-weight">
91
+ <strong>{{size}}</strong>
92
+ <span style="opacity: .5">Mo</span>
93
+ </div>
94
+ </div>
95
+ <div class="map-desc">
96
+ {{mapDescription}}
97
+ </div>
98
+ <div class="map-testurl">
99
+ <a href="#" class="btn" data-map-path="{{path}}">Test my map</a>
100
+ </div>
101
+ `;
102
+
103
+ // Load maps from API and render map cards with Mustache
104
+ async function loadTMJ() {
105
+ try {
106
+ const Mustache = (await import('https://cdn.jsdelivr.net/npm/mustache@4.2.0/+esm')).default;
107
+ const maps = await getMapsList();
108
+
109
+ const mapImages = maps
110
+ .map((map) => {
111
+ if (map.mapImage) {
112
+ return map.mapImage.startsWith('http') ? map.mapImage : `/${map.mapImage}`;
113
+ }
114
+ return null;
115
+ })
116
+ .filter((img) => img !== null);
117
+
118
+ if (mapImages.length > 0) {
119
+ await createBackgroundImageFade(mapImages);
120
+ }
121
+
122
+ const defaultPlaceholder = 'data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" width="1620" height="1024"><rect fill="%231b2a41" width="100%" height="100%"/></svg>';
123
+ const mapsData = maps.map((map) => {
124
+ const mapImageUrl = map.mapImage
125
+ ? (map.mapImage.startsWith('http') ? map.mapImage : `/${map.mapImage}`)
126
+ : (mapImages.length > 0 ? mapImages[0] : defaultPlaceholder);
127
+ return {
128
+ ...map,
129
+ mapImageUrl,
130
+ mapDescription: map.mapDescription || 'No description available',
131
+ };
132
+ });
133
+
134
+ const mainElement = document.querySelector('main');
135
+ if (!mainElement) return;
136
+
137
+ mainElement.innerHTML = '';
138
+ mapsData.forEach((map) => {
139
+ const section = document.createElement('section');
140
+ section.className = 'card-map';
141
+ section.innerHTML = Mustache.render(CARD_TEMPLATE, map);
142
+
143
+ const testBtn = section.querySelector('.map-testurl a');
144
+ if (testBtn) {
145
+ testBtn.addEventListener('click', (e) => {
146
+ e.preventDefault();
147
+ const host = window.location.host;
148
+ let path = window.location.pathname;
149
+ if (path.endsWith('index.html')) {
150
+ path = path.slice(0, -'index.html'.length);
151
+ }
152
+ const instanceId = Math.random().toString(36).substring(2, 15);
153
+ const url = `https://play.workadventu.re/_/${instanceId}/${host}${path}${map.path}`;
154
+ window.open(url, '_blank');
155
+ });
156
+ }
157
+ mainElement.appendChild(section);
158
+ });
159
+ } catch (error) {
160
+ console.error('Error loading maps:', error);
161
+ }
162
+ }
163
+
164
+ export { getMapsList, getImagesList, createBackgroundImageFade, loadTMJ };
@@ -0,0 +1,71 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+
4
+ <head>
5
+ <meta charset="UTF-8">
6
+ <meta http-equiv="X-UA-Compatible" content="IE=edge">
7
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
8
+ <meta name="robots" content="noindex">
9
+ <meta name="title" content="WorkAdventure Starter Kit">
10
+
11
+ <link href="public/styles/styles.css" rel="stylesheet">
12
+
13
+ <title>WorkAdventure build your map</title>
14
+ <link rel="icon" href="public/images/favicon.svg" type="image/svg+xml">
15
+ <script type="module">
16
+ document.addEventListener("DOMContentLoaded", () => {
17
+ import('/public/assets/js/index.js').then((module) => {
18
+ module.loadTMJ();
19
+ });
20
+ });
21
+ </script>
22
+ </head>
23
+
24
+ <body>
25
+ <div class="content">
26
+ <header>
27
+ <div class="logo">
28
+ <a href="https://workadventu.re/" target="_blank" title="Workadventure">
29
+ <img src="public/images/logo.svg" alt="Workadventure logo" height="36" />
30
+ </a>
31
+ </div>
32
+ <div style="flex-grow: 1;"></div>
33
+ <div class="socials">
34
+ <a href="https://discord.gg/G6Xh9ZM9aR" target="_blank" title="discord">
35
+ <img src="/public/images/brand-discord.svg" alt="discord">
36
+ </a>
37
+ <a href="https://github.com/thecodingmachine/workadventure" target="_blank" title="github">
38
+ <img src="/public/images/brand-github.svg" alt="github">
39
+ </a>
40
+ <a href="https://www.youtube.com/channel/UCXJ9igV-kb9gw1ftR33y5tA" target="_blank" title="youtube">
41
+ <img src="/public/images/brand-youtube.svg" alt="youtube">
42
+ </a>
43
+ <a href="https://twitter.com/Workadventure_" target="_blank" title="twitter">
44
+ <img src="/public/images/brand-x.svg" alt="X">
45
+ </a>
46
+ <a href="https://www.linkedin.com/company/workadventu-re" target="_blank" title="linkedin">
47
+ <img src="/public/images/brand-linkedin.svg" alt="linkedin">
48
+ </a>
49
+ </div>
50
+ <div class="btn-header-wrapper">
51
+ <a href="https://discord.gg/G6Xh9ZM9aR" target="_blank" class="btn btn-light">Talk to the community</a>
52
+ <a href="https://docs.workadventu.re/map-building/" target="_blank" class="btn">Documentation</a>
53
+ </div>
54
+ </header>
55
+ <main>
56
+ <!-- Map cards are injected here by index.js -->
57
+ </main>
58
+ <div class="button-wrapper">
59
+ <div style="flex-grow: 1;">
60
+ </div>
61
+ <div>
62
+ <a href="step1-git">
63
+ Publish
64
+ </a>
65
+ </div>
66
+ </div>
67
+ </div>
68
+ <div class="bg"></div>
69
+ </body>
70
+
71
+ </html>
@@ -0,0 +1,154 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+
4
+ <head>
5
+ <meta charset="UTF-8">
6
+ <meta http-equiv="X-UA-Compatible" content="IE=edge">
7
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
8
+ <meta name="robots" content="noindex">
9
+ <meta name="title" content="WorkAdventure Starter Kit">
10
+
11
+ <link href="public/styles/styles.css" rel="stylesheet">
12
+
13
+ <title>WorkAdventure build your map</title>
14
+ <link rel="icon" href="public/images/favicon.svg" type="image/svg+xml">
15
+ <script type="module">
16
+ document.addEventListener("DOMContentLoaded", (event) => {
17
+ // Load index.js to have access to getMapsList
18
+ import('/public/assets/js/index.js').then((module) => {
19
+ module.createBackgroundImageFade();
20
+ });
21
+ });
22
+ </script>
23
+ </head>
24
+
25
+ <body>
26
+ <div class="content">
27
+ <header>
28
+ <div class="logo">
29
+ <a href="https://workadventu.re/" target="_blank" title="Workadventure">
30
+ <img src="public/images/logo.svg" alt="Workadventure logo" height="36" />
31
+ </a>
32
+ </div>
33
+ <div style="flex-grow: 1;"></div>
34
+ <div class="socials">
35
+ <a href="https://discord.gg/G6Xh9ZM9aR" target="_blank" title="discord">
36
+ <img src="/public/images/brand-discord.svg" alt="discord">
37
+ </a>
38
+ <a href="https://github.com/thecodingmachine/workadventure" target="_blank" title="github">
39
+ <img src="/public/images/brand-github.svg" alt="github">
40
+ </a>
41
+ <a href="https://www.youtube.com/channel/UCXJ9igV-kb9gw1ftR33y5tA" target="_blank" title="youtube">
42
+ <img src="/public/images/brand-youtube.svg" alt="youtube">
43
+ </a>
44
+ <a href="https://twitter.com/Workadventure_" target="_blank" title="twitter">
45
+ <img src="/public/images/brand-x.svg" alt="X">
46
+ </a>
47
+ <a href="https://www.linkedin.com/company/workadventu-re" target="_blank" title="linkedin">
48
+ <img src="/public/images/brand-linkedin.svg" alt="linkedin">
49
+ </a>
50
+ </div>
51
+ <div class="btn-header-wrapper">
52
+ <a href="https://discord.gg/G6Xh9ZM9aR" target="_blank" class="btn btn-light">Talk to the community</a>
53
+ <a href="https://docs.workadventu.re/map-building/" target="_blank" class="btn">Documentation</a>
54
+ </div>
55
+ </header>
56
+ <main>
57
+ <section class="form-center">
58
+ <h1>
59
+ How do you want to publish your map?
60
+ </h1>
61
+ <div class="sub-heading">
62
+ Choose the workflow that best fits your team and your way of working.
63
+ </div>
64
+ <div class="radio-wrapper">
65
+ <label class="radio-card">
66
+ <input name="advanced" class="radio" type="radio">
67
+ <div class="card-details">
68
+ <svg width="39" height="39" viewBox="0 0 39 39" fill="none" xmlns="http://www.w3.org/2000/svg">
69
+ <path d="M8.125 19.5L16.25 27.625L32.5 11.375" stroke="#4156F6" stroke-width="3" stroke-linecap="round" stroke-linejoin="round"/>
70
+ </svg>
71
+
72
+ <h2>
73
+ Advanced publishing
74
+ </h2>
75
+ <div>
76
+ <strong>Designed for teams using Git and file versioning.</strong>
77
+ Full control over your files and collaboration workflow.
78
+ </div>
79
+ </div>
80
+ </label>
81
+ <label class="radio-card">
82
+ <input name="advanced" class="radio" type="radio" checked>
83
+ <div class="card-details">
84
+ <svg width="39" height="39" viewBox="0 0 39 39" fill="none" xmlns="http://www.w3.org/2000/svg">
85
+ <path d="M8.125 19.5L16.25 27.625L32.5 11.375" stroke="#4156F6" stroke-width="3" stroke-linecap="round" stroke-linejoin="round"/>
86
+ </svg>
87
+
88
+ <h2>
89
+ Recommended publishing
90
+ </h2>
91
+ <div>
92
+ <strong>The easiest and fastest way to publish your map.</strong>
93
+ No technical setup required. Ideal for getting started quickly.
94
+ </div>
95
+ </div>
96
+ </label>
97
+ </div>
98
+
99
+ </section>
100
+ </main>
101
+ <div class="button-wrapper">
102
+ <div>
103
+ <a href="/" class="btn btn-ghost">
104
+ Previous
105
+ </a>
106
+ </div>
107
+ <div style="flex-grow: 1;">
108
+ </div>
109
+ <div>
110
+ <a href="step2-hosting" class="btn btn-secondary">
111
+ Start configuration
112
+ </a>
113
+ </div>
114
+ </div>
115
+ </div>
116
+ <div class="bg"></div>
117
+ <script>
118
+ // Get radio buttons by finding the label containing "Advanced publishing"
119
+ const radioButtons = document.querySelectorAll('input[name="advanced"]');
120
+ const startConfigButton = document.querySelector('a[href="step2-hosting"]');
121
+ const docUrl = "https://docs.workadventu.re/map-building/tiled-editor/publish/wa-hosted";
122
+
123
+ // Find Advanced publishing radio button by checking parent label text
124
+ let advancedPublishingRadio = null;
125
+ radioButtons.forEach(radio => {
126
+ const label = radio.closest('label');
127
+ if (label && label.textContent.includes('Advanced publishing')) {
128
+ advancedPublishingRadio = radio;
129
+ }
130
+ });
131
+
132
+ // Function to update button href based on selection
133
+ function updateButtonHref() {
134
+ // Check if Advanced publishing is selected
135
+ if (advancedPublishingRadio && advancedPublishingRadio.checked) {
136
+ startConfigButton.href = docUrl;
137
+ startConfigButton.target = "_blank";
138
+ } else {
139
+ startConfigButton.href = "step2-hosting";
140
+ startConfigButton.removeAttribute("target");
141
+ }
142
+ }
143
+
144
+ // Add event listeners to all radio buttons
145
+ radioButtons.forEach(radio => {
146
+ radio.addEventListener('change', updateButtonHref);
147
+ });
148
+
149
+ // Initialize on page load
150
+ updateButtonHref();
151
+ </script>
152
+ </body>
153
+
154
+ </html>
@@ -0,0 +1,153 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+
4
+ <head>
5
+ <meta charset="UTF-8">
6
+ <meta http-equiv="X-UA-Compatible" content="IE=edge">
7
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
8
+ <meta name="robots" content="noindex">
9
+ <meta name="title" content="WorkAdventure Starter Kit">
10
+
11
+ <link href="public/styles/styles.css" rel="stylesheet">
12
+
13
+ <title>WorkAdventure build your map</title>
14
+ <link rel="icon" href="public/images/favicon.svg" type="image/svg+xml">
15
+ </head>
16
+
17
+ <body>
18
+ <div class="content">
19
+ <header>
20
+ <div class="logo">
21
+ <a href="https://workadventu.re/" target="_blank" title="Workadventure">
22
+ <img src="public/images/logo.svg" alt="Workadventure logo" height="36" />
23
+ </a>
24
+ </div>
25
+ <div style="flex-grow: 1;"></div>
26
+ <div class="socials">
27
+ <a href="https://discord.gg/G6Xh9ZM9aR" target="_blank" title="discord">
28
+ <img src="/public/images/brand-discord.svg" alt="discord">
29
+ </a>
30
+ <a href="https://github.com/thecodingmachine/workadventure" target="_blank" title="github">
31
+ <img src="/public/images/brand-github.svg" alt="github">
32
+ </a>
33
+ <a href="https://www.youtube.com/channel/UCXJ9igV-kb9gw1ftR33y5tA" target="_blank" title="youtube">
34
+ <img src="/public/images/brand-youtube.svg" alt="youtube">
35
+ </a>
36
+ <a href="https://twitter.com/Workadventure_" target="_blank" title="twitter">
37
+ <img src="/public/images/brand-x.svg" alt="X">
38
+ </a>
39
+ <a href="https://www.linkedin.com/company/workadventu-re" target="_blank" title="linkedin">
40
+ <img src="/public/images/brand-linkedin.svg" alt="linkedin">
41
+ </a>
42
+ </div>
43
+ <div class="btn-header-wrapper">
44
+ <a href="#" class="btn btn-light">Talk to the community</a>
45
+ <a href="#" class="btn">Documentation</a>
46
+ </div>
47
+ <script type="module">
48
+ document.addEventListener("DOMContentLoaded", (event) => {
49
+ // Load index.js to have access to getMapsList
50
+ import('/public/assets/js/index.js').then((module) => {
51
+ module.createBackgroundImageFade();
52
+ });
53
+ });
54
+ </script>
55
+ </header>
56
+ <main>
57
+ <section class="form-center">
58
+ <h1>
59
+ Which version of WorkAdventure do you use?
60
+ </h1>
61
+ <div class="sub-heading">
62
+ Choose the setup that matches how your WorkAdventure instance is running. This will help us adapt the publishing process to your setup.
63
+ </div>
64
+ <div class="radio-wrapper">
65
+ <label class="radio-card">
66
+ <input name="advanced" class="radio" type="radio">
67
+ <div class="card-details">
68
+ <svg width="39" height="39" viewBox="0 0 39 39" fill="none" xmlns="http://www.w3.org/2000/svg">
69
+ <path d="M8.125 19.5L16.25 27.625L32.5 11.375" stroke="#4156F6" stroke-width="3" stroke-linecap="round" stroke-linejoin="round"/>
70
+ </svg>
71
+
72
+ <h2>
73
+ I use self-hosted
74
+ </h2>
75
+ <div>
76
+ Your map is published on your own WorkAdventure instance.
77
+ <strong>You manage the hosting, configuration, and updates yourself.</strong>
78
+ </div>
79
+ </div>
80
+ </label>
81
+ <label class="radio-card">
82
+ <input name="advanced" class="radio" type="radio">
83
+ <div class="card-details">
84
+ <svg width="39" height="39" viewBox="0 0 39 39" fill="none" xmlns="http://www.w3.org/2000/svg">
85
+ <path d="M8.125 19.5L16.25 27.625L32.5 11.375" stroke="#4156F6" stroke-width="3" stroke-linecap="round" stroke-linejoin="round"/>
86
+ </svg>
87
+
88
+ <h2>
89
+ I use SaaS version
90
+ </h2>
91
+ <div>
92
+ Your map is published on the WorkAdventure platform.
93
+ <strong>We handle hosting, updates, and infrastructure for you.</strong>
94
+ </div>
95
+ </div>
96
+ </label>
97
+ </div>
98
+
99
+ </section>
100
+ </main>
101
+ <div class="button-wrapper">
102
+ <div>
103
+ <a href="step1-git" class="btn btn-ghost">
104
+ Previous
105
+ </a>
106
+ </div>
107
+ <div style="flex-grow: 1;">
108
+ </div>
109
+ <div>
110
+ <a href="step3-steps" class="btn btn-secondary">
111
+ Configure
112
+ </a>
113
+ </div>
114
+ </div>
115
+ </div>
116
+ <div class="bg"></div>
117
+ <script>
118
+ // Get radio buttons by finding the label containing "I use self-hosted"
119
+ const radioButtons = document.querySelectorAll('input[name="advanced"]');
120
+ const configureButton = document.querySelector('a[href="step3-steps"]');
121
+
122
+ // Find "I use self-hosted" radio button by checking parent label text
123
+ let selfHostedRadio = null;
124
+ radioButtons.forEach(radio => {
125
+ const label = radio.closest('label');
126
+ if (label && label.textContent.includes('I use self-hosted')) {
127
+ selfHostedRadio = radio;
128
+ }
129
+ });
130
+
131
+ // Function to update button href based on selection
132
+ function updateButtonHref() {
133
+ // Check if "I use self-hosted" is selected
134
+ if (selfHostedRadio && selfHostedRadio.checked) {
135
+ configureButton.href = "step3-steps-selfhosted";
136
+ configureButton.removeAttribute("target");
137
+ } else {
138
+ configureButton.href = "step3-steps";
139
+ configureButton.removeAttribute("target");
140
+ }
141
+ }
142
+
143
+ // Add event listeners to all radio buttons
144
+ radioButtons.forEach(radio => {
145
+ radio.addEventListener('change', updateButtonHref);
146
+ });
147
+
148
+ // Initialize on page load
149
+ updateButtonHref();
150
+ </script>
151
+ </body>
152
+
153
+ </html>