@scalemule/news-publication 0.0.37 → 0.0.38
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.
|
@@ -104,23 +104,49 @@ function createPublicationCommunityMapsHandler(options) {
|
|
|
104
104
|
headers: {
|
|
105
105
|
...sdk.buildClientContextHeaders(clientContext),
|
|
106
106
|
"x-api-key": scope.apiKey,
|
|
107
|
-
...callOptions.headers
|
|
107
|
+
...callOptions.headers,
|
|
108
|
+
...request.headers.has("range") ? { range: request.headers.get("range") } : {}
|
|
108
109
|
},
|
|
109
110
|
cache: "no-store",
|
|
110
111
|
redirect: "error",
|
|
111
112
|
signal: AbortSignal.timeout(3e4)
|
|
112
113
|
}
|
|
113
114
|
);
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
);
|
|
115
|
+
const contentType = upstream.headers.get("content-type")?.split(";")[0] || "";
|
|
116
|
+
const allowed = [
|
|
117
|
+
"image/png",
|
|
118
|
+
"video/mp4",
|
|
119
|
+
"video/webm",
|
|
120
|
+
"audio/mpeg",
|
|
121
|
+
"audio/mp4",
|
|
122
|
+
"audio/ogg",
|
|
123
|
+
"audio/wav"
|
|
124
|
+
].includes(contentType);
|
|
125
|
+
const mediaHeaders = new Headers({
|
|
126
|
+
"cache-control": "private, no-store",
|
|
127
|
+
"x-content-type-options": "nosniff"
|
|
128
|
+
});
|
|
129
|
+
for (const key of [
|
|
130
|
+
"content-range",
|
|
131
|
+
"accept-ranges",
|
|
132
|
+
"content-length"
|
|
133
|
+
]) {
|
|
134
|
+
const value = upstream.headers.get(key);
|
|
135
|
+
if (value) mediaHeaders.set(key, value);
|
|
136
|
+
}
|
|
137
|
+
if ((upstream.ok || upstream.status === 416) && allowed) {
|
|
138
|
+
mediaHeaders.set("content-type", contentType);
|
|
139
|
+
response = new Response(upstream.body, {
|
|
140
|
+
status: upstream.status,
|
|
141
|
+
headers: mediaHeaders
|
|
142
|
+
});
|
|
143
|
+
} else {
|
|
144
|
+
await upstream.body?.cancel();
|
|
145
|
+
response = json(
|
|
146
|
+
{ error: { message: "Media unavailable" } },
|
|
147
|
+
upstream.ok || upstream.status >= 500 ? 503 : upstream.status
|
|
148
|
+
);
|
|
149
|
+
}
|
|
124
150
|
} else {
|
|
125
151
|
let result;
|
|
126
152
|
if (read) {
|
|
@@ -164,22 +190,23 @@ function createPublicationCommunityMapsHandler(options) {
|
|
|
164
190
|
} else if (upload) {
|
|
165
191
|
const contentType = request.headers.get("content-type") || "";
|
|
166
192
|
if (!contentType.startsWith("multipart/form-data;"))
|
|
167
|
-
throw new ProxyProblem(415, "Choose a
|
|
168
|
-
const bytes = await boundedBody(request,
|
|
193
|
+
throw new ProxyProblem(415, "Choose a photo, video or audio file.");
|
|
194
|
+
const bytes = await boundedBody(request, 26 * 1024 * 1024);
|
|
169
195
|
const form = await new Response(bytes, {
|
|
170
196
|
headers: { "content-type": contentType }
|
|
171
197
|
}).formData();
|
|
172
198
|
const file = form.get("file");
|
|
173
199
|
if (!(file instanceof Blob))
|
|
174
|
-
throw new ProxyProblem(400, "
|
|
175
|
-
result = await sdk$1.communityMaps.
|
|
200
|
+
throw new ProxyProblem(400, "Media is required.");
|
|
201
|
+
result = await sdk$1.communityMaps.uploadMedia(
|
|
176
202
|
slug,
|
|
177
203
|
rest[1],
|
|
178
204
|
file,
|
|
179
205
|
{
|
|
180
206
|
caption: String(form.get("caption") || ""),
|
|
181
207
|
attribution: String(form.get("attribution") || ""),
|
|
182
|
-
rights_confirmed: form.get("rights_confirmed") === "true"
|
|
208
|
+
rights_confirmed: form.get("rights_confirmed") === "true",
|
|
209
|
+
consent_version: String(form.get("consent_version") || "")
|
|
183
210
|
},
|
|
184
211
|
callOptions
|
|
185
212
|
);
|
|
@@ -102,23 +102,49 @@ function createPublicationCommunityMapsHandler(options) {
|
|
|
102
102
|
headers: {
|
|
103
103
|
...buildClientContextHeaders(clientContext),
|
|
104
104
|
"x-api-key": scope.apiKey,
|
|
105
|
-
...callOptions.headers
|
|
105
|
+
...callOptions.headers,
|
|
106
|
+
...request.headers.has("range") ? { range: request.headers.get("range") } : {}
|
|
106
107
|
},
|
|
107
108
|
cache: "no-store",
|
|
108
109
|
redirect: "error",
|
|
109
110
|
signal: AbortSignal.timeout(3e4)
|
|
110
111
|
}
|
|
111
112
|
);
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
);
|
|
113
|
+
const contentType = upstream.headers.get("content-type")?.split(";")[0] || "";
|
|
114
|
+
const allowed = [
|
|
115
|
+
"image/png",
|
|
116
|
+
"video/mp4",
|
|
117
|
+
"video/webm",
|
|
118
|
+
"audio/mpeg",
|
|
119
|
+
"audio/mp4",
|
|
120
|
+
"audio/ogg",
|
|
121
|
+
"audio/wav"
|
|
122
|
+
].includes(contentType);
|
|
123
|
+
const mediaHeaders = new Headers({
|
|
124
|
+
"cache-control": "private, no-store",
|
|
125
|
+
"x-content-type-options": "nosniff"
|
|
126
|
+
});
|
|
127
|
+
for (const key of [
|
|
128
|
+
"content-range",
|
|
129
|
+
"accept-ranges",
|
|
130
|
+
"content-length"
|
|
131
|
+
]) {
|
|
132
|
+
const value = upstream.headers.get(key);
|
|
133
|
+
if (value) mediaHeaders.set(key, value);
|
|
134
|
+
}
|
|
135
|
+
if ((upstream.ok || upstream.status === 416) && allowed) {
|
|
136
|
+
mediaHeaders.set("content-type", contentType);
|
|
137
|
+
response = new Response(upstream.body, {
|
|
138
|
+
status: upstream.status,
|
|
139
|
+
headers: mediaHeaders
|
|
140
|
+
});
|
|
141
|
+
} else {
|
|
142
|
+
await upstream.body?.cancel();
|
|
143
|
+
response = json(
|
|
144
|
+
{ error: { message: "Media unavailable" } },
|
|
145
|
+
upstream.ok || upstream.status >= 500 ? 503 : upstream.status
|
|
146
|
+
);
|
|
147
|
+
}
|
|
122
148
|
} else {
|
|
123
149
|
let result;
|
|
124
150
|
if (read) {
|
|
@@ -162,22 +188,23 @@ function createPublicationCommunityMapsHandler(options) {
|
|
|
162
188
|
} else if (upload) {
|
|
163
189
|
const contentType = request.headers.get("content-type") || "";
|
|
164
190
|
if (!contentType.startsWith("multipart/form-data;"))
|
|
165
|
-
throw new ProxyProblem(415, "Choose a
|
|
166
|
-
const bytes = await boundedBody(request,
|
|
191
|
+
throw new ProxyProblem(415, "Choose a photo, video or audio file.");
|
|
192
|
+
const bytes = await boundedBody(request, 26 * 1024 * 1024);
|
|
167
193
|
const form = await new Response(bytes, {
|
|
168
194
|
headers: { "content-type": contentType }
|
|
169
195
|
}).formData();
|
|
170
196
|
const file = form.get("file");
|
|
171
197
|
if (!(file instanceof Blob))
|
|
172
|
-
throw new ProxyProblem(400, "
|
|
173
|
-
result = await sdk.communityMaps.
|
|
198
|
+
throw new ProxyProblem(400, "Media is required.");
|
|
199
|
+
result = await sdk.communityMaps.uploadMedia(
|
|
174
200
|
slug,
|
|
175
201
|
rest[1],
|
|
176
202
|
file,
|
|
177
203
|
{
|
|
178
204
|
caption: String(form.get("caption") || ""),
|
|
179
205
|
attribution: String(form.get("attribution") || ""),
|
|
180
|
-
rights_confirmed: form.get("rights_confirmed") === "true"
|
|
206
|
+
rights_confirmed: form.get("rights_confirmed") === "true",
|
|
207
|
+
consent_version: String(form.get("consent_version") || "")
|
|
181
208
|
},
|
|
182
209
|
callOptions
|
|
183
210
|
);
|
|
@@ -33,7 +33,8 @@ function PublicationCommunityMapPage({
|
|
|
33
33
|
areaId,
|
|
34
34
|
correctionFor,
|
|
35
35
|
basePath,
|
|
36
|
-
apiPath
|
|
36
|
+
apiPath,
|
|
37
|
+
atlas
|
|
37
38
|
}) {
|
|
38
39
|
const client = react.useMemo(
|
|
39
40
|
() => communityMaps.createCommunityMapsBrowserClient(apiPath),
|
|
@@ -51,7 +52,9 @@ function PublicationCommunityMapPage({
|
|
|
51
52
|
client,
|
|
52
53
|
collection,
|
|
53
54
|
initialAreaId: areaId,
|
|
54
|
-
correctionFor
|
|
55
|
+
correctionFor,
|
|
56
|
+
guidelinesHref: "/editorial-standards",
|
|
57
|
+
termsHref: "/terms"
|
|
55
58
|
}
|
|
56
59
|
) : mode === "feature" && feature ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
57
60
|
communityMaps.CommunityFeatureDetail,
|
|
@@ -61,6 +64,16 @@ function PublicationCommunityMapPage({
|
|
|
61
64
|
feature,
|
|
62
65
|
correctionHref: `${basePath}/submit?correction=${feature.id}&area=${feature.area_id}`
|
|
63
66
|
}
|
|
67
|
+
) : atlas ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
68
|
+
communityMaps.CommunityCityGuide,
|
|
69
|
+
{
|
|
70
|
+
client,
|
|
71
|
+
collection,
|
|
72
|
+
atlas,
|
|
73
|
+
featureHref,
|
|
74
|
+
communityHref: (id) => `${basePath}?area=${id}`,
|
|
75
|
+
submitHref: `${basePath}/submit?area=${collection.areas.find((a) => a.slug === atlas.areaSlug)?.id || ""}`
|
|
76
|
+
}
|
|
64
77
|
) : /* @__PURE__ */ jsxRuntime.jsx(
|
|
65
78
|
communityMaps.CommunityGuide,
|
|
66
79
|
{
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as react from 'react';
|
|
2
|
-
import { CommunityMapCollection, CommunityMapFeature } from '@scalemule/react/community-maps';
|
|
2
|
+
import { CommunityMapCollection, CommunityMapFeature, CommunityCityAtlasConfig } from '@scalemule/react/community-maps';
|
|
3
3
|
export { c as communityMapEmbeds } from './community-maps-DKcYhQYN.cjs';
|
|
4
4
|
|
|
5
5
|
interface PublicationCommunityMapPageProps {
|
|
@@ -10,9 +10,10 @@ interface PublicationCommunityMapPageProps {
|
|
|
10
10
|
correctionFor?: string;
|
|
11
11
|
basePath: string;
|
|
12
12
|
apiPath?: string;
|
|
13
|
+
atlas?: CommunityCityAtlasConfig;
|
|
13
14
|
}
|
|
14
15
|
/** The newspaper supplies its chrome and inherited type. The platform owns map behavior. */
|
|
15
|
-
declare function PublicationCommunityMapPage({ collection, feature, mode, areaId, correctionFor, basePath, apiPath, }: PublicationCommunityMapPageProps): react.JSX.Element;
|
|
16
|
+
declare function PublicationCommunityMapPage({ collection, feature, mode, areaId, correctionFor, basePath, apiPath, atlas, }: PublicationCommunityMapPageProps): react.JSX.Element;
|
|
16
17
|
|
|
17
18
|
declare function CommunityMapArticleEmbeds({ metadata, apiPath, }: {
|
|
18
19
|
metadata: unknown;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as react from 'react';
|
|
2
|
-
import { CommunityMapCollection, CommunityMapFeature } from '@scalemule/react/community-maps';
|
|
2
|
+
import { CommunityMapCollection, CommunityMapFeature, CommunityCityAtlasConfig } from '@scalemule/react/community-maps';
|
|
3
3
|
export { c as communityMapEmbeds } from './community-maps-DKcYhQYN.js';
|
|
4
4
|
|
|
5
5
|
interface PublicationCommunityMapPageProps {
|
|
@@ -10,9 +10,10 @@ interface PublicationCommunityMapPageProps {
|
|
|
10
10
|
correctionFor?: string;
|
|
11
11
|
basePath: string;
|
|
12
12
|
apiPath?: string;
|
|
13
|
+
atlas?: CommunityCityAtlasConfig;
|
|
13
14
|
}
|
|
14
15
|
/** The newspaper supplies its chrome and inherited type. The platform owns map behavior. */
|
|
15
|
-
declare function PublicationCommunityMapPage({ collection, feature, mode, areaId, correctionFor, basePath, apiPath, }: PublicationCommunityMapPageProps): react.JSX.Element;
|
|
16
|
+
declare function PublicationCommunityMapPage({ collection, feature, mode, areaId, correctionFor, basePath, apiPath, atlas, }: PublicationCommunityMapPageProps): react.JSX.Element;
|
|
16
17
|
|
|
17
18
|
declare function CommunityMapArticleEmbeds({ metadata, apiPath, }: {
|
|
18
19
|
metadata: unknown;
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import { communityMapEmbeds } from './chunk-IMYBSG7J.js';
|
|
3
3
|
export { communityMapEmbeds } from './chunk-IMYBSG7J.js';
|
|
4
4
|
import { useMemo, useState, useEffect } from 'react';
|
|
5
|
-
import { createCommunityMapsBrowserClient, CommunitySubmissionForm, CommunityFeatureDetail, CommunityGuide, CommunityCards, CommunityMap, CommunityFeatureCard } from '@scalemule/react/community-maps';
|
|
5
|
+
import { createCommunityMapsBrowserClient, CommunitySubmissionForm, CommunityFeatureDetail, CommunityCityGuide, CommunityGuide, CommunityCards, CommunityMap, CommunityFeatureCard } from '@scalemule/react/community-maps';
|
|
6
6
|
import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
|
|
7
7
|
|
|
8
8
|
function PublicationCommunityMapPage({
|
|
@@ -12,7 +12,8 @@ function PublicationCommunityMapPage({
|
|
|
12
12
|
areaId,
|
|
13
13
|
correctionFor,
|
|
14
14
|
basePath,
|
|
15
|
-
apiPath
|
|
15
|
+
apiPath,
|
|
16
|
+
atlas
|
|
16
17
|
}) {
|
|
17
18
|
const client = useMemo(
|
|
18
19
|
() => createCommunityMapsBrowserClient(apiPath),
|
|
@@ -30,7 +31,9 @@ function PublicationCommunityMapPage({
|
|
|
30
31
|
client,
|
|
31
32
|
collection,
|
|
32
33
|
initialAreaId: areaId,
|
|
33
|
-
correctionFor
|
|
34
|
+
correctionFor,
|
|
35
|
+
guidelinesHref: "/editorial-standards",
|
|
36
|
+
termsHref: "/terms"
|
|
34
37
|
}
|
|
35
38
|
) : mode === "feature" && feature ? /* @__PURE__ */ jsx(
|
|
36
39
|
CommunityFeatureDetail,
|
|
@@ -40,6 +43,16 @@ function PublicationCommunityMapPage({
|
|
|
40
43
|
feature,
|
|
41
44
|
correctionHref: `${basePath}/submit?correction=${feature.id}&area=${feature.area_id}`
|
|
42
45
|
}
|
|
46
|
+
) : atlas ? /* @__PURE__ */ jsx(
|
|
47
|
+
CommunityCityGuide,
|
|
48
|
+
{
|
|
49
|
+
client,
|
|
50
|
+
collection,
|
|
51
|
+
atlas,
|
|
52
|
+
featureHref,
|
|
53
|
+
communityHref: (id) => `${basePath}?area=${id}`,
|
|
54
|
+
submitHref: `${basePath}/submit?area=${collection.areas.find((a) => a.slug === atlas.areaSlug)?.id || ""}`
|
|
55
|
+
}
|
|
43
56
|
) : /* @__PURE__ */ jsx(
|
|
44
57
|
CommunityGuide,
|
|
45
58
|
{
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@scalemule/news-publication",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.38",
|
|
4
4
|
"description": "Shared server framework for ScaleMule local news publications. Walnut Creek Times is the broadsheet default; each paper supplies its own identity and feature flags.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.cjs",
|
|
@@ -162,6 +162,7 @@
|
|
|
162
162
|
},
|
|
163
163
|
"dependencies": {
|
|
164
164
|
"@scalemule/compliance": "^0.0.5",
|
|
165
|
-
"@scalemule/sdk": "
|
|
165
|
+
"@scalemule/sdk": "0.0.73",
|
|
166
|
+
"@scalemule/react": "0.0.14"
|
|
166
167
|
}
|
|
167
168
|
}
|