@yuuvis/client-framework 3.18.0 → 3.20.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/fesm2022/yuuvis-client-framework-forms.mjs +4 -2
- package/fesm2022/yuuvis-client-framework-forms.mjs.map +1 -1
- package/fesm2022/yuuvis-client-framework-object-details.mjs +2 -1
- package/fesm2022/yuuvis-client-framework-object-details.mjs.map +1 -1
- package/fesm2022/yuuvis-client-framework-object-flavor.mjs +2 -1
- package/fesm2022/yuuvis-client-framework-object-flavor.mjs.map +1 -1
- package/fesm2022/yuuvis-client-framework-object-form.mjs +3 -1
- package/fesm2022/yuuvis-client-framework-object-form.mjs.map +1 -1
- package/fesm2022/yuuvis-client-framework-object-preview.mjs +25 -13
- package/fesm2022/yuuvis-client-framework-object-preview.mjs.map +1 -1
- package/fesm2022/yuuvis-client-framework-object-relationship.mjs +9 -3
- package/fesm2022/yuuvis-client-framework-object-relationship.mjs.map +1 -1
- package/fesm2022/yuuvis-client-framework-object-summary.mjs +4 -1
- package/fesm2022/yuuvis-client-framework-object-summary.mjs.map +1 -1
- package/fesm2022/yuuvis-client-framework-renderer.mjs +100 -16
- package/fesm2022/yuuvis-client-framework-renderer.mjs.map +1 -1
- package/fesm2022/yuuvis-client-framework-smart-search.mjs +433 -69
- package/fesm2022/yuuvis-client-framework-smart-search.mjs.map +1 -1
- package/fesm2022/yuuvis-client-framework-tile-list.mjs +2 -2
- package/fesm2022/yuuvis-client-framework-tile-list.mjs.map +1 -1
- package/package.json +5 -5
- package/smart-search/README.md +57 -7
- package/types/yuuvis-client-framework-object-form.d.ts +6 -0
- package/types/yuuvis-client-framework-object-preview.d.ts +14 -1
- package/types/yuuvis-client-framework-renderer.d.ts +40 -6
- package/types/yuuvis-client-framework-smart-search.d.ts +171 -22
- package/types/yuuvis-client-framework-tile-list.d.ts +5 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@yuuvis/client-framework",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.20.0",
|
|
4
4
|
"author": "OPTIMAL SYSTEMS GmbH <npm@optimal-systems.de>",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"peerDependencies": {
|
|
@@ -8,16 +8,16 @@
|
|
|
8
8
|
"@angular/common": "^21.2.19",
|
|
9
9
|
"@angular/core": "^21.2.19",
|
|
10
10
|
"angular-gridster2": "^21.0.1",
|
|
11
|
-
"@yuuvis/client-core": "^3.
|
|
12
|
-
"@yuuvis/client-shell-core": "^3.
|
|
13
|
-
"@yuuvis/client-components": "^3.
|
|
11
|
+
"@yuuvis/client-core": "^3.20.0",
|
|
12
|
+
"@yuuvis/client-shell-core": "^3.20.0",
|
|
13
|
+
"@yuuvis/client-components": "^3.20.0",
|
|
14
14
|
"ng-dynamic-component": "^10.8.2",
|
|
15
15
|
"modern-normalize": "^3.0.1"
|
|
16
16
|
},
|
|
17
17
|
"dependencies": {
|
|
18
18
|
"@angular/material": "^21.2.14",
|
|
19
19
|
"@ngrx/signals": "^21.1.0",
|
|
20
|
-
"@yuuvis/material": "^3.
|
|
20
|
+
"@yuuvis/material": "^3.20.0",
|
|
21
21
|
"@yuuvis/media-viewer": "^4.0.0",
|
|
22
22
|
"angular-split": "^20.0.0",
|
|
23
23
|
"vis-network": "^10.0.2",
|
package/smart-search/README.md
CHANGED
|
@@ -46,16 +46,66 @@ export class SearchComponent {
|
|
|
46
46
|
|
|
47
47
|
### Inputs
|
|
48
48
|
|
|
49
|
-
| Input
|
|
50
|
-
|
|
|
51
|
-
| `types`
|
|
52
|
-
| `skipProperties`
|
|
49
|
+
| Input | Type | Default | Description |
|
|
50
|
+
| -------------------------- | ---------- | ------- | ---------------------------------------------------------------------------------------------------------------------------- |
|
|
51
|
+
| `types` | `string[]` | `[]` | Object-type ids that may be searched. Set at least one to enable building blocks. |
|
|
52
|
+
| `skipProperties` | `string[]` | `[]` | Field ids to hide from the field picker (e.g. internal/system properties). |
|
|
53
|
+
| `fulltextOnly` | `boolean` | `false` | Renders only the full-text bar — no condition builder. See [Full-text only](#full-text-only). |
|
|
54
|
+
| `supportDynamicConditions` | `boolean` | `false` | Enables marking conditions as *dynamic* and the form-mode toggle that swaps the builder for a fill-out form of those fields. |
|
|
53
55
|
|
|
54
56
|
### Outputs
|
|
55
57
|
|
|
56
|
-
| Output | Type | Description
|
|
57
|
-
| ------------- | -------- |
|
|
58
|
-
| `queryChange` | `string` | The current CMIS query. Emitted on every change; `''` means an empty search ("no query").
|
|
58
|
+
| Output | Type | Description |
|
|
59
|
+
| ------------- | -------- | ---------------------------------------------------------------------------------------------------------------- |
|
|
60
|
+
| `queryChange` | `string` | The current CMIS query. Emitted on **every** change; `''` means an empty search ("no query"). |
|
|
61
|
+
| `querySubmit` | `string` | The current CMIS query, emitted when the user presses <kbd>Enter</kbd> to submit. Same `''` convention. |
|
|
62
|
+
|
|
63
|
+
### Full-text only
|
|
64
|
+
|
|
65
|
+
`fulltextOnly` reduces the component to a plain full-text search: the term box, the scope
|
|
66
|
+
select and the object-type filter stay, everything else — type blocks, the add-type row, the
|
|
67
|
+
inline condition editor and the form-mode toggle — is not rendered.
|
|
68
|
+
|
|
69
|
+
```html
|
|
70
|
+
<yuv-smart-search [types]="['document', 'invoice']" [fulltextOnly]="true" (querySubmit)="runSearch($event)" />
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
`types` keeps its meaning, so the emitted query is still scoped to the allowed types:
|
|
74
|
+
|
|
75
|
+
```sql
|
|
76
|
+
-- types=['document','invoice'], full-text "acme", type filter left on "All types"
|
|
77
|
+
SELECT * FROM system:object WHERE (objectTypeId IN ('document','invoice') AND CONTAINS('acme'))
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
Because the blocks are not rendered, they are not queried either: a state restored via
|
|
81
|
+
`loadState()` keeps its blocks (they come back when the flag is cleared) but only its full-text
|
|
82
|
+
unit contributes to the emitted query while the flag is set.
|
|
83
|
+
|
|
84
|
+
### Submitting with Enter
|
|
85
|
+
|
|
86
|
+
`queryChange` is a live preview — it fires on every keystroke and every edit. To run a
|
|
87
|
+
search only when the user is *done*, bind `querySubmit` instead: it behaves like an HTML
|
|
88
|
+
form, emitting when <kbd>Enter</kbd> reaches the component without an inner widget having
|
|
89
|
+
claimed the key.
|
|
90
|
+
|
|
91
|
+
Widgets that own <kbd>Enter</kbd> for their own purpose keep it, so a submit never
|
|
92
|
+
happens by surprise:
|
|
93
|
+
|
|
94
|
+
| Where <kbd>Enter</kbd> is pressed | What happens |
|
|
95
|
+
| ------------------------------------------------ | ------------------------------------------------ |
|
|
96
|
+
| Suggestion list open (type / field / operator) | Picks the highlighted suggestion |
|
|
97
|
+
| Catalog, date or other value widget with a panel | Opens the panel / picks the value |
|
|
98
|
+
| Inline editor with a condition in progress | Commits the condition — the *next* Enter submits |
|
|
99
|
+
| Add-type input with staged types | Confirms the type block |
|
|
100
|
+
| Focus on a button (remove, confirm, …) | Activates the button |
|
|
101
|
+
| Anywhere else (full-text bar, fill-out form, …) | **Submits** — `querySubmit` emits |
|
|
102
|
+
|
|
103
|
+
<kbd>Shift</kbd>+<kbd>Enter</kbd> and <kbd>Enter</kbd> inside a multi-line value never
|
|
104
|
+
submit, so long text entry keeps working.
|
|
105
|
+
|
|
106
|
+
```html
|
|
107
|
+
<yuv-smart-search [types]="types" (queryChange)="preview.set($event)" (querySubmit)="runSearch($event)" />
|
|
108
|
+
```
|
|
59
109
|
|
|
60
110
|
### Saving and restoring state
|
|
61
111
|
|
|
@@ -25,6 +25,12 @@ interface ObjectFormOptions {
|
|
|
25
25
|
*/
|
|
26
26
|
data: Record<string, unknown>;
|
|
27
27
|
objectId?: string;
|
|
28
|
+
/**
|
|
29
|
+
* ID of the object type (or secondary object type) the form model belongs to. Used to
|
|
30
|
+
* enrich form elements from the schema in the context of that type — a type may bind a
|
|
31
|
+
* shared property to its own dynamic catalog. Falls back to the form model's own id.
|
|
32
|
+
*/
|
|
33
|
+
objectTypeId?: string;
|
|
28
34
|
/**
|
|
29
35
|
* whether or not to disable the complete form
|
|
30
36
|
*/
|
|
@@ -61,7 +61,20 @@ declare class ObjectPreviewService {
|
|
|
61
61
|
dmsObject: _angular_core.Signal<DmsObject | undefined>;
|
|
62
62
|
setDmsObject(object: DmsObject): void;
|
|
63
63
|
getDmsObject(id: string): Observable<DmsObject>;
|
|
64
|
-
|
|
64
|
+
/**
|
|
65
|
+
* Builds the media viewer source URL for an object's content.
|
|
66
|
+
*
|
|
67
|
+
* The URL of the *current* version is keyed on the content stream (`_cs=<contentStreamId>`) when one is
|
|
68
|
+
* given. The viewers only reload when their `src` input is a *different string*: `DynamicViewerDirective`
|
|
69
|
+
* `setInput`s the same viewer instance for a same-type update, `PdfComponent` skips `#loadPDF` for a src
|
|
70
|
+
* it has already loaded and `ImageComponent` derives its cache-busting URL from `src()` alone. Without
|
|
71
|
+
* the key a content replacement that keeps the mime type kept showing the previous file (the object id,
|
|
72
|
+
* and therefore the URL, never changed). `ObjectPreviewComponent` rebuilds the details exactly when the
|
|
73
|
+
* content stream changes, so the key changes exactly then — never on metadata-only saves.
|
|
74
|
+
*
|
|
75
|
+
* Versioned URLs (`/versions/{n}/…`) address immutable content and are returned unchanged.
|
|
76
|
+
*/
|
|
77
|
+
getMediaViewerSrc(id: string, mimeType: string | undefined, version?: number, contentStreamId?: string): string;
|
|
65
78
|
getEmailViewerDetails(object: DmsObject, version?: number, MAIL_APP_ID?: string): ViewerDataEmail;
|
|
66
79
|
getEmailMetadata(object: DmsObject, MAIL_APP_ID?: string): EmailMetadata;
|
|
67
80
|
getViewerDetails(object: DmsObject, version: number | undefined): ViewerDataEmail | ViewerDataDefault | undefined;
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import * as i0 from '@angular/core';
|
|
2
2
|
import { ComponentRef, Type } from '@angular/core';
|
|
3
3
|
import { AuditEntry, SchemaResponseFieldDefinition, TranslateService, ResolvedObjectConfigItem, RendererType } from '@yuuvis/client-core';
|
|
4
|
-
import * as dist_libs_yuuvis_client_core_types_yuuvis_client_core from 'dist/libs/yuuvis/client-core/types/yuuvis-client-core';
|
|
5
4
|
|
|
6
5
|
/**
|
|
7
6
|
* Abstract class to be extended by audit-entry renderers. The renderer controls the
|
|
@@ -71,9 +70,15 @@ declare abstract class AbstractRendererComponent<T = string, U = null> {
|
|
|
71
70
|
propertyName: i0.InputSignal<string>;
|
|
72
71
|
value: i0.InputSignal<T | null>;
|
|
73
72
|
meta: i0.InputSignal<U | Record<string, unknown> | undefined>;
|
|
73
|
+
/**
|
|
74
|
+
* ID of the object type (or secondary object type) the property is rendered for, when known.
|
|
75
|
+
* Some schema attributes — most notably the dynamic `catalog` a property is bound to — may be
|
|
76
|
+
* overridden per type, and can only be resolved with that context.
|
|
77
|
+
*/
|
|
78
|
+
objectTypeId: i0.InputSignal<string | undefined>;
|
|
74
79
|
protected getProperty(): SchemaResponseFieldDefinition | undefined;
|
|
75
80
|
static ɵfac: i0.ɵɵFactoryDeclaration<AbstractRendererComponent<any, any>, never>;
|
|
76
|
-
static ɵcmp: i0.ɵɵComponentDeclaration<AbstractRendererComponent<any, any>, "yuv-abstract-renderer", never, { "propertyName": { "alias": "propertyName"; "required": true; "isSignal": true; }; "value": { "alias": "value"; "required": true; "isSignal": true; }; "meta": { "alias": "meta"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
|
|
81
|
+
static ɵcmp: i0.ɵɵComponentDeclaration<AbstractRendererComponent<any, any>, "yuv-abstract-renderer", never, { "propertyName": { "alias": "propertyName"; "required": true; "isSignal": true; }; "value": { "alias": "value"; "required": true; "isSignal": true; }; "meta": { "alias": "meta"; "required": false; "isSignal": true; }; "objectTypeId": { "alias": "objectTypeId"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
|
|
77
82
|
}
|
|
78
83
|
|
|
79
84
|
declare class BooleanRendererComponent extends AbstractRendererComponent {
|
|
@@ -82,6 +87,11 @@ declare class BooleanRendererComponent extends AbstractRendererComponent {
|
|
|
82
87
|
}
|
|
83
88
|
|
|
84
89
|
declare class DateTimeRendererComponent extends AbstractRendererComponent<Date> {
|
|
90
|
+
/**
|
|
91
|
+
* Fields declared with `resolution: 'date'` hold a calendar day, so rendering them with the
|
|
92
|
+
* default `short` format would invent a time that is not stored anywhere.
|
|
93
|
+
*/
|
|
94
|
+
protected dateOnly: i0.Signal<boolean>;
|
|
85
95
|
static ɵfac: i0.ɵɵFactoryDeclaration<DateTimeRendererComponent, never>;
|
|
86
96
|
static ɵcmp: i0.ɵɵComponentDeclaration<DateTimeRendererComponent, "yuv-datetime-renderer", never, {}, {}, never, never, true, never>;
|
|
87
97
|
}
|
|
@@ -91,6 +101,22 @@ declare class DecimalRendererComponent extends AbstractRendererComponent<number>
|
|
|
91
101
|
static ɵcmp: i0.ɵɵComponentDeclaration<DecimalRendererComponent, "yuv-decimal-renderer", never, {}, {}, never, never, true, never>;
|
|
92
102
|
}
|
|
93
103
|
|
|
104
|
+
/**
|
|
105
|
+
* Renders the value(s) of a dynamic catalog field (schema field carrying a `catalog` reference).
|
|
106
|
+
*
|
|
107
|
+
* Those fields store the technical entry name, so the label has to be resolved from the catalog
|
|
108
|
+
* entry's localizations — the same resolution `yuv-dynamic-catalog` does for the form element.
|
|
109
|
+
* The entries are fetched and cached by `CatalogLabelService` (once per catalog, not once per
|
|
110
|
+
* renderer instance — a summary or tile list mounts many rows of the same catalog).
|
|
111
|
+
* Values without a matching entry fall back to the technical value.
|
|
112
|
+
*/
|
|
113
|
+
declare class DynamicCatalogRendererComponent extends AbstractRendererComponent<string | string[]> {
|
|
114
|
+
#private;
|
|
115
|
+
readonly label: i0.Signal<string>;
|
|
116
|
+
static ɵfac: i0.ɵɵFactoryDeclaration<DynamicCatalogRendererComponent, never>;
|
|
117
|
+
static ɵcmp: i0.ɵɵComponentDeclaration<DynamicCatalogRendererComponent, "yuv-dynamic-catalog-renderer", never, {}, {}, never, never, true, never>;
|
|
118
|
+
}
|
|
119
|
+
|
|
94
120
|
declare class FileSizeRendererComponent extends AbstractRendererComponent {
|
|
95
121
|
parsedValue: i0.Signal<number>;
|
|
96
122
|
static ɵfac: i0.ɵɵFactoryDeclaration<FileSizeRendererComponent, never>;
|
|
@@ -162,8 +188,16 @@ declare class UnknownRendererComponent extends AbstractRendererComponent<any> {
|
|
|
162
188
|
static ɵcmp: i0.ɵɵComponentDeclaration<UnknownRendererComponent, "yuv-unknown-renderer", never, {}, {}, never, never, true, never>;
|
|
163
189
|
}
|
|
164
190
|
|
|
165
|
-
type RendererComponent = IntegerRendererComponent | DecimalRendererComponent | DateTimeRendererComponent | IconRendererComponent | StringRendererComponent | BooleanRendererComponent | TableRendererComponent | I18nCatalogRendererComponent;
|
|
166
|
-
|
|
191
|
+
type RendererComponent = IntegerRendererComponent | DecimalRendererComponent | DateTimeRendererComponent | IconRendererComponent | StringRendererComponent | BooleanRendererComponent | TableRendererComponent | I18nCatalogRendererComponent | DynamicCatalogRendererComponent;
|
|
192
|
+
/**
|
|
193
|
+
* Input of the `yuvRenderer` directive. `objectTypeId` is optional type context: a type may bind
|
|
194
|
+
* a shared property to its own dynamic catalog, and that override can only be resolved when the
|
|
195
|
+
* type (or secondary object type) the property is rendered for is known. Without it the renderer
|
|
196
|
+
* falls back to the global property definition.
|
|
197
|
+
*/
|
|
198
|
+
type RendererDirectiveInput = ResolvedObjectConfigItem & {
|
|
199
|
+
objectTypeId?: string;
|
|
200
|
+
};
|
|
167
201
|
|
|
168
202
|
/**
|
|
169
203
|
* Service for managing property type renderers. Renderers are components that will render certain
|
|
@@ -202,10 +236,10 @@ declare class RendererService {
|
|
|
202
236
|
declare class RendererDirective {
|
|
203
237
|
#private;
|
|
204
238
|
component: ComponentRef<RendererComponent>;
|
|
205
|
-
yuvRenderer: i0.InputSignal<
|
|
239
|
+
yuvRenderer: i0.InputSignal<RendererDirectiveInput | undefined>;
|
|
206
240
|
static ɵfac: i0.ɵɵFactoryDeclaration<RendererDirective, never>;
|
|
207
241
|
static ɵdir: i0.ɵɵDirectiveDeclaration<RendererDirective, "[yuvRenderer]", never, { "yuvRenderer": { "alias": "yuvRenderer"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
|
|
208
242
|
}
|
|
209
243
|
|
|
210
|
-
export { AbstractAuditRendererComponent, AbstractRendererComponent, AuditRendererDirective, AuditRendererService, BooleanRendererComponent, DateTimeRendererComponent, DecimalRendererComponent, DefaultAuditRendererComponent, FileSizeRendererComponent, I18nCatalogRendererComponent, IconRendererComponent, IntegerRendererComponent, OrganizationRendererComponent, RendererDirective, RendererService, StringRendererComponent, TableRendererComponent, UnknownRendererComponent };
|
|
244
|
+
export { AbstractAuditRendererComponent, AbstractRendererComponent, AuditRendererDirective, AuditRendererService, BooleanRendererComponent, DateTimeRendererComponent, DecimalRendererComponent, DefaultAuditRendererComponent, DynamicCatalogRendererComponent, FileSizeRendererComponent, I18nCatalogRendererComponent, IconRendererComponent, IntegerRendererComponent, OrganizationRendererComponent, RendererDirective, RendererService, StringRendererComponent, TableRendererComponent, UnknownRendererComponent };
|
|
211
245
|
export type { RendererComponent, RendererDirectiveInput };
|
|
@@ -116,6 +116,12 @@ interface SuggestionItem {
|
|
|
116
116
|
* Capture via {@link SmartSearchComponent.getState} and restore via
|
|
117
117
|
* {@link SmartSearchComponent.loadState}. Safe for `JSON.stringify` /
|
|
118
118
|
* `JSON.parse` roundtrips (plain data, no class instances or signals).
|
|
119
|
+
*
|
|
120
|
+
* The display labels it carries (`SearchBlockType.label`, `FieldCondition.fieldLabel` /
|
|
121
|
+
* `operatorLabel` / `conditionLabel` and `TableCondition.fieldLabel`) are a snapshot of the
|
|
122
|
+
* language the state was captured in. `loadState` re-resolves them from the live schema and the
|
|
123
|
+
* current language, so a state built by hand only needs the ids — the labels are a fallback for
|
|
124
|
+
* ids that can no longer be resolved.
|
|
119
125
|
*/
|
|
120
126
|
interface SmartSearchState {
|
|
121
127
|
blocks: SearchBlock[];
|
|
@@ -154,7 +160,10 @@ interface DynamicFormBlock {
|
|
|
154
160
|
*/
|
|
155
161
|
declare class SmartSearchEditController {
|
|
156
162
|
#private;
|
|
157
|
-
/**
|
|
163
|
+
/**
|
|
164
|
+
* The set of object type IDs the search is scoped to. Empty = unscoped: every
|
|
165
|
+
* searchable type of the schema is a candidate and nothing is restricted.
|
|
166
|
+
*/
|
|
158
167
|
allowedTypes: _angular_core.WritableSignal<string[]>;
|
|
159
168
|
/** ObjectTypeField IDs to exclude from the field-step autocomplete suggestions. */
|
|
160
169
|
skipProperties: _angular_core.WritableSignal<string[]>;
|
|
@@ -189,6 +198,12 @@ declare class SmartSearchEditController {
|
|
|
189
198
|
fulltext: _angular_core.WritableSignal<FulltextSearch>;
|
|
190
199
|
/** Whether the dynamic-conditions feature is enabled (mirrors the host `supportDynamicConditions` input). */
|
|
191
200
|
supportDynamic: _angular_core.WritableSignal<boolean>;
|
|
201
|
+
/**
|
|
202
|
+
* Whether the host renders a plain full-text search (mirrors its `fulltextOnly` input).
|
|
203
|
+
* The condition builder is hidden and {@link cmisQuery} is built from {@link fulltext}
|
|
204
|
+
* alone, so blocks a loaded state carries can't contribute invisible clauses.
|
|
205
|
+
*/
|
|
206
|
+
fulltextOnly: _angular_core.WritableSignal<boolean>;
|
|
192
207
|
/**
|
|
193
208
|
* Form mode: replace the builder with a generated form of the user-marked dynamic
|
|
194
209
|
* conditions. View state only — the template ({@link blocks}) is never mutated; the
|
|
@@ -207,6 +222,17 @@ declare class SmartSearchEditController {
|
|
|
207
222
|
/** Whether any condition is marked dynamic (gates the form-mode toggle). */
|
|
208
223
|
hasDynamicConditions: _angular_core.Signal<boolean>;
|
|
209
224
|
objectTypes: _angular_core.Signal<GenericObjectType[]>;
|
|
225
|
+
/**
|
|
226
|
+
* The types an "all types" pick resolves to. With a configured allow-list, "all types"
|
|
227
|
+
* means *any of the allowed types* — not every type of the system — so the restriction
|
|
228
|
+
* is still emitted. Without one the list is empty and "all types" restricts nothing.
|
|
229
|
+
*
|
|
230
|
+
* Resolved id-by-id against the schema (rather than from {@link objectTypes}) so an
|
|
231
|
+
* allowed id the current schema doesn't know still narrows the query instead of silently
|
|
232
|
+
* widening it; `isSot` decides whether the id lands in the primary or the secondary
|
|
233
|
+
* object-type clause.
|
|
234
|
+
*/
|
|
235
|
+
scopeTypes: _angular_core.Signal<SearchBlockType[]>;
|
|
210
236
|
/** Fields for the active top-level block, used by the field-step suggestions. */
|
|
211
237
|
activeBlockFields: _angular_core.Signal<SuggestionItem[]>;
|
|
212
238
|
/**
|
|
@@ -221,7 +247,13 @@ declare class SmartSearchEditController {
|
|
|
221
247
|
*/
|
|
222
248
|
activeFields: _angular_core.Signal<SuggestionItem[]>;
|
|
223
249
|
suggestions: _angular_core.Signal<SuggestionItem[]>;
|
|
224
|
-
/**
|
|
250
|
+
/**
|
|
251
|
+
* Whether the full-text unit contributes to the query — a term, a type restriction, or both.
|
|
252
|
+
* Drives its own muted styling and the joiner below it, so what reads as active matches what
|
|
253
|
+
* is actually queried (see {@link isFulltextActive}).
|
|
254
|
+
*/
|
|
255
|
+
fulltextActive: _angular_core.Signal<boolean>;
|
|
256
|
+
/** Number of top-level query units: the full-text unit (when it contributes one) plus each block. */
|
|
225
257
|
unitCount: _angular_core.Signal<number>;
|
|
226
258
|
showCombinator: _angular_core.Signal<boolean>;
|
|
227
259
|
cmisQuery: _angular_core.Signal<string>;
|
|
@@ -229,7 +261,16 @@ declare class SmartSearchEditController {
|
|
|
229
261
|
activeCtrl: _angular_core.Signal<FormControl<unknown>>;
|
|
230
262
|
/** Deep-clone the current blocks, combinator and full-text unit into a serializable {@link SmartSearchState}. */
|
|
231
263
|
getState(): SmartSearchState;
|
|
232
|
-
/**
|
|
264
|
+
/**
|
|
265
|
+
* Replace the current state with a saved one, normalizing legacy blocks and cancelling any
|
|
266
|
+
* in-progress edit.
|
|
267
|
+
*
|
|
268
|
+
* Everything a persisted state carries for display only — type, field and operator labels and
|
|
269
|
+
* the composed condition label — is re-resolved against the live schema and the *current* UI
|
|
270
|
+
* language (see {@link #resolveType} / {@link #relabelNodes}), so a query saved in one language
|
|
271
|
+
* reads in the language it is restored in. The persisted strings act as the fallback for ids the
|
|
272
|
+
* schema or the translations can no longer resolve.
|
|
273
|
+
*/
|
|
233
274
|
loadState(state: SmartSearchState): void;
|
|
234
275
|
/** Reset all search state back to its initial empty values. */
|
|
235
276
|
reset(): void;
|
|
@@ -245,9 +286,19 @@ declare class SmartSearchEditController {
|
|
|
245
286
|
exitFormMode(): void;
|
|
246
287
|
/** Toggle form mode (rebuilds the form rows on each entry). */
|
|
247
288
|
toggleFormMode(): void;
|
|
248
|
-
/**
|
|
289
|
+
/**
|
|
290
|
+
* Record a value entered in the form for a dynamic condition (drives the overlaid
|
|
291
|
+
* {@link cmisQuery}). No-op when unchanged, so re-applying a row's current value —
|
|
292
|
+
* e.g. flushing the debounced controls on submit — can't churn the query.
|
|
293
|
+
*/
|
|
249
294
|
setFormValue(condition: FieldCondition, raw: unknown): void;
|
|
250
|
-
/**
|
|
295
|
+
/**
|
|
296
|
+
* Re-apply every generated form row's current control value. The row controls are
|
|
297
|
+
* debounced, so a submit fired immediately after typing would otherwise read a stale
|
|
298
|
+
* overlay. Rows whose value already matches are skipped by {@link setFormValue}.
|
|
299
|
+
*/
|
|
300
|
+
flushFormValues(): void;
|
|
301
|
+
/** Set the full-text search term. No-op when unchanged, so re-setting it can't churn {@link cmisQuery}. */
|
|
251
302
|
setFulltextTerm(term: string): void;
|
|
252
303
|
/** Set the full-text search scope (`all` / `metadata` / `content`). */
|
|
253
304
|
setFulltextScope(scope: FulltextScope): void;
|
|
@@ -312,7 +363,10 @@ declare class SmartSearchEditController {
|
|
|
312
363
|
isConditionComplete(): boolean;
|
|
313
364
|
/** The operators available for a field's internal type, as autocomplete items. */
|
|
314
365
|
operatorsForField(field: SuggestionItem): SuggestionItem[];
|
|
315
|
-
/**
|
|
366
|
+
/**
|
|
367
|
+
* Human-readable label for an operator id: a math symbol (`=`, `≠`, …), a translated
|
|
368
|
+
* key, a translated date-preset label (`date:thisMonth` → “This month”) or the id itself.
|
|
369
|
+
*/
|
|
316
370
|
operatorLabel(operator: string): string;
|
|
317
371
|
/** Build a condition record from a date preset / boolean operator / value. */
|
|
318
372
|
buildCommitCondition(field: SuggestionItem, operatorId: string, operatorLabelText: string, value: string | string[], internalTypeOverride?: string): FieldCondition;
|
|
@@ -349,9 +403,30 @@ declare function isConditionUnset(cond: FieldCondition): boolean;
|
|
|
349
403
|
declare function buildNodeClause(node: ConditionNode): string;
|
|
350
404
|
/**
|
|
351
405
|
* Build the whole-object full-text clause: a single `CONTAINS('term')` predicate, optionally scoped
|
|
352
|
-
* to a column and AND-ed with a type restriction.
|
|
406
|
+
* to a column and AND-ed with a type restriction.
|
|
407
|
+
*
|
|
408
|
+
* A type restriction on its own — types picked in the full-text bar's type filter with nothing
|
|
409
|
+
* typed — is a query in its own right ("show me everything of this type"), exactly like a type
|
|
410
|
+
* block carrying no conditions. So the picked types are returned alone in that case; only a unit
|
|
411
|
+
* with neither a term nor a picked type contributes nothing and yields `''`.
|
|
412
|
+
*
|
|
413
|
+
* @param fulltext The full-text unit. An empty `types` list means "all types".
|
|
414
|
+
* @param scopeTypes The types the search is scoped to (the host's `types` allow-list). When the
|
|
415
|
+
* unit picks no concrete type, "all types" means *any of these* — so the restriction is still
|
|
416
|
+
* emitted. Pass an empty list for an unscoped search: then "all types" restricts nothing.
|
|
417
|
+
*
|
|
418
|
+
* The scope deliberately only narrows a *term* search. With nothing typed and no type picked the
|
|
419
|
+
* panel is simply untouched, and falling back to the scope there would turn it into a standing
|
|
420
|
+
* "everything in scope" query the moment it opens.
|
|
353
421
|
*/
|
|
354
|
-
declare function buildFulltextClause(fulltext: FulltextSearch): string;
|
|
422
|
+
declare function buildFulltextClause(fulltext: FulltextSearch, scopeTypes?: SearchBlockType[]): string;
|
|
423
|
+
/**
|
|
424
|
+
* Whether the full-text unit contributes a clause to the query — a term, a type restriction, or
|
|
425
|
+
* both. Lives next to {@link buildFulltextClause} so the UI's notion of "this unit is active"
|
|
426
|
+
* (its muted styling, the joiner to the blocks below it, the unit count behind the AND/OR toggle)
|
|
427
|
+
* cannot drift from what actually ends up in the query.
|
|
428
|
+
*/
|
|
429
|
+
declare function isFulltextActive(fulltext: FulltextSearch): boolean;
|
|
355
430
|
/**
|
|
356
431
|
* Assemble the full CMIS statement from the search state. Each unit — the
|
|
357
432
|
* full-text clause plus every type block (type restriction `AND`-ed with its
|
|
@@ -361,9 +436,12 @@ declare function buildFulltextClause(fulltext: FulltextSearch): string;
|
|
|
361
436
|
* @param blocks The type blocks with their conditions.
|
|
362
437
|
* @param combinator How the top-level units combine (`AND` / `OR`).
|
|
363
438
|
* @param fulltext Optional whole-object full-text unit.
|
|
439
|
+
* @param scopeTypes The types the whole search is scoped to (the host's `types` allow-list).
|
|
440
|
+
* Applied to the full-text unit when it targets "all types"; the blocks always carry their own
|
|
441
|
+
* (already scoped) types. Empty = unscoped, i.e. "all types" restricts nothing.
|
|
364
442
|
* @returns A `SELECT * FROM system:object WHERE …` statement, or `''`.
|
|
365
443
|
*/
|
|
366
|
-
declare function buildCmisQuery(blocks: SearchBlock[], combinator: Combinator, fulltext?: FulltextSearch): string;
|
|
444
|
+
declare function buildCmisQuery(blocks: SearchBlock[], combinator: Combinator, fulltext?: FulltextSearch, scopeTypes?: SearchBlockType[]): string;
|
|
367
445
|
|
|
368
446
|
/**
|
|
369
447
|
* Visual query builder that turns guided, chip-based user input into a CMIS query.
|
|
@@ -374,15 +452,26 @@ declare function buildCmisQuery(blocks: SearchBlock[], combinator: Combinator, f
|
|
|
374
452
|
* - one or more **type blocks**, each targeting one or more object types and holding
|
|
375
453
|
* field conditions, nested groups and table-column conditions.
|
|
376
454
|
*
|
|
455
|
+
* Set {@link fulltextOnly} to drop the second part entirely and render a plain full-text
|
|
456
|
+
* search bar.
|
|
457
|
+
*
|
|
377
458
|
* Conditions are built step by step (type → field → operator → value) with an inline
|
|
378
459
|
* autocomplete editor; the value step renders the field's real metadata widget
|
|
379
460
|
* (datepicker, catalog select, organization picker, …). The resulting CMIS query is
|
|
380
461
|
* emitted through {@link queryChange} on every change and can be saved/restored as a
|
|
381
|
-
* plain-data {@link SmartSearchState} via {@link getState} / {@link loadState}.
|
|
462
|
+
* plain-data {@link SmartSearchState} via {@link getState} / {@link loadState}. A restored
|
|
463
|
+
* state is re-labelled in the current UI language (see {@link loadState}).
|
|
382
464
|
*
|
|
383
465
|
* State and mutators live in {@link SmartSearchEditController} (provided per instance);
|
|
384
466
|
* this component owns only the UI concerns (focus, autocomplete plumbing, blur handling).
|
|
385
467
|
*
|
|
468
|
+
* **Submitting.** {@link queryChange} is a live preview — it fires on every change. To run
|
|
469
|
+
* a search only when the user is done, bind {@link querySubmit}: it emits when ENTER
|
|
470
|
+
* reaches the component without an inner widget having claimed it, the way a plain HTML
|
|
471
|
+
* form submits on ENTER. Widgets that own ENTER for their own purpose keep it: the
|
|
472
|
+
* suggestion autocomplete picks an option, a catalog select picks a value, and the inline
|
|
473
|
+
* editor commits the condition it is building. Only the *next* ENTER then submits.
|
|
474
|
+
*
|
|
386
475
|
* @example
|
|
387
476
|
* ```html
|
|
388
477
|
* <!-- Restrict the picker to two object types and skip a noisy property -->
|
|
@@ -417,9 +506,14 @@ declare class SmartSearchComponent {
|
|
|
417
506
|
#private;
|
|
418
507
|
ctrl: SmartSearchEditController;
|
|
419
508
|
/**
|
|
420
|
-
* Object-type ids that may be searched
|
|
421
|
-
* full-text type filter and the type-block multi-select)
|
|
422
|
-
*
|
|
509
|
+
* Object-type ids that may be searched — the scope of the whole search. Restricts
|
|
510
|
+
* the type picker (both the full-text type filter and the type-block multi-select)
|
|
511
|
+
* to these types, and narrows the emitted query: picking *All types* in the
|
|
512
|
+
* full-text filter then means "any of these types" (`objectTypeId IN (…)`), not
|
|
513
|
+
* every type the system knows.
|
|
514
|
+
*
|
|
515
|
+
* When empty the search is unscoped — *All types* restricts nothing — and no type
|
|
516
|
+
* is offered in the picker, so only a full-text search can be built.
|
|
423
517
|
*/
|
|
424
518
|
types: _angular_core.InputSignal<string[]>;
|
|
425
519
|
/**
|
|
@@ -428,6 +522,14 @@ declare class SmartSearchComponent {
|
|
|
428
522
|
* table columns alike.
|
|
429
523
|
*/
|
|
430
524
|
skipProperties: _angular_core.InputSignal<string[]>;
|
|
525
|
+
/**
|
|
526
|
+
* Renders the component as a plain full-text search: only the full-text bar (term, scope
|
|
527
|
+
* and the object-type filter) is shown — no type blocks, no condition builder, no
|
|
528
|
+
* form-mode toggle. The emitted query is built from the full-text unit alone, so a
|
|
529
|
+
* previously {@link loadState loaded} state's blocks do not contribute while this is set.
|
|
530
|
+
* {@link types} keeps its meaning: the search stays scoped to those types.
|
|
531
|
+
*/
|
|
532
|
+
fulltextOnly: _angular_core.InputSignal<boolean>;
|
|
431
533
|
/**
|
|
432
534
|
* Enables the **dynamic conditions** feature. When `true`, each committed condition can
|
|
433
535
|
* be marked dynamic and a form-mode toggle appears that swaps the builder for a generated
|
|
@@ -442,6 +544,14 @@ declare class SmartSearchComponent {
|
|
|
442
544
|
* non-empty values.
|
|
443
545
|
*/
|
|
444
546
|
queryChange: _angular_core.OutputEmitterRef<string>;
|
|
547
|
+
/**
|
|
548
|
+
* Emits the current CMIS query when the user presses ENTER and no inner widget
|
|
549
|
+
* claimed that key — the smart-search equivalent of submitting a form. Bind this
|
|
550
|
+
* (rather than {@link queryChange}) to run the search only once the user is done
|
|
551
|
+
* building it. Like {@link queryChange}, `''` means "no query"; an empty search
|
|
552
|
+
* still submits.
|
|
553
|
+
*/
|
|
554
|
+
querySubmit: _angular_core.OutputEmitterRef<string>;
|
|
445
555
|
auto: _angular_core.Signal<MatAutocomplete>;
|
|
446
556
|
/** Trigger of the currently-focused autocomplete input — used to re-open the
|
|
447
557
|
* panel after a type pick so the multi-select stays open. */
|
|
@@ -450,6 +560,14 @@ declare class SmartSearchComponent {
|
|
|
450
560
|
fulltextTermCtrl: FormControl<string | null>;
|
|
451
561
|
/** Sentinel option value representing "no type restriction" in the type multi-select. */
|
|
452
562
|
readonly ALL_TYPES = "__all__";
|
|
563
|
+
/**
|
|
564
|
+
* Empty `matChipInputSeparatorKeyCodes` for the add-type input. The directive defaults
|
|
565
|
+
* to `[ENTER]` and then calls `preventDefault()` on *every* Enter to end a chip — but
|
|
566
|
+
* we never bind `matChipInputTokenEnd`, so that only served to hide the key from
|
|
567
|
+
* {@link onHostEnter}. A stable reference: a `[]` literal in the template would be a
|
|
568
|
+
* new array on each change-detection run.
|
|
569
|
+
*/
|
|
570
|
+
readonly NO_SEPARATOR_KEYS: number[];
|
|
453
571
|
/**
|
|
454
572
|
* Guard that prevents `onInlineBlur` from cancelling the pending condition
|
|
455
573
|
* when we programmatically open the inline editor.
|
|
@@ -485,6 +603,7 @@ declare class SmartSearchComponent {
|
|
|
485
603
|
readonly showCombinator: _angular_core.Signal<boolean>;
|
|
486
604
|
readonly suggestions: _angular_core.Signal<SuggestionItem[]>;
|
|
487
605
|
readonly fulltext: _angular_core.WritableSignal<_yuuvis_client_framework_smart_search.FulltextSearch>;
|
|
606
|
+
readonly fulltextActive: _angular_core.Signal<boolean>;
|
|
488
607
|
readonly objectTypes: _angular_core.Signal<_yuuvis_client_core.GenericObjectType[]>;
|
|
489
608
|
readonly activeBlockFields: _angular_core.Signal<SuggestionItem[]>;
|
|
490
609
|
readonly formMode: _angular_core.WritableSignal<boolean>;
|
|
@@ -523,7 +642,15 @@ declare class SmartSearchComponent {
|
|
|
523
642
|
* later restore it with {@link loadState}.
|
|
524
643
|
*/
|
|
525
644
|
getState(): SmartSearchState;
|
|
526
|
-
/**
|
|
645
|
+
/**
|
|
646
|
+
* Restore a previously {@link getState saved} search, replacing the current one.
|
|
647
|
+
*
|
|
648
|
+
* The display labels a state carries (type, field and operator labels and the chip's composed
|
|
649
|
+
* condition label) are re-resolved against the live schema and the *current* UI language, so a
|
|
650
|
+
* search saved in one language reads in the language it is restored in. Ids the schema or the
|
|
651
|
+
* translations can no longer resolve keep the label the state carried. Nothing that drives the
|
|
652
|
+
* emitted query is affected.
|
|
653
|
+
*/
|
|
527
654
|
loadState(state: SmartSearchState): void;
|
|
528
655
|
/** Clear the whole search: discard all blocks, conditions and the full-text term. */
|
|
529
656
|
clear(): void;
|
|
@@ -579,14 +706,32 @@ declare class SmartSearchComponent {
|
|
|
579
706
|
* pick, so Enter commits the staged types — even while the autocomplete panel
|
|
580
707
|
* is open. While the user is typing a filter term, Enter is left to the
|
|
581
708
|
* autocomplete so it can select the highlighted option.
|
|
709
|
+
*
|
|
710
|
+
* Unlike {@link onEnter} this deliberately lets an unusable Enter fall through:
|
|
711
|
+
* the add-type input is the resting state of an empty search, so Enter with
|
|
712
|
+
* nothing staged has to reach {@link onHostEnter} and submit.
|
|
713
|
+
*/
|
|
714
|
+
onTypeEnter(event: Event): void;
|
|
715
|
+
/**
|
|
716
|
+
* Enter / confirm-button handler for the inline editor. Commits the in-progress
|
|
717
|
+
* condition once it has a field and an operator. No-op while the autocomplete
|
|
718
|
+
* panel is open (Enter selects the highlighted option there).
|
|
719
|
+
*
|
|
720
|
+
* Bound on the editor wrapper, so it covers every step — including the value
|
|
721
|
+
* step's real metadata widget — and runs after the widgets' own key handling.
|
|
722
|
+
* The `event` is optional because the confirm button calls this from a click.
|
|
582
723
|
*/
|
|
583
|
-
|
|
724
|
+
onEnter(event?: Event): void;
|
|
584
725
|
/**
|
|
585
|
-
* Enter
|
|
586
|
-
*
|
|
587
|
-
*
|
|
726
|
+
* Enter that bubbled all the way up to the component host without being claimed:
|
|
727
|
+
* submit the search, the way a plain HTML form does.
|
|
728
|
+
*
|
|
729
|
+
* Everything inside that owns Enter marks the event handled via `preventDefault()`
|
|
730
|
+
* — Material's autocomplete and select do, and so do {@link onEnter} /
|
|
731
|
+
* {@link onTypeEnter} — so this only sees the "nothing else wanted it" case. The
|
|
732
|
+
* remaining guards cover keys the browser itself is still acting on.
|
|
588
733
|
*/
|
|
589
|
-
|
|
734
|
+
onHostEnter(event: KeyboardEvent | Event): void;
|
|
590
735
|
/**
|
|
591
736
|
* Called when the inline-input wrapper loses focus.
|
|
592
737
|
* Commits the condition if complete, discards it if incomplete.
|
|
@@ -609,7 +754,11 @@ declare class SmartSearchComponent {
|
|
|
609
754
|
* condition, mirroring the blur path.
|
|
610
755
|
*/
|
|
611
756
|
onPickerClosed(): void;
|
|
612
|
-
/**
|
|
757
|
+
/**
|
|
758
|
+
* Abandon the in-progress condition edit, discarding any partial input. When an
|
|
759
|
+
* existing condition was opened for editing it is put back verbatim rather than
|
|
760
|
+
* lost — cancelling an edit means "leave it as it was", the same as the blur path.
|
|
761
|
+
*/
|
|
613
762
|
cancelPending(): void;
|
|
614
763
|
/** Jump the inline editor back to the field step so the user can re-pick the field. */
|
|
615
764
|
editField(): void;
|
|
@@ -639,7 +788,7 @@ declare class SmartSearchComponent {
|
|
|
639
788
|
*/
|
|
640
789
|
getObjectTypeField(item: SuggestionItem | null): ObjectTypeField | null;
|
|
641
790
|
static ɵfac: _angular_core.ɵɵFactoryDeclaration<SmartSearchComponent, never>;
|
|
642
|
-
static ɵcmp: _angular_core.ɵɵComponentDeclaration<SmartSearchComponent, "yuv-smart-search", never, { "types": { "alias": "types"; "required": false; "isSignal": true; }; "skipProperties": { "alias": "skipProperties"; "required": false; "isSignal": true; }; "supportDynamicConditions": { "alias": "supportDynamicConditions"; "required": false; "isSignal": true; }; }, { "queryChange": "queryChange"; }, never, never, true, never>;
|
|
791
|
+
static ɵcmp: _angular_core.ɵɵComponentDeclaration<SmartSearchComponent, "yuv-smart-search", never, { "types": { "alias": "types"; "required": false; "isSignal": true; }; "skipProperties": { "alias": "skipProperties"; "required": false; "isSignal": true; }; "fulltextOnly": { "alias": "fulltextOnly"; "required": false; "isSignal": true; }; "supportDynamicConditions": { "alias": "supportDynamicConditions"; "required": false; "isSignal": true; }; }, { "queryChange": "queryChange"; "querySubmit": "querySubmit"; }, never, never, true, never>;
|
|
643
792
|
}
|
|
644
793
|
|
|
645
794
|
declare class YuvSmartSearchModule {
|
|
@@ -648,5 +797,5 @@ declare class YuvSmartSearchModule {
|
|
|
648
797
|
static ɵinj: _angular_core.ɵɵInjectorDeclaration<YuvSmartSearchModule>;
|
|
649
798
|
}
|
|
650
799
|
|
|
651
|
-
export { SmartSearchComponent, YuvSmartSearchModule, buildCmisQuery, buildFulltextClause, buildNodeClause, isConditionGroup, isFieldCondition, isTableCondition };
|
|
800
|
+
export { SmartSearchComponent, YuvSmartSearchModule, buildCmisQuery, buildFulltextClause, buildNodeClause, isConditionGroup, isFieldCondition, isFulltextActive, isTableCondition };
|
|
652
801
|
export type { BuildStep, Combinator, ConditionContainer, ConditionGroup, ConditionNode, FieldCondition, FulltextScope, FulltextSearch, SearchBlock, SearchBlockType, SmartSearchState, SuggestionItem, TableCondition };
|
|
@@ -29,6 +29,11 @@ interface TileListConfigOptions {
|
|
|
29
29
|
*/
|
|
30
30
|
configTypes: VirtualObjectType[];
|
|
31
31
|
configFlavors?: ObjectFlavor[];
|
|
32
|
+
/**
|
|
33
|
+
* Property IDs that should not be offered for selection in the property
|
|
34
|
+
* slots. Added on top of the always-excluded system/base fields.
|
|
35
|
+
*/
|
|
36
|
+
excludeProperties?: string[];
|
|
32
37
|
actionContext?: ActionContext;
|
|
33
38
|
}
|
|
34
39
|
interface TileListHighlight {
|