@zthun/romulator-web 1.13.0 → 1.14.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/dist/index.html CHANGED
@@ -4,7 +4,7 @@
4
4
  <meta charset="UTF-8" />
5
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
6
  <title>Romulator: Organize your Games</title>
7
- <script type="module" crossorigin src="/assets/index-CmYDPIXb.js"></script>
7
+ <script type="module" crossorigin src="/assets/index-nHUlV-0_.js"></script>
8
8
  </head>
9
9
  <body>
10
10
  <div id="zthunworks-romulator"></div>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zthun/romulator-web",
3
- "version": "1.13.0",
3
+ "version": "1.14.0",
4
4
  "description": "Romulator frontend",
5
5
  "author": "Anthony Bonta",
6
6
  "license": "MIT",
@@ -28,7 +28,7 @@
28
28
  "@zthun/helpful-query": "^9.10.0",
29
29
  "@zthun/helpful-react": "^9.10.0",
30
30
  "@zthun/janitor-build-config": "^19.4.1",
31
- "@zthun/romulator-client": "^1.13.0",
31
+ "@zthun/romulator-client": "^1.14.0",
32
32
  "@zthun/webigail-http": "^5.0.0",
33
33
  "@zthun/webigail-rest": "^5.0.0",
34
34
  "@zthun/webigail-url": "^5.0.0",
@@ -43,5 +43,5 @@
43
43
  "vitest": "^4.0.3",
44
44
  "vitest-mock-extended": "^3.1.0"
45
45
  },
46
- "gitHead": "2faf3cd32e39657ec9c22313332ed98525b18ce1"
46
+ "gitHead": "28aff2325d3e89c2ad5b4c7cb9c632f55f26fa15"
47
47
  }
@@ -23,8 +23,6 @@ export class ZRomulatorMenuComponentModel extends ZCircusComponentModel {
23
23
 
24
24
  public systems = this.listItem.bind(this, "systems");
25
25
  public games = this.listItem.bind(this, "games");
26
- public audits = this.listItem.bind(this, "audits");
27
- public steam = this.listItem.bind(this, "steam");
28
26
  public settings = this.listItem.bind(this, "settings");
29
27
 
30
28
  public drawer(): Promise<ZDialogComponentModel> {
@@ -103,13 +103,5 @@ describe("ZRomulatorMenu", () => {
103
103
  it("should navigate to the settings page", async () => {
104
104
  await shouldNavigateTo("/settings", "settings");
105
105
  });
106
-
107
- it("should navigate to the audits page", async () => {
108
- await shouldNavigateTo("/audits", "audits");
109
- });
110
-
111
- it("should navigate to the steam page", async () => {
112
- await shouldNavigateTo("/steam", "steam");
113
- });
114
106
  });
115
107
  });
