@raketa-cloud/admin 0.0.69 → 0.0.70
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/package.json +1 -1
- package/src/handlers/articles/TranslationsHandler.js +129 -44
- package/src/handlers/events/TranslationsHandler.js +132 -49
- package/src/tests/handlers/articles/TranslationHandler.test/create.test.js +291 -0
- package/src/tests/handlers/articles/TranslationHandler.test/create_form.test.js +71 -0
- package/src/tests/handlers/articles/TranslationHandler.test/index.test.js +91 -0
- package/src/tests/handlers/events/TranslationHandler.test/create.test.js +297 -0
- package/src/tests/handlers/events/TranslationHandler.test/create_form.test.js +71 -0
- package/src/tests/handlers/events/TranslationHandler.test/index.test.js +91 -0
- package/src/tests/handlers/pages/TranslationHandler.test/create.test.js +1 -1
- package/src/views/articles/_shared/_history_toolbar.ejs +2 -2
- package/src/views/articles/show.ejs +15 -4
- package/src/views/articles/translations/_translation_toolbar.ejs +18 -0
- package/src/views/articles/translations/create_form.ejs +68 -4
- package/src/views/articles/translations/index.ejs +39 -0
- package/src/views/events/_shared/_history_toolbar.ejs +2 -2
- package/src/views/events/show.ejs +15 -4
- package/src/views/events/translations/_translation_toolbar.ejs +18 -0
- package/src/views/events/translations/create_form.ejs +68 -4
- package/src/views/events/translations/index.ejs +39 -0
- package/src/views/pages/_shared/_history_toolbar.ejs +2 -2
- package/src/views/pages/show.ejs +2 -4
- package/src/views/pages/translations/_translation_toolbar.ejs +18 -0
- package/src/views/pages/translations/index.ejs +2 -19
- package/src/views/articles/translations/_form.ejs +0 -31
- package/src/views/events/translations/_form.ejs +0 -33
package/package.json
CHANGED
|
@@ -1,25 +1,73 @@
|
|
|
1
|
-
|
|
1
|
+
const index = async (ctx) => {
|
|
2
|
+
const { parent_id } = ctx.params;
|
|
3
|
+
const { translations } = ctx.query;
|
|
4
|
+
let translatedArticles = [];
|
|
5
|
+
|
|
6
|
+
if (translations) {
|
|
7
|
+
const translationPairs = translations.split(";").map((pair) => {
|
|
8
|
+
const [locale, id] = pair.split(":");
|
|
9
|
+
return { locale, id };
|
|
10
|
+
});
|
|
11
|
+
|
|
12
|
+
translatedArticles = await Promise.all(
|
|
13
|
+
translationPairs.map(async ({ locale, id }) => {
|
|
14
|
+
const article = await ctx.client.articles.find(id, locale);
|
|
15
|
+
|
|
16
|
+
if (!article) {
|
|
17
|
+
throw new Error(
|
|
18
|
+
`Cannot find translated article with id ${id} and locale ${locale}`
|
|
19
|
+
);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
const revisions = await ctx.client.articleRevisions.all(id, locale);
|
|
23
|
+
const openRevision = revisions.list[0];
|
|
24
|
+
|
|
25
|
+
return {
|
|
26
|
+
...article,
|
|
27
|
+
translationLocale: locale,
|
|
28
|
+
revisionId: openRevision?.id,
|
|
29
|
+
};
|
|
30
|
+
})
|
|
31
|
+
);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
const items = await ctx.client.articles.list(
|
|
35
|
+
ctx.query,
|
|
36
|
+
ctx.locale,
|
|
37
|
+
ctx.resourceConfig.articleType
|
|
38
|
+
);
|
|
39
|
+
|
|
40
|
+
const originalArticle = await ctx.client.articles.find(parent_id, ctx.locale);
|
|
41
|
+
|
|
42
|
+
return {
|
|
43
|
+
assigns: {
|
|
44
|
+
items,
|
|
45
|
+
visibilityOptions: ctx.client.articles.visibilityOptions(),
|
|
46
|
+
translations: translatedArticles,
|
|
47
|
+
parent_id,
|
|
48
|
+
articleTitle: originalArticle.title,
|
|
49
|
+
},
|
|
50
|
+
};
|
|
51
|
+
};
|
|
2
52
|
|
|
3
53
|
const create_form = async (ctx) => {
|
|
4
|
-
const { target_locale } = ctx.query;
|
|
5
|
-
const target_locate_tags = await ctx.client.tags.all(target_locale);
|
|
54
|
+
const { target_locale = "" } = ctx.query;
|
|
6
55
|
|
|
7
56
|
const { parent_id } = ctx.params;
|
|
8
57
|
const blueprint = await ctx.client.articles.find(parent_id, ctx.locale);
|
|
58
|
+
|
|
59
|
+
if (!blueprint) {
|
|
60
|
+
throw new Error(`Cannot find article with id ${parent_id}`);
|
|
61
|
+
}
|
|
62
|
+
|
|
9
63
|
const resource = structuredClone(blueprint);
|
|
10
64
|
|
|
11
65
|
return {
|
|
12
66
|
assigns: {
|
|
13
|
-
resource
|
|
14
|
-
...resource,
|
|
15
|
-
tags: [],
|
|
16
|
-
publishAt: toDateTimeInput(blueprint.publishAt),
|
|
17
|
-
},
|
|
67
|
+
resource,
|
|
18
68
|
blueprint,
|
|
19
69
|
targetLocale: target_locale,
|
|
20
|
-
tags: target_locate_tags.list,
|
|
21
70
|
errors: {},
|
|
22
|
-
visibilityOptions: ctx.client.articles.visibilityOptions(),
|
|
23
71
|
_translations: [],
|
|
24
72
|
},
|
|
25
73
|
};
|
|
@@ -27,54 +75,91 @@ const create_form = async (ctx) => {
|
|
|
27
75
|
|
|
28
76
|
const create = async (ctx) => {
|
|
29
77
|
const { parent_id } = ctx.params;
|
|
78
|
+
const originalLocale = ctx.locale;
|
|
30
79
|
const blueprint = await ctx.client.articles.find(parent_id, ctx.locale);
|
|
31
80
|
|
|
32
|
-
const
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
const resource = ctx.client.articles.deepMerge(
|
|
36
|
-
{
|
|
37
|
-
settings: {
|
|
38
|
-
...blueprint.settings,
|
|
39
|
-
},
|
|
40
|
-
widgets: blueprint.widgets,
|
|
41
|
-
categories: blueprint.categories.map((category) => category.id),
|
|
42
|
-
tags: [],
|
|
43
|
-
},
|
|
44
|
-
ctx.client.articles.formatDates(params)
|
|
45
|
-
);
|
|
81
|
+
const formLanguages = Array.isArray(ctx.resourceParams.resource.languages)
|
|
82
|
+
? ctx.resourceParams.resource.languages
|
|
83
|
+
: [ctx.resourceParams.resource.languages].filter(Boolean);
|
|
46
84
|
|
|
47
|
-
const
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
85
|
+
const existingTranslations = Object.keys(blueprint.translations || {});
|
|
86
|
+
const selectedLocales = formLanguages.filter(
|
|
87
|
+
(locale) =>
|
|
88
|
+
locale !== originalLocale && !existingTranslations.includes(locale)
|
|
51
89
|
);
|
|
52
90
|
|
|
53
|
-
|
|
54
|
-
|
|
91
|
+
const params = {
|
|
92
|
+
settings: blueprint.settings,
|
|
93
|
+
widgets: blueprint.widgets,
|
|
94
|
+
categories: blueprint.categories.map((category) => category.id),
|
|
95
|
+
publishAt: blueprint.publishAt,
|
|
96
|
+
title: blueprint.title,
|
|
97
|
+
slug: blueprint.slug,
|
|
98
|
+
tags: [],
|
|
99
|
+
};
|
|
100
|
+
|
|
101
|
+
const translationIds = [];
|
|
102
|
+
|
|
103
|
+
for (const locale of selectedLocales) {
|
|
104
|
+
const resource = ctx.client.articles.deepMerge(params, {
|
|
105
|
+
visibility: "private",
|
|
106
|
+
});
|
|
107
|
+
|
|
108
|
+
const { errors, article } = await ctx.client.articles.translate(
|
|
109
|
+
parent_id,
|
|
110
|
+
locale,
|
|
111
|
+
resource
|
|
112
|
+
);
|
|
113
|
+
|
|
114
|
+
if (errors) {
|
|
115
|
+
return {
|
|
116
|
+
assigns: {
|
|
117
|
+
resource: {
|
|
118
|
+
...resource,
|
|
119
|
+
translations: blueprint.translations || {},
|
|
120
|
+
languages: formLanguages,
|
|
121
|
+
},
|
|
122
|
+
blueprint,
|
|
123
|
+
targetLocale: locale,
|
|
124
|
+
errors: { resource: ctx.client.articles.formatErrors(errors) },
|
|
125
|
+
},
|
|
126
|
+
};
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
if (article) {
|
|
130
|
+
translationIds.push(`${locale}:${article.id}`);
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
const { errors: revisionErrors } = await ctx.client.articleRevisions.create(
|
|
134
|
+
article.id,
|
|
135
|
+
locale
|
|
136
|
+
);
|
|
55
137
|
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
138
|
+
if (revisionErrors) {
|
|
139
|
+
return {
|
|
140
|
+
assigns: {
|
|
141
|
+
resource: {
|
|
142
|
+
...resource,
|
|
143
|
+
translations: blueprint.translations || {},
|
|
144
|
+
languages: formLanguages,
|
|
145
|
+
},
|
|
146
|
+
blueprint,
|
|
147
|
+
targetLocale: locale,
|
|
148
|
+
errors: {
|
|
149
|
+
resource: ctx.client.articles.formatErrors(revisionErrors),
|
|
150
|
+
},
|
|
61
151
|
},
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
tags: tags.list,
|
|
65
|
-
errors: { resource: ctx.client.pages.formatErrors(errors) },
|
|
66
|
-
visibilityOptions: ctx.client.articles.visibilityOptions(),
|
|
67
|
-
_translations: [],
|
|
68
|
-
},
|
|
69
|
-
};
|
|
152
|
+
};
|
|
153
|
+
}
|
|
70
154
|
}
|
|
71
155
|
|
|
72
156
|
return {
|
|
73
|
-
redirect: `/${
|
|
157
|
+
redirect: `/${originalLocale}/${ctx.resourceConfig.articleTypePlural}/${parent_id}/translations?translations=${translationIds.join(";")}`,
|
|
74
158
|
};
|
|
75
159
|
};
|
|
76
160
|
|
|
77
161
|
export default {
|
|
162
|
+
index,
|
|
78
163
|
create_form,
|
|
79
164
|
create,
|
|
80
165
|
};
|
|
@@ -1,29 +1,73 @@
|
|
|
1
|
-
|
|
1
|
+
const index = async (ctx) => {
|
|
2
|
+
const { parent_id } = ctx.params;
|
|
3
|
+
const { translations } = ctx.query;
|
|
4
|
+
let translatedEvents = [];
|
|
5
|
+
|
|
6
|
+
if (translations) {
|
|
7
|
+
const translationPairs = translations.split(";").map((pair) => {
|
|
8
|
+
const [locale, id] = pair.split(":");
|
|
9
|
+
return { locale, id };
|
|
10
|
+
});
|
|
11
|
+
|
|
12
|
+
translatedEvents = await Promise.all(
|
|
13
|
+
translationPairs.map(async ({ locale, id }) => {
|
|
14
|
+
const event = await ctx.client.events.find(id, locale);
|
|
15
|
+
|
|
16
|
+
if (!event) {
|
|
17
|
+
throw new Error(
|
|
18
|
+
`Cannot find translated event with id ${id} and locale ${locale}`
|
|
19
|
+
);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
const revisions = await ctx.client.eventRevisions.all(id, locale);
|
|
23
|
+
const openRevision = revisions.list[0];
|
|
24
|
+
|
|
25
|
+
return {
|
|
26
|
+
...event,
|
|
27
|
+
translationLocale: locale,
|
|
28
|
+
revisionId: openRevision?.id,
|
|
29
|
+
};
|
|
30
|
+
})
|
|
31
|
+
);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
const items = await ctx.client.events.list(
|
|
35
|
+
ctx.query,
|
|
36
|
+
ctx.locale,
|
|
37
|
+
ctx.resourceConfig.eventType
|
|
38
|
+
);
|
|
39
|
+
|
|
40
|
+
const originalEvent = await ctx.client.events.find(parent_id, ctx.locale);
|
|
41
|
+
|
|
42
|
+
return {
|
|
43
|
+
assigns: {
|
|
44
|
+
items,
|
|
45
|
+
visibilityOptions: ctx.client.events.visibilityOptions(),
|
|
46
|
+
translations: translatedEvents,
|
|
47
|
+
parent_id,
|
|
48
|
+
eventTitle: originalEvent.title,
|
|
49
|
+
},
|
|
50
|
+
};
|
|
51
|
+
};
|
|
2
52
|
|
|
3
53
|
const create_form = async (ctx) => {
|
|
4
|
-
|
|
5
|
-
const { target_locale } = ctx.query;
|
|
6
|
-
const target_locate_tags = await ctx.client.tags.all(target_locale);
|
|
54
|
+
const { target_locale = "" } = ctx.query;
|
|
7
55
|
|
|
8
56
|
const { parent_id } = ctx.params;
|
|
9
57
|
const blueprint = await ctx.client.events.find(parent_id, ctx.locale);
|
|
10
58
|
|
|
59
|
+
if (!blueprint) {
|
|
60
|
+
throw new Error(`Cannot find event with id ${parent_id}`);
|
|
61
|
+
}
|
|
62
|
+
|
|
11
63
|
const resource = structuredClone(blueprint);
|
|
12
64
|
|
|
13
65
|
return {
|
|
14
66
|
assigns: {
|
|
15
|
-
resource
|
|
16
|
-
...resource,
|
|
17
|
-
tags: [],
|
|
18
|
-
publishAt: toDateTimeInput(blueprint.publishAt),
|
|
19
|
-
startsAt: toDateTimeInput(blueprint.startsAt),
|
|
20
|
-
endsAt: toDateTimeInput(blueprint.endsAt),
|
|
21
|
-
},
|
|
67
|
+
resource,
|
|
22
68
|
blueprint,
|
|
23
69
|
targetLocale: target_locale,
|
|
24
|
-
tags: target_locate_tags.list,
|
|
25
70
|
errors: {},
|
|
26
|
-
visibilityOptions: ctx.client.events.visibilityOptions(),
|
|
27
71
|
_translations: [],
|
|
28
72
|
},
|
|
29
73
|
};
|
|
@@ -31,54 +75,93 @@ const create_form = async (ctx) => {
|
|
|
31
75
|
|
|
32
76
|
const create = async (ctx) => {
|
|
33
77
|
const { parent_id } = ctx.params;
|
|
78
|
+
const originalLocale = ctx.locale;
|
|
34
79
|
const blueprint = await ctx.client.events.find(parent_id, ctx.locale);
|
|
35
80
|
|
|
36
|
-
const
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
const resource = ctx.client.events.deepMerge(
|
|
40
|
-
{
|
|
41
|
-
settings: {
|
|
42
|
-
...blueprint.settings,
|
|
43
|
-
},
|
|
44
|
-
widgets: blueprint.widgets,
|
|
45
|
-
categories: blueprint.categories.map((category) => category.id),
|
|
46
|
-
tags: [],
|
|
47
|
-
},
|
|
48
|
-
ctx.client.events.formatDates(params)
|
|
49
|
-
);
|
|
81
|
+
const formLanguages = Array.isArray(ctx.resourceParams.resource.languages)
|
|
82
|
+
? ctx.resourceParams.resource.languages
|
|
83
|
+
: [ctx.resourceParams.resource.languages].filter(Boolean);
|
|
50
84
|
|
|
51
|
-
const
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
85
|
+
const existingTranslations = Object.keys(blueprint.translations || {});
|
|
86
|
+
const selectedLocales = formLanguages.filter(
|
|
87
|
+
(locale) =>
|
|
88
|
+
locale !== originalLocale && !existingTranslations.includes(locale)
|
|
55
89
|
);
|
|
56
90
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
91
|
+
const params = {
|
|
92
|
+
settings: blueprint.settings,
|
|
93
|
+
widgets: blueprint.widgets,
|
|
94
|
+
categories: blueprint.categories.map((category) => category.id),
|
|
95
|
+
publishAt: blueprint.publishAt,
|
|
96
|
+
startsAt: blueprint.startsAt,
|
|
97
|
+
endsAt: blueprint.endsAt,
|
|
98
|
+
title: blueprint.title,
|
|
99
|
+
slug: blueprint.slug,
|
|
100
|
+
tags: [],
|
|
101
|
+
};
|
|
102
|
+
|
|
103
|
+
const translationIds = [];
|
|
104
|
+
|
|
105
|
+
for (const locale of selectedLocales) {
|
|
106
|
+
const resource = ctx.client.events.deepMerge(params, {
|
|
107
|
+
visibility: "private",
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
const { errors, event } = await ctx.client.events.translate(
|
|
111
|
+
parent_id,
|
|
112
|
+
locale,
|
|
113
|
+
resource
|
|
114
|
+
);
|
|
115
|
+
|
|
116
|
+
if (errors) {
|
|
117
|
+
return {
|
|
118
|
+
assigns: {
|
|
119
|
+
resource: {
|
|
120
|
+
...resource,
|
|
121
|
+
translations: blueprint.translations || {},
|
|
122
|
+
languages: formLanguages,
|
|
123
|
+
},
|
|
124
|
+
blueprint,
|
|
125
|
+
targetLocale: locale,
|
|
126
|
+
errors: { resource: ctx.client.events.formatErrors(errors) },
|
|
127
|
+
},
|
|
128
|
+
};
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
if (event) {
|
|
132
|
+
translationIds.push(`${locale}:${event.id}`);
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
const { errors: revisionErrors } = await ctx.client.eventRevisions.create(
|
|
136
|
+
event.id,
|
|
137
|
+
locale
|
|
138
|
+
);
|
|
139
|
+
|
|
140
|
+
if (revisionErrors) {
|
|
141
|
+
return {
|
|
142
|
+
assigns: {
|
|
143
|
+
resource: {
|
|
144
|
+
...resource,
|
|
145
|
+
translations: blueprint.translations || {},
|
|
146
|
+
languages: formLanguages,
|
|
147
|
+
},
|
|
148
|
+
blueprint,
|
|
149
|
+
targetLocale: locale,
|
|
150
|
+
errors: {
|
|
151
|
+
resource: ctx.client.events.formatErrors(revisionErrors),
|
|
152
|
+
},
|
|
66
153
|
},
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
tags: tags.list,
|
|
70
|
-
errors: { resource: ctx.client.pages.formatErrors(errors) },
|
|
71
|
-
visibilityOptions: ctx.client.events.visibilityOptions(),
|
|
72
|
-
_translations: [],
|
|
73
|
-
},
|
|
74
|
-
};
|
|
154
|
+
};
|
|
155
|
+
}
|
|
75
156
|
}
|
|
157
|
+
|
|
76
158
|
return {
|
|
77
|
-
redirect: `/${
|
|
159
|
+
redirect: `/${originalLocale}/${ctx.resourceConfig.eventTypePlural}/${parent_id}/translations?translations=${translationIds.join(";")}`,
|
|
78
160
|
};
|
|
79
161
|
};
|
|
80
162
|
|
|
81
163
|
export default {
|
|
164
|
+
index,
|
|
82
165
|
create_form,
|
|
83
166
|
create,
|
|
84
167
|
};
|