@wix/himalaya-cli 0.1222.0 → 0.1224.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/authoring-runtime/node_modules/@wix/himalaya/dist/_types/stdlib/wix-sdk/events/src/display.d.ts +3 -0
- package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/wix-events.mjs +3 -1
- package/dist/cli.mjs +33 -24
- package/dist/preview-assets.generated.bin +0 -0
- package/guides/sdk-reference.json +1 -1
- package/package.json +2 -2
- package/templates/beauty-salon/dev/index.ts +5 -1
- package/templates/beauty-salon/tier5-src/_shared/collection-contract.ts +15 -2
- package/templates/beauty-salon/tier5-src/wix-spaces-create-post/index.ts +14 -4
- package/templates/beauty-salon-owner/tier5-src/_shared/collection-contract.ts +15 -2
- package/templates/branded-lite/dev/index.ts +520 -274
- package/templates/branded-lite/tier5-src/_shared/collection-contract.ts +15 -2
- package/templates/branded-lite/tier5-src/wix-spaces-create-post/index.ts +14 -4
- package/templates/community-club/dev/index.ts +518 -272
- package/templates/community-club/tier5-src/_shared/collection-contract.ts +15 -2
- package/templates/community-club/tier5-src/wix-spaces-create-post/index.ts +14 -4
- package/templates/community-club-owner/tier5-src/_shared/collection-contract.ts +15 -2
- package/templates/community-club-owner/tier5-src/himi-owner-lite-events/index.ts +1 -0
- package/templates/events-meetups/dev/index.ts +518 -272
- package/templates/events-meetups/tier5-src/_shared/collection-contract.ts +15 -2
- package/templates/events-meetups/tier5-src/wix-spaces-create-post/index.ts +14 -4
- package/templates/events-meetups-owner/tier5-src/_shared/collection-contract.ts +15 -2
- package/templates/events-meetups-owner/tier5-src/himi-owner-lite-events/index.ts +1 -0
- package/templates/gym-fitness/dev/index.ts +520 -274
- package/templates/gym-fitness/tier5-src/_shared/collection-contract.ts +15 -2
- package/templates/gym-fitness/tier5-src/wix-spaces-create-post/index.ts +14 -4
- package/templates/gym-fitness-owner/tier5-src/_shared/collection-contract.ts +15 -2
- package/templates/gym-fitness-owner/tier5-src/himi-owner-lite-events/index.ts +1 -0
- package/templates/nonprofit-cause/dev/index.ts +518 -272
- package/templates/nonprofit-cause/tier5-src/_shared/collection-contract.ts +15 -2
- package/templates/nonprofit-cause/tier5-src/wix-spaces-create-post/index.ts +14 -4
- package/templates/nonprofit-cause-owner/tier5-src/_shared/collection-contract.ts +15 -2
- package/templates/nonprofit-cause-owner/tier5-src/himi-owner-lite-events/index.ts +1 -0
- package/templates/owner-lite/tier5-src/_shared/collection-contract.ts +15 -2
- package/templates/owner-lite/tier5-src/himi-owner-lite-events/index.ts +1 -0
- package/templates/podcast-creator/dev/index.ts +518 -272
- package/templates/podcast-creator/tier5-src/_shared/collection-contract.ts +15 -2
- package/templates/podcast-creator/tier5-src/wix-spaces-create-post/index.ts +14 -4
- package/templates/podcast-creator-owner/tier5-src/_shared/collection-contract.ts +15 -2
- package/templates/podcast-creator-owner/tier5-src/himi-owner-lite-events/index.ts +1 -0
- package/templates/portfolio-creative/dev/index.ts +520 -274
- package/templates/portfolio-creative/tier5-src/_shared/collection-contract.ts +15 -2
- package/templates/portfolio-creative/tier5-src/wix-spaces-create-post/index.ts +14 -4
- package/templates/portfolio-creative-owner/tier5-src/_shared/collection-contract.ts +15 -2
- package/templates/restaurant/dev/index.ts +518 -272
- package/templates/restaurant/tier5-src/_shared/collection-contract.ts +15 -2
- package/templates/restaurant/tier5-src/wix-spaces-create-post/index.ts +14 -4
- package/templates/restaurant-owner/tier5-src/_shared/collection-contract.ts +15 -2
- package/templates/restaurant-owner/tier5-src/himi-owner-lite-events/index.ts +1 -0
- package/templates/retail-store/dev/index.ts +5 -1
- package/templates/retail-store/tier5-src/_shared/collection-contract.ts +15 -2
- package/templates/retail-store/tier5-src/wix-spaces-create-post/index.ts +14 -4
- package/templates/retail-store-owner/tier5-src/_shared/collection-contract.ts +15 -2
- package/templates/yoga-studio/dev/index.ts +518 -272
- package/templates/yoga-studio/tier5-src/_shared/collection-contract.ts +15 -2
- package/templates/yoga-studio/tier5-src/wix-spaces-create-post/index.ts +14 -4
- package/templates/yoga-studio-owner/tier5-src/_shared/collection-contract.ts +15 -2
- package/templates/yoga-studio-owner/tier5-src/himi-owner-lite-events/index.ts +1 -0
|
@@ -8,6 +8,9 @@ export interface EventRow {
|
|
|
8
8
|
dateLine: string;
|
|
9
9
|
/** "Past" once the event has finished, else "". */
|
|
10
10
|
statusLabel: string;
|
|
11
|
+
/** Has the event finished? The SAME `eventIsPast` answer `statusLabel` reads — one call,
|
|
12
|
+
* both fields — so a card can never say "Past" and still offer Register. */
|
|
13
|
+
isPast: boolean;
|
|
11
14
|
location: string;
|
|
12
15
|
status: string;
|
|
13
16
|
image: string;
|
|
@@ -222,6 +222,7 @@ function normalizeEventAt(e, now) {
|
|
|
222
222
|
const start = startDateOf(e);
|
|
223
223
|
const date = start ? new Date(start) : null;
|
|
224
224
|
const image = eventImage(e);
|
|
225
|
+
const past = eventIsPast(e, now);
|
|
225
226
|
return {
|
|
226
227
|
id,
|
|
227
228
|
title,
|
|
@@ -230,7 +231,8 @@ function normalizeEventAt(e, now) {
|
|
|
230
231
|
dateLine: eventWhen(e, now),
|
|
231
232
|
// "Past" for a finished event, "" otherwise — the shared collection row prints it in the
|
|
232
233
|
// meta line, so an event from last month no longer reads as current.
|
|
233
|
-
statusLabel:
|
|
234
|
+
statusLabel: past ? "Past" : "",
|
|
235
|
+
isPast: past,
|
|
234
236
|
location: eventLocation(e),
|
|
235
237
|
status: titleCase(e.eventStatus) || titleCase(e.status),
|
|
236
238
|
image,
|
package/dist/cli.mjs
CHANGED
|
@@ -16814,9 +16814,10 @@ var init_native_requirements = __esm({
|
|
|
16814
16814
|
// Silent / background push wakes the app for a content-available payload.
|
|
16815
16815
|
infoPlist: { UIBackgroundModes: ["remote-notification"] }
|
|
16816
16816
|
},
|
|
16817
|
-
// macOS also uses APNs
|
|
16818
|
-
//
|
|
16819
|
-
|
|
16817
|
+
// macOS also uses APNs, but its entitlement key is `com.apple.developer.aps-environment`
|
|
16818
|
+
// (iOS's is the bare `aps-environment`). No UIBackgroundModes — background delivery on macOS
|
|
16819
|
+
// doesn't use the iOS remote-notification background mode.
|
|
16820
|
+
macos: { entitlements: { "com.apple.developer.aps-environment": "development" } },
|
|
16820
16821
|
android: { permissions: ["android.permission.POST_NOTIFICATIONS"] },
|
|
16821
16822
|
privacy: {
|
|
16822
16823
|
collectedDataTypes: [
|
|
@@ -20362,7 +20363,7 @@ var PLAYER_HOST_MANIFEST;
|
|
|
20362
20363
|
var init_player_host_manifest = __esm({
|
|
20363
20364
|
"../../apps/himi-player/player-host-manifest.ts"() {
|
|
20364
20365
|
PLAYER_HOST_MANIFEST = {
|
|
20365
|
-
"version": "1.
|
|
20366
|
+
"version": "1.3.0",
|
|
20366
20367
|
"capabilities": [
|
|
20367
20368
|
"app_info",
|
|
20368
20369
|
"audio_record",
|
|
@@ -20405,19 +20406,27 @@ var init_player_host_manifest = __esm({
|
|
|
20405
20406
|
"wix_platform"
|
|
20406
20407
|
],
|
|
20407
20408
|
"unlinked": {
|
|
20408
|
-
"web": [],
|
|
20409
20409
|
"ios": [
|
|
20410
20410
|
"base44",
|
|
20411
20411
|
"godot"
|
|
20412
20412
|
],
|
|
20413
20413
|
"macos": [
|
|
20414
|
+
"audio_record_background",
|
|
20414
20415
|
"base44",
|
|
20415
|
-
"
|
|
20416
|
+
"browser_auth",
|
|
20417
|
+
"godot",
|
|
20418
|
+
"iap",
|
|
20419
|
+
"live_activity",
|
|
20420
|
+
"motion",
|
|
20421
|
+
"push",
|
|
20422
|
+
"speech",
|
|
20423
|
+
"wix_cashier"
|
|
20416
20424
|
],
|
|
20417
20425
|
"android": [
|
|
20418
20426
|
"base44",
|
|
20419
20427
|
"godot"
|
|
20420
|
-
]
|
|
20428
|
+
],
|
|
20429
|
+
"web": []
|
|
20421
20430
|
},
|
|
20422
20431
|
"nativeComponents": [
|
|
20423
20432
|
"template.HimiPlayerCard",
|
|
@@ -143304,23 +143313,23 @@ var init_preview_assets_generated = __esm({
|
|
|
143304
143313
|
"../../packages/serve/src/preview-assets.generated.ts"() {
|
|
143305
143314
|
init_preview_assets_format();
|
|
143306
143315
|
PREVIEW_ASSET_MANIFEST = [
|
|
143307
|
-
{ key: "assets/index-
|
|
143308
|
-
{ key: "assets/pdf.worker.min-BmVo14Nb.mjs", contentType: "application/octet-stream", offset:
|
|
143309
|
-
{ key: "assets/pdfDocument-
|
|
143310
|
-
{ key: "fonts/Roboto-LICENSE.txt", contentType: "application/octet-stream", offset:
|
|
143311
|
-
{ key: "fonts/Roboto-Variable.ttf", contentType: "font/ttf", offset:
|
|
143312
|
-
{ key: "fonts/WixMadeforDisplay-Bold.ttf", contentType: "font/ttf", offset:
|
|
143313
|
-
{ key: "fonts/WixMadeforDisplay-ExtraBold.ttf", contentType: "font/ttf", offset:
|
|
143314
|
-
{ key: "fonts/WixMadeforDisplay-Medium.ttf", contentType: "font/ttf", offset:
|
|
143315
|
-
{ key: "fonts/WixMadeforDisplay-Regular.ttf", contentType: "font/ttf", offset:
|
|
143316
|
-
{ key: "fonts/WixMadeforDisplay-SemiBold.ttf", contentType: "font/ttf", offset:
|
|
143317
|
-
{ key: "fonts/WixMadeforText-Bold.ttf", contentType: "font/ttf", offset:
|
|
143318
|
-
{ key: "fonts/WixMadeforText-ExtraBold.ttf", contentType: "font/ttf", offset:
|
|
143319
|
-
{ key: "fonts/WixMadeforText-Medium.ttf", contentType: "font/ttf", offset:
|
|
143320
|
-
{ key: "fonts/WixMadeforText-Regular.ttf", contentType: "font/ttf", offset:
|
|
143321
|
-
{ key: "fonts/WixMadeforText-SemiBold.ttf", contentType: "font/ttf", offset:
|
|
143322
|
-
{ key: "index.html", contentType: "text/html; charset=utf-8", offset:
|
|
143323
|
-
{ key: "t5-frame.html", contentType: "text/html; charset=utf-8", offset:
|
|
143316
|
+
{ key: "assets/index-DiC0HNa3.js", contentType: "application/javascript; charset=utf-8", offset: 8, length: 1187655, sha256: "08fb74d8752e2f7ae5dcffd520eb03d2eb3def8db9d8fa4b9d5de1a7ae293100" },
|
|
143317
|
+
{ key: "assets/pdf.worker.min-BmVo14Nb.mjs", contentType: "application/octet-stream", offset: 1187663, length: 1317034, sha256: "a33cfe728c584fdba4fcc1fd54bcdc2f9f2f13889ddbb5b2bd1d0f8cbe49b84e" },
|
|
143318
|
+
{ key: "assets/pdfDocument-CXSifjpc.js", contentType: "application/javascript; charset=utf-8", offset: 2504697, length: 489166, sha256: "7dd04afebfbeeede2222a8beb5d87e58391ed36493b57a190a3e2eed4da35356" },
|
|
143319
|
+
{ key: "fonts/Roboto-LICENSE.txt", contentType: "application/octet-stream", offset: 2993863, length: 4610, sha256: "994062dd7af4186a739de55dd9e151c63b6301f8e2cbafc608d35c2e87da0cd2" },
|
|
143320
|
+
{ key: "fonts/Roboto-Variable.ttf", contentType: "font/ttf", offset: 2998473, length: 488584, sha256: "d7598e12c5dbef095ff8272cfc55da0250bd07fbdecbac8a530b9b277872a134" },
|
|
143321
|
+
{ key: "fonts/WixMadeforDisplay-Bold.ttf", contentType: "font/ttf", offset: 3487057, length: 90924, sha256: "ec4c7d63772d980d6e147b2df6215fd2737e4b04cebe0cf7e11dc695fb63cdcf" },
|
|
143322
|
+
{ key: "fonts/WixMadeforDisplay-ExtraBold.ttf", contentType: "font/ttf", offset: 3577981, length: 90984, sha256: "bf4c16a2774edd38a921edf3099469866cd74c094fd596f3fa4e81f54a04dfaa" },
|
|
143323
|
+
{ key: "fonts/WixMadeforDisplay-Medium.ttf", contentType: "font/ttf", offset: 3668965, length: 90980, sha256: "368faca44fb9f7207e4af784e94750b1ee59c1098b8689e0f4a918926f244fb5" },
|
|
143324
|
+
{ key: "fonts/WixMadeforDisplay-Regular.ttf", contentType: "font/ttf", offset: 3759945, length: 90872, sha256: "97ed8f1a6772abe26e3d8af5cecfc4b02faa94497d585b0398b5053b739a70c1" },
|
|
143325
|
+
{ key: "fonts/WixMadeforDisplay-SemiBold.ttf", contentType: "font/ttf", offset: 3850817, length: 90980, sha256: "642feab8a48ddf6c7a89d7c2a7c0edfa0e6e773f671287e460e222703563191e" },
|
|
143326
|
+
{ key: "fonts/WixMadeforText-Bold.ttf", contentType: "font/ttf", offset: 3941797, length: 108636, sha256: "37c179b4fefb63ea9637322b84583a2df53aa226c150294eea1675c14b1b8e29" },
|
|
143327
|
+
{ key: "fonts/WixMadeforText-ExtraBold.ttf", contentType: "font/ttf", offset: 4050433, length: 109084, sha256: "62e2fe4718129f36ecdb0ae4de385bd6b81ecc876146447167c6c140fad699a9" },
|
|
143328
|
+
{ key: "fonts/WixMadeforText-Medium.ttf", contentType: "font/ttf", offset: 4159517, length: 109048, sha256: "4ecf270136af928612c76fe4ebade91d8156975e5ea4c0cf9225501dd1788e02" },
|
|
143329
|
+
{ key: "fonts/WixMadeforText-Regular.ttf", contentType: "font/ttf", offset: 4268565, length: 107700, sha256: "dee56f09fd3efc127c1ea95557edc74110c1460a46287da36e0af25efd341ef5" },
|
|
143330
|
+
{ key: "fonts/WixMadeforText-SemiBold.ttf", contentType: "font/ttf", offset: 4376265, length: 88108, sha256: "dced97a77624bc5f8b1ae65850360908297f4588e09feb6f22792d29dc7e765b" },
|
|
143331
|
+
{ key: "index.html", contentType: "text/html; charset=utf-8", offset: 4464373, length: 4947, sha256: "e46144d08f1a73203c2313ca0ed8b607fd383f4889a82701d6c37f00e4720c95" },
|
|
143332
|
+
{ key: "t5-frame.html", contentType: "text/html; charset=utf-8", offset: 4469320, length: 17344, sha256: "d057298d75e7373e5e2c4d11b7d1bcbea88e03af555ba63d97641c78509c58e4" }
|
|
143324
143333
|
];
|
|
143325
143334
|
}
|
|
143326
143335
|
});
|
|
Binary file
|
|
@@ -15665,7 +15665,7 @@
|
|
|
15665
15665
|
"name": "EventRow",
|
|
15666
15666
|
"kind": "interface",
|
|
15667
15667
|
"jsdoc": "",
|
|
15668
|
-
"decl": "export interface EventRow {\n id: string;\n title: string;\n day: string;\n month: string;\n dateLine: string;\n /** \"Past\" once the event has finished, else \"\". */\n statusLabel: string;\n location: string;\n status: string;\n image: string;\n hasImage: boolean;\n noImage: boolean;\n detailScreenId: string;\n}"
|
|
15668
|
+
"decl": "export interface EventRow {\n id: string;\n title: string;\n day: string;\n month: string;\n dateLine: string;\n /** \"Past\" once the event has finished, else \"\". */\n statusLabel: string;\n /** Has the event finished? The SAME `eventIsPast` answer `statusLabel` reads — one call,\n * both fields — so a card can never say \"Past\" and still offer Register. */\n isPast: boolean;\n location: string;\n status: string;\n image: string;\n hasImage: boolean;\n noImage: boolean;\n detailScreenId: string;\n}"
|
|
15669
15669
|
},
|
|
15670
15670
|
{
|
|
15671
15671
|
"name": "titleCase",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@wix/himalaya-cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.1224.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "himi — the Himalaya authoring CLI. Build a Tier-5 content package on your own machine, push it to the production serve as a draft, preview it on web + Himi Player, and read worker logs back — the remote dev loop. Wraps @himalaya/serve-cli for transport.",
|
|
6
6
|
"keywords": [
|
|
@@ -67,5 +67,5 @@
|
|
|
67
67
|
"artifactId": "himalaya-cli"
|
|
68
68
|
}
|
|
69
69
|
},
|
|
70
|
-
"falconPackageHash": "
|
|
70
|
+
"falconPackageHash": "6b76728b30d33797b71068367615815eb886dc05bb87adbcc4577a32"
|
|
71
71
|
}
|
|
@@ -21370,6 +21370,7 @@ const SCREENS = runtimeSetting({
|
|
|
21370
21370
|
"props": {
|
|
21371
21371
|
"id": "title",
|
|
21372
21372
|
"label": "Title",
|
|
21373
|
+
"required": true,
|
|
21373
21374
|
"kind": "text",
|
|
21374
21375
|
"text": {
|
|
21375
21376
|
"placeholder": "Add a title",
|
|
@@ -21417,7 +21418,10 @@ const SCREENS = runtimeSetting({
|
|
|
21417
21418
|
"style": "primary",
|
|
21418
21419
|
"fullWidth": true,
|
|
21419
21420
|
"action": {
|
|
21420
|
-
"actionId": "tier5.spacesCreatePost.submit"
|
|
21421
|
+
"actionId": "tier5.spacesCreatePost.submit",
|
|
21422
|
+
"params": {
|
|
21423
|
+
"postScreenId": "himi_blog_post"
|
|
21424
|
+
}
|
|
21421
21425
|
}
|
|
21422
21426
|
}
|
|
21423
21427
|
}
|
|
@@ -37,6 +37,13 @@ export interface CollectionConfig {
|
|
|
37
37
|
* `screenId` opens that screen with the row id; without it the verb reuses the
|
|
38
38
|
* row's own tap action (the detail screen that owns the verb). */
|
|
39
39
|
primaryVerb?: { label: string; screenId?: string };
|
|
40
|
+
/** A TIME-BOUND entity (an event, a booking, a reservation): the boolean row field the
|
|
41
|
+
* DOMAIN sets once the record has finished — computed by the same rule as the row's own
|
|
42
|
+
* "Past" label, in the same place, so the two cannot disagree. A finished
|
|
43
|
+
* record's `primaryVerb` (Register, Book…) is transactional and would act on something
|
|
44
|
+
* that is over, so it is swapped for a non-transactional "View details" that opens the
|
|
45
|
+
* row's own detail. Without a row tap action the verb is simply hidden. */
|
|
46
|
+
endedWhen?: string;
|
|
40
47
|
/** A catalog card whose one expected per-item action is "favorite".
|
|
41
48
|
* The ellipsis overflow is replaced by an always-visible heart toggle wired to
|
|
42
49
|
* the same `collectionSave` reducer. A dropdown `Menu` anchored inside a
|
|
@@ -57,7 +64,7 @@ export const COLLECTIONS: Record<string, CollectionConfig> = {
|
|
|
57
64
|
himiBookingBookings: { rows: 'rows', title: 'title', subtitle: 'subtitle', metadata: ['status'], view: 'list', backendQuery: true,
|
|
58
65
|
defaultFilter: 'value:Upcoming', searchPlaceholder: 'Search by booking ID', countNoun: ['booking', 'bookings'], filterValues: ['Upcoming', 'Past', 'Cancelled'],
|
|
59
66
|
sortLabels: { default: 'Soonest', az: 'Oldest', za: 'Latest' } },
|
|
60
|
-
himiEvents: { rows: 'results', title: 'title', subtitle: 'dateLine', image: 'image', view: 'grid', backendQuery: true, defaultFilter: 'value:Upcoming', searchPlaceholder: 'Search events', countNoun: ['event', 'events'], filterValues: ['Upcoming', 'Past'], sortLabels: { default: 'Date', az: 'Title A–Z', za: 'Title Z–A' }, primaryVerb: { label: 'Register' } },
|
|
67
|
+
himiEvents: { rows: 'results', title: 'title', subtitle: 'dateLine', image: 'image', view: 'grid', backendQuery: true, defaultFilter: 'value:Upcoming', searchPlaceholder: 'Search events', countNoun: ['event', 'events'], filterValues: ['Upcoming', 'Past'], sortLabels: { default: 'Date', az: 'Title A–Z', za: 'Title Z–A' }, primaryVerb: { label: 'Register' }, endedWhen: 'isPast' },
|
|
61
68
|
himiBlogFeed: { rows: 'posts', title: 'title', subtitle: 'excerpt', image: 'image', filter: 'category', filterValuesFrom: 'categories', view: 'grid', narrowedBy: 'selectedCategoryId' },
|
|
62
69
|
himiOwnerLiteProducts: { rows: 'products', title: 'name', subtitle: 'price', image: 'image', view: 'grid', backendQuery: true, countNoun: ['product', 'products'] },
|
|
63
70
|
himiOwnerModules: { instanceInput: 'module', rows: 'rows', title: 'title', subtitle: 'subtitle', image: 'image', filter: 'statusLabel', view: 'list', paged: true, reviewAction: 'prepareRecord', reviewSelectedAction: 'prepareSelected' },
|
|
@@ -180,7 +187,13 @@ export function projectCollection(source: CollectionRow[], config: CollectionCon
|
|
|
180
187
|
collectionSubtitle: scalar(row[config.subtitle ?? '']) || scalar(row.subtitle) || scalar(row.description) || scalar(row.meta),
|
|
181
188
|
collectionImage: scalar(row[config.image ?? '']), collectionNoImage: !scalar(row[config.image ?? '']), collectionHasImage: !!scalar(row[config.image ?? '']),
|
|
182
189
|
collectionSaved: prefs.savedIds.includes(collectionId(row)), collectionNotSaved: !prefs.savedIds.includes(collectionId(row)), collectionSelected: prefs.selectedIds.includes(collectionId(row)),
|
|
183
|
-
collectionNoIdentity: !collectionId(row)
|
|
190
|
+
collectionNoIdentity: !collectionId(row),
|
|
191
|
+
// Older cached EventRows predate `isPast` but already stored `statusLabel: "Past"`.
|
|
192
|
+
// Keep their ended state through an offline render until the row is refreshed.
|
|
193
|
+
...(config.endedWhen ? (() => {
|
|
194
|
+
const ended = row[config.endedWhen] === true || (config.endedWhen === 'isPast' && row.statusLabel === 'Past');
|
|
195
|
+
return { collectionEnded: ended, collectionNotEnded: !ended };
|
|
196
|
+
})() : {}) })),
|
|
184
197
|
filters, loaded: rows.length,
|
|
185
198
|
};
|
|
186
199
|
}
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
// Holds the typed title + body; submit creates AND publishes a real blog post via
|
|
3
3
|
// the Wix Blog API, then the new post shows up in ws_blog. (Forum has no member
|
|
4
4
|
// create endpoint in the SDK; blog is the available authored-content write.)
|
|
5
|
-
import { defineService } from "@himalaya/state";
|
|
5
|
+
import { defineService, navigate } from "@himalaya/state";
|
|
6
6
|
import { createDraftPost, publishDraftPost } from "@himalaya/wix-blog";
|
|
7
7
|
import { memberAccess } from "../_shared/member-access.js";
|
|
8
8
|
|
|
@@ -38,7 +38,7 @@ function val(arg?: unknown): string {
|
|
|
38
38
|
return typeof arg === "string" ? arg : ((arg as { value?: string; text?: string })?.value ?? (arg as { text?: string })?.text ?? "");
|
|
39
39
|
}
|
|
40
40
|
|
|
41
|
-
const svc = defineService<S, { load: (s: S) => Promise<S>; setTitle: (s: S, a?: unknown) => S; setBody: (s: S, a?: unknown) => S; focusBody: (s: S) => S; submit: (s: S) => Promise<S> }>("spacesCreatePost", {
|
|
41
|
+
const svc = defineService<S, { load: (s: S) => Promise<S>; setTitle: (s: S, a?: unknown) => S; setBody: (s: S, a?: unknown) => S; focusBody: (s: S) => S; submit: (s: S, a?: unknown) => Promise<S> }>("spacesCreatePost", {
|
|
42
42
|
state: { status: "ready", title: "", body: "", hint: "Share something with the community.", bodyFocus: "", needsSignIn: false, noSignIn: true, hideForm: true },
|
|
43
43
|
actions: {
|
|
44
44
|
load: async (s) => {
|
|
@@ -50,7 +50,11 @@ const svc = defineService<S, { load: (s: S) => Promise<S>; setTitle: (s: S, a?:
|
|
|
50
50
|
// Title's Next key lands here. The keyboard stays up (that is the "next"
|
|
51
51
|
// contract) and the body field takes focus.
|
|
52
52
|
focusBody: (s) => ({ ...s, bodyFocus: bumpToken(s.bodyFocus) }),
|
|
53
|
-
|
|
53
|
+
// `postScreenId` (a submit param) names the screen that shows ONE post, so a host
|
|
54
|
+
// with one lands the author on what they just posted. Several apps share this
|
|
55
|
+
// worker and each owns its own post screen, so the descriptor names it; without
|
|
56
|
+
// it the composer clears and confirms in place.
|
|
57
|
+
submit: async (s, a) => {
|
|
54
58
|
if (s.needsSignIn) return { ...s, hint: "Sign in to post." };
|
|
55
59
|
const title = s.title.trim();
|
|
56
60
|
if (!title) return { ...s, hint: "Please enter a title." };
|
|
@@ -73,7 +77,13 @@ const svc = defineService<S, { load: (s: S) => Promise<S>; setTitle: (s: S, a?:
|
|
|
73
77
|
// steals focus, so those transitions must clear it (see himi-store-account's
|
|
74
78
|
// NO_FOCUS on its mode switches). Same token, opposite fix; the deciding
|
|
75
79
|
// question is always whether the field stays mounted.
|
|
76
|
-
|
|
80
|
+
const posted: S = { ...s, status: "ready", title: "", body: "", bodyFocus: s.bodyFocus, hint: `Posted “${title}” ✓ — it now appears in Blog.` };
|
|
81
|
+
// Only after the worker has the post's id — a failure takes the catch below and
|
|
82
|
+
// keeps every character the user typed.
|
|
83
|
+
const postScreenId = (a as { postScreenId?: unknown } | undefined)?.postScreenId;
|
|
84
|
+
return id && typeof postScreenId === "string" && postScreenId
|
|
85
|
+
? navigate(posted, { screenId: postScreenId, args: { id } })
|
|
86
|
+
: posted;
|
|
77
87
|
} catch {
|
|
78
88
|
return { ...s, status: "ready", hint: "Couldn't post — check your connection and try again." };
|
|
79
89
|
} finally {
|
|
@@ -37,6 +37,13 @@ export interface CollectionConfig {
|
|
|
37
37
|
* `screenId` opens that screen with the row id; without it the verb reuses the
|
|
38
38
|
* row's own tap action (the detail screen that owns the verb). */
|
|
39
39
|
primaryVerb?: { label: string; screenId?: string };
|
|
40
|
+
/** A TIME-BOUND entity (an event, a booking, a reservation): the boolean row field the
|
|
41
|
+
* DOMAIN sets once the record has finished — computed by the same rule as the row's own
|
|
42
|
+
* "Past" label, in the same place, so the two cannot disagree. A finished
|
|
43
|
+
* record's `primaryVerb` (Register, Book…) is transactional and would act on something
|
|
44
|
+
* that is over, so it is swapped for a non-transactional "View details" that opens the
|
|
45
|
+
* row's own detail. Without a row tap action the verb is simply hidden. */
|
|
46
|
+
endedWhen?: string;
|
|
40
47
|
/** A catalog card whose one expected per-item action is "favorite".
|
|
41
48
|
* The ellipsis overflow is replaced by an always-visible heart toggle wired to
|
|
42
49
|
* the same `collectionSave` reducer. A dropdown `Menu` anchored inside a
|
|
@@ -57,7 +64,7 @@ export const COLLECTIONS: Record<string, CollectionConfig> = {
|
|
|
57
64
|
himiBookingBookings: { rows: 'rows', title: 'title', subtitle: 'subtitle', metadata: ['status'], view: 'list', backendQuery: true,
|
|
58
65
|
defaultFilter: 'value:Upcoming', searchPlaceholder: 'Search by booking ID', countNoun: ['booking', 'bookings'], filterValues: ['Upcoming', 'Past', 'Cancelled'],
|
|
59
66
|
sortLabels: { default: 'Soonest', az: 'Oldest', za: 'Latest' } },
|
|
60
|
-
himiEvents: { rows: 'results', title: 'title', subtitle: 'dateLine', image: 'image', view: 'grid', backendQuery: true, defaultFilter: 'value:Upcoming', searchPlaceholder: 'Search events', countNoun: ['event', 'events'], filterValues: ['Upcoming', 'Past'], sortLabels: { default: 'Date', az: 'Title A–Z', za: 'Title Z–A' }, primaryVerb: { label: 'Register' } },
|
|
67
|
+
himiEvents: { rows: 'results', title: 'title', subtitle: 'dateLine', image: 'image', view: 'grid', backendQuery: true, defaultFilter: 'value:Upcoming', searchPlaceholder: 'Search events', countNoun: ['event', 'events'], filterValues: ['Upcoming', 'Past'], sortLabels: { default: 'Date', az: 'Title A–Z', za: 'Title Z–A' }, primaryVerb: { label: 'Register' }, endedWhen: 'isPast' },
|
|
61
68
|
himiBlogFeed: { rows: 'posts', title: 'title', subtitle: 'excerpt', image: 'image', filter: 'category', filterValuesFrom: 'categories', view: 'grid', narrowedBy: 'selectedCategoryId' },
|
|
62
69
|
himiOwnerLiteProducts: { rows: 'products', title: 'name', subtitle: 'price', image: 'image', view: 'grid', backendQuery: true, countNoun: ['product', 'products'] },
|
|
63
70
|
himiOwnerModules: { instanceInput: 'module', rows: 'rows', title: 'title', subtitle: 'subtitle', image: 'image', filter: 'statusLabel', view: 'list', paged: true, reviewAction: 'prepareRecord', reviewSelectedAction: 'prepareSelected' },
|
|
@@ -180,7 +187,13 @@ export function projectCollection(source: CollectionRow[], config: CollectionCon
|
|
|
180
187
|
collectionSubtitle: scalar(row[config.subtitle ?? '']) || scalar(row.subtitle) || scalar(row.description) || scalar(row.meta),
|
|
181
188
|
collectionImage: scalar(row[config.image ?? '']), collectionNoImage: !scalar(row[config.image ?? '']), collectionHasImage: !!scalar(row[config.image ?? '']),
|
|
182
189
|
collectionSaved: prefs.savedIds.includes(collectionId(row)), collectionNotSaved: !prefs.savedIds.includes(collectionId(row)), collectionSelected: prefs.selectedIds.includes(collectionId(row)),
|
|
183
|
-
collectionNoIdentity: !collectionId(row)
|
|
190
|
+
collectionNoIdentity: !collectionId(row),
|
|
191
|
+
// Older cached EventRows predate `isPast` but already stored `statusLabel: "Past"`.
|
|
192
|
+
// Keep their ended state through an offline render until the row is refreshed.
|
|
193
|
+
...(config.endedWhen ? (() => {
|
|
194
|
+
const ended = row[config.endedWhen] === true || (config.endedWhen === 'isPast' && row.statusLabel === 'Past');
|
|
195
|
+
return { collectionEnded: ended, collectionNotEnded: !ended };
|
|
196
|
+
})() : {}) })),
|
|
184
197
|
filters, loaded: rows.length,
|
|
185
198
|
};
|
|
186
199
|
}
|