@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.
- package/README.md +165 -0
- package/dist/assets/js/index.js +164 -0
- package/dist/assets/views/index.html +71 -0
- package/dist/assets/views/step1-git.html +154 -0
- package/dist/assets/views/step2-hosting.html +153 -0
- package/dist/assets/views/step3-steps-selfhosted.html +502 -0
- package/dist/assets/views/step3-steps.html +549 -0
- package/dist/assets/views/step4-validated-selfhosted.html +188 -0
- package/dist/assets/views/step4-validated.html +80 -0
- package/dist/images/world-select.png +0 -0
- package/dist/server.js +4 -4
- package/dist/server.js.map +1 -1
- package/dist/styles/styles.css +1 -8
- package/package.json +3 -1
- package/public/assets/js/index.js +164 -0
- package/public/assets/views/index.html +71 -0
- package/public/assets/views/step1-git.html +154 -0
- package/public/assets/views/step2-hosting.html +153 -0
- package/public/assets/views/step3-steps-selfhosted.html +502 -0
- package/public/assets/views/step3-steps.html +549 -0
- package/public/assets/views/step4-validated-selfhosted.html +188 -0
- package/public/assets/views/step4-validated.html +80 -0
- package/public/images/badumtss.svg +12 -0
- package/public/images/brand-discord.svg +22 -0
- package/public/images/brand-github.svg +19 -0
- package/public/images/brand-linkedin.svg +23 -0
- package/public/images/brand-x.svg +20 -0
- package/public/images/brand-youtube.svg +20 -0
- package/public/images/favicon.svg +50 -0
- package/public/images/logo.svg +72 -0
- package/public/images/world-select.png +0 -0
- package/public/styles/styles.css +424 -0
- package/public/styles/styles.css.map +1 -0
- package/types/server.d.ts +5 -0
- package/dist/assets/index.js +0 -80
- /package/{dist/images/unknown-room-image copy.png → public/images/unknown-room-image.png} +0 -0
package/README.md
ADDED
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
# @workadventure/map-starter-kit-core
|
|
2
|
+
|
|
3
|
+
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.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- **Web UI** – Step-by-step wizard (Git, hosting, steps, validation) for setting up and validating your map project
|
|
8
|
+
- **Map listing** – Discovers `.tmj` maps on disk with properties (name, description, image, copyright, size, last modified)
|
|
9
|
+
- **Uploader** – Configure and run map uploads to [map-storage](https://github.com/workadventure/map-storage); list maps from map-storage for self-hosted flows
|
|
10
|
+
- **Static assets** – Serves public assets, tilesets, and compiled JS; transforms and serves TypeScript under `/src` (esbuild) for browser scripts
|
|
11
|
+
- **Express app** – CORS, JSON body parsing, cache headers; can be mounted in another app or run standalone via Vite
|
|
12
|
+
|
|
13
|
+
## Installation
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
npm install @workadventure/map-starter-kit-core
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
**Peer / consumer:** The built server expects `express` to be available at runtime. For TypeScript consumers, `@types/express` is used for the exported `Application` type.
|
|
20
|
+
|
|
21
|
+
## Usage
|
|
22
|
+
|
|
23
|
+
### As a dependency (programmatic)
|
|
24
|
+
|
|
25
|
+
Use the built Express app in your own server:
|
|
26
|
+
|
|
27
|
+
```ts
|
|
28
|
+
import core from "@workadventure/map-starter-kit-core/dist/server.js";
|
|
29
|
+
|
|
30
|
+
const app = core.default; // or core.viteNodeApp
|
|
31
|
+
|
|
32
|
+
// Mount or start your server
|
|
33
|
+
app.listen(3000, () => console.log("Listening on 3000"));
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
Types are provided: `core` is typed as `{ default: Application; viteNodeApp: Application }` (see `types/server.d.ts`).
|
|
37
|
+
|
|
38
|
+
### Development server (standalone)
|
|
39
|
+
|
|
40
|
+
From the **map-starter-kit** repo (or a project that uses this package as the core):
|
|
41
|
+
|
|
42
|
+
```bash
|
|
43
|
+
npm run dev
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
Runs the Vite dev server with vite-plugin-node (Express). Opens the app at the configured host (e.g. `http://localhost:5173/`).
|
|
47
|
+
|
|
48
|
+
### Build for production
|
|
49
|
+
|
|
50
|
+
```bash
|
|
51
|
+
npm run build
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
- Runs `tsc` (type-check only; `noEmit: true` in tsconfig)
|
|
55
|
+
- Builds the server bundle with Vite into `dist/server.js`
|
|
56
|
+
- Copies `types/server.d.ts` to `dist/server.d.ts` for published types
|
|
57
|
+
|
|
58
|
+
## Project structure
|
|
59
|
+
|
|
60
|
+
```
|
|
61
|
+
map-starter-kit-core/
|
|
62
|
+
├── src/
|
|
63
|
+
│ ├── server.ts # Express app entry (CORS, static, routes)
|
|
64
|
+
│ ├── getCoreRoot.ts # Resolve core package root (cwd vs package dir)
|
|
65
|
+
│ ├── controllers/
|
|
66
|
+
│ │ ├── FrontController.ts # HTML pages (Mustache): /, step1-git, step2-hosting, step3-*, step4-*
|
|
67
|
+
│ │ ├── MapController.ts # /maps/list – list .tmj maps with properties
|
|
68
|
+
│ │ └── UploaderController.ts # /uploader/* – configure, status, maps-storage-list, upload
|
|
69
|
+
│ └── views/ # Mustache HTML templates
|
|
70
|
+
│ ├── index.html
|
|
71
|
+
│ ├── step1-git.html … step4-validated-selfhosted.html
|
|
72
|
+
├── public/ # Static assets (images, styles, etc.)
|
|
73
|
+
├── types/
|
|
74
|
+
│ └── server.d.ts # Module declaration for dist/server.js (copied to dist on build)
|
|
75
|
+
├── dist/ # Build output (server.js, server.d.ts, assets)
|
|
76
|
+
├── vite.config.ts
|
|
77
|
+
├── tsconfig.json
|
|
78
|
+
└── package.json
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
## API / Routes
|
|
82
|
+
|
|
83
|
+
| Method | Path | Description |
|
|
84
|
+
|--------|------|-------------|
|
|
85
|
+
| **Front (HTML)** | | |
|
|
86
|
+
| GET | `/` | Home (index) |
|
|
87
|
+
| GET | `/step1-git` | Step 1 – Git |
|
|
88
|
+
| GET | `/step2-hosting` | Step 2 – Hosting |
|
|
89
|
+
| GET | `/step3-steps` | Step 3 – Steps |
|
|
90
|
+
| GET | `/step3-steps-selfhosted` | Step 3 – Self-hosted |
|
|
91
|
+
| GET | `/step4-validated` | Step 4 – Validated |
|
|
92
|
+
| GET | `/step4-validated-selfhosted` | Step 4 – Validated (self-hosted) |
|
|
93
|
+
| **Maps** | | |
|
|
94
|
+
| GET | `/maps/list` | List `.tmj` maps with properties (path, mapName, mapImage, size, lastModified, etc.) |
|
|
95
|
+
| **Uploader** | | |
|
|
96
|
+
| POST | `/uploader/configure` | Configure MAP_STORAGE (body: `mapStorageUrl`, `mapStorageApiKey`, `uploadDirectory`) |
|
|
97
|
+
| GET | `/uploader/status` | Current config status (e.g. presence of `.env.secret`) |
|
|
98
|
+
| GET | `/uploader/maps-storage-list` | List maps from map-storage (for self-hosted step 4) |
|
|
99
|
+
| POST | `/uploader/upload` | Run the upload (uses config from `.env.secret`) |
|
|
100
|
+
|
|
101
|
+
Static and special paths:
|
|
102
|
+
|
|
103
|
+
- `/public/*` – Static files from core’s `public/`
|
|
104
|
+
- `/assets/*` – From project’s `dist/assets/`
|
|
105
|
+
- `/tilesets/*` – From project’s `tilesets/`
|
|
106
|
+
- `/src/*.ts` – Served as compiled JS (esbuild), e.g. for browser scripts using WorkAdventure APIs
|
|
107
|
+
|
|
108
|
+
## Configuration
|
|
109
|
+
|
|
110
|
+
### Uploader (MAP_STORAGE)
|
|
111
|
+
|
|
112
|
+
Configure via **POST `/uploader/configure`** with:
|
|
113
|
+
|
|
114
|
+
- `mapStorageUrl` – map-storage base URL
|
|
115
|
+
- `mapStorageApiKey` – API key for map-storage
|
|
116
|
+
- `uploadDirectory` – Local directory to upload from
|
|
117
|
+
|
|
118
|
+
This writes (or updates) a secret file (e.g. `.env.secret` or `src/.env.secret` depending on route) used by the upload and maps-storage-list endpoints. Do not commit this file.
|
|
119
|
+
|
|
120
|
+
### Core root
|
|
121
|
+
|
|
122
|
+
`getCoreRoot()` resolves the root of the core package:
|
|
123
|
+
|
|
124
|
+
- When run from the **project root** (e.g. map-starter-kit): `process.cwd()`
|
|
125
|
+
- When run from **packages/map-starter-kit-core** or **node_modules**: the package directory
|
|
126
|
+
|
|
127
|
+
So templates and `public` are always loaded from the core package, while maps, `.env`, and `tilesets` stay in the project root.
|
|
128
|
+
|
|
129
|
+
## Scripts
|
|
130
|
+
|
|
131
|
+
| Script | Command | Description |
|
|
132
|
+
|--------|---------|-------------|
|
|
133
|
+
| `dev` | `vite` | Start dev server (Express via vite-plugin-node) |
|
|
134
|
+
| `build` | `tsc && vite build && node -e "…"` | Type-check, build server to `dist/`, copy `server.d.ts` |
|
|
135
|
+
|
|
136
|
+
## Releasing
|
|
137
|
+
|
|
138
|
+
Releases are automated with **semantic-release** and **GitHub Actions**:
|
|
139
|
+
|
|
140
|
+
- **Workflow:** `.github/workflows/release.yml`
|
|
141
|
+
- **Trigger:** Push to `main` or `master`
|
|
142
|
+
- **Conventions:** [Conventional Commits](https://www.conventionalcommits.org/) (`feat:`, `fix:`, `BREAKING CHANGE:`) determine the next version; a release is published only when there are relevant commits.
|
|
143
|
+
- **Artifacts:** GitHub Release + **npm** publish of `@workadventure/map-starter-kit-core`.
|
|
144
|
+
|
|
145
|
+
**npm auth (after classic token deprecation):**
|
|
146
|
+
|
|
147
|
+
- **Recommended:** [Trusted Publishing (OIDC)](https://docs.npmjs.com/trusted-publishers) for this repo and workflow (no long-lived token).
|
|
148
|
+
- **Alternative:** Create a **granular access token** on [npm](https://www.npmjs.com/settings/~/tokens), then set the **NPM_TOKEN** secret in the repo.
|
|
149
|
+
|
|
150
|
+
## Tech stack
|
|
151
|
+
|
|
152
|
+
- **Runtime:** Node.js, Express 5
|
|
153
|
+
- **Build:** TypeScript 5, Vite 7, vite-plugin-node
|
|
154
|
+
- **Templates:** Mustache
|
|
155
|
+
- **Release:** semantic-release
|
|
156
|
+
|
|
157
|
+
## License
|
|
158
|
+
|
|
159
|
+
MIT. See [LICENSE](LICENSE).
|
|
160
|
+
|
|
161
|
+
## Links
|
|
162
|
+
|
|
163
|
+
- **Repository:** [github.com/workadventure/map-starter-kit-core](https://github.com/workadventure/map-starter-kit-core)
|
|
164
|
+
- **Issues:** [github.com/workadventure/map-starter-kit-core/issues](https://github.com/workadventure/map-starter-kit-core/issues)
|
|
165
|
+
- **npm:** [@workadventure/map-starter-kit-core](https://www.npmjs.com/package/@workadventure/map-starter-kit-core)
|
|
@@ -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>
|