package/src/menu/menu.tsx CHANGED
@@ -85,32 +85,6 @@ export function ZRomulatorMenu() {
85
85
  />
86
86
  </ZListItem>
87
87
 
88
- <ZListItem
89
- name="audits"
90
- interactive
91
- cursor="pointer"
92
- onClick={navigateAndClose.bind(null, "/audits")}
93
- >
94
- <ZContentTitle
95
- avatar={<ZIconFontAwesome name="magnifying-glass" />}
96
- heading={<ZH3 compact>Audits</ZH3>}
97
- subHeading={<ZCaption>Audit your games</ZCaption>}
98
- />
99
- </ZListItem>
100
-
101
- <ZListItem
102
- name="steam"
103
- interactive
104
- cursor="pointer"
105
- onClick={navigateAndClose.bind(null, "/steam")}
106
- >
107
- <ZContentTitle
108
- avatar={<ZIconFontAwesome name="steam" family="brands" />}
109
- heading={<ZH3 compact>Steam</ZH3>}
110
- subHeading={<ZCaption>Integrate your games with Steam</ZCaption>}
111
- />
112
- </ZListItem>
113
-
114
88
  <ZListItem
115
89
  name="settings"
116
90
  interactive
@@ -35,6 +35,10 @@ export class ZRomulatorSystemPageComponentModel extends ZCircusComponentModel {
35
35
  return ZCircusBy.optional(this.driver, ZCardComponentModel, "system-info");
36
36
  }
37
37
 
38
+ public media(): Promise<ZCardComponentModel | null> {
39
+ return ZCircusBy.optional(this.driver, ZCardComponentModel, "system-media");
40
+ }
41
+
38
42
  private async fieldValue(key: string): Promise<string> {
39
43
  const klass = `.ZRomulatorSystemPage-${kebabCase(key)}`;
40
44
  const element = await this.driver.select(klass);
@@ -172,6 +172,18 @@ describe("SystemPage", () => {
172
172
  expect(actual).toBeTruthy();
173
173
  });
174
174
 
175
+ it("should render the system media card", async () => {
176
+ // Arrange.
177
+ const target = await createTestTarget();
178
+ await target.load();
179
+
180
+ // Act.
181
+ const actual = target.media();
182
+
183
+ // Assert.
184
+ expect(actual).toBeTruthy();
185
+ });
186
+
175
187
  it("should render the games list", async () => {
176
188
  // Arrange.
177
189
  const target = await createTestTarget();
@@ -3,10 +3,13 @@ import {
3
3
  useParams,
4
4
  ZAlert,
5
5
  ZBreadcrumbsLocation,
6
+ ZBubble,
6
7
  ZCaption,
7
8
  ZCard,
9
+ ZCarousel,
8
10
  ZGrid,
9
11
  ZIconFontAwesome,
12
+ ZImageSource,
10
13
  ZLabel,
11
14
  ZStack,
12
15
  ZSuspenseProgress,
@@ -22,13 +25,19 @@ import {
22
25
  isStateLoading,
23
26
  useSyncState,
24
27
  } from "@zthun/helpful-react";
28
+ import type {
29
+ IZRomulatorSystem,
30
+ ZRomulatorMediaType,
31
+ } from "@zthun/romulator-client";
25
32
  import {
26
33
  ZRomulatorSystemContentType,
27
34
  ZRomulatorSystemHardwareType,
28
35
  ZRomulatorSystemMediaFormat,
36
+ ZRomulatorSystemMediaType,
29
37
  } from "@zthun/romulator-client";
30
38
  import { kebabCase, startCase } from "lodash-es";
31
- import { useMemo } from "react";
39
+ import { useMemo, useState } from "react";
40
+ import { ZRomulatorEnvironmentBuilder } from "../environment/environment.mjs";
32
41
  import { ZRomulatorGamesList } from "../games/games-list.js";
33
42
  import { useSystem } from "./systems-service.mjs";
34
43
 
@@ -66,6 +75,7 @@ export function ZRomulatorSystemPage() {
66
75
  const { id } = useParams();
67
76
  const { error } = useFashionTheme();
68
77
  const [system] = useSystem(firstDefined("", id));
78
+ const [mediaIndex, setMediaIndex] = useState(0);
69
79
  const gameFilter = useMemo(
70
80
  () =>
71
81
  new ZFilterBinaryBuilder().subject("system").equal().value(id).build(),
@@ -73,7 +83,7 @@ export function ZRomulatorSystemPage() {
73
83
  );
74
84
 
75
85
  const baseGameRequest = useMemo(
76
- () => new ZDataRequestBuilder().size(12).filter(gameFilter).build(),
86
+ () => new ZDataRequestBuilder().size(36).filter(gameFilter).build(),
77
87
  [gameFilter],
78
88
  );
79
89
 
@@ -96,6 +106,113 @@ export function ZRomulatorSystemPage() {
96
106
  </>
97
107
  );
98
108
 
109
+ const renderSystemInfoCard = (system: IZRomulatorSystem) => {
110
+ const { name, company, classification, productionYears } = system;
111
+ const { hardwareType, mediaFormat, contentType } = classification;
112
+ const { start, end } = productionYears;
113
+
114
+ const _hardware = HardwareTypeDisplay[hardwareType];
115
+ const _media = MediaFormatDisplay[mediaFormat];
116
+ const _content = ContentTypeDisplay[contentType];
117
+
118
+ return (
119
+ <ZCard
120
+ name="system-info"
121
+ TitleProps={{
122
+ avatar: (
123
+ <ZIconFontAwesome name="puzzle-piece" width={ZSizeFixed.Medium} />
124
+ ),
125
+ heading: "Information",
126
+ subHeading: "Details about this system",
127
+ }}
128
+ >
129
+ <ZGrid
130
+ columns="auto auto"
131
+ gap={ZSizeFixed.Medium}
132
+ width={ZSizeVaried.Fit}
133
+ align={{ items: "center" }}
134
+ >
135
+ {renderSystemInfoField("Name", name)}
136
+ {renderSystemInfoField("Company", company)}
137
+ {renderSystemInfoField("Hardware Type", hardwareType, _hardware)}
138
+ {renderSystemInfoField("Media Format", mediaFormat, _media)}
139
+ {renderSystemInfoField("Content Type", contentType, _content)}
140
+ {renderSystemInfoField("Production Start", String(start))}
141
+ {renderSystemInfoField(
142
+ "Production End",
143
+ String(end),
144
+ startCase(String(end)),
145
+ )}
146
+ </ZGrid>
147
+ </ZCard>
148
+ );
149
+ };
150
+
151
+ const renderSystemGameListCard = (system: IZRomulatorSystem) => {
152
+ const { extensions } = system;
153
+
154
+ return (
155
+ <ZCard
156
+ name="game-list"
157
+ TitleProps={{
158
+ avatar: <ZIconFontAwesome name="gamepad" width={ZSizeFixed.Medium} />,
159
+ heading: "Games",
160
+ subHeading: extensions.join(", "),
161
+ }}
162
+ >
163
+ <ZRomulatorGamesList
164
+ value={userRequest}
165
+ onValueChange={setGameRequest}
166
+ />
167
+ </ZCard>
168
+ );
169
+ };
170
+
171
+ const renderSystemMedia = (
172
+ type: ZRomulatorMediaType,
173
+ system: IZRomulatorSystem,
174
+ ) => {
175
+ const { api } = new ZRomulatorEnvironmentBuilder().build();
176
+ const id = `${system.id}-${type}`;
177
+ const media = `${api}/media/${id}`;
178
+
179
+ return (
180
+ <ZBubble width={ZSizeFixed.ExtraLarge}>
181
+ <ZImageSource
182
+ className="ZRomulatorSystemsPage-wheel"
183
+ src={media}
184
+ width={ZSizeVaried.Full}
185
+ />
186
+ </ZBubble>
187
+ );
188
+ };
189
+
190
+ const renderSystemMediaCard = (system: IZRomulatorSystem) => {
191
+ const media = [
192
+ ZRomulatorSystemMediaType.Picture,
193
+ ZRomulatorSystemMediaType.Controller,
194
+ ZRomulatorSystemMediaType.Wheel,
195
+ ];
196
+
197
+ return (
198
+ <ZCard
199
+ name="system-media"
200
+ TitleProps={{
201
+ avatar: <ZIconFontAwesome name="image" width={ZSizeFixed.Medium} />,
202
+ heading: "Media",
203
+ subHeading: startCase(media[mediaIndex]),
204
+ }}
205
+ >
206
+ <ZCarousel
207
+ count={media.length}
208
+ renderAtIndex={(i) => renderSystemMedia(media[i], system)}
209
+ value={mediaIndex}
210
+ onValueChange={setMediaIndex}
211
+ />
212
+ </ZCard>
213
+ );
214
+ };
215
+
99
216
  const renderPageContent = () => {
100
217
  if (isStateLoading(system)) {
101
218
  return (
@@ -113,67 +230,15 @@ export function ZRomulatorSystemPage() {
113
230
  );
114
231
  }
115
232
 
116
- const { name, company, classification, extensions, productionYears } =
117
- system;
118
- const { hardwareType, mediaFormat, contentType } = classification;
119
- const { start, end } = productionYears;
120
-
121
- const _hardware = HardwareTypeDisplay[hardwareType];
122
- const _media = MediaFormatDisplay[mediaFormat];
123
- const _content = ContentTypeDisplay[contentType];
124
-
125
233
  return (
126
- <ZStack gap={ZSizeFixed.Medium}>
127
- <ZGrid columns="auto 1fr">
128
- <ZCard
129
- name="system-info"
130
- TitleProps={{
131
- avatar: (
132
- <ZIconFontAwesome
133
- name="puzzle-piece"
134
- width={ZSizeFixed.Medium}
135
- />
136
- ),
137
- heading: "Information",
138
- subHeading: "Details about this system",
139
- }}
140
- >
141
- <ZGrid
142
- columns="auto auto"
143
- gap={ZSizeFixed.Medium}
144
- width={ZSizeVaried.Fit}
145
- align={{ items: "center" }}
146
- >
147
- {renderSystemInfoField("Name", name)}
148
- {renderSystemInfoField("Company", company)}
149
- {renderSystemInfoField("Hardware Type", hardwareType, _hardware)}
150
- {renderSystemInfoField("Media Format", mediaFormat, _media)}
151
- {renderSystemInfoField("Content Type", contentType, _content)}
152
- {renderSystemInfoField("Production Start", String(start))}
153
- {renderSystemInfoField(
154
- "Production End",
155
- String(end),
156
- startCase(String(end)),
157
- )}
158
- </ZGrid>
159
- </ZCard>
160
- </ZGrid>
161
- <ZCard
162
- name="game-list"
163
- TitleProps={{
164
- avatar: (
165
- <ZIconFontAwesome name="gamepad" width={ZSizeFixed.Medium} />
166
- ),
167
- heading: "Games",
168
- subHeading: extensions.join(", "),
169
- }}
170
- >
171
- <ZRomulatorGamesList
172
- value={userRequest}
173
- onValueChange={setGameRequest}
174
- />
175
- </ZCard>
176
- </ZStack>
234
+ <ZGrid columns={{ xl: "1fr auto", sm: "1fr" }} gap={ZSizeFixed.Medium}>
235
+ {renderSystemGameListCard(system)}
236
+
237
+ <ZStack gap={ZSizeFixed.Medium}>
238
+ {renderSystemInfoCard(system)}
239
+ {renderSystemMediaCard(system)}
240
+ </ZStack>
241
+ </ZGrid>
177
242
  );
178
243
  };
179
244