@aglyn/plugins-ai 1.0.0-beta.263 → 1.0.0-beta.266
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 +17 -17
- package/src/lib/assets/site-styles/beauty.webp +0 -0
- package/src/lib/assets/site-styles/blog.webp +0 -0
- package/src/lib/assets/site-styles/business.webp +0 -0
- package/src/lib/assets/site-styles/coming-soon.webp +0 -0
- package/src/lib/assets/site-styles/education.webp +0 -0
- package/src/lib/assets/site-styles/events.webp +0 -0
- package/src/lib/assets/site-styles/fitness.webp +0 -0
- package/src/lib/assets/site-styles/landing.webp +0 -0
- package/src/lib/assets/site-styles/music.webp +0 -0
- package/src/lib/assets/site-styles/nonprofit.webp +0 -0
- package/src/lib/assets/site-styles/personal.webp +0 -0
- package/src/lib/assets/site-styles/photography.webp +0 -0
- package/src/lib/assets/site-styles/portfolio.webp +0 -0
- package/src/lib/assets/site-styles/professional.webp +0 -0
- package/src/lib/assets/site-styles/realestate.webp +0 -0
- package/src/lib/assets/site-styles/restaurant.webp +0 -0
- package/src/lib/assets/site-styles/store.webp +0 -0
- package/src/lib/assets/site-styles/studio.webp +0 -0
- package/src/lib/assets/site-styles/trades.webp +0 -0
- package/src/lib/assets/site-styles/wellness.webp +0 -0
- package/src/lib/assets/site-styles/yoga.webp +0 -0
- package/src/lib/components/ai-site-start-card.component.d.ts +12 -0
- package/src/lib/components/ai-site-start-card.component.js +256 -236
- package/src/lib/components/ai-site-start-card.component.js.map +1 -1
- package/src/lib/components/ai-site-start-steps.component.d.ts +108 -0
- package/src/lib/components/ai-site-start-steps.component.js +451 -0
- package/src/lib/components/ai-site-start-steps.component.js.map +1 -0
- package/src/lib/components/ai-site-start-tracking.d.ts +114 -0
- package/src/lib/components/ai-site-start-tracking.js +277 -0
- package/src/lib/components/ai-site-start-tracking.js.map +1 -0
- package/src/lib/components/ai-site-style-previews.d.ts +26 -0
- package/src/lib/components/ai-site-style-previews.js +115 -0
- package/src/lib/components/ai-site-style-previews.js.map +1 -0
- package/src/lib/insights/ai-insight-digest.d.ts +9 -0
- package/src/lib/insights/ai-insight-digest.js +35 -11
- package/src/lib/insights/ai-insight-digest.js.map +1 -1
- package/src/lib/jobs/ai-job-page-language.d.ts +9 -0
- package/src/lib/jobs/ai-job-page-language.js +20 -2
- package/src/lib/jobs/ai-job-page-language.js.map +1 -1
- package/src/lib/jobs/ai-job-page-sections.js +8 -2
- package/src/lib/jobs/ai-job-page-sections.js.map +1 -1
- package/src/lib/jobs/ai-job-plan-step.d.ts +43 -8
- package/src/lib/jobs/ai-job-plan-step.js +99 -18
- package/src/lib/jobs/ai-job-plan-step.js.map +1 -1
- package/src/lib/jobs/ai-job-site-datasets.d.ts +93 -2
- package/src/lib/jobs/ai-job-site-datasets.js +308 -21
- package/src/lib/jobs/ai-job-site-datasets.js.map +1 -1
- package/src/lib/jobs/ai-layout-stock-photos.d.ts +191 -13
- package/src/lib/jobs/ai-layout-stock-photos.js +1709 -69
- package/src/lib/jobs/ai-layout-stock-photos.js.map +1 -1
- package/src/lib/jobs/fixtures/ai-site-foreign-datasets-recording.d.ts +58 -0
- package/src/lib/jobs/fixtures/ai-site-foreign-datasets-recording.js +678 -0
- package/src/lib/jobs/fixtures/ai-site-foreign-datasets-recording.js.map +1 -0
- package/src/lib/jobs/fixtures/ai-stock-photo-agl3856-beta265-recordings.d.ts +33 -0
- package/src/lib/jobs/fixtures/ai-stock-photo-agl3856-beta265-recordings.js +270 -0
- package/src/lib/jobs/fixtures/ai-stock-photo-agl3856-beta265-recordings.js.map +1 -0
- package/src/lib/jobs/fixtures/ai-stock-photo-agl3856-people-recordings.d.ts +33 -0
- package/src/lib/jobs/fixtures/ai-stock-photo-agl3856-people-recordings.js +277 -0
- package/src/lib/jobs/fixtures/ai-stock-photo-agl3856-people-recordings.js.map +1 -0
- package/src/lib/jobs/fixtures/ai-stock-photo-juniper-records-recordings.d.ts +23 -0
- package/src/lib/jobs/fixtures/ai-stock-photo-juniper-records-recordings.js +163 -0
- package/src/lib/jobs/fixtures/ai-stock-photo-juniper-records-recordings.js.map +1 -0
- package/src/lib/jobs/fixtures/ai-stock-photo-learning-center-recordings.d.ts +23 -0
- package/src/lib/jobs/fixtures/ai-stock-photo-learning-center-recordings.js +53 -0
- package/src/lib/jobs/fixtures/ai-stock-photo-learning-center-recordings.js.map +1 -0
- package/src/lib/jobs/fixtures/ai-stock-photo-synchronicity-recordings.d.ts +21 -0
- package/src/lib/jobs/fixtures/ai-stock-photo-synchronicity-recordings.js +119 -0
- package/src/lib/jobs/fixtures/ai-stock-photo-synchronicity-recordings.js.map +1 -0
- package/src/lib/layout-language/ai-layout-compiler.js +54 -15
- package/src/lib/layout-language/ai-layout-compiler.js.map +1 -1
- package/src/lib/layout-language/ai-layout-design.d.ts +6 -3
- package/src/lib/layout-language/ai-layout-design.js +14 -13
- package/src/lib/layout-language/ai-layout-design.js.map +1 -1
- package/src/lib/layout-language/ai-layout-listings.d.ts +55 -0
- package/src/lib/layout-language/ai-layout-listings.js +103 -5
- package/src/lib/layout-language/ai-layout-listings.js.map +1 -1
- package/src/lib/layout-language/ai-layout-pictures.d.ts +42 -8
- package/src/lib/layout-language/ai-layout-pictures.js +91 -6
- package/src/lib/layout-language/ai-layout-pictures.js.map +1 -1
- package/src/lib/model/ai-site-home-arcs.d.ts +75 -0
- package/src/lib/model/ai-site-home-arcs.js +741 -0
- package/src/lib/model/ai-site-home-arcs.js.map +1 -0
- package/src/lib/model/ai-site-inventory.d.ts +18 -0
- package/src/lib/model/ai-site-inventory.js.map +1 -1
- package/src/lib/model/ai-site-job.d.ts +9 -6
- package/src/lib/model/ai-site-job.js +8 -5
- package/src/lib/model/ai-site-job.js.map +1 -1
- package/src/lib/model/ai-site-kinds.js +24 -24
- package/src/lib/model/ai-site-kinds.js.map +1 -1
- package/src/lib/model/ai-site-start-steps.d.ts +67 -0
- package/src/lib/model/ai-site-start-steps.js +127 -0
- package/src/lib/model/ai-site-start-steps.js.map +1 -0
- package/src/lib/model/ai-site-start.js +4 -1
- package/src/lib/model/ai-site-start.js.map +1 -1
- package/src/lib/runtime/ai-doctrine-validators.d.ts +32 -0
- package/src/lib/runtime/ai-doctrine-validators.js +119 -2
- package/src/lib/runtime/ai-doctrine-validators.js.map +1 -1
- package/src/lib/runtime/ai-doctrine.d.ts +6 -1
- package/src/lib/runtime/ai-doctrine.js +9 -5
- package/src/lib/runtime/ai-doctrine.js.map +1 -1
- package/src/lib/runtime/ai-palette.generated.js +5 -2
- package/src/lib/runtime/ai-palette.generated.js.map +1 -1
- package/src/lib/runtime/site-inventory.js +6 -0
- package/src/lib/runtime/site-inventory.js.map +1 -1
- package/src/lib/server/ai-insight-digest-route.js +2 -2
- package/src/lib/server/ai-insight-digest-route.js.map +1 -1
- package/src/lib/usage/assist-free-taste.js +3 -0
- package/src/lib/usage/assist-free-taste.js.map +1 -1
|
@@ -15,7 +15,8 @@
|
|
|
15
15
|
* limitations under the License.
|
|
16
16
|
*/
|
|
17
17
|
import { pluginResourceDraftWriter } from '@aglyn/aglyn/plugin-manager/plugin-resource-drafts';
|
|
18
|
-
import { type AiBuildPlanCreate, type AiBuildPlanScreen } from '../model/ai-build-plan';
|
|
18
|
+
import { type AiBuildPlan, type AiBuildPlanCreate, type AiBuildPlanScreen } from '../model/ai-build-plan';
|
|
19
|
+
import type { AiInventoryDataset, AiSiteInventory } from '../model/ai-site-inventory';
|
|
19
20
|
import type { AiJob, AiJobOutput, AiJobPlan } from '../model/ai-jobs.types';
|
|
20
21
|
import type { AiPlanCapabilities } from '../model/ai-plan-capabilities';
|
|
21
22
|
import { generateAiDataset } from '../runtime/ai-dataset-generation';
|
|
@@ -143,12 +144,20 @@ export declare function aiSiteFormDatasetNote(form: string): string;
|
|
|
143
144
|
export declare const AI_SITE_DATASET_PHOTOS_BUDGET_MS = 20000;
|
|
144
145
|
/** The field a pictured dataset's photo is kept in, where the plan gave it none. */
|
|
145
146
|
export declare const AI_SITE_DATASET_IMAGE_FIELD = "Image";
|
|
147
|
+
/**
|
|
148
|
+
* The field a pictured dataset keeps what each record's photo shows in
|
|
149
|
+
* (AGL-3856), which its card's and its page's Image take as their alt text:
|
|
150
|
+
* a record's title is what it is called, never what its photo shows.
|
|
151
|
+
*/
|
|
152
|
+
export declare const AI_SITE_DATASET_IMAGE_ALT_FIELD = "Image description";
|
|
146
153
|
/** One record's photo: the address its Image shows, and the library asset placed, which no page shows again. */
|
|
147
154
|
export interface AiSiteDatasetRecordPhoto {
|
|
148
155
|
/** The media library's CDN path, or a starter's site path; `null` for none. */
|
|
149
156
|
src: string | null;
|
|
150
157
|
/** The `media:` reference of the stock photo placed, or `null` for a starter. */
|
|
151
158
|
placed: string | null;
|
|
159
|
+
/** What the photo shows, in its own words (AGL-3856); `null` for none. */
|
|
160
|
+
alt?: string | null;
|
|
152
161
|
}
|
|
153
162
|
/**
|
|
154
163
|
* A photo for each record of a pictured dataset (AGL-3616), in order: a stock
|
|
@@ -167,6 +176,8 @@ export declare function aiSiteDatasetRecordPhotos(input: {
|
|
|
167
176
|
name: string;
|
|
168
177
|
/** Each record's name, by position. */
|
|
169
178
|
names: readonly string[];
|
|
179
|
+
/** What each record is filed under, by position ({@link aiSiteDatasetCategoryOf}, AGL-3856); absent for a list that files none. */
|
|
180
|
+
categories?: ReadonlyArray<string | null>;
|
|
170
181
|
pictures: AiSiteDatasetPictures;
|
|
171
182
|
signal?: AbortSignal;
|
|
172
183
|
stockPhotos?: typeof aiLayoutStockPhotoSource;
|
|
@@ -178,13 +189,32 @@ export declare function aiSiteDatasetRecordPhotos(input: {
|
|
|
178
189
|
* and each record holds its photo there; a record with none holds nothing.
|
|
179
190
|
* Pure.
|
|
180
191
|
*/
|
|
181
|
-
export declare function aiSiteDatasetContentWithPhotos(content: Record<string, unknown>, photos: ReadonlyArray<string | null
|
|
192
|
+
export declare function aiSiteDatasetContentWithPhotos(content: Record<string, unknown>, photos: ReadonlyArray<string | null>,
|
|
193
|
+
/** What each record's photo shows (AGL-3856), kept in {@link AI_SITE_DATASET_IMAGE_ALT_FIELD}; none adds no field. */
|
|
194
|
+
alts?: ReadonlyArray<string | null>): Record<string, unknown>;
|
|
182
195
|
export interface AiSiteDatasetRunnerDeps {
|
|
183
196
|
generate?: typeof generateAiDataset;
|
|
184
197
|
writerFor?: typeof pluginResourceDraftWriter;
|
|
185
198
|
/** Where a pictured dataset's photos come from; the stock library, else the starters, otherwise. */
|
|
186
199
|
photos?: typeof aiSiteDatasetRecordPhotos;
|
|
187
200
|
}
|
|
201
|
+
/**
|
|
202
|
+
* What a designed dataset's records are filed under (AGL-3921): its first
|
|
203
|
+
* field whose name says it files them ("Category", "Type", "Session type"),
|
|
204
|
+
* with each record's value, where they hold at least two different values
|
|
205
|
+
* and some record shares one — a list that files every record apart files
|
|
206
|
+
* none. `null` otherwise. Pure.
|
|
207
|
+
*/
|
|
208
|
+
export declare function aiSiteDatasetCategoryOf(dataset: {
|
|
209
|
+
fields: ReadonlyArray<{
|
|
210
|
+
name: string;
|
|
211
|
+
}>;
|
|
212
|
+
records: ReadonlyArray<ReadonlyArray<string | undefined>>;
|
|
213
|
+
}): {
|
|
214
|
+
column: number;
|
|
215
|
+
name: string;
|
|
216
|
+
values: Array<string | null>;
|
|
217
|
+
} | null;
|
|
188
218
|
/**
|
|
189
219
|
* The fields of a designed dataset that its records leave empty on most of
|
|
190
220
|
* them — every record, or more than half — by the id the data plugin gave
|
|
@@ -239,6 +269,11 @@ export declare function aiDatasetListingsOf(datasets: ReadonlyArray<{
|
|
|
239
269
|
imageField?: string | null;
|
|
240
270
|
/** The record's page-address field, where the writer added one (AGL-3727). */
|
|
241
271
|
addressField?: string | null;
|
|
272
|
+
/** What its records are filed under, by position as `records` (AGL-3921): a section named for one value lists its records alone. */
|
|
273
|
+
groups?: {
|
|
274
|
+
field: string;
|
|
275
|
+
values: readonly string[];
|
|
276
|
+
} | null;
|
|
242
277
|
}>, screens: readonly AiLayoutListingScreen[]): AiLayoutListing[];
|
|
243
278
|
/**
|
|
244
279
|
* A `records` listing for each dataset the workspace already keeps that a
|
|
@@ -257,6 +292,62 @@ export declare function aiSiteReusedDatasetListings(input: {
|
|
|
257
292
|
/** The listings the start already has, whose datasets are not listed twice. */
|
|
258
293
|
listed: ReadonlyArray<Pick<AiLayoutListing, 'datasetId'>>;
|
|
259
294
|
}): AiLayoutListing[];
|
|
295
|
+
/**
|
|
296
|
+
* A SITE START NEVER SHOWS ANOTHER SITE'S RECORDS (AGL-3912).
|
|
297
|
+
*
|
|
298
|
+
* Datasets belong to the organization, and so do their records: neither
|
|
299
|
+
* names the site it was written for, and a dataset outlives the site that
|
|
300
|
+
* filled it (the data plugin keeps `visibleTo` and nothing else of a site). A
|
|
301
|
+
* gym's start reused the workspace's "Session packages", "Coaches" and "Gym
|
|
302
|
+
* FAQs", and published a deleted photographer's wedding packages and a
|
|
303
|
+
* deleted studio's coach bio ("Leads coaching at Ironline Strength Studio")
|
|
304
|
+
* with four broken photos; a photographer's start reused another
|
|
305
|
+
* photographer's gallery and drew six broken covers.
|
|
306
|
+
*
|
|
307
|
+
* So a site start reuses a dataset only when its records are this site's to
|
|
308
|
+
* show ({@link aiSiteDatasetIsThisSites}):
|
|
309
|
+
* - it holds no records at all — an empty list, such as the one a form
|
|
310
|
+
* writes its submissions to, is the same list on any site; or
|
|
311
|
+
* - its scope names this site alone (`siteOnly`), so it was made for it; or
|
|
312
|
+
* - this site already serves its records pages of their own (`recordBase`).
|
|
313
|
+
* Anything else — records in a dataset shared with the workspace or with
|
|
314
|
+
* other sites, and a dataset whose records could not be counted — was filled
|
|
315
|
+
* for something else, and the plan is settled in code before the rules read
|
|
316
|
+
* it ({@link aiSettleSiteForeignDatasets}): the reuse becomes a creation of
|
|
317
|
+
* the same name and fields, designed from this site's brief with photos of
|
|
318
|
+
* its own, and every section, record template and form that named it names
|
|
319
|
+
* the creation. Where this job may create no dataset, the reuse comes off
|
|
320
|
+
* instead and each section writes its items out. Never a refusal, and
|
|
321
|
+
* nothing a member is asked.
|
|
322
|
+
*
|
|
323
|
+
* An Assist change to a site that exists keeps reusing what the site lists:
|
|
324
|
+
* this is a site start's rule, and only its plan is settled by it.
|
|
325
|
+
*/
|
|
326
|
+
export declare function aiSiteDatasetIsThisSites(row: Pick<AiInventoryDataset, 'records' | 'siteOnly' | 'recordBase'>): boolean;
|
|
327
|
+
/**
|
|
328
|
+
* A site start's plan with every dataset it reuses that holds another
|
|
329
|
+
* site's records made again for this one (AGL-3912): each the inventory marks
|
|
330
|
+
* `foreign` ({@link aiSiteInventoryWithRecordCounts}, by
|
|
331
|
+
* {@link aiSiteDatasetIsThisSites}). The creation keeps the dataset's name,
|
|
332
|
+
* which rule 7 does not hold against it as a duplicate. Pure; a plan that
|
|
333
|
+
* reuses none comes back as it was.
|
|
334
|
+
*/
|
|
335
|
+
export declare function aiSettleSiteForeignDatasets(plan: AiBuildPlan, inventory: Pick<AiSiteInventory, 'datasets'> | null, capabilities?: AiPlanCapabilities | null): AiBuildPlan;
|
|
336
|
+
/** How a dataset's records are counted: the data plugin's index, which answers `facts.records`. */
|
|
337
|
+
export type AiDatasetRecordCounter = (request: {
|
|
338
|
+
orgId: string;
|
|
339
|
+
id: string;
|
|
340
|
+
}) => Promise<number | null>;
|
|
341
|
+
/** The production counter: the data plugin's `dataset` index, read one dataset at a time. */
|
|
342
|
+
export declare const aiDatasetRecordCount: AiDatasetRecordCounter;
|
|
343
|
+
/**
|
|
344
|
+
* A site start's inventory with how many records each dataset holds
|
|
345
|
+
* (AGL-3912), and each whose records are not this site's to show
|
|
346
|
+
* ({@link aiSiteDatasetIsThisSites}) marked `foreign`. The count is asked
|
|
347
|
+
* once per plan, of every dataset the site sees, all at once; a count that
|
|
348
|
+
* fails leaves `records` out, which reads as another site's. Never throws.
|
|
349
|
+
*/
|
|
350
|
+
export declare function aiSiteInventoryWithRecordCounts(inventory: AiSiteInventory | null, orgId: string, count?: AiDatasetRecordCounter): Promise<AiSiteInventory | null>;
|
|
260
351
|
/**
|
|
261
352
|
* The site's datasets a layout or a page unit is handed (AGL-3616), each a
|
|
262
353
|
* `records` listing with the sections of the plan's pages that name it, once
|
|
@@ -16,7 +16,9 @@ import { _ as _extends } from "@swc/helpers/_/_extends";
|
|
|
16
16
|
* limitations under the License.
|
|
17
17
|
*/ import { checkDatasetQuota } from "@aglyn/aglyn/app-utils/plan-entitlements";
|
|
18
18
|
import { pluginResourceDraftWriter } from "@aglyn/aglyn/plugin-manager/plugin-resource-drafts";
|
|
19
|
-
import {
|
|
19
|
+
import { pluginRecordIndex } from "@aglyn/aglyn/plugin-manager/plugin-record-index";
|
|
20
|
+
import { AI_BUILD_PLAN_LIMITS, AI_PLAN_NEW_REF_PREFIX, isAiPlanNewRef } from "../model/ai-build-plan.js";
|
|
21
|
+
import { AI_TYPED_LIST_MIN_ITEMS } from "../runtime/ai-doctrine-validators.js";
|
|
20
22
|
import { AI_SITE_DATASETS_MAX } from "../model/ai-site-job.js";
|
|
21
23
|
import { AI_STEP_TIERS } from "../providers/catalog.js";
|
|
22
24
|
import { aiModelForStep } from "../providers/routing.js";
|
|
@@ -219,6 +221,11 @@ const limitReview = (message)=>({
|
|
|
219
221
|
});
|
|
220
222
|
/** The wall clock a dataset's photos may take inside its pass: the 20 seconds a page's pictures had (AGL-3660). */ export const AI_SITE_DATASET_PHOTOS_BUDGET_MS = 20000;
|
|
221
223
|
/** The field a pictured dataset's photo is kept in, where the plan gave it none. */ export const AI_SITE_DATASET_IMAGE_FIELD = 'Image';
|
|
224
|
+
/**
|
|
225
|
+
* The field a pictured dataset keeps what each record's photo shows in
|
|
226
|
+
* (AGL-3856), which its card's and its page's Image take as their alt text:
|
|
227
|
+
* a record's title is what it is called, never what its photo shows.
|
|
228
|
+
*/ export const AI_SITE_DATASET_IMAGE_ALT_FIELD = 'Image description';
|
|
222
229
|
/** A planned field that already names a record's photo. */ const IMAGE_FIELD_NAME = /^(?:main |cover |hero |featured? )?(?:image|photo|picture|photograph|thumbnail|headshot|portrait|cover)s?$/i;
|
|
223
230
|
/**
|
|
224
231
|
* A photo for each record of a pictured dataset (AGL-3616), in order: a stock
|
|
@@ -237,7 +244,9 @@ const limitReview = (message)=>({
|
|
|
237
244
|
placed: null
|
|
238
245
|
}));
|
|
239
246
|
const people = input.pictures === 'people';
|
|
240
|
-
const slots = input.names.map((name, index)=>
|
|
247
|
+
const slots = input.names.map((name, index)=>{
|
|
248
|
+
var _input_categories_index, _input_categories;
|
|
249
|
+
return _extends({
|
|
241
250
|
imageId: `record${index}`,
|
|
242
251
|
frameId: null,
|
|
243
252
|
iconId: null,
|
|
@@ -245,8 +254,17 @@ const limitReview = (message)=>({
|
|
|
245
254
|
// The record card's own shape: a team's portraits stand, pieces sit wide.
|
|
246
255
|
aspect: people ? 4 / 5 : 4 / 3,
|
|
247
256
|
sectionIndex: 0,
|
|
248
|
-
role: people ? 'about' : 'gallery'
|
|
249
|
-
|
|
257
|
+
role: people ? 'about' : 'gallery',
|
|
258
|
+
// A record's name is a search's words, never what its photo shows (AGL-3856).
|
|
259
|
+
standIn: true
|
|
260
|
+
}, people ? {
|
|
261
|
+
people: true
|
|
262
|
+
} : {}, people ? {} : {
|
|
263
|
+
record: ((_input_categories = input.categories) == null ? void 0 : (_input_categories_index = _input_categories[index]) == null ? void 0 : _input_categories_index.trim()) ? {
|
|
264
|
+
category: input.categories[index].trim()
|
|
265
|
+
} : {}
|
|
266
|
+
});
|
|
267
|
+
});
|
|
250
268
|
const seed = `${job.$id}:records`;
|
|
251
269
|
let found = [];
|
|
252
270
|
try {
|
|
@@ -278,15 +296,17 @@ const limitReview = (message)=>({
|
|
|
278
296
|
const hostId = job.hostId;
|
|
279
297
|
return slots.map((_slot, index)=>{
|
|
280
298
|
var _ref;
|
|
281
|
-
var _found_index, _found_index1, _starters_index;
|
|
299
|
+
var _found_index, _found_index1, _found_index_alt, _found_index2, _starters_index, _starters_index_alt, _starters_index1;
|
|
282
300
|
const stock = aiSiteProductPhotoSrc((_found_index = found[index]) == null ? void 0 : _found_index.src, hostId);
|
|
283
301
|
if (stock) return {
|
|
284
302
|
src: stock,
|
|
285
|
-
placed: (_ref = (_found_index1 = found[index]) == null ? void 0 : _found_index1.src) != null ? _ref : null
|
|
303
|
+
placed: (_ref = (_found_index1 = found[index]) == null ? void 0 : _found_index1.src) != null ? _ref : null,
|
|
304
|
+
alt: ((_found_index2 = found[index]) == null ? void 0 : (_found_index_alt = _found_index2.alt) == null ? void 0 : _found_index_alt.trim()) || null
|
|
286
305
|
};
|
|
287
306
|
return {
|
|
288
307
|
src: aiSiteProductPhotoSrc((_starters_index = starters[index]) == null ? void 0 : _starters_index.src, hostId),
|
|
289
|
-
placed: null
|
|
308
|
+
placed: null,
|
|
309
|
+
alt: ((_starters_index1 = starters[index]) == null ? void 0 : (_starters_index_alt = _starters_index1.alt) == null ? void 0 : _starters_index_alt.trim()) || null
|
|
290
310
|
};
|
|
291
311
|
});
|
|
292
312
|
}
|
|
@@ -296,11 +316,11 @@ const limitReview = (message)=>({
|
|
|
296
316
|
* plugin's `image` field, else one called "Image" is added after the others,
|
|
297
317
|
* and each record holds its photo there; a record with none holds nothing.
|
|
298
318
|
* Pure.
|
|
299
|
-
*/ export function aiSiteDatasetContentWithPhotos(content, photos) {
|
|
319
|
+
*/ export function aiSiteDatasetContentWithPhotos(content, photos, /** What each record's photo shows (AGL-3856), kept in {@link AI_SITE_DATASET_IMAGE_ALT_FIELD}; none adds no field. */ alts = []) {
|
|
300
320
|
const fields = Array.isArray(content['fields']) ? content['fields'] : [];
|
|
301
321
|
const named = fields.find((field)=>IMAGE_FIELD_NAME.test(str(field.name)));
|
|
302
322
|
const fieldName = named ? named.name : AI_SITE_DATASET_IMAGE_FIELD;
|
|
303
|
-
const
|
|
323
|
+
const withImage = named ? fields.map((field)=>field === named ? _extends({}, field, {
|
|
304
324
|
type: 'image'
|
|
305
325
|
}) : field) : [
|
|
306
326
|
...fields,
|
|
@@ -309,6 +329,15 @@ const limitReview = (message)=>({
|
|
|
309
329
|
type: 'image'
|
|
310
330
|
}
|
|
311
331
|
];
|
|
332
|
+
const described = alts.some((alt, index)=>Boolean(alt && photos[index]));
|
|
333
|
+
const altName = AI_SITE_DATASET_IMAGE_ALT_FIELD;
|
|
334
|
+
const nextFields = described && !withImage.some((field)=>str(field.name).toLowerCase() === altName.toLowerCase()) ? [
|
|
335
|
+
...withImage,
|
|
336
|
+
{
|
|
337
|
+
name: altName,
|
|
338
|
+
type: 'text'
|
|
339
|
+
}
|
|
340
|
+
] : withImage;
|
|
312
341
|
const records = Array.isArray(content['records']) ? content['records'] : [];
|
|
313
342
|
return _extends({}, content, {
|
|
314
343
|
fields: nextFields,
|
|
@@ -316,12 +345,60 @@ const limitReview = (message)=>({
|
|
|
316
345
|
const next = _extends({}, record);
|
|
317
346
|
delete next[fieldName];
|
|
318
347
|
const photo = photos[index];
|
|
348
|
+
const alt = photo && described ? alts[index] : null;
|
|
319
349
|
return photo ? _extends({}, next, {
|
|
320
350
|
[fieldName]: photo
|
|
321
|
-
}
|
|
351
|
+
}, alt ? {
|
|
352
|
+
[altName]: alt
|
|
353
|
+
} : {}) : next;
|
|
322
354
|
})
|
|
323
355
|
});
|
|
324
356
|
}
|
|
357
|
+
/** A field whose name says it files its records: a category, a type, a kind. */ const CATEGORY_FIELD = /^(?:(?:gallery|session|service|event|course|class|product|menu|work|project) )?(?:category|categories|type|kind|collection|genre|group|section|subject|occasion|series)$/i;
|
|
358
|
+
/**
|
|
359
|
+
* What a designed dataset's records are filed under (AGL-3921): its first
|
|
360
|
+
* field whose name says it files them ("Category", "Type", "Session type"),
|
|
361
|
+
* with each record's value, where they hold at least two different values
|
|
362
|
+
* and some record shares one — a list that files every record apart files
|
|
363
|
+
* none. `null` otherwise. Pure.
|
|
364
|
+
*/ export function aiSiteDatasetCategoryOf(dataset) {
|
|
365
|
+
for (const [column, field] of dataset.fields.entries()){
|
|
366
|
+
if (column === 0 || !CATEGORY_FIELD.test(field.name.trim())) continue;
|
|
367
|
+
const values = dataset.records.map((values)=>{
|
|
368
|
+
var _values_column;
|
|
369
|
+
return ((_values_column = values[column]) != null ? _values_column : '').replace(/\s+/g, ' ').trim() || null;
|
|
370
|
+
});
|
|
371
|
+
const distinct = new Set(values.filter((value)=>Boolean(value)).map((value)=>value.toLowerCase()));
|
|
372
|
+
if (distinct.size >= 2 && distinct.size < values.filter(Boolean).length) return {
|
|
373
|
+
column,
|
|
374
|
+
name: field.name,
|
|
375
|
+
values
|
|
376
|
+
};
|
|
377
|
+
}
|
|
378
|
+
return null;
|
|
379
|
+
}
|
|
380
|
+
/**
|
|
381
|
+
* A dataset's groups as its proposal keeps them: the written field's id, and
|
|
382
|
+
* the value of each record its {@link AiSiteDatasetProposal.recordNames} names.
|
|
383
|
+
*/ function aiSiteDatasetGroupsOf(category, written, designed) {
|
|
384
|
+
var _ref;
|
|
385
|
+
var _written_find, _written_category_column;
|
|
386
|
+
if (!category) return {};
|
|
387
|
+
const field = (_ref = (_written_find = written.find((entry)=>entry.name.trim().toLowerCase() === category.name.trim().toLowerCase())) == null ? void 0 : _written_find.id) != null ? _ref : written.length === designed.fields.length ? (_written_category_column = written[category.column]) == null ? void 0 : _written_category_column.id : undefined;
|
|
388
|
+
if (!field) return {};
|
|
389
|
+
const values = designed.records.flatMap((record, index)=>{
|
|
390
|
+
var _category_values_index;
|
|
391
|
+
return record[0] ? [
|
|
392
|
+
(_category_values_index = category.values[index]) != null ? _category_values_index : ''
|
|
393
|
+
] : [];
|
|
394
|
+
}).slice(0, 12);
|
|
395
|
+
return {
|
|
396
|
+
groups: {
|
|
397
|
+
field,
|
|
398
|
+
values
|
|
399
|
+
}
|
|
400
|
+
};
|
|
401
|
+
}
|
|
325
402
|
/**
|
|
326
403
|
* The fields of a designed dataset that its records leave empty on most of
|
|
327
404
|
* them — every record, or more than half — by the id the data plugin gave
|
|
@@ -350,7 +427,7 @@ const limitReview = (message)=>({
|
|
|
350
427
|
function proposalOf(output) {
|
|
351
428
|
var _output_proposal;
|
|
352
429
|
const raw = (_output_proposal = output.proposal) != null ? _output_proposal : {};
|
|
353
|
-
return {
|
|
430
|
+
return _extends({
|
|
354
431
|
fields: Array.isArray(raw.fields) ? raw.fields.filter((field)=>field && typeof field.id === 'string' && field.id).map((field)=>({
|
|
355
432
|
id: field.id,
|
|
356
433
|
name: str(field.name) || field.id,
|
|
@@ -361,7 +438,12 @@ function proposalOf(output) {
|
|
|
361
438
|
imageField: str(raw.imageField) || null,
|
|
362
439
|
photos: Array.isArray(raw.photos) ? raw.photos.map(str).filter((src)=>src.startsWith('media:')).slice(0, 24) : [],
|
|
363
440
|
sparseFields: Array.isArray(raw.sparseFields) ? raw.sparseFields.map(str).filter(Boolean) : []
|
|
364
|
-
}
|
|
441
|
+
}, raw.groups && typeof raw.groups === 'object' && str(raw.groups.field) && Array.isArray(raw.groups.values) ? {
|
|
442
|
+
groups: {
|
|
443
|
+
field: str(raw.groups.field),
|
|
444
|
+
values: raw.groups.values.slice(0, 12).map(str)
|
|
445
|
+
}
|
|
446
|
+
} : {});
|
|
365
447
|
}
|
|
366
448
|
/**
|
|
367
449
|
* The dataset unit's runner, on the job the scaffold derived for it: the one
|
|
@@ -374,7 +456,7 @@ function proposalOf(output) {
|
|
|
374
456
|
const writerFor = (_deps_writerFor = deps.writerFor) != null ? _deps_writerFor : pluginResourceDraftWriter;
|
|
375
457
|
const photosFor = (_deps_photos = deps.photos) != null ? _deps_photos : aiSiteDatasetRecordPhotos;
|
|
376
458
|
return async (context)=>{
|
|
377
|
-
var _ref, _context_org, _facts_fields, _facts_addressField, _facts_fields1, _facts_records;
|
|
459
|
+
var _ref, _context_org, _facts_fields, _facts_addressField, _facts_fields1, _facts_fields2, _facts_records;
|
|
378
460
|
var _job_plan_create, _job_plan;
|
|
379
461
|
const { job, firestore, signal } = context;
|
|
380
462
|
const model = (_ref = context.modelFor == null ? void 0 : context.modelFor.call(context, AI_DATASET_STEP)) != null ? _ref : aiModelForStep(AI_DATASET_STEP);
|
|
@@ -408,10 +490,10 @@ function proposalOf(output) {
|
|
|
408
490
|
id: job.$id
|
|
409
491
|
});
|
|
410
492
|
if (written) {
|
|
411
|
-
var
|
|
493
|
+
var _facts_fields3, _facts_addressField1, _facts_imageField;
|
|
412
494
|
const facts = written.facts;
|
|
413
495
|
const again = output(written.id, written.name || creation.name, {
|
|
414
|
-
fields: (
|
|
496
|
+
fields: (_facts_fields3 = facts.fields) != null ? _facts_fields3 : [],
|
|
415
497
|
recordNames: [],
|
|
416
498
|
addressField: (_facts_addressField1 = facts.addressField) != null ? _facts_addressField1 : null,
|
|
417
499
|
imageField: (_facts_imageField = facts.imageField) != null ? _facts_imageField : null
|
|
@@ -427,7 +509,7 @@ function proposalOf(output) {
|
|
|
427
509
|
// A form's dataset (AGL-3616): its records are the submissions, so it is
|
|
428
510
|
// designed from the plan with no model, and starts empty.
|
|
429
511
|
if (input.forForm) {
|
|
430
|
-
var _context_org1,
|
|
512
|
+
var _context_org1, _facts_fields4;
|
|
431
513
|
const content = aiSiteFormDatasetContent(creation.name, creation.fields, input.forForm);
|
|
432
514
|
const checked = keeper.writer.check(content, {
|
|
433
515
|
hostId: job.hostId
|
|
@@ -464,7 +546,7 @@ function proposalOf(output) {
|
|
|
464
546
|
return aiUnspentOutcome(model, {
|
|
465
547
|
outputs: [
|
|
466
548
|
_extends({}, output(result.id, result.name, {
|
|
467
|
-
fields: (
|
|
549
|
+
fields: (_facts_fields4 = facts.fields) != null ? _facts_fields4 : [],
|
|
468
550
|
recordNames: [],
|
|
469
551
|
addressField: null
|
|
470
552
|
}, 0), {
|
|
@@ -496,6 +578,8 @@ function proposalOf(output) {
|
|
|
496
578
|
const designed = aiDatasetDraftContent(creation.name, generation.value, {
|
|
497
579
|
recordPages: input.recordPages
|
|
498
580
|
});
|
|
581
|
+
// What each record is filed under, which its photo and the sections that list it by its value read (AGL-3856).
|
|
582
|
+
const category = aiSiteDatasetCategoryOf(generation.value);
|
|
499
583
|
// A list a visitor looks at keeps its records' photos (AGL-3616): searched
|
|
500
584
|
// in code, never asked of the model, so they cost no credits.
|
|
501
585
|
const photos = input.pictures ? await photosFor(_extends({
|
|
@@ -504,7 +588,10 @@ function proposalOf(output) {
|
|
|
504
588
|
names: generation.value.records.map((values)=>{
|
|
505
589
|
var _values_;
|
|
506
590
|
return (_values_ = values[0]) != null ? _values_ : '';
|
|
507
|
-
})
|
|
591
|
+
})
|
|
592
|
+
}, category ? {
|
|
593
|
+
categories: category.values
|
|
594
|
+
} : {}, {
|
|
508
595
|
pictures: input.pictures
|
|
509
596
|
}, signal ? {
|
|
510
597
|
signal
|
|
@@ -513,6 +600,10 @@ function proposalOf(output) {
|
|
|
513
600
|
var _ref;
|
|
514
601
|
var _photos_index;
|
|
515
602
|
return (_ref = (_photos_index = photos[index]) == null ? void 0 : _photos_index.src) != null ? _ref : null;
|
|
603
|
+
}), generation.value.records.map((_values, index)=>{
|
|
604
|
+
var _ref;
|
|
605
|
+
var _photos_index;
|
|
606
|
+
return (_ref = (_photos_index = photos[index]) == null ? void 0 : _photos_index.alt) != null ? _ref : null;
|
|
516
607
|
})) : designed;
|
|
517
608
|
// The data plugin's own rules, before anything is written: content we
|
|
518
609
|
// made that its model refuses is our failure, refunded.
|
|
@@ -565,7 +656,7 @@ function proposalOf(output) {
|
|
|
565
656
|
photos: placed
|
|
566
657
|
} : {}, {
|
|
567
658
|
sparseFields: aiDatasetSparseFields(generation.value, (_facts_fields1 = facts.fields) != null ? _facts_fields1 : [])
|
|
568
|
-
});
|
|
659
|
+
}, aiSiteDatasetGroupsOf(category, (_facts_fields2 = facts.fields) != null ? _facts_fields2 : [], generation.value));
|
|
569
660
|
return _extends({}, spent, {
|
|
570
661
|
outputs: [
|
|
571
662
|
output(result.id, result.name, proposal, (_facts_records = facts.records) != null ? _facts_records : generation.value.records.length)
|
|
@@ -702,6 +793,201 @@ export const runAiSiteDatasetUnit = createAiSiteDatasetRunner();
|
|
|
702
793
|
});
|
|
703
794
|
return aiDatasetListingsOf(datasets, input.screens);
|
|
704
795
|
}
|
|
796
|
+
/**
|
|
797
|
+
* A SITE START NEVER SHOWS ANOTHER SITE'S RECORDS (AGL-3912).
|
|
798
|
+
*
|
|
799
|
+
* Datasets belong to the organization, and so do their records: neither
|
|
800
|
+
* names the site it was written for, and a dataset outlives the site that
|
|
801
|
+
* filled it (the data plugin keeps `visibleTo` and nothing else of a site). A
|
|
802
|
+
* gym's start reused the workspace's "Session packages", "Coaches" and "Gym
|
|
803
|
+
* FAQs", and published a deleted photographer's wedding packages and a
|
|
804
|
+
* deleted studio's coach bio ("Leads coaching at Ironline Strength Studio")
|
|
805
|
+
* with four broken photos; a photographer's start reused another
|
|
806
|
+
* photographer's gallery and drew six broken covers.
|
|
807
|
+
*
|
|
808
|
+
* So a site start reuses a dataset only when its records are this site's to
|
|
809
|
+
* show ({@link aiSiteDatasetIsThisSites}):
|
|
810
|
+
* - it holds no records at all — an empty list, such as the one a form
|
|
811
|
+
* writes its submissions to, is the same list on any site; or
|
|
812
|
+
* - its scope names this site alone (`siteOnly`), so it was made for it; or
|
|
813
|
+
* - this site already serves its records pages of their own (`recordBase`).
|
|
814
|
+
* Anything else — records in a dataset shared with the workspace or with
|
|
815
|
+
* other sites, and a dataset whose records could not be counted — was filled
|
|
816
|
+
* for something else, and the plan is settled in code before the rules read
|
|
817
|
+
* it ({@link aiSettleSiteForeignDatasets}): the reuse becomes a creation of
|
|
818
|
+
* the same name and fields, designed from this site's brief with photos of
|
|
819
|
+
* its own, and every section, record template and form that named it names
|
|
820
|
+
* the creation. Where this job may create no dataset, the reuse comes off
|
|
821
|
+
* instead and each section writes its items out. Never a refusal, and
|
|
822
|
+
* nothing a member is asked.
|
|
823
|
+
*
|
|
824
|
+
* An Assist change to a site that exists keeps reusing what the site lists:
|
|
825
|
+
* this is a site start's rule, and only its plan is settled by it.
|
|
826
|
+
*/ export function aiSiteDatasetIsThisSites(row) {
|
|
827
|
+
return row.records === 0 || row.siteOnly === true || Boolean(row.recordBase);
|
|
828
|
+
}
|
|
829
|
+
/** A planned field that is a record's page address, which the writer adds itself. */ const ADDRESS_FIELD_NAME = /^(?:page )?(?:address|slug|url|link)$/i;
|
|
830
|
+
/** The fields a dataset is made again with: its own, less the photo, its description and the page address the writer adds. */ function remadeFields(row) {
|
|
831
|
+
var _row_fieldIds;
|
|
832
|
+
const ids = (_row_fieldIds = row.fieldIds) != null ? _row_fieldIds : [];
|
|
833
|
+
return row.fields.filter((name, index)=>{
|
|
834
|
+
const id = ids[index];
|
|
835
|
+
if (id && (id === row.imageField || id === row.addressField)) return false;
|
|
836
|
+
if (IMAGE_FIELD_NAME.test(name.trim()) || ADDRESS_FIELD_NAME.test(name.trim())) return false;
|
|
837
|
+
return name.trim().toLowerCase() !== AI_SITE_DATASET_IMAGE_ALT_FIELD.toLowerCase();
|
|
838
|
+
}).slice(0, AI_BUILD_PLAN_LIMITS.fields);
|
|
839
|
+
}
|
|
840
|
+
/**
|
|
841
|
+
* A site start's plan with every dataset it reuses that holds another
|
|
842
|
+
* site's records made again for this one (AGL-3912): each the inventory marks
|
|
843
|
+
* `foreign` ({@link aiSiteInventoryWithRecordCounts}, by
|
|
844
|
+
* {@link aiSiteDatasetIsThisSites}). The creation keeps the dataset's name,
|
|
845
|
+
* which rule 7 does not hold against it as a duplicate. Pure; a plan that
|
|
846
|
+
* reuses none comes back as it was.
|
|
847
|
+
*/ export function aiSettleSiteForeignDatasets(plan, inventory, capabilities = null) {
|
|
848
|
+
var _ref, _plan_items;
|
|
849
|
+
const rows = new Map(((_ref = inventory == null ? void 0 : inventory.datasets) != null ? _ref : []).map((row)=>[
|
|
850
|
+
row.id,
|
|
851
|
+
row
|
|
852
|
+
]));
|
|
853
|
+
const foreign = plan.reuse.filter((entry)=>{
|
|
854
|
+
var _rows_get;
|
|
855
|
+
return entry.kind === 'dataset' && ((_rows_get = rows.get(entry.id)) == null ? void 0 : _rows_get.foreign) === true;
|
|
856
|
+
});
|
|
857
|
+
if (!foreign.length) return plan;
|
|
858
|
+
const creatable = !capabilities || capabilities.create.dataset.allowed;
|
|
859
|
+
const taken = new Map([
|
|
860
|
+
...plan.create.map((entry)=>[
|
|
861
|
+
entry.name.trim().toLowerCase(),
|
|
862
|
+
entry
|
|
863
|
+
]),
|
|
864
|
+
...((_plan_items = plan.items) != null ? _plan_items : []).map((item)=>[
|
|
865
|
+
item.name.trim().toLowerCase(),
|
|
866
|
+
null
|
|
867
|
+
])
|
|
868
|
+
]);
|
|
869
|
+
// Each foreign dataset's id → the `new:` reference that replaces it, or `null` where it comes off.
|
|
870
|
+
const replaced = new Map();
|
|
871
|
+
const added = [];
|
|
872
|
+
for (const entry of foreign){
|
|
873
|
+
const row = rows.get(entry.id);
|
|
874
|
+
const base = row.name.trim() || 'Records';
|
|
875
|
+
if (!creatable) {
|
|
876
|
+
replaced.set(entry.id, null);
|
|
877
|
+
continue;
|
|
878
|
+
}
|
|
879
|
+
// The plan already makes one of that name: that one is this site's.
|
|
880
|
+
const same = taken.get(base.toLowerCase());
|
|
881
|
+
if ((same == null ? void 0 : same.kind) === 'dataset') {
|
|
882
|
+
replaced.set(entry.id, `${AI_PLAN_NEW_REF_PREFIX}${same.name}`);
|
|
883
|
+
continue;
|
|
884
|
+
}
|
|
885
|
+
let name = base;
|
|
886
|
+
for(let n = 2; taken.has(name.toLowerCase()); n += 1)name = `${base} ${n}`;
|
|
887
|
+
const creation = {
|
|
888
|
+
kind: 'dataset',
|
|
889
|
+
name,
|
|
890
|
+
why: entry.purpose || `Lists ${base} on this site.`,
|
|
891
|
+
duplicateOf: null,
|
|
892
|
+
fields: remadeFields(row)
|
|
893
|
+
};
|
|
894
|
+
added.push(creation);
|
|
895
|
+
taken.set(name.toLowerCase(), creation);
|
|
896
|
+
replaced.set(entry.id, `${AI_PLAN_NEW_REF_PREFIX}${name}`);
|
|
897
|
+
}
|
|
898
|
+
const swap = (ref)=>{
|
|
899
|
+
var _replaced_get;
|
|
900
|
+
return replaced.has(ref) ? (_replaced_get = replaced.get(ref)) != null ? _replaced_get : null : ref;
|
|
901
|
+
};
|
|
902
|
+
return _extends({}, plan, {
|
|
903
|
+
reuse: plan.reuse.filter((entry)=>!(entry.kind === 'dataset' && replaced.has(entry.id))),
|
|
904
|
+
create: [
|
|
905
|
+
...plan.create.map((entry)=>{
|
|
906
|
+
if (entry.kind !== 'form' || !entry.writesTo || !replaced.has(entry.writesTo)) return entry;
|
|
907
|
+
const writesTo = swap(entry.writesTo);
|
|
908
|
+
if (writesTo) return _extends({}, entry, {
|
|
909
|
+
writesTo
|
|
910
|
+
});
|
|
911
|
+
// A form whose dataset comes off sends its submissions to the Inbox only.
|
|
912
|
+
const rest = _extends({}, entry);
|
|
913
|
+
delete rest.writesTo;
|
|
914
|
+
return rest;
|
|
915
|
+
}),
|
|
916
|
+
...added
|
|
917
|
+
],
|
|
918
|
+
screens: plan.screens.map((screen)=>{
|
|
919
|
+
// A record template of a dataset made again shows the new one; of one that comes off, it is a page of its own.
|
|
920
|
+
const record = screen.record && replaced.has(screen.record.dataset) ? {
|
|
921
|
+
record: swap(screen.record.dataset)
|
|
922
|
+
} : null;
|
|
923
|
+
const sections = screen.sections.map((section)=>{
|
|
924
|
+
if (!section.uses.some((ref)=>replaced.has(ref))) return section;
|
|
925
|
+
const uses = section.uses.flatMap((ref)=>{
|
|
926
|
+
const next = swap(ref);
|
|
927
|
+
return next ? [
|
|
928
|
+
next
|
|
929
|
+
] : [];
|
|
930
|
+
});
|
|
931
|
+
// A list that comes off is written out on the page, as fewer items than a dataset binds.
|
|
932
|
+
const dropped = section.uses.some((ref)=>replaced.has(ref) && !replaced.get(ref));
|
|
933
|
+
return _extends({}, section, {
|
|
934
|
+
uses
|
|
935
|
+
}, dropped ? {
|
|
936
|
+
items: Math.min(section.items, AI_TYPED_LIST_MIN_ITEMS - 1)
|
|
937
|
+
} : {});
|
|
938
|
+
});
|
|
939
|
+
return _extends({}, screen, record && screen.record ? {
|
|
940
|
+
record: record.record ? _extends({}, screen.record, {
|
|
941
|
+
dataset: record.record
|
|
942
|
+
}) : null
|
|
943
|
+
} : {}, {
|
|
944
|
+
sections
|
|
945
|
+
});
|
|
946
|
+
})
|
|
947
|
+
});
|
|
948
|
+
}
|
|
949
|
+
/** The production counter: the data plugin's `dataset` index, read one dataset at a time. */ export const aiDatasetRecordCount = async ({ orgId, id })=>{
|
|
950
|
+
var _pluginRecordIndex;
|
|
951
|
+
const index = (_pluginRecordIndex = pluginRecordIndex('dataset')) == null ? void 0 : _pluginRecordIndex.index;
|
|
952
|
+
if (!index) return null;
|
|
953
|
+
const found = await index.get({
|
|
954
|
+
orgId,
|
|
955
|
+
id
|
|
956
|
+
});
|
|
957
|
+
const records = found == null ? void 0 : found.facts['records'];
|
|
958
|
+
return typeof records === 'number' && Number.isFinite(records) ? records : null;
|
|
959
|
+
};
|
|
960
|
+
/**
|
|
961
|
+
* A site start's inventory with how many records each dataset holds
|
|
962
|
+
* (AGL-3912), and each whose records are not this site's to show
|
|
963
|
+
* ({@link aiSiteDatasetIsThisSites}) marked `foreign`. The count is asked
|
|
964
|
+
* once per plan, of every dataset the site sees, all at once; a count that
|
|
965
|
+
* fails leaves `records` out, which reads as another site's. Never throws.
|
|
966
|
+
*/ export async function aiSiteInventoryWithRecordCounts(inventory, orgId, count = aiDatasetRecordCount) {
|
|
967
|
+
if (!(inventory == null ? void 0 : inventory.datasets.length)) return inventory;
|
|
968
|
+
const counts = await Promise.all(inventory.datasets.map((row)=>count({
|
|
969
|
+
orgId,
|
|
970
|
+
id: row.id
|
|
971
|
+
}).catch((error)=>{
|
|
972
|
+
console.warn('ai site plan: a dataset’s records could not be counted', {
|
|
973
|
+
orgId,
|
|
974
|
+
id: row.id,
|
|
975
|
+
error: String(error)
|
|
976
|
+
});
|
|
977
|
+
return null;
|
|
978
|
+
})));
|
|
979
|
+
return _extends({}, inventory, {
|
|
980
|
+
datasets: inventory.datasets.map((row, index)=>{
|
|
981
|
+
const records = counts[index];
|
|
982
|
+
const counted = typeof records === 'number' ? _extends({}, row, {
|
|
983
|
+
records
|
|
984
|
+
}) : row;
|
|
985
|
+
return aiSiteDatasetIsThisSites(counted) ? counted : _extends({}, counted, {
|
|
986
|
+
foreign: true
|
|
987
|
+
});
|
|
988
|
+
})
|
|
989
|
+
});
|
|
990
|
+
}
|
|
705
991
|
/**
|
|
706
992
|
* The site's datasets a layout or a page unit is handed (AGL-3616), each a
|
|
707
993
|
* `records` listing with the sections of the plan's pages that name it, once
|
|
@@ -709,7 +995,7 @@ export const runAiSiteDatasetUnit = createAiSiteDatasetRunner();
|
|
|
709
995
|
* nowhere: the pages built without it write the items out.
|
|
710
996
|
*/ export function aiSiteDatasetListings(input) {
|
|
711
997
|
const made = input.datasets.flatMap((dataset)=>{
|
|
712
|
-
var _proposal_imageField;
|
|
998
|
+
var _proposal_imageField, _proposal_groups;
|
|
713
999
|
const id = input.delivered.get(dataset.name.trim().toLowerCase());
|
|
714
1000
|
const output = id ? input.outputs.find((entry)=>entry.resource === 'draft' && entry.draftResource === AI_SITE_DATASET_RESOURCE && entry.id === id) : undefined;
|
|
715
1001
|
if (!id || !output) return [];
|
|
@@ -728,7 +1014,8 @@ export const runAiSiteDatasetUnit = createAiSiteDatasetRunner();
|
|
|
728
1014
|
return field.id !== proposal.addressField && field.id !== proposal.imageField && (index === 0 || !((_proposal_sparseFields = proposal.sparseFields) == null ? void 0 : _proposal_sparseFields.includes(field.id)));
|
|
729
1015
|
}),
|
|
730
1016
|
imageField: (_proposal_imageField = proposal.imageField) != null ? _proposal_imageField : null,
|
|
731
|
-
addressField: proposal.addressField
|
|
1017
|
+
addressField: proposal.addressField,
|
|
1018
|
+
groups: (_proposal_groups = proposal.groups) != null ? _proposal_groups : null
|
|
732
1019
|
}
|
|
733
1020
|
];
|
|
734
1021
|
});
|