@hexah/create-skin 0.1.0
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/LICENSE +21 -0
- package/README.md +34 -0
- package/index.js +57 -0
- package/lib/scaffold.js +75 -0
- package/package.json +40 -0
- package/template/README.md +41 -0
- package/template/_gitignore +4 -0
- package/template/_package.json +23 -0
- package/template/rspack.config.js +56 -0
- package/template/src/ReportScreen.jsx +71 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Hexah Team
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
# @hexah/create-skin
|
|
2
|
+
|
|
3
|
+
Scaffolder skórki Hexah — generuje projekt **zdalnej skórki Module Federation** (rspack +
|
|
4
|
+
`@hexah/skin-sdk`) z gotowym workflowem dev (HMR) i podłączeniem do hosta na środowisku
|
|
5
|
+
testowym.
|
|
6
|
+
|
|
7
|
+
## Użycie
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
npm create @hexah/skin moja-skorka # albo: npx @hexah/create-skin moja-skorka
|
|
11
|
+
cd moja-skorka
|
|
12
|
+
npm install
|
|
13
|
+
npm run dev # rspack serve z HMR
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
Następnie podłącz remote do hosta na teście (instrukcja w wygenerowanym `README.md` skórki):
|
|
17
|
+
`localStorage["hexah.skinRemote"]` + motyw „SDK Remote (zdalna skórka)".
|
|
18
|
+
|
|
19
|
+
## Co generuje
|
|
20
|
+
|
|
21
|
+
Starter (`template/`) z placeholderami `__SKIN_NAME__` / `__SKIN_FEDERATION_NAME__`:
|
|
22
|
+
|
|
23
|
+
- `rspack.config.js` — `ModuleFederationPlugin` wystawiający `./ReportScreen`, paczki
|
|
24
|
+
współdzielone z hostem (`import: false`), dev server na `:3001` z CORS.
|
|
25
|
+
- `src/ReportScreen.jsx` — przykładowy ekran na `@hexah/skin-sdk`.
|
|
26
|
+
- `package.json`, `.gitignore`, `README.md`.
|
|
27
|
+
|
|
28
|
+
Nazwa kontenera MF jest sanityzowana z nazwy katalogu (`toFederationName` — identyfikator JS).
|
|
29
|
+
|
|
30
|
+
## Status
|
|
31
|
+
|
|
32
|
+
POC etapu C. Publikowany jako `@hexah/create-skin` (licencja MIT) przez ręczny workflow —
|
|
33
|
+
patrz `docs/skin-sdk/publishing.md`. Przed publikacją działa tylko z repo
|
|
34
|
+
(`node packages/create-hexah-skin/index.js <katalog>`). Pełne demo wymaga środowiska testowego.
|
package/index.js
ADDED
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
"use strict";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* create-hexah-skin — scaffolder skórki Hexah (zdalny kontener Module Federation).
|
|
6
|
+
* Użycie: `npx create-hexah-skin <katalog>` (lub `node index.js <katalog>`).
|
|
7
|
+
*
|
|
8
|
+
* Tworzy projekt skórki ze startera (rspack + MF + `@hexah/skin-sdk`) i wypisuje kolejne
|
|
9
|
+
* kroki: `npm run dev` (rspack serve z HMR) oraz jak podłączyć remote do hosta na teście.
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
const fs = require("fs");
|
|
13
|
+
const path = require("path");
|
|
14
|
+
const { toFederationName, copyTemplate } = require("./lib/scaffold");
|
|
15
|
+
|
|
16
|
+
/** @param {string[]} argv @returns {number} kod wyjścia */
|
|
17
|
+
function main(argv) {
|
|
18
|
+
const target = argv[2];
|
|
19
|
+
if (!target) {
|
|
20
|
+
console.error("Użycie: create-hexah-skin <katalog>");
|
|
21
|
+
return 1;
|
|
22
|
+
}
|
|
23
|
+
const destDir = path.resolve(process.cwd(), target);
|
|
24
|
+
if (fs.existsSync(destDir) && fs.readdirSync(destDir).length > 0) {
|
|
25
|
+
console.error(`Katalog „${target}" istnieje i nie jest pusty — przerywam.`);
|
|
26
|
+
return 1;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
const skinName = path.basename(destDir);
|
|
30
|
+
const federationName = toFederationName(skinName);
|
|
31
|
+
const templateDir = path.join(__dirname, "template");
|
|
32
|
+
copyTemplate(templateDir, destDir, { skinName, federationName });
|
|
33
|
+
|
|
34
|
+
console.log(`✓ Skórka „${skinName}" utworzona w ${target}`);
|
|
35
|
+
console.log("");
|
|
36
|
+
console.log("Dalej:");
|
|
37
|
+
console.log(` cd ${target}`);
|
|
38
|
+
console.log(" npm install");
|
|
39
|
+
console.log(" npm run dev # rspack serve z HMR (np. http://localhost:3001/remoteEntry.js)");
|
|
40
|
+
console.log("");
|
|
41
|
+
console.log("Podłączenie do hosta (środowisko testowe) — w konsoli przeglądarki:");
|
|
42
|
+
console.log(
|
|
43
|
+
` localStorage.setItem('hexah.skinRemote', JSON.stringify({ name: '${federationName}',`,
|
|
44
|
+
);
|
|
45
|
+
console.log(
|
|
46
|
+
" entry: 'http://localhost:3001/remoteEntry.js', template: 'sdkremote',",
|
|
47
|
+
);
|
|
48
|
+
console.log(" screens: { report: './ReportScreen' }, apiVersion: '0.2.0' }))");
|
|
49
|
+
console.log("Następnie w Ustawieniach Gry wybierz motyw „SDK Remote (zdalna skórka)\".");
|
|
50
|
+
return 0;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
if (require.main === module) {
|
|
54
|
+
process.exit(main(process.argv));
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
module.exports = { main };
|
package/lib/scaffold.js
ADDED
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Czyste funkcje scaffoldu skórki — łatwe do testu, bez efektów sieciowych.
|
|
5
|
+
* CLI (`../index.js`) tylko spina je z argv i FS.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
const fs = require("fs");
|
|
9
|
+
const path = require("path");
|
|
10
|
+
|
|
11
|
+
/** Pliki template'u zapisane z prefiksem `_`, by nie kolidować z narzędziami repo. */
|
|
12
|
+
const RENAME = Object.freeze({
|
|
13
|
+
"_package.json": "package.json",
|
|
14
|
+
"_gitignore": ".gitignore",
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Sanityzuje nazwę skórki do poprawnej nazwy kontenera Module Federation
|
|
19
|
+
* (identyfikator JS: małe litery, cyfry, `_`; nie zaczyna się od cyfry).
|
|
20
|
+
* @param {string} skinName
|
|
21
|
+
* @returns {string}
|
|
22
|
+
*/
|
|
23
|
+
function toFederationName(skinName) {
|
|
24
|
+
const cleaned = String(skinName)
|
|
25
|
+
.trim()
|
|
26
|
+
.toLowerCase()
|
|
27
|
+
.replace(/[^a-z0-9]+/g, "_")
|
|
28
|
+
.replace(/^_+|_+$/g, "");
|
|
29
|
+
const base = cleaned || "skin";
|
|
30
|
+
return /^[0-9]/.test(base) ? `skin_${base}` : base;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Podstawia placeholdery template'u.
|
|
35
|
+
* @param {string} content
|
|
36
|
+
* @param {{ skinName: string, federationName: string }} vars
|
|
37
|
+
* @returns {string}
|
|
38
|
+
*/
|
|
39
|
+
function applyPlaceholders(content, vars) {
|
|
40
|
+
return content
|
|
41
|
+
.replace(/__SKIN_NAME__/g, vars.skinName)
|
|
42
|
+
.replace(/__SKIN_FEDERATION_NAME__/g, vars.federationName);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/** @param {string} file @returns {boolean} czy traktować jako tekst (placeholdery). */
|
|
46
|
+
function isTextFile(file) {
|
|
47
|
+
return /\.(js|jsx|json|md|txt)$/.test(file) || file === "_gitignore" || file === "_package.json";
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Kopiuje template do katalogu docelowego, podstawiając placeholdery i zmieniając nazwy
|
|
52
|
+
* z mapy {@link RENAME}. Zwraca listę zapisanych ścieżek.
|
|
53
|
+
* @param {string} srcDir
|
|
54
|
+
* @param {string} destDir
|
|
55
|
+
* @param {{ skinName: string, federationName: string }} vars
|
|
56
|
+
* @returns {string[]}
|
|
57
|
+
*/
|
|
58
|
+
function copyTemplate(srcDir, destDir, vars) {
|
|
59
|
+
fs.mkdirSync(destDir, { recursive: true });
|
|
60
|
+
const written = [];
|
|
61
|
+
for (const entry of fs.readdirSync(srcDir, { withFileTypes: true })) {
|
|
62
|
+
const src = path.join(srcDir, entry.name);
|
|
63
|
+
const dest = path.join(destDir, RENAME[entry.name] || entry.name);
|
|
64
|
+
if (entry.isDirectory()) {
|
|
65
|
+
written.push(...copyTemplate(src, dest, vars));
|
|
66
|
+
continue;
|
|
67
|
+
}
|
|
68
|
+
const raw = fs.readFileSync(src, "utf8");
|
|
69
|
+
fs.writeFileSync(dest, isTextFile(entry.name) ? applyPlaceholders(raw, vars) : raw);
|
|
70
|
+
written.push(dest);
|
|
71
|
+
}
|
|
72
|
+
return written;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
module.exports = { RENAME, toFederationName, applyPlaceholders, isTextFile, copyTemplate };
|
package/package.json
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@hexah/create-skin",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Scaffolder skórki Hexah (zdalny kontener Module Federation, harness dev z HMR).",
|
|
5
|
+
"bin": {
|
|
6
|
+
"create-hexah-skin": "index.js"
|
|
7
|
+
},
|
|
8
|
+
"main": "index.js",
|
|
9
|
+
"license": "MIT",
|
|
10
|
+
"author": "Hexah Team <kontakt@hexah.pl>",
|
|
11
|
+
"homepage": "https://github.com/Kroniki-Fallathanu/hexah/tree/develop/packages/create-hexah-skin#readme",
|
|
12
|
+
"repository": {
|
|
13
|
+
"type": "git",
|
|
14
|
+
"url": "git+https://github.com/Kroniki-Fallathanu/hexah.git",
|
|
15
|
+
"directory": "packages/create-hexah-skin"
|
|
16
|
+
},
|
|
17
|
+
"keywords": [
|
|
18
|
+
"hexah",
|
|
19
|
+
"skin",
|
|
20
|
+
"create",
|
|
21
|
+
"scaffold",
|
|
22
|
+
"module-federation"
|
|
23
|
+
],
|
|
24
|
+
"engines": {
|
|
25
|
+
"node": ">=20.16.0"
|
|
26
|
+
},
|
|
27
|
+
"files": [
|
|
28
|
+
"index.js",
|
|
29
|
+
"lib",
|
|
30
|
+
"template",
|
|
31
|
+
"LICENSE",
|
|
32
|
+
"README.md"
|
|
33
|
+
],
|
|
34
|
+
"publishConfig": {
|
|
35
|
+
"access": "public"
|
|
36
|
+
},
|
|
37
|
+
"scripts": {
|
|
38
|
+
"test": "node --test"
|
|
39
|
+
}
|
|
40
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
# __SKIN_NAME__
|
|
2
|
+
|
|
3
|
+
Skórka Hexah zbudowana jako **zdalny kontener Module Federation**. Działa na realnej
|
|
4
|
+
aplikacji Hexah (host) podpiętej do środowiska testowego — bez dostępu do kodu gry.
|
|
5
|
+
|
|
6
|
+
## Start
|
|
7
|
+
|
|
8
|
+
```bash
|
|
9
|
+
npm install
|
|
10
|
+
npm run dev # rspack serve z HMR → http://localhost:3001/remoteEntry.js
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## Podłączenie do hosta (środowisko testowe)
|
|
14
|
+
|
|
15
|
+
W konsoli przeglądarki na środowisku testowym Hexah:
|
|
16
|
+
|
|
17
|
+
```js
|
|
18
|
+
localStorage.setItem('hexah.skinRemote', JSON.stringify({
|
|
19
|
+
name: '__SKIN_FEDERATION_NAME__',
|
|
20
|
+
entry: 'http://localhost:3001/remoteEntry.js',
|
|
21
|
+
template: 'sdkremote',
|
|
22
|
+
screens: { report: './ReportScreen' },
|
|
23
|
+
apiVersion: '0.2.0',
|
|
24
|
+
}))
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
Odśwież, w **Ustawieniach Gry** wybierz motyw **„SDK Remote (zdalna skórka)"** i wejdź na ekran
|
|
28
|
+
zgłoszeń — zobaczysz swój `ReportScreen` na realnych danych. Dzięki HMR zmiany w `src/` są
|
|
29
|
+
widoczne po odświeżeniu (rebuild remote'a).
|
|
30
|
+
|
|
31
|
+
## Co możesz edytować
|
|
32
|
+
|
|
33
|
+
- `src/ReportScreen.jsx` — Twój ekran. Importuj wyłącznie z `@hexah/skin-sdk` (+ React/MUI).
|
|
34
|
+
- `rspack.config.js` → `exposes` — dołóż kolejne ekrany (klucze z `SCREEN_KEYS`).
|
|
35
|
+
|
|
36
|
+
## Zasady
|
|
37
|
+
|
|
38
|
+
- Importuj tylko z `@hexah/skin-sdk` — to publiczny kontrakt (stałe, typy, hooki, UI).
|
|
39
|
+
- Pakiety react/jotai/@mui/@emotion/@hexah/skin-sdk są współdzielone (`import: false`) —
|
|
40
|
+
nie pakujesz ich, bierzesz instancje hosta.
|
|
41
|
+
- Host ładuje skórkę tylko z dozwolonych originów i przy zgodnym `apiVersion`.
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "__SKIN_NAME__",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"private": true,
|
|
5
|
+
"description": "Skórka Hexah (zdalny kontener Module Federation).",
|
|
6
|
+
"scripts": {
|
|
7
|
+
"build": "rspack build",
|
|
8
|
+
"dev": "rspack serve",
|
|
9
|
+
"serve": "rspack serve"
|
|
10
|
+
},
|
|
11
|
+
"dependencies": {
|
|
12
|
+
"@hexah/skin-sdk": "^0.2.0"
|
|
13
|
+
},
|
|
14
|
+
"devDependencies": {
|
|
15
|
+
"@module-federation/enhanced": "^0.9.0",
|
|
16
|
+
"@rspack/cli": "^1.1.0",
|
|
17
|
+
"@rspack/core": "^1.1.0"
|
|
18
|
+
},
|
|
19
|
+
"peerDependencies": {
|
|
20
|
+
"react": "^19",
|
|
21
|
+
"react-dom": "^19"
|
|
22
|
+
}
|
|
23
|
+
}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
// @ts-nocheck
|
|
2
|
+
/**
|
|
3
|
+
* Build skórki „__SKIN_NAME__" jako zdalnego kontenera Module Federation.
|
|
4
|
+
*
|
|
5
|
+
* Pakiety react/jotai/@mui/@emotion/@hexah/skin-sdk są współdzielone z `import: false` —
|
|
6
|
+
* skórka ich NIE pakuje, konsumuje instancje hosta przez shareScope (jeden React, jeden
|
|
7
|
+
* store Jotai, jeden ThemeProvider). Wynik: `dist/remoteEntry.js`.
|
|
8
|
+
*/
|
|
9
|
+
const { ModuleFederationPlugin } = require("@module-federation/enhanced/rspack");
|
|
10
|
+
|
|
11
|
+
const singleton = (requiredVersion) => ({
|
|
12
|
+
singleton: true,
|
|
13
|
+
import: false,
|
|
14
|
+
requiredVersion,
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
module.exports = {
|
|
18
|
+
mode: "production",
|
|
19
|
+
entry: {},
|
|
20
|
+
output: { publicPath: "auto", uniqueName: "__SKIN_FEDERATION_NAME__" },
|
|
21
|
+
resolve: { extensions: [".js", ".jsx"] },
|
|
22
|
+
module: {
|
|
23
|
+
rules: [
|
|
24
|
+
{
|
|
25
|
+
test: /\.jsx?$/,
|
|
26
|
+
use: {
|
|
27
|
+
loader: "builtin:swc-loader",
|
|
28
|
+
options: {
|
|
29
|
+
jsc: {
|
|
30
|
+
parser: { syntax: "ecmascript", jsx: true },
|
|
31
|
+
transform: { react: { runtime: "automatic" } },
|
|
32
|
+
},
|
|
33
|
+
},
|
|
34
|
+
},
|
|
35
|
+
},
|
|
36
|
+
],
|
|
37
|
+
},
|
|
38
|
+
plugins: [
|
|
39
|
+
new ModuleFederationPlugin({
|
|
40
|
+
name: "__SKIN_FEDERATION_NAME__",
|
|
41
|
+
filename: "remoteEntry.js",
|
|
42
|
+
exposes: { "./ReportScreen": "./src/ReportScreen.jsx" },
|
|
43
|
+
shared: {
|
|
44
|
+
react: singleton("^19"),
|
|
45
|
+
"react-dom": singleton("^19"),
|
|
46
|
+
jotai: singleton("^2"),
|
|
47
|
+
"@emotion/react": singleton("^11"),
|
|
48
|
+
"@emotion/styled": singleton("^11"),
|
|
49
|
+
"@mui/material": singleton("^7"),
|
|
50
|
+
"@mui/material/styles": singleton("^7"),
|
|
51
|
+
"@hexah/skin-sdk": singleton("^0.2"),
|
|
52
|
+
},
|
|
53
|
+
}),
|
|
54
|
+
],
|
|
55
|
+
devServer: { port: 3001, headers: { "Access-Control-Allow-Origin": "*" } },
|
|
56
|
+
};
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Ekran skórki „__SKIN_NAME__" — importuje WYŁĄCZNIE z `@hexah/skin-sdk` (+ React/MUI jako
|
|
3
|
+
* współdzielone singletony hosta). Host ładuje go w runtime i rejestruje pod `SCREEN_KEYS.REPORT`.
|
|
4
|
+
*
|
|
5
|
+
* Edytuj swobodnie — to Twój punkt startowy. Read-modele (`useReports`…) i prymitywy UI
|
|
6
|
+
* (`PageBox`, `DataList`, `HexahChip`) dostarcza host; tu masz tylko ich kontrakt.
|
|
7
|
+
*/
|
|
8
|
+
import { useEffect, useMemo, useState } from "react";
|
|
9
|
+
import Box from "@mui/material/Box";
|
|
10
|
+
import Typography from "@mui/material/Typography";
|
|
11
|
+
import {
|
|
12
|
+
PageBox,
|
|
13
|
+
DataList,
|
|
14
|
+
HexahChip,
|
|
15
|
+
useReports,
|
|
16
|
+
useSnackbar,
|
|
17
|
+
useGamePageShell,
|
|
18
|
+
} from "@hexah/skin-sdk";
|
|
19
|
+
|
|
20
|
+
export default function ReportScreen() {
|
|
21
|
+
const reports = useReports();
|
|
22
|
+
const { notify } = useSnackbar();
|
|
23
|
+
const [issues, setIssues] = useState([]);
|
|
24
|
+
useGamePageShell(useMemo(() => ({ title: "Zgłoszenia (__SKIN_NAME__)" }), []));
|
|
25
|
+
|
|
26
|
+
useEffect(() => {
|
|
27
|
+
reports.list({
|
|
28
|
+
page: 1,
|
|
29
|
+
pageSize: 10,
|
|
30
|
+
callback: (ret) => {
|
|
31
|
+
if (ret?.error) {
|
|
32
|
+
notify([{ severity: "error", message: ret.error }]);
|
|
33
|
+
return;
|
|
34
|
+
}
|
|
35
|
+
setIssues(ret.issues || []);
|
|
36
|
+
},
|
|
37
|
+
});
|
|
38
|
+
}, [reports, notify]);
|
|
39
|
+
|
|
40
|
+
const items = useMemo(
|
|
41
|
+
() =>
|
|
42
|
+
issues.map((issue) => ({
|
|
43
|
+
id: issue.id,
|
|
44
|
+
title: `#${issue.issueNumber} ${issue.title}`,
|
|
45
|
+
chips: (
|
|
46
|
+
<HexahChip
|
|
47
|
+
label={issue.state === "closed" ? "Zamknięte" : "Otwarte"}
|
|
48
|
+
size="small"
|
|
49
|
+
/>
|
|
50
|
+
),
|
|
51
|
+
})),
|
|
52
|
+
[issues],
|
|
53
|
+
);
|
|
54
|
+
|
|
55
|
+
return (
|
|
56
|
+
<PageBox>
|
|
57
|
+
<Box sx={{ px: { xs: 2, sm: 3 }, pt: 2 }}>
|
|
58
|
+
<Typography variant="body2" sx={{ mb: 2, opacity: 0.8 }}>
|
|
59
|
+
Skórka „__SKIN_NAME__" (Module Federation) na realnych danych test backendu hosta.
|
|
60
|
+
</Typography>
|
|
61
|
+
{items.length === 0 ? (
|
|
62
|
+
<Typography color="primary" sx={{ py: 2 }}>
|
|
63
|
+
Brak zgłoszeń do wyświetlenia.
|
|
64
|
+
</Typography>
|
|
65
|
+
) : (
|
|
66
|
+
<DataList disableListItemAvatar itemsList={items} />
|
|
67
|
+
)}
|
|
68
|
+
</Box>
|
|
69
|
+
</PageBox>
|
|
70
|
+
);
|
|
71
|
+
}
|