@raketa-cloud/admin 0.0.17 → 0.0.19

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 (31) hide show
  1. package/package.json +1 -1
  2. package/src/HonoAdapter.js +2 -0
  3. package/src/cloud/Events.js +3 -3
  4. package/src/handlers/articles/DeletesHandler.js +5 -2
  5. package/src/handlers/articles/URLsHandler.js +5 -1
  6. package/src/handlers/events/DeletesHandler.js +5 -2
  7. package/src/handlers/events/URLsHandler.js +5 -2
  8. package/src/handlers/pages/DeletesHandler.js +1 -2
  9. package/src/handlers/pages/URLsHandler.js +1 -2
  10. package/src/styles/application.css +4 -0
  11. package/src/tests/handlers/article_revisions/GeneralHandler.test/edit_form.test.js +1 -1
  12. package/src/tests/handlers/article_revisions/GeneralHandler.test/update.test.js +2 -2
  13. package/src/tests/handlers/articles/ArticlesHandler.test/create.test.js +2 -2
  14. package/src/tests/handlers/articles/DeletesHandler.test/create.test.js +4 -3
  15. package/src/tests/handlers/articles/DeletesHandler.test/create_form.test.js +2 -1
  16. package/src/tests/handlers/articles/URLsHandler.test/create.test.js +2 -1
  17. package/src/tests/handlers/event_revisions/GeneralHandler.test/edit_form.test.js +3 -3
  18. package/src/tests/handlers/event_revisions/GeneralHandler.test/update.test.js +6 -6
  19. package/src/tests/handlers/events/DeletesHandler.test/create.test.js +4 -3
  20. package/src/tests/handlers/events/DeletesHandler.test/create_form.test.js +2 -1
  21. package/src/tests/handlers/events/EventsHandler.test/create.test.js +6 -6
  22. package/src/tests/handlers/events/URLsHandler.test/create.test.js +4 -3
  23. package/src/tests/handlers/pages/DeletesHandler.test/create.test.js +4 -3
  24. package/src/tests/handlers/pages/DeletesHandler.test/create_form.test.js +2 -1
  25. package/src/tests/handlers/pages/URLsHandler.test/create.test.js +4 -3
  26. package/src/utils.js +18 -34
  27. package/src/views/article_revisions/general/edit_form.ejs +1 -1
  28. package/src/views/event_revisions/general/edit_form.ejs +3 -3
  29. package/src/views/layouts/application.ejs +32 -0
  30. package/test/factory.js +3 -3
  31. package/test/handlersHelper.js +23 -1
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@raketa-cloud/admin",
3
- "version": "0.0.17",
3
+ "version": "0.0.19",
4
4
  "main": "src/index.js",
5
5
  "scripts": {
6
6
  "dev": "npx tailwindcss -i ./src/styles/application.css -o ../../apps/admin/static/application.css --watch",
@@ -99,8 +99,10 @@ export default class HonoAdapter extends Adapter {
99
99
  ctx.locales = this.globalConfig.i18n.locales;
100
100
  ctx.defaultLocale = this.globalConfig.i18n.defaultLocale;
101
101
  ctx.locale = currentLocale;
102
+ ctx.remoteConfig = { ...this.globalConfig.remoteConfig };
102
103
 
103
104
  const _context = {
105
+ timezones: this.globalConfig.i18n.timezones,
104
106
  locales: ctx.locales,
105
107
  locale: ctx.locale,
106
108
  defaultLocale: ctx.defaultLocale,
@@ -15,9 +15,9 @@ export default class Events extends RaketaClient {
15
15
  return {
16
16
  visibility: "private",
17
17
  layout: "default",
18
- publish_at: toDateTimeInput(new Date()),
19
- starts_at: toDateTimeInput(new Date()),
20
- ends_at: toDateTimeInput(new Date()),
18
+ publish_at: toDateTimeInput(),
19
+ starts_at: toDateTimeInput(),
20
+ ends_at: toDateTimeInput(),
21
21
  tags: [],
22
22
  categories: [],
23
23
  };
@@ -31,8 +31,11 @@ const create = async (ctx, opts) => {
31
31
 
32
32
  if (params.redirect === "301" || params.redirect === "410") {
33
33
  redirect = {
34
- // TODO: fix url with consideration of locale & defaultLocale in the frontend project
35
- url: `/${article.slug}`,
34
+ url: ctx.remoteConfig.resourcePath(
35
+ article,
36
+ article.articleType.slug,
37
+ ctx.locale
38
+ ),
36
39
  destination: params.redirect === "301" ? params.destination : "/",
37
40
  httpResponseCode: Number.parseInt(params.redirect, 10),
38
41
  note: "Created via article deletion process",
@@ -33,7 +33,11 @@ const create = async (ctx, opts) => {
33
33
 
34
34
  if (change.redirect) {
35
35
  redirectParams = {
36
- // TODO: We need some config from the FE project on how to build paths here!
36
+ url: ctx.remoteConfig.resourcePath(
37
+ article,
38
+ article.articleType.slug,
39
+ ctx.locale
40
+ ),
37
41
  url: `/${article.slug}`,
38
42
  destination: change.slug,
39
43
  httpResponseCode: 301,
@@ -31,8 +31,11 @@ const create = async (ctx, opts) => {
31
31
 
32
32
  if (params.redirect === "301" || params.redirect === "410") {
33
33
  redirect = {
34
- // TODO: fix url with consideration of locale & defaultLocale in the frontend project
35
- url: `/${event.slug}`,
34
+ url: ctx.remoteConfig.resourcePath(
35
+ event,
36
+ event.eventType.slug,
37
+ ctx.locale
38
+ ),
36
39
  destination: params.redirect === "301" ? params.destination : "/",
37
40
  httpResponseCode: Number.parseInt(params.redirect, 10),
38
41
  note: "Created via event deletion process",
@@ -33,8 +33,11 @@ const create = async (ctx, opts) => {
33
33
 
34
34
  if (change.redirect) {
35
35
  redirectParams = {
36
- // TODO: We need some config from the FE project on how to build paths here!
37
- url: `/${event.slug}`,
36
+ url: ctx.remoteConfig.resourcePath(
37
+ event,
38
+ event.eventType.slug,
39
+ ctx.locale
40
+ ),
38
41
  destination: change.slug,
39
42
  httpResponseCode: 301,
40
43
  note: `Created with changed URL for a resource of type ${opts.eventType}`,
@@ -31,8 +31,7 @@ const create = async (ctx, opts) => {
31
31
 
32
32
  if (params.redirect === "301" || params.redirect === "410") {
33
33
  redirect = {
34
- // TODO: fix url with consideration of locale & defaultLocale in the frontend project
35
- url: `/${page.slug}`,
34
+ url: ctx.remoteConfig.resourcePath(page, page.pageType.slug, ctx.locale),
36
35
  destination: params.redirect === "301" ? params.destination : "/",
37
36
  httpResponseCode: Number.parseInt(params.redirect, 10),
38
37
  note: "Created via page deletion process",
@@ -33,8 +33,7 @@ const create = async (ctx, opts) => {
33
33
 
34
34
  if (change.redirect) {
35
35
  redirectParams = {
36
- // TODO: We need some config from the FE project on how to build paths here!
37
- url: `/${page.slug}`,
36
+ url: ctx.remoteConfig.resourcePath(page, page.pageType.slug, ctx.locale),
38
37
  destination: change.slug,
39
38
  httpResponseCode: 301,
40
39
  note: `Created with changed URL for a ${opts.pageType}`,
@@ -166,6 +166,10 @@ body {
166
166
  .checkbox-wrapper input[type="checkbox"] {
167
167
  @apply size-4 px-0;
168
168
  }
169
+
170
+ .hint {
171
+ @apply text-sm opacity-50;
172
+ }
169
173
  }
170
174
 
171
175
  .inline-form {
@@ -38,7 +38,7 @@ describe("Article revision genereal settings", () => {
38
38
  title: revision.title,
39
39
  slug: revision.slug,
40
40
  visibility: revision.visibility,
41
- publish_at: "2024-08-30T19:05",
41
+ publish_at: "2024-08-30T16:05:00",
42
42
  username: revision.settings?.credentials?.user || "",
43
43
  password: revision.settings?.credentials?.password || "",
44
44
  },
@@ -54,7 +54,7 @@ describe("Article revision general settings", () => {
54
54
  slug: updateSettings.slug,
55
55
  title: updateSettings.title,
56
56
  visibility: updateSettings.visibility,
57
- publishAt: "2024-08-30T16:05:00Z",
57
+ publishAt: "2024-08-30T19:05:00Z",
58
58
  widgets: JSON.stringify(revision.widgets),
59
59
  tags: revision.tags.map((t) => t.id),
60
60
  categories: revision.categories.map((c) => c.id),
@@ -107,7 +107,7 @@ describe("Article revision general settings", () => {
107
107
  slug: updateSettings.slug,
108
108
  title: updateSettings.title,
109
109
  visibility: updateSettings.visibility,
110
- publishAt: "2024-08-30T16:05:00Z",
110
+ publishAt: "2024-08-30T19:05:00Z",
111
111
  widgets: JSON.stringify(revision.widgets),
112
112
  tags: revision.tags.map((t) => t.id),
113
113
  categories: revision.categories.map((c) => c.id),
@@ -50,7 +50,7 @@ describe("Articles Handler", () => {
50
50
  title: params.title,
51
51
  slug: params.slug,
52
52
  visibility: params.visibility,
53
- publishAt: "2024-10-10T03:58:00Z",
53
+ publishAt: "2024-10-10T06:58:00Z",
54
54
  settings: {
55
55
  layout: params.layout,
56
56
  meta: {
@@ -116,7 +116,7 @@ describe("Articles Handler", () => {
116
116
  title: params.title,
117
117
  slug: "",
118
118
  visibility: params.visibility,
119
- publishAt: "2024-10-10T03:58:00Z",
119
+ publishAt: "2024-10-10T06:58:00Z",
120
120
  settings: {
121
121
  layout: params.layout,
122
122
  meta: {
@@ -1,7 +1,7 @@
1
1
  import DeletesHandler from "../../../../handlers/articles/DeletesHandler";
2
2
  import Articles from "../../../../cloud/Articles";
3
3
  import Factory from "../../../../../test/factory";
4
- import { testConfig } from "../../../../../test//handlersHelper";
4
+ import { testConfig, remoteConfig } from "../../../../../test//handlersHelper";
5
5
 
6
6
  function buildCtx(article, updateSettings) {
7
7
  return {
@@ -13,6 +13,7 @@ function buildCtx(article, updateSettings) {
13
13
  deleteAction: updateSettings,
14
14
  },
15
15
  locale: "en",
16
+ remoteConfig: remoteConfig(),
16
17
  };
17
18
  }
18
19
 
@@ -40,7 +41,7 @@ describe("Article delete", () => {
40
41
 
41
42
  expect(mockFind).toHaveBeenCalledWith(article.id, "en");
42
43
  expect(mockDelete).toHaveBeenCalledWith(article.id, "en", {
43
- url: `/${article.slug}`,
44
+ url: `/en/blog/${article.slug}`,
44
45
  destination: updateSettings.destination,
45
46
  httpResponseCode: 301,
46
47
  note: "Created via article deletion process",
@@ -83,7 +84,7 @@ describe("Article delete", () => {
83
84
 
84
85
  expect(mockFind).toHaveBeenCalledWith(article.id, "en");
85
86
  expect(mockDelete).toHaveBeenCalledWith(article.id, "en", {
86
- url: `/${article.slug}`,
87
+ url: `/en/blog/${article.slug}`,
87
88
  destination: "/",
88
89
  httpResponseCode: 410,
89
90
  note: "Created via article deletion process",
@@ -1,7 +1,7 @@
1
1
  import DeletesHandler from "../../../../handlers/articles/DeletesHandler";
2
2
  import Articles from "../../../../cloud/Articles";
3
3
  import Factory from "../../../../../test/factory";
4
- import { testConfig } from "../../../../../test//handlersHelper";
4
+ import { testConfig, remoteConfig } from "../../../../../test//handlersHelper";
5
5
 
6
6
  function buildCtx(article) {
7
7
  return {
@@ -10,6 +10,7 @@ function buildCtx(article) {
10
10
  },
11
11
  params: { parent_id: article.id },
12
12
  locale: "en",
13
+ remoteConfig: remoteConfig(),
13
14
  };
14
15
  }
15
16
 
@@ -1,7 +1,7 @@
1
1
  import URLsHandler from "../../../../handlers/articles/URLsHandler";
2
2
  import Articles from "../../../../cloud/Articles";
3
3
  import Factory from "../../../../../test/factory";
4
- import { testConfig } from "../../../../../test/handlersHelper";
4
+ import { testConfig, remoteConfig } from "../../../../../test/handlersHelper";
5
5
 
6
6
  function buildCtx(article, updateSettings) {
7
7
  return {
@@ -13,6 +13,7 @@ function buildCtx(article, updateSettings) {
13
13
  change: updateSettings,
14
14
  },
15
15
  locale: "en",
16
+ remoteConfig: remoteConfig(),
16
17
  };
17
18
  }
18
19
 
@@ -40,9 +40,9 @@ describe("Event revision genereal settings", () => {
40
40
  title: revision.title,
41
41
  slug: revision.slug,
42
42
  visibility: revision.visibility,
43
- publish_at: "2024-08-30T22:05",
44
- starts_at: "2024-08-30T22:10",
45
- ends_at: "2024-08-30T22:15",
43
+ publish_at: "2024-08-30T19:05:00",
44
+ starts_at: "2024-08-30T19:10:00",
45
+ ends_at: "2024-08-30T19:15:00",
46
46
  username: revision.settings?.credentials?.user || "",
47
47
  password: revision.settings?.credentials?.password || "",
48
48
  },
@@ -56,9 +56,9 @@ describe("Event revision general settings", () => {
56
56
  slug: updateSettings.slug,
57
57
  title: updateSettings.title,
58
58
  visibility: updateSettings.visibility,
59
- publishAt: "2024-08-30T16:05:00Z",
60
- startsAt: "2024-08-30T16:10:00Z",
61
- endsAt: "2024-08-30T16:15:00Z",
59
+ publishAt: "2024-08-30T19:05:00Z",
60
+ startsAt: "2024-08-30T19:10:00Z",
61
+ endsAt: "2024-08-30T19:15:00Z",
62
62
  widgets: JSON.stringify(revision.widgets),
63
63
  tags: revision.tags.map((t) => t.id),
64
64
  categories: revision.categories.map((c) => c.id),
@@ -113,9 +113,9 @@ describe("Event revision general settings", () => {
113
113
  slug: updateSettings.slug,
114
114
  title: updateSettings.title,
115
115
  visibility: updateSettings.visibility,
116
- publishAt: "2024-08-30T16:05:00Z",
117
- startsAt: "2024-08-30T16:10:00Z",
118
- endsAt: "2024-08-30T16:15:00Z",
116
+ publishAt: "2024-08-30T19:05:00Z",
117
+ startsAt: "2024-08-30T19:10:00Z",
118
+ endsAt: "2024-08-30T19:15:00Z",
119
119
  widgets: JSON.stringify(revision.widgets),
120
120
  tags: revision.tags.map((t) => t.id),
121
121
  categories: revision.categories.map((c) => c.id),
@@ -1,7 +1,7 @@
1
1
  import DeletesHandler from "../../../../handlers/events/DeletesHandler";
2
2
  import Events from "../../../../cloud/Events";
3
3
  import Factory from "../../../../../test/factory";
4
- import { testConfig } from "../../../../../test//handlersHelper";
4
+ import { testConfig, remoteConfig } from "../../../../../test//handlersHelper";
5
5
 
6
6
  function buildCtx(event, updateSettings) {
7
7
  return {
@@ -13,6 +13,7 @@ function buildCtx(event, updateSettings) {
13
13
  deleteAction: updateSettings,
14
14
  },
15
15
  locale: "en",
16
+ remoteConfig: remoteConfig(),
16
17
  };
17
18
  }
18
19
 
@@ -40,7 +41,7 @@ describe("Event delete", () => {
40
41
 
41
42
  expect(mockFind).toHaveBeenCalledWith(event.id, "en");
42
43
  expect(mockDelete).toHaveBeenCalledWith(event.id, "en", {
43
- url: `/${event.slug}`,
44
+ url: `/en/events/${event.slug}`,
44
45
  destination: updateSettings.destination,
45
46
  httpResponseCode: 301,
46
47
  note: "Created via event deletion process",
@@ -83,7 +84,7 @@ describe("Event delete", () => {
83
84
 
84
85
  expect(mockFind).toHaveBeenCalledWith(event.id, "en");
85
86
  expect(mockDelete).toHaveBeenCalledWith(event.id, "en", {
86
- url: `/${event.slug}`,
87
+ url: `/en/events/${event.slug}`,
87
88
  destination: "/",
88
89
  httpResponseCode: 410,
89
90
  note: "Created via event deletion process",
@@ -1,7 +1,7 @@
1
1
  import DeletesHandler from "../../../../handlers/events/DeletesHandler";
2
2
  import Events from "../../../../cloud/Events";
3
3
  import Factory from "../../../../../test/factory";
4
- import { testConfig } from "../../../../../test//handlersHelper";
4
+ import { testConfig, remoteConfig } from "../../../../../test//handlersHelper";
5
5
 
6
6
  function buildCtx(event) {
7
7
  return {
@@ -10,6 +10,7 @@ function buildCtx(event) {
10
10
  },
11
11
  params: { parent_id: event.id },
12
12
  locale: "en",
13
+ remoteConfig: remoteConfig(),
13
14
  };
14
15
  }
15
16
 
@@ -52,9 +52,9 @@ describe("Events Handler", () => {
52
52
  title: params.title,
53
53
  slug: params.slug,
54
54
  visibility: params.visibility,
55
- publishAt: "2024-10-10T03:40:00Z",
56
- startsAt: "2024-10-10T03:50:00Z",
57
- endsAt: "2024-10-10T03:59:00Z",
55
+ publishAt: "2024-10-10T06:40:00Z",
56
+ startsAt: "2024-10-10T06:50:00Z",
57
+ endsAt: "2024-10-10T06:59:00Z",
58
58
  settings: {
59
59
  layout: params.layout,
60
60
  meta: {
@@ -122,9 +122,9 @@ describe("Events Handler", () => {
122
122
  title: params.title,
123
123
  slug: "",
124
124
  visibility: params.visibility,
125
- publishAt: "2024-10-10T03:40:00Z",
126
- startsAt: "2024-10-10T03:50:00Z",
127
- endsAt: "2024-10-10T03:59:00Z",
125
+ publishAt: "2024-10-10T06:40:00Z",
126
+ startsAt: "2024-10-10T06:50:00Z",
127
+ endsAt: "2024-10-10T06:59:00Z",
128
128
  settings: {
129
129
  layout: params.layout,
130
130
  meta: {
@@ -1,7 +1,7 @@
1
1
  import URLsHandler from "../../../../handlers/events/URLsHandler";
2
2
  import Events from "../../../../cloud/Events";
3
3
  import Factory from "../../../../../test/factory";
4
- import { testConfig } from "../../../../../test/handlersHelper";
4
+ import { testConfig, remoteConfig } from "../../../../../test/handlersHelper";
5
5
 
6
6
  function buildCtx(event, updateSettings) {
7
7
  return {
@@ -13,6 +13,7 @@ function buildCtx(event, updateSettings) {
13
13
  change: updateSettings,
14
14
  },
15
15
  locale: "en",
16
+ remoteConfig: remoteConfig(),
16
17
  };
17
18
  }
18
19
 
@@ -44,7 +45,7 @@ describe("Event change url", () => {
44
45
  updateSettings.slug,
45
46
  "en",
46
47
  {
47
- url: `/${event.slug}`,
48
+ url: `/en/events/${event.slug}`,
48
49
  destination: updateSettings.slug,
49
50
  httpResponseCode: 301,
50
51
  note: "Created with changed URL for a resource of type event",
@@ -132,7 +133,7 @@ describe("Event change url", () => {
132
133
  updateSettings.slug,
133
134
  "en",
134
135
  {
135
- url: `/${event.slug}`,
136
+ url: `/en/events/${event.slug}`,
136
137
  destination: updateSettings.slug,
137
138
  httpResponseCode: 301,
138
139
  note: "Created with changed URL for a resource of type event",
@@ -1,7 +1,7 @@
1
1
  import DeletesHandler from "../../../../handlers/pages/DeletesHandler";
2
2
  import Pages from "../../../../cloud/Pages";
3
3
  import Factory from "../../../../../test/factory";
4
- import { testConfig } from "../../../../../test//handlersHelper";
4
+ import { testConfig, remoteConfig } from "../../../../../test//handlersHelper";
5
5
 
6
6
  function buildCtx(page, updateSettings) {
7
7
  return {
@@ -13,6 +13,7 @@ function buildCtx(page, updateSettings) {
13
13
  deleteAction: updateSettings,
14
14
  },
15
15
  locale: "en",
16
+ remoteConfig: remoteConfig(),
16
17
  };
17
18
  }
18
19
 
@@ -40,7 +41,7 @@ describe("Page delete", () => {
40
41
 
41
42
  expect(mockFind).toHaveBeenCalledWith(page.id, "en");
42
43
  expect(mockDelete).toHaveBeenCalledWith(page.id, "en", {
43
- url: `/${page.slug}`,
44
+ url: `/en/${page.slug}`,
44
45
  destination: updateSettings.destination,
45
46
  httpResponseCode: 301,
46
47
  note: "Created via page deletion process",
@@ -83,7 +84,7 @@ describe("Page delete", () => {
83
84
 
84
85
  expect(mockFind).toHaveBeenCalledWith(page.id, "en");
85
86
  expect(mockDelete).toHaveBeenCalledWith(page.id, "en", {
86
- url: `/${page.slug}`,
87
+ url: `/en/${page.slug}`,
87
88
  destination: "/",
88
89
  httpResponseCode: 410,
89
90
  note: "Created via page deletion process",
@@ -1,7 +1,7 @@
1
1
  import DeletesHandler from "../../../../handlers/pages/DeletesHandler";
2
2
  import Pages from "../../../../cloud/Pages";
3
3
  import Factory from "../../../../../test/factory";
4
- import { testConfig } from "../../../../../test//handlersHelper";
4
+ import { testConfig, remoteConfig } from "../../../../../test//handlersHelper";
5
5
 
6
6
  function buildCtx(page) {
7
7
  return {
@@ -10,6 +10,7 @@ function buildCtx(page) {
10
10
  },
11
11
  params: { parent_id: page.id },
12
12
  locale: "en",
13
+ remoteConfig: remoteConfig(),
13
14
  };
14
15
  }
15
16
 
@@ -1,7 +1,7 @@
1
1
  import URLsHandler from "../../../../handlers/pages/URLsHandler";
2
2
  import Pages from "../../../../cloud/Pages";
3
3
  import Factory from "../../../../../test/factory";
4
- import { testConfig } from "../../../../../test/handlersHelper";
4
+ import { testConfig, remoteConfig } from "../../../../../test/handlersHelper";
5
5
 
6
6
  function buildCtx(page, updateSettings) {
7
7
  return {
@@ -13,6 +13,7 @@ function buildCtx(page, updateSettings) {
13
13
  change: updateSettings,
14
14
  },
15
15
  locale: "en",
16
+ remoteConfig: remoteConfig(),
16
17
  };
17
18
  }
18
19
 
@@ -44,7 +45,7 @@ describe("Page change url", () => {
44
45
  updateSettings.slug,
45
46
  "en",
46
47
  {
47
- url: `/${page.slug}`,
48
+ url: `/en/${page.slug}`,
48
49
  destination: updateSettings.slug,
49
50
  httpResponseCode: 301,
50
51
  note: "Created with changed URL for a page",
@@ -132,7 +133,7 @@ describe("Page change url", () => {
132
133
  updateSettings.slug,
133
134
  "en",
134
135
  {
135
- url: `/${page.slug}`,
136
+ url: `/en/${page.slug}`,
136
137
  destination: updateSettings.slug,
137
138
  httpResponseCode: 301,
138
139
  note: "Created with changed URL for a page",
package/src/utils.js CHANGED
@@ -1,46 +1,30 @@
1
- export function toUTCISO8601String(initialDate) {
2
- let date = null;
3
-
4
- if (typeof initialDate === "string") {
5
- date = new Date(initialDate);
6
- } else {
7
- date = initialDate;
8
- }
9
-
10
- return [
11
- date.getUTCFullYear(),
12
- "-",
13
- (date.getUTCMonth() + 1).toString().padStart(2, "0"),
14
- "-",
15
- date.getUTCDate().toString().padStart(2, "0"),
16
- "T",
17
- date.getUTCHours().toString().padStart(2, "0"),
18
- ":",
19
- date.getUTCMinutes().toString().padStart(2, "0"),
20
- ":",
21
- date.getUTCSeconds().toString().padStart(2, "0"),
22
- "Z",
23
- ].join("");
1
+ export function toUTCISO8601String(inputDate) {
2
+ // The format coming from the datetie-local input is YYYY-mm-ddTHH:MM
3
+ // e.g. 2024-10-10T14:25
4
+ // Currently we will just use that as a UTC value and show some explanation in the UI!
5
+ return `${inputDate}:00Z`;
24
6
  }
25
7
 
26
- export function toDateTimeInput(initialDate) {
27
- let date = null;
28
-
8
+ export function toDateTimeInput(initialDate = null) {
29
9
  if (typeof initialDate === "string") {
30
- date = new Date(initialDate);
31
- } else {
32
- date = initialDate;
10
+ // The case where it comes from the DB it is in UTC. We are going to directly feed it to the
11
+ // datetime-local input and add explanations in the UI!
12
+ return initialDate.replace("Z", "");
33
13
  }
34
14
 
15
+ // Directly use the current time for to feed the datetime-local input.
16
+ // show UI hints that this is going to be used as UTC time.
17
+ const now = new Date();
18
+
35
19
  return [
36
- date.getFullYear(),
20
+ now.getFullYear(),
37
21
  "-",
38
- (date.getMonth() + 1).toString().padStart(2, "0"),
22
+ (now.getMonth() + 1).toString().padStart(2, "0"),
39
23
  "-",
40
- date.getDate().toString().padStart(2, "0"),
24
+ now.getDate().toString().padStart(2, "0"),
41
25
  "T",
42
- date.getHours().toString().padStart(2, "0"),
26
+ now.getHours().toString().padStart(2, "0"),
43
27
  ":",
44
- date.getMinutes().toString().padStart(2, "0"),
28
+ now.getMinutes().toString().padStart(2, "0"),
45
29
  ].join("");
46
30
  }
@@ -11,7 +11,7 @@
11
11
  <form action="<%= `/${_context.locale}/article_revisions/${general_settings.id}/general` %>" method="POST" class="form">
12
12
  <%- f.field('general_settings.title', { required: true }) %>
13
13
  <%- f.field('general_settings.slug', { label: "URL", required: true }) %>
14
- <%- f.field('general_settings.publish_at', { required: true, type: 'datetime-local' }) %>
14
+ <%- f.field('general_settings.publish_at', { required: true, type: 'datetime-local', label: 'Publish at (UTC)' }) %>
15
15
  <%- f.field('general_settings.visibility', { as: 'select', required: true, options: visibilityOptions }) %>
16
16
 
17
17
  <%- f.field('general_settings.username', { required: true }) %>
@@ -11,9 +11,9 @@
11
11
  <form action="<%= `/${_context.locale}/event_revisions/${general_settings.id}/general` %>" method="POST" class="form">
12
12
  <%- f.field('general_settings.title', { required: true }) %>
13
13
  <%- f.field('general_settings.slug', { label: "URL", required: true }) %>
14
- <%- f.field('general_settings.publish_at', { required: true, type: 'datetime-local' }) %>
15
- <%- f.field('general_settings.starts_at', { required: true, type: 'datetime-local' }) %>
16
- <%- f.field('general_settings.ends_at', { required: true, type: 'datetime-local' }) %>
14
+ <%- f.field('general_settings.publish_at', { required: true, type: 'datetime-local', label: 'Publish at (UTC)' }) %>
15
+ <%- f.field('general_settings.starts_at', { required: true, type: 'datetime-local', label: 'Starts at (UTC)' }) %>
16
+ <%- f.field('general_settings.ends_at', { required: true, type: 'datetime-local', label: 'Ends at (UTC)' }) %>
17
17
  <%- f.field('general_settings.visibility', { as: 'select', required: true, options: visibilityOptions }) %>
18
18
 
19
19
  <%- f.field('general_settings.username', { required: true }) %>
@@ -104,6 +104,38 @@
104
104
  initToggle();
105
105
  toggleEl.addEventListener('click', handleToggle);
106
106
  </script>
107
+
108
+ <script>
109
+ // Don't ask
110
+ const TIMEZONES = JSON.parse("<%= JSON.stringify(_context.timezones) %>".replaceAll("&#34;", '"'))
111
+
112
+ function enhanceDateTimeInputs(input) {
113
+ // skew the date so it is like in UTC for the user...
114
+ // The datetime-local input gives the result witout a timezone so we can just attach the UTC one...
115
+ const fakeUTCDate = new Date(`${input.value}:00Z`)
116
+
117
+ const parent = input.parentNode;
118
+
119
+ parent.querySelectorAll('[data-auto="1"]').forEach(node => node.remove())
120
+
121
+ TIMEZONES.forEach(timeZone => {
122
+ const strTime = fakeUTCDate.toLocaleString("en-EU",{timeZone: `${timeZone.value}`});
123
+ const hint = document.createElement("div");
124
+
125
+ hint.classList.add('hint')
126
+ hint.innerText = `${timeZone.label}: ${strTime}`;
127
+ hint.dataset.auto = "1";
128
+
129
+ parent.appendChild(hint)
130
+ })
131
+ }
132
+
133
+ document.querySelectorAll('input[type="datetime-local"]').forEach(input => {
134
+ enhanceDateTimeInputs(input);
135
+
136
+ input.addEventListener("change", (event) => enhanceDateTimeInputs(event.target))
137
+ } )
138
+ </script>
107
139
  </body>
108
140
 
109
141
  </html>
package/test/factory.js CHANGED
@@ -29,7 +29,7 @@ const PAGE = {
29
29
  originalId: null,
30
30
  insertedAt: "2024-08-30T19:05:00Z",
31
31
  tags: [],
32
- pageType: {},
32
+ pageType: { slug: "page" },
33
33
  categories: [],
34
34
  };
35
35
 
@@ -50,7 +50,7 @@ const ARTICLE = {
50
50
  originalId: null,
51
51
  insertedAt: "2024-08-30T19:05:00Z",
52
52
  tags: [],
53
- articleType: {},
53
+ articleType: { slug: "article" },
54
54
  categories: [],
55
55
  };
56
56
 
@@ -73,7 +73,7 @@ const EVENT = {
73
73
  originalId: null,
74
74
  insertedAt: "2024-08-30T19:05:00Z",
75
75
  tags: [],
76
- articleType: {},
76
+ eventType: { slug: "event" },
77
77
  categories: [],
78
78
  };
79
79
 
@@ -6,4 +6,26 @@ function testConfig() {
6
6
  };
7
7
  }
8
8
 
9
- export { testConfig };
9
+ function remoteConfig() {
10
+ return {
11
+ resourcePath: (resource, resourceType, locale) => {
12
+ const PREFIX_MAP = {
13
+ page: "/",
14
+ article: "/blog",
15
+ event: "/events",
16
+ };
17
+
18
+ const prefix = PREFIX_MAP[resourceType];
19
+
20
+ if (!prefix) {
21
+ throw new Error(`Unknown resource type: ${resourceType}`);
22
+ }
23
+
24
+ return [`/${locale}`, prefix, "/", resource.slug]
25
+ .join("")
26
+ .replace("//", "/");
27
+ },
28
+ };
29
+ }
30
+
31
+ export { testConfig, remoteConfig };