@protobase/schema 0.15.5 → 0.16.1
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/app-address.d.ts +2 -0
- package/dist/app-address.js +7 -2
- package/dist/index.d.ts +2 -1
- package/dist/index.js +2 -1
- package/dist/model.d.ts +22 -4
- package/dist/sign-in-address.d.ts +33 -0
- package/dist/sign-in-address.js +51 -0
- package/dist/view-displays.d.ts +11 -2
- package/dist/view-displays.js +26 -4
- package/dist/view-field.d.ts +5 -0
- package/dist/view-field.js +7 -0
- package/dist/view.d.ts +2 -2
- package/dist/view.js +2 -2
- package/package.json +1 -1
package/dist/app-address.d.ts
CHANGED
|
@@ -15,6 +15,8 @@ export declare const addressWords: {
|
|
|
15
15
|
readonly filterLayout: "layout";
|
|
16
16
|
/** Where a list's map display looks: `latitude,longitude,zoom`. */
|
|
17
17
|
readonly map: "map";
|
|
18
|
+
/** The saved search a list was opened from, by its key. */
|
|
19
|
+
readonly savedSearch: "saved_search";
|
|
18
20
|
/** The second path segment that opens a resource's create form instead of a record. */
|
|
19
21
|
readonly create: "new";
|
|
20
22
|
};
|
package/dist/app-address.js
CHANGED
|
@@ -15,6 +15,8 @@ const addressWords = {
|
|
|
15
15
|
filterLayout: "layout",
|
|
16
16
|
/** Where a list's map display looks: `latitude,longitude,zoom`. */
|
|
17
17
|
map: "map",
|
|
18
|
+
/** The saved search a list was opened from, by its key. */
|
|
19
|
+
savedSearch: "saved_search",
|
|
18
20
|
/** The second path segment that opens a resource's create form instead of a record. */
|
|
19
21
|
create: "new"
|
|
20
22
|
};
|
|
@@ -22,7 +24,8 @@ const listWords = [
|
|
|
22
24
|
"display",
|
|
23
25
|
"filter",
|
|
24
26
|
"orderBy",
|
|
25
|
-
"filterLayout"
|
|
27
|
+
"filterLayout",
|
|
28
|
+
"savedSearch"
|
|
26
29
|
];
|
|
27
30
|
const mapText = (view) => `${view.latitude.toFixed(5)},${view.longitude.toFixed(5)},${view.zoom.toFixed(2)}`;
|
|
28
31
|
const inRange = (value, limit, low = -limit) => Number.isFinite(value) && value >= low && value <= limit;
|
|
@@ -101,6 +104,7 @@ const readAppPath = (pathAndQuery, pages) => {
|
|
|
101
104
|
const orderBy = params.get(addressWords.orderBy) || void 0;
|
|
102
105
|
const layout = filterLayout(params.get(addressWords.filterLayout));
|
|
103
106
|
const map = readMap(params.get(addressWords.map));
|
|
107
|
+
const savedSearch = params.get(addressWords.savedSearch) || void 0;
|
|
104
108
|
return {
|
|
105
109
|
kind: "list",
|
|
106
110
|
resource: first,
|
|
@@ -108,7 +112,8 @@ const readAppPath = (pathAndQuery, pages) => {
|
|
|
108
112
|
...filter && { filter },
|
|
109
113
|
...orderBy && { orderBy },
|
|
110
114
|
...layout && { filterLayout: layout },
|
|
111
|
-
...map && { map }
|
|
115
|
+
...map && { map },
|
|
116
|
+
...savedSearch && { savedSearch }
|
|
112
117
|
};
|
|
113
118
|
};
|
|
114
119
|
//#endregion
|
package/dist/index.d.ts
CHANGED
|
@@ -20,6 +20,7 @@ import { BottomBarNames, bottomBarErrors } from "./bottom-bar-errors.js";
|
|
|
20
20
|
import { layout } from "./layout.js";
|
|
21
21
|
import { KeyType, keyTypes } from "./keys.js";
|
|
22
22
|
import { addressWords, appPath, readAppPath } from "./app-address.js";
|
|
23
|
+
import { SignInAddress, SignInStep, readSignInAddress, signInParams, signInPath, signInRoute, signInSteps } from "./sign-in-address.js";
|
|
23
24
|
import { FilterLimits, FilterParse, parseFilter } from "./filter/parse.js";
|
|
24
25
|
import { CheckResult, checkFilter } from "./filter/check.js";
|
|
25
26
|
import { EvaluateOptions, evaluateFilter } from "./filter/evaluate.js";
|
|
@@ -36,4 +37,4 @@ import { AccessSource, ResolveOptions, ResolvedAccess, RowFilterOperation, acces
|
|
|
36
37
|
import { restrictModel } from "./access/restrict.js";
|
|
37
38
|
import "./access/index.js";
|
|
38
39
|
import { AssistantAction, AssistantActionRequest, AssistantCardPart, AssistantDiff, AssistantEvent, AssistantMessage, AssistantMessageRequest, AssistantPart, AssistantState, AssistantStep, AssistantStepState, AssistantTablePart, AssistantTextPart, AssistantTone, AssistantWidgetPart } from "./assistant/protocol.js";
|
|
39
|
-
export { type Access, type AccessAction, type AccessContext, type AccessFn, type AccessResult, type AccessSource, type AccessUser, type ActionModel, type ActionRun, type AnyField, type AppAddress, type AssistantAction, type AssistantActionRequest, type AssistantCardPart, type AssistantDiff, type AssistantEvent, type AssistantMessage, type AssistantMessageRequest, type AssistantPart, type AssistantState, type AssistantStep, type AssistantStepState, type AssistantTablePart, type AssistantTextPart, type AssistantTone, type AssistantWidgetPart, type BadgeShape, type BottomBarItemModel, type BottomBarModel, type BottomBarNames, type BottomBarSource, type Capability, type CapabilityAction, type CapabilityLimit, type CapabilityScope, type CardFavoriteModel, type CardPhotosModel, type ChartGranularity, type ChartModel, type ChartRange, type CheckResult, type CheckedFilter, type CompareOp, type ComponentRef, type Constraint, type CreatedOptions, type CustomSectionModel, type DatePreset, type DeletedOptions, type DurationLiteral, type DurationUnit, type EvaluateOptions, type EventActor, type EventContext, type EventHelpers, type EventMatch, type EventModel, type EventOperation, type EventSpec, type Field, type FieldAccess, type FieldFormat, type FieldMeta, type FieldModel, type FieldPath, type FieldRefValue, type FieldRefs, type FieldRule, type FieldType, type FieldTypeDef, type FieldView, type FieldViewModel, type FieldViews, type FieldWidgetModel, type FieldsInput, type FileField, type FileFieldModel, type FileOptions, type FileProcessor, type FileProcessorInput, type FilterError, type FilterErrorCode, type FilterExpr, type FilterLayout, type FilterLimits, type FilterOf, type FilterParse, type FilterValue, type FilterWidgetModel, type Grant, type HeldCapability, type ImageFormat, type ImageVariant, type ImageVariantOptions, type InferRecord, type Issue, type JsonValue, type KeyOf, type KeyRefs, type KeyType, type KeyValue, type LayoutItemModel, type ListDisplayModel, type ListModel, type ListQuery, type Literal, type MapSectionModel, type MapView, type NavModel, type NavRecentModel, type NowValue, type OrderByCheck, type OrderByItem, type OrderByParse, type RecordKey, type RecordOf, type Ref, type Refs, type RelatedModel, type RelationField, type ResolveOptions, type ResolvedAccess, type ResourceBuilder, type ResourceModel, type RoleEntry, type RoleLimit, type Roles, type RolesOptions, type RowFilterOperation, type Rule, type SaveFeedback, type SaveSearchModel, type SearchMatch, type SearchRef, type SearchRefs, type SearchResultModel, type SearchesOfModel, type SignInPromptModel, type SignInViewModel, type SortSpec, type Span, type StatusTone, type UndeletedOptions, type UpdatedOptions, type UserMenuItemModel, type UserMenuModel, type UserMenuSource, type Validator, type ViewBuilder, type ViewModel, type ViewProps, accessWarnings, addressWords, anonymousRole, appPath, bottomBar, bottomBarErrors, checkFilter, checkOrderBy, checkRecord, createWhere, defineRoles, enumLabel, evaluateFilter, f, fieldRef, fieldsUsedBy, imageFormats, keyTypes, layout as l, maxBottomBarItems, parseFilter, parseOrderBy, pickView, printFilter, printOrderBy, readAppPath, resolveAccess, resource, restrictModel, rule, userMenu, view, where };
|
|
40
|
+
export { type Access, type AccessAction, type AccessContext, type AccessFn, type AccessResult, type AccessSource, type AccessUser, type ActionModel, type ActionRun, type AnyField, type AppAddress, type AssistantAction, type AssistantActionRequest, type AssistantCardPart, type AssistantDiff, type AssistantEvent, type AssistantMessage, type AssistantMessageRequest, type AssistantPart, type AssistantState, type AssistantStep, type AssistantStepState, type AssistantTablePart, type AssistantTextPart, type AssistantTone, type AssistantWidgetPart, type BadgeShape, type BottomBarItemModel, type BottomBarModel, type BottomBarNames, type BottomBarSource, type Capability, type CapabilityAction, type CapabilityLimit, type CapabilityScope, type CardFavoriteModel, type CardPhotosModel, type ChartGranularity, type ChartModel, type ChartRange, type CheckResult, type CheckedFilter, type CompareOp, type ComponentRef, type Constraint, type CreatedOptions, type CustomSectionModel, type DatePreset, type DeletedOptions, type DurationLiteral, type DurationUnit, type EvaluateOptions, type EventActor, type EventContext, type EventHelpers, type EventMatch, type EventModel, type EventOperation, type EventSpec, type Field, type FieldAccess, type FieldFormat, type FieldMeta, type FieldModel, type FieldPath, type FieldRefValue, type FieldRefs, type FieldRule, type FieldType, type FieldTypeDef, type FieldView, type FieldViewModel, type FieldViews, type FieldWidgetModel, type FieldsInput, type FileField, type FileFieldModel, type FileOptions, type FileProcessor, type FileProcessorInput, type FilterError, type FilterErrorCode, type FilterExpr, type FilterLayout, type FilterLimits, type FilterOf, type FilterParse, type FilterValue, type FilterWidgetModel, type Grant, type HeldCapability, type ImageFormat, type ImageVariant, type ImageVariantOptions, type InferRecord, type Issue, type JsonValue, type KeyOf, type KeyRefs, type KeyType, type KeyValue, type LayoutItemModel, type ListDisplayModel, type ListModel, type ListQuery, type Literal, type MapSectionModel, type MapView, type NavModel, type NavRecentModel, type NowValue, type OrderByCheck, type OrderByItem, type OrderByParse, type RecordKey, type RecordOf, type Ref, type Refs, type RelatedModel, type RelationField, type ResolveOptions, type ResolvedAccess, type ResourceBuilder, type ResourceModel, type RoleEntry, type RoleLimit, type Roles, type RolesOptions, type RowFilterOperation, type Rule, type SaveFeedback, type SaveSearchModel, type SearchMatch, type SearchRef, type SearchRefs, type SearchResultModel, type SearchesOfModel, type SignInAddress, type SignInPromptModel, type SignInStep, type SignInViewModel, type SortSpec, type Span, type StatusTone, type UndeletedOptions, type UpdatedOptions, type UserMenuItemModel, type UserMenuModel, type UserMenuSource, type Validator, type ViewBuilder, type ViewModel, type ViewProps, accessWarnings, addressWords, anonymousRole, appPath, bottomBar, bottomBarErrors, checkFilter, checkOrderBy, checkRecord, createWhere, defineRoles, enumLabel, evaluateFilter, f, fieldRef, fieldsUsedBy, imageFormats, keyTypes, layout as l, maxBottomBarItems, parseFilter, parseOrderBy, pickView, printFilter, printOrderBy, readAppPath, readSignInAddress, resolveAccess, resource, restrictModel, rule, signInParams, signInPath, signInRoute, signInSteps, userMenu, view, where };
|
package/dist/index.js
CHANGED
|
@@ -18,8 +18,9 @@ import { bottomBarErrors } from "./bottom-bar-errors.js";
|
|
|
18
18
|
import { layout } from "./layout.js";
|
|
19
19
|
import { keyTypes } from "./keys.js";
|
|
20
20
|
import { addressWords, appPath, readAppPath } from "./app-address.js";
|
|
21
|
+
import { readSignInAddress, signInParams, signInPath, signInRoute, signInSteps } from "./sign-in-address.js";
|
|
21
22
|
import { rule } from "./access/rule.js";
|
|
22
23
|
import { defineRoles } from "./access/roles.js";
|
|
23
24
|
import { pickView } from "./access/pick-view.js";
|
|
24
25
|
import { restrictModel } from "./access/restrict.js";
|
|
25
|
-
export { accessWarnings, addressWords, anonymousRole, appPath, bottomBar, bottomBarErrors, checkFilter, checkOrderBy, checkRecord, createWhere, defineRoles, enumLabel, evaluateFilter, f, fieldRef, fieldsUsedBy, imageFormats, keyTypes, layout as l, maxBottomBarItems, parseFilter, parseOrderBy, pickView, printFilter, printOrderBy, readAppPath, resolveAccess, resource, restrictModel, rule, userMenu, view, where };
|
|
26
|
+
export { accessWarnings, addressWords, anonymousRole, appPath, bottomBar, bottomBarErrors, checkFilter, checkOrderBy, checkRecord, createWhere, defineRoles, enumLabel, evaluateFilter, f, fieldRef, fieldsUsedBy, imageFormats, keyTypes, layout as l, maxBottomBarItems, parseFilter, parseOrderBy, pickView, printFilter, printOrderBy, readAppPath, readSignInAddress, resolveAccess, resource, restrictModel, rule, signInParams, signInPath, signInRoute, signInSteps, userMenu, view, where };
|
package/dist/model.d.ts
CHANGED
|
@@ -176,6 +176,11 @@ export type AppAddress = {
|
|
|
176
176
|
filterLayout?: FilterLayout;
|
|
177
177
|
/** Where its map display looks. */
|
|
178
178
|
map?: MapView;
|
|
179
|
+
/**
|
|
180
|
+
* The saved search the list was opened from, by its key in the text form the record API takes: while the list's
|
|
181
|
+
* filter differs from the search's, the list offers to update the search.
|
|
182
|
+
*/
|
|
183
|
+
savedSearch?: string;
|
|
179
184
|
} | {
|
|
180
185
|
/** One record. */
|
|
181
186
|
kind: 'record';
|
|
@@ -209,6 +214,8 @@ export type FieldViewModel = {
|
|
|
209
214
|
help?: string;
|
|
210
215
|
/** How the value is shown. */
|
|
211
216
|
format?: FieldFormat;
|
|
217
|
+
/** A text that runs over several lines: forms edit it in a box that grows with it, and its line breaks show. */
|
|
218
|
+
multiline?: boolean;
|
|
212
219
|
/** Text before a number wherever it is shown, such as `€`. */
|
|
213
220
|
prefix?: string;
|
|
214
221
|
/** Text after a number wherever it is shown, such as a unit: `m²` shows `120 m²`. */
|
|
@@ -292,6 +299,16 @@ export type ListDisplayModel = {
|
|
|
292
299
|
longitude: string;
|
|
293
300
|
/** The cards display whose card a chosen marker shows; the list's first cards display when omitted. */
|
|
294
301
|
cards?: string;
|
|
302
|
+
/** The boolean field that is true when the record's position is approximate. */
|
|
303
|
+
approximate?: string;
|
|
304
|
+
/** The boolean field that is false when the record's position is approximate. */
|
|
305
|
+
exact?: string;
|
|
306
|
+
/** The number field holding the radius, in metres, of the circle around an approximate position. */
|
|
307
|
+
radius?: string;
|
|
308
|
+
/** The radius, in metres, of the circle around an approximate position whose record states no area or radius. */
|
|
309
|
+
defaultRadius?: number;
|
|
310
|
+
/** The field holding the GeoJSON geometry around an approximate position: a polygon, or a line such as a street. */
|
|
311
|
+
area?: string;
|
|
295
312
|
} | {
|
|
296
313
|
/** The rows drawn by a project component. */
|
|
297
314
|
kind: 'custom';
|
|
@@ -390,13 +407,14 @@ export type SearchesOfModel = {
|
|
|
390
407
|
resource: string;
|
|
391
408
|
/** The text field holding the search's filter, as the list's address has it. */
|
|
392
409
|
filter: string;
|
|
393
|
-
/** The text field
|
|
410
|
+
/** The text field holding the name the user gives a search, if any; without one, the search's filters are its title. */
|
|
394
411
|
name?: string;
|
|
395
412
|
/** Enum and boolean fields changed in place on each search, such as how often to hear of new records. */
|
|
396
413
|
controls?: string[];
|
|
397
414
|
/**
|
|
398
|
-
* With it, each search shows
|
|
399
|
-
* search's `seenAt` (a timestamp field of this resource), which opening all of its
|
|
415
|
+
* With it, each search shows its records newest first by `field` (of `resource`) and marks those new to the user:
|
|
416
|
+
* those whose `field` is after the search's `seenAt` (a timestamp field of this resource), which opening all of its
|
|
417
|
+
* results sets to now.
|
|
400
418
|
*/
|
|
401
419
|
unseen?: {
|
|
402
420
|
/** When the user last opened the search's results. */
|
|
@@ -404,7 +422,7 @@ export type SearchesOfModel = {
|
|
|
404
422
|
/** The searched resource's timestamp that makes a record new, such as when it was published. */
|
|
405
423
|
field: string;
|
|
406
424
|
};
|
|
407
|
-
/** How many records each search shows; default
|
|
425
|
+
/** How many records each search shows at most; default every one it finds, loaded as its row scrolls. */
|
|
408
426
|
limit?: number;
|
|
409
427
|
};
|
|
410
428
|
/** A view's list page (`.list(...)`). */
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
//#region src/sign-in-address.d.ts
|
|
2
|
+
/** The path of the sign-in route, below the app's base path. Its steps and the page to come back to are in its query. */
|
|
3
|
+
export declare const signInRoute = "/-/sign-in";
|
|
4
|
+
/** The names of the sign-in route's query parameters: the step it shows, and the page to come back to after it. */
|
|
5
|
+
export declare const signInParams: {
|
|
6
|
+
/** The step the route shows, when it is not the first. */
|
|
7
|
+
readonly step: "step";
|
|
8
|
+
/** The page below the base path to come back to after signing in. */
|
|
9
|
+
readonly next: "next";
|
|
10
|
+
};
|
|
11
|
+
/**
|
|
12
|
+
* A step of signing in or making an account, each with an address of its own: Back from a step returns to the one
|
|
13
|
+
* before. `email-code` and `sign-up-code` enter the code emailed to an address the step before asked for, and
|
|
14
|
+
* `sign-up-details` asks for the name and password once that code was right.
|
|
15
|
+
*/
|
|
16
|
+
export declare const signInSteps: readonly ["sign-in", "forgot-password", "email-code", "sign-up", "sign-up-code", "sign-up-details"];
|
|
17
|
+
/** A step of the sign-in route: one of `signInSteps`. */
|
|
18
|
+
export type SignInStep = (typeof signInSteps)[number];
|
|
19
|
+
/** Where the sign-in route is: its step, and the page below the base path to come back to, when it names one. */
|
|
20
|
+
export type SignInAddress = {
|
|
21
|
+
/** The step the route shows. */
|
|
22
|
+
step: SignInStep;
|
|
23
|
+
/** The page below the base path to come back to, when it names one. */
|
|
24
|
+
next?: string;
|
|
25
|
+
};
|
|
26
|
+
/** The path below the base path of a step of the sign-in route, coming back to `next` after it, the start by default. */
|
|
27
|
+
export declare const signInPath: ({ step, next }?: {
|
|
28
|
+
step?: SignInStep;
|
|
29
|
+
next?: string;
|
|
30
|
+
}) => string;
|
|
31
|
+
/** The sign-in route's step and the page to come back to, for the path below the base path; `undefined` elsewhere. */
|
|
32
|
+
export declare const readSignInAddress: (path: string, params: URLSearchParams) => SignInAddress | undefined;
|
|
33
|
+
//#endregion
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
//#region src/sign-in-address.ts
|
|
2
|
+
/** The path of the sign-in route, below the app's base path. Its steps and the page to come back to are in its query. */
|
|
3
|
+
const signInRoute = "/-/sign-in";
|
|
4
|
+
/** The names of the sign-in route's query parameters: the step it shows, and the page to come back to after it. */
|
|
5
|
+
const signInParams = {
|
|
6
|
+
/** The step the route shows, when it is not the first. */
|
|
7
|
+
step: "step",
|
|
8
|
+
/** The page below the base path to come back to after signing in. */
|
|
9
|
+
next: "next"
|
|
10
|
+
};
|
|
11
|
+
/**
|
|
12
|
+
* A step of signing in or making an account, each with an address of its own: Back from a step returns to the one
|
|
13
|
+
* before. `email-code` and `sign-up-code` enter the code emailed to an address the step before asked for, and
|
|
14
|
+
* `sign-up-details` asks for the name and password once that code was right.
|
|
15
|
+
*/
|
|
16
|
+
const signInSteps = [
|
|
17
|
+
"sign-in",
|
|
18
|
+
"forgot-password",
|
|
19
|
+
"email-code",
|
|
20
|
+
"sign-up",
|
|
21
|
+
"sign-up-code",
|
|
22
|
+
"sign-up-details"
|
|
23
|
+
];
|
|
24
|
+
const isStep = (value) => signInSteps.includes(value);
|
|
25
|
+
const localPage = (next) => {
|
|
26
|
+
if (!next?.startsWith("/")) return void 0;
|
|
27
|
+
const url = new URL(next, "http://local");
|
|
28
|
+
if (url.origin !== "http://local" || url.pathname === "/-/sign-in") return void 0;
|
|
29
|
+
return `${url.pathname}${url.search}`;
|
|
30
|
+
};
|
|
31
|
+
/** The path below the base path of a step of the sign-in route, coming back to `next` after it, the start by default. */
|
|
32
|
+
const signInPath = ({ step = "sign-in", next } = {}) => {
|
|
33
|
+
const params = new URLSearchParams();
|
|
34
|
+
if (step !== "sign-in") params.set(signInParams.step, step);
|
|
35
|
+
const page = localPage(next);
|
|
36
|
+
if (page && page !== "/") params.set(signInParams.next, page);
|
|
37
|
+
const query = params.toString();
|
|
38
|
+
return query ? `${signInRoute}?${query}` : signInRoute;
|
|
39
|
+
};
|
|
40
|
+
/** The sign-in route's step and the page to come back to, for the path below the base path; `undefined` elsewhere. */
|
|
41
|
+
const readSignInAddress = (path, params) => {
|
|
42
|
+
if (path !== "/-/sign-in") return void 0;
|
|
43
|
+
const step = params.get(signInParams.step);
|
|
44
|
+
const next = localPage(params.get(signInParams.next));
|
|
45
|
+
return {
|
|
46
|
+
step: isStep(step) ? step : "sign-in",
|
|
47
|
+
...next && { next }
|
|
48
|
+
};
|
|
49
|
+
};
|
|
50
|
+
//#endregion
|
|
51
|
+
export { readSignInAddress, signInParams, signInPath, signInRoute, signInSteps };
|
package/dist/view-displays.d.ts
CHANGED
|
@@ -53,13 +53,22 @@ export declare const displays: {
|
|
|
53
53
|
* map style. It asks for the records in its view as it pans and zooms: from far out a count for each part of the map,
|
|
54
54
|
* which zooms in when chosen, closer in the records. A marker stands for the records that lie close together at the
|
|
55
55
|
* zoom; choosing it shows their card at the map's bottom, with arrows through them. The card is the one of the cards display named `cards`, the list's first cards display
|
|
56
|
-
* when it names none, or the record's title alone without one.
|
|
56
|
+
* when it names none, or the record's title alone without one. A record's position is approximate when its boolean
|
|
57
|
+
* `approximate` field is true, or its `exact` field false: its marker is drawn hollow and says so, and close enough in
|
|
58
|
+
* an area is drawn around it, the GeoJSON polygon or line its `area` field holds, else a circle of its `radius` field
|
|
59
|
+
* in metres, else one of `defaultRadius`. Named `map` unless `name` says otherwise. See
|
|
60
|
+
* [Approximate positions](website/src/content/docs/reference/ui-config.mdx#approximate-positions).
|
|
57
61
|
*/
|
|
58
62
|
map: (fields: {
|
|
59
63
|
latitude: Ref;
|
|
60
64
|
longitude: Ref;
|
|
65
|
+
approximate?: Ref;
|
|
66
|
+
exact?: Ref;
|
|
67
|
+
radius?: Ref;
|
|
68
|
+
area?: Ref;
|
|
61
69
|
}, o?: Naming & {
|
|
62
70
|
cards?: string;
|
|
71
|
+
defaultRadius?: number;
|
|
63
72
|
}) => ListDisplayModel;
|
|
64
73
|
/**
|
|
65
74
|
* The list drawn by a component of the project, registered in `protobase.ui.tsx` under its name. It gets `props` and
|
|
@@ -72,6 +81,6 @@ export declare const displays: {
|
|
|
72
81
|
props?: ViewProps<P>;
|
|
73
82
|
}) => ListDisplayModel;
|
|
74
83
|
};
|
|
75
|
-
/** Every field a display names: what it shows, a map's position, and the field references in a custom display's props. */
|
|
84
|
+
/** Every field a display names: what it shows, a map's position and the fields saying how exact it is, and the field references in a custom display's props. */
|
|
76
85
|
export declare const displayFields: (display: ListDisplayModel) => string[];
|
|
77
86
|
//#endregion
|
package/dist/view-displays.js
CHANGED
|
@@ -48,7 +48,11 @@ const displays = {
|
|
|
48
48
|
* map style. It asks for the records in its view as it pans and zooms: from far out a count for each part of the map,
|
|
49
49
|
* which zooms in when chosen, closer in the records. A marker stands for the records that lie close together at the
|
|
50
50
|
* zoom; choosing it shows their card at the map's bottom, with arrows through them. The card is the one of the cards display named `cards`, the list's first cards display
|
|
51
|
-
* when it names none, or the record's title alone without one.
|
|
51
|
+
* when it names none, or the record's title alone without one. A record's position is approximate when its boolean
|
|
52
|
+
* `approximate` field is true, or its `exact` field false: its marker is drawn hollow and says so, and close enough in
|
|
53
|
+
* an area is drawn around it, the GeoJSON polygon or line its `area` field holds, else a circle of its `radius` field
|
|
54
|
+
* in metres, else one of `defaultRadius`. Named `map` unless `name` says otherwise. See
|
|
55
|
+
* [Approximate positions](website/src/content/docs/reference/ui-config.mdx#approximate-positions).
|
|
52
56
|
*/
|
|
53
57
|
map: (fields, o = {}) => ({
|
|
54
58
|
kind: "map",
|
|
@@ -56,7 +60,12 @@ const displays = {
|
|
|
56
60
|
...naming(o),
|
|
57
61
|
latitude: fields.latitude.name,
|
|
58
62
|
longitude: fields.longitude.name,
|
|
59
|
-
...o.cards !== void 0 && { cards: o.cards }
|
|
63
|
+
...o.cards !== void 0 && { cards: o.cards },
|
|
64
|
+
...fields.approximate && { approximate: fields.approximate.name },
|
|
65
|
+
...fields.exact && { exact: fields.exact.name },
|
|
66
|
+
...fields.radius && { radius: fields.radius.name },
|
|
67
|
+
...o.defaultRadius !== void 0 && { defaultRadius: o.defaultRadius },
|
|
68
|
+
...fields.area && { area: fields.area.name }
|
|
60
69
|
}),
|
|
61
70
|
/**
|
|
62
71
|
* The list drawn by a component of the project, registered in `protobase.ui.tsx` under its name. It gets `props` and
|
|
@@ -81,12 +90,25 @@ const displayErrors = (list) => {
|
|
|
81
90
|
...names.filter((name) => name === tableDisplay).map(() => `"${tableDisplay}" is the list's own display; give the display another name`),
|
|
82
91
|
...names.filter((name, index) => names.indexOf(name) !== index).map((name) => `display "${name}" is defined twice`),
|
|
83
92
|
...(list.displays ?? []).flatMap((display) => display.kind === "map" && display.cards !== void 0 && !list.displays.some((other) => other.kind === "cards" && other.name === display.cards) ? [`display "${display.name}" names cards "${display.cards}", which is not a cards display of the list`] : []),
|
|
93
|
+
...(list.displays ?? []).flatMap((display) => display.kind === "map" ? approximateErrors(display).map((error) => `display "${display.name}": ${error}`) : []),
|
|
84
94
|
...list.default === void 0 || list.default === "table" || names.includes(list.default) ? [] : [`default "${list.default}" is not one of the displays (${[tableDisplay, ...names].join(", ")})`]
|
|
85
95
|
];
|
|
86
96
|
};
|
|
87
|
-
|
|
97
|
+
const approximateErrors = (display) => {
|
|
98
|
+
const { approximate, exact, radius, defaultRadius, area } = display;
|
|
99
|
+
if (approximate !== void 0 && exact !== void 0) return ["name approximate or exact, not both"];
|
|
100
|
+
return [...(radius !== void 0 || defaultRadius !== void 0 || area !== void 0) && approximate === void 0 && exact === void 0 ? ["an area around approximate positions needs the approximate or exact field"] : [], ...defaultRadius === void 0 || Number.isFinite(defaultRadius) && defaultRadius > 0 ? [] : [`defaultRadius ${defaultRadius} is not a number of metres above 0`]];
|
|
101
|
+
};
|
|
102
|
+
/** Every field a display names: what it shows, a map's position and the fields saying how exact it is, and the field references in a custom display's props. */
|
|
88
103
|
const displayFields = (display) => {
|
|
89
|
-
if (display.kind === "map") return [
|
|
104
|
+
if (display.kind === "map") return [
|
|
105
|
+
display.latitude,
|
|
106
|
+
display.longitude,
|
|
107
|
+
display.approximate,
|
|
108
|
+
display.exact,
|
|
109
|
+
display.radius,
|
|
110
|
+
display.area
|
|
111
|
+
].filter((name) => name !== void 0);
|
|
90
112
|
if (display.kind === "custom") return [...display.fields, ...fieldRefsIn(display.props)];
|
|
91
113
|
return [
|
|
92
114
|
display.image,
|
package/dist/view-field.d.ts
CHANGED
|
@@ -18,6 +18,11 @@ export declare class FieldView<N extends string = string, V = unknown> {
|
|
|
18
18
|
help(help: string): FieldView<N, V>;
|
|
19
19
|
/** How the value shows: `badge` for statuses, `code` in monospace, `percent` with a % sign. */
|
|
20
20
|
format(format: FieldFormat): FieldView<N, V>;
|
|
21
|
+
/**
|
|
22
|
+
* A text of several lines, such as a description: forms edit it in a box that grows with the text, and the record
|
|
23
|
+
* page and cards keep its line breaks. Only a text field takes it.
|
|
24
|
+
*/
|
|
25
|
+
multiline(): FieldView<N, V>;
|
|
21
26
|
/** Text before a number wherever it is shown, such as a currency: `.prefix('€')`. */
|
|
22
27
|
prefix(prefix: string): FieldView<N, V>;
|
|
23
28
|
/** Text after a number wherever it is shown, such as a unit: `.suffix(' m²')`. */
|
package/dist/view-field.js
CHANGED
|
@@ -21,6 +21,13 @@ var FieldView = class FieldView {
|
|
|
21
21
|
format(format) {
|
|
22
22
|
return this.with({ format });
|
|
23
23
|
}
|
|
24
|
+
/**
|
|
25
|
+
* A text of several lines, such as a description: forms edit it in a box that grows with the text, and the record
|
|
26
|
+
* page and cards keep its line breaks. Only a text field takes it.
|
|
27
|
+
*/
|
|
28
|
+
multiline() {
|
|
29
|
+
return this.with({ multiline: true });
|
|
30
|
+
}
|
|
24
31
|
/** Text before a number wherever it is shown, such as a currency: `.prefix('€')`. */
|
|
25
32
|
prefix(prefix) {
|
|
26
33
|
return this.with({ prefix });
|
package/dist/view.d.ts
CHANGED
|
@@ -122,8 +122,8 @@ export declare class ViewBuilder<R extends {
|
|
|
122
122
|
saveSearch(search: SaveSearchModel): ViewBuilder<R>;
|
|
123
123
|
/**
|
|
124
124
|
* This resource holds saved searches of `resource`, which a list page saves with `.saveSearch(...)`: its list page
|
|
125
|
-
* shows each of the user's searches with its filters, its `controls` to change in place, the
|
|
126
|
-
*
|
|
125
|
+
* shows each of the user's searches with its filters, its `controls` to change in place, the records it finds (with
|
|
126
|
+
* `unseen`, newest first, those new since the user last opened its results marked) and a link to all of them. Throws in
|
|
127
127
|
* `toModel` when `filter` or `name` is not a text field, `unseen.seenAt` not a timestamp or a control not an enum or
|
|
128
128
|
* boolean field.
|
|
129
129
|
* See [Saved searches](website/src/content/docs/reference/ui-config.mdx#saved-searches).
|
package/dist/view.js
CHANGED
|
@@ -153,8 +153,8 @@ var ViewBuilder = class ViewBuilder {
|
|
|
153
153
|
}
|
|
154
154
|
/**
|
|
155
155
|
* This resource holds saved searches of `resource`, which a list page saves with `.saveSearch(...)`: its list page
|
|
156
|
-
* shows each of the user's searches with its filters, its `controls` to change in place, the
|
|
157
|
-
*
|
|
156
|
+
* shows each of the user's searches with its filters, its `controls` to change in place, the records it finds (with
|
|
157
|
+
* `unseen`, newest first, those new since the user last opened its results marked) and a link to all of them. Throws in
|
|
158
158
|
* `toModel` when `filter` or `name` is not a text field, `unseen.seenAt` not a timestamp or a control not an enum or
|
|
159
159
|
* boolean field.
|
|
160
160
|
* See [Saved searches](website/src/content/docs/reference/ui-config.mdx#saved-searches).
|