diff --git a/.gitmodules b/.gitmodules
index e2d7c95..1b742ab 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -2,3 +2,6 @@
path = static
ignore = all
url = git@unknown.name:DebaucheryLibrarian/traxxx-assets.git
+[submodule "common"]
+ path = common
+ url = git@unknown.name:DebaucheryLibrarian/traxxx-common.git
diff --git a/common b/common
new file mode 160000
index 0000000..40011a6
--- /dev/null
+++ b/common
@@ -0,0 +1 @@
+Subproject commit 40011a62dae9da8deda71e9f8daf39665a8b7958
diff --git a/components/actors/bio.vue b/components/actors/bio.vue
index f04fe5b..363c0a3 100644
--- a/components/actors/bio.vue
+++ b/components/actors/bio.vue
@@ -136,13 +136,32 @@
class="bio-item figure"
>
Figure
+ {{ actor.bust || '??' }}{{ actor.cup || '?' }}-{{ actor.waist || '??' }}-{{ actor.hip || '??' }}
+
+
+
@@ -294,13 +328,16 @@
diff --git a/pages/actors/@actorId/edit/+route.js b/pages/actors/@actorId/edit/+route.js
new file mode 100644
index 0000000..e7d4e8e
--- /dev/null
+++ b/pages/actors/@actorId/edit/+route.js
@@ -0,0 +1 @@
+export default '/actor/edit/@actorId/*';
diff --git a/pages/actors/@actorId/revisions/+Page.vue b/pages/actors/@actorId/revisions/+Page.vue
new file mode 100644
index 0000000..d31a6be
--- /dev/null
+++ b/pages/actors/@actorId/revisions/+Page.vue
@@ -0,0 +1,62 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/pages/actors/@actorId/revisions/+onBeforeRender.js b/pages/actors/@actorId/revisions/+onBeforeRender.js
new file mode 100644
index 0000000..8f948a5
--- /dev/null
+++ b/pages/actors/@actorId/revisions/+onBeforeRender.js
@@ -0,0 +1,24 @@
+import { fetchActorsById } from '#/src/actors.js';
+import { fetchSceneRevisions } from '#/src/scenes.js';
+
+export async function onBeforeRender(pageContext) {
+ const [actor] = await fetchActorsById([Number(pageContext.routeParams.actorId)], {}, pageContext.user);
+
+ const {
+ revisions,
+ } = await fetchSceneRevisions(null, {
+ sceneId: actor.id,
+ isFinalized: true,
+ limit: 100,
+ }, pageContext.user);
+
+ return {
+ pageContext: {
+ title: `Revisions for '${actor.name}'`,
+ pageProps: {
+ actor,
+ revisions,
+ },
+ },
+ };
+}
diff --git a/pages/actors/@actorId/revisions/+route.js b/pages/actors/@actorId/revisions/+route.js
new file mode 100644
index 0000000..4d6def5
--- /dev/null
+++ b/pages/actors/@actorId/revisions/+route.js
@@ -0,0 +1 @@
+export default '/actor/revisions/@actorId/*';
diff --git a/pages/admin/revisions/+route.js b/pages/admin/revisions/+route.js
deleted file mode 100644
index d9cb684..0000000
--- a/pages/admin/revisions/+route.js
+++ /dev/null
@@ -1 +0,0 @@
-export default '/admin/@section/*';
diff --git a/pages/admin/revisions/actors/+onBeforeRender.js b/pages/admin/revisions/actors/+onBeforeRender.js
new file mode 100644
index 0000000..b8084b4
--- /dev/null
+++ b/pages/admin/revisions/actors/+onBeforeRender.js
@@ -0,0 +1,24 @@
+import { render } from 'vike/abort'; /* eslint-disable-line import/extensions */
+import { fetchActorRevisions } from '#/src/actors.js';
+
+export async function onBeforeRender(pageContext) {
+ if (!pageContext.user || pageContext.user.role === 'user') {
+ throw render(404);
+ }
+
+ const {
+ revisions,
+ } = await fetchActorRevisions(null, {
+ isFinalized: false,
+ limit: 50,
+ }, pageContext.user);
+
+ return {
+ pageContext: {
+ title: pageContext.routeParams.section,
+ pageProps: {
+ revisions,
+ },
+ },
+ };
+}
diff --git a/pages/admin/revisions/actors/+route.js b/pages/admin/revisions/actors/+route.js
new file mode 100644
index 0000000..08c00f4
--- /dev/null
+++ b/pages/admin/revisions/actors/+route.js
@@ -0,0 +1,19 @@
+import { match } from 'path-to-regexp';
+
+const path = '/admin/:section/:domain(actors)';
+const urlMatch = match(path, { decode: decodeURIComponent });
+
+export default (pageContext) => {
+ const matched = urlMatch(pageContext.urlPathname);
+
+ if (matched) {
+ return {
+ routeParams: {
+ section: matched.params.section,
+ domain: matched.params.domain,
+ },
+ };
+ }
+
+ return false;
+};
diff --git a/pages/admin/revisions/+onBeforeRender.js b/pages/admin/revisions/scenes/+onBeforeRender.js
similarity index 100%
rename from pages/admin/revisions/+onBeforeRender.js
rename to pages/admin/revisions/scenes/+onBeforeRender.js
diff --git a/pages/admin/revisions/scenes/+route.js b/pages/admin/revisions/scenes/+route.js
new file mode 100644
index 0000000..6ef6184
--- /dev/null
+++ b/pages/admin/revisions/scenes/+route.js
@@ -0,0 +1,19 @@
+import { match } from 'path-to-regexp';
+
+const path = '/admin/:section/:domain(scenes)';
+const urlMatch = match(path, { decode: decodeURIComponent });
+
+export default (pageContext) => {
+ const matched = urlMatch(pageContext.urlPathname);
+
+ if (matched) {
+ return {
+ routeParams: {
+ section: matched.params.section,
+ domain: matched.params.domain,
+ },
+ };
+ }
+
+ return false;
+};
diff --git a/pages/entities/+Page.vue b/pages/entities/+Page.vue
index d552788..76690a0 100644
--- a/pages/entities/+Page.vue
+++ b/pages/entities/+Page.vue
@@ -36,8 +36,11 @@
>
@@ -58,7 +61,7 @@