• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

jumpinjackie / mapguide-react-layout / 15160437878

21 May 2025 11:00AM UTC coverage: 21.631% (-42.6%) from 64.24%
15160437878

Pull #1552

github

web-flow
Merge 8b7153d9e into 236e2ea07
Pull Request #1552: Feature/package updates 2505

839 of 1165 branches covered (72.02%)

11 of 151 new or added lines in 25 files covered. (7.28%)

1332 existing lines in 50 files now uncovered.

4794 of 22163 relevant lines covered (21.63%)

6.89 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

81.72
/src/api/registry/command-spec.ts
1
import { ApplicationDefinition, ContainerItem, UIWidget, Widget } from '../contracts/fusion';
2
import { DefaultCommands, isSupportedCommandInStatelessMode } from './command';
1✔
3
import { DefaultComponentNames } from './component';
1✔
4
import { tr } from '../i18n';
1✔
5
import { CommandTarget, Dictionary, ICommand, IInvokeUrlCommand, ISearchCommand } from '../common';
6
import { assertNever } from '../../utils/never';
1✔
7
import { strIsNullOrEmpty } from '../../utils/string';
1✔
8
import { warn } from '../../utils/logger';
1✔
9
import { UIItem, CommandDef, isCommandItem, isTargetedCommand, isBasicCommand, isSeparatorItem, isFlyoutItem, WebLayout, isInvokeURLCommand, isSearchCommand } from '../contracts/weblayout';
1✔
10
import { isStateless } from '../../actions/init-command';
1✔
11
import { SPRITE_INVOKE_SCRIPT, SPRITE_INVOKE_URL } from '../../constants/assets';
1✔
12
import { WEBLAYOUT_CONTEXTMENU, WEBLAYOUT_TASKMENU } from '../../constants';
1✔
13
import { ScopedId } from '../../utils/scoped-id';
1✔
14

15
const scopedId = new ScopedId();
1✔
16

17
function isCommandSpec(cmd: ICommandSpec | IUnknownCommandSpec): cmd is ICommandSpec {
74✔
18
    return !strIsNullOrEmpty((cmd as any).command);
74✔
19
}
74✔
20

21
export function isUIWidget(widget: any): widget is UIWidget {
1✔
22
    return widget.WidgetType === "UiWidgetType";
237✔
23
}
237✔
24

25
/**
26
 *
27
 */
28
export interface ToolbarConf {
29
    items: (IFlyoutSpec | ISeparatorSpec | IUnknownCommandSpec | ICommandSpec)[];
30
}
31

32
/**
33
 *
34
 */
35
export interface PreparedSubMenuSet {
36
    toolbars: Dictionary<ToolbarConf>;
37
    flyouts: Dictionary<IFlyoutSpec>;
38
}
39

40
/**
41
 * @hidden
42
 */
43
export function isFlyoutSpec(item: any): item is IFlyoutSpec {
1✔
44
    return typeof (item.children) != 'undefined';
×
UNCOV
45
}
×
46

47
/**
48
 *
49
 */
50
export interface IFlyoutSpec {
51
    label?: string;
52
    tooltip?: string;
53
    icon?: string;
54
    spriteClass?: string;
55
    children: (IFlyoutSpec | ISeparatorSpec | IUnknownCommandSpec | ICommandSpec)[];
56
}
57

58
/**
59
 *
60
 */
61
export interface ISeparatorSpec {
62
    isSeparator: boolean;
63
}
64

65
/**
66
 *
67
 */
68
export interface IUnknownCommandSpec {
69
    error: string;
70
}
71

72
/**
73
 *
74
 */
75
export interface ICommandSpec {
76
    icon: string;
77
    spriteClass: string;
78
    label: string | null;
79
    tooltip: string;
80
    parameters: any;
81
    command?: string;
82
    componentName?: string;
83
    flyoutId?: string;
84
}
85

86
function makeCommand(widget: UIWidget, noToolbarLabels: boolean, cmdType: DefaultCommands): ICommandSpec {
169✔
87
    return { icon: widget.ImageUrl, spriteClass: widget.ImageClass, command: cmdType, label: (noToolbarLabels ? null : widget.Label), tooltip: widget.Tooltip, parameters: widget.Extension };
169!
88
}
169✔
89

90
function convertWidget(widget: UIWidget, locale: string, noToolbarLabels: boolean): ICommandSpec | IUnknownCommandSpec {
207✔
91
    switch (widget.Type) {
207✔
92
        case "Select":
207✔
93
            return makeCommand(widget, noToolbarLabels, DefaultCommands.Select);
12✔
94
        case "Pan":
207✔
95
            return makeCommand(widget, noToolbarLabels, DefaultCommands.Pan);
10✔
96
        //case "PanQuery":
97
        //case "PanOnClick":
98
        case "Zoom":
207✔
99
            return makeCommand(widget, noToolbarLabels, DefaultCommands.Zoom);
9✔
100
        case "ZoomOnClick": //Covers in and out. Look at Factor parameter
207✔
101
            {
19✔
102
                const factor = parseFloat(widget.Extension.Factor);
19✔
103
                if (factor >= 1.0) {
19✔
104
                    return makeCommand(widget, noToolbarLabels, DefaultCommands.ZoomIn);
9✔
105
                } else {
19✔
106
                    return makeCommand(widget, noToolbarLabels, DefaultCommands.ZoomOut);
10✔
107
                }
10✔
108
            }
19✔
109
        case "InitialMapView":
207✔
110
            return makeCommand(widget, noToolbarLabels, DefaultCommands.ZoomExtents);
6✔
111
        case "ZoomToSelection":
207✔
112
            return makeCommand(widget, noToolbarLabels, DefaultCommands.ZoomToSelection);
7✔
113
        case "ExtentHistory": //Covers prev and next. Look at Direction parameter
207✔
114
            {
12✔
115
                if (widget.Extension.Direction == "previous") {
12✔
116
                    return makeCommand(widget, noToolbarLabels, DefaultCommands.PreviousView);
4✔
117
                } else {
12✔
118
                    return makeCommand(widget, noToolbarLabels, DefaultCommands.NextView);
8✔
119
                }
8✔
120
            }
12✔
121
        case "CenterSelection":
207!
122
            return makeCommand(widget, noToolbarLabels, DefaultCommands.CenterSelection);
×
123
        case "About":
207✔
124
            return makeCommand(widget, noToolbarLabels, DefaultCommands.About);
4✔
125
        case "BufferPanel":
207✔
126
            return makeCommand(widget, noToolbarLabels, DefaultCommands.Buffer);
9✔
127
        case "ClearSelection":
207✔
128
            return makeCommand(widget, noToolbarLabels, DefaultCommands.ClearSelection);
6✔
129
        //case "ColorPicker":
130
        case "CoordinateTracker":
207✔
131
            return makeCommand(widget, noToolbarLabels, DefaultCommands.CoordinateTracker);
4✔
132
        case "FeatureInfo":
207✔
133
            return makeCommand(widget, noToolbarLabels, DefaultCommands.FeatureInfo);
6✔
134
        case "Geolocation":
207✔
135
            return makeCommand(widget, noToolbarLabels, DefaultCommands.Geolocation);
2✔
136
        //case "GoogleStreetViewer":
137
        case "Help":
207✔
138
            return makeCommand(widget, noToolbarLabels, DefaultCommands.Help);
4✔
139
        case "Maptip":
207✔
140
            return makeCommand(widget, noToolbarLabels, DefaultCommands.MapTip);
3✔
141
        case "MapMenu":
207✔
142
            return { icon: widget.ImageUrl, spriteClass: widget.ImageClass, label: (noToolbarLabels ? null : widget.Label), tooltip: widget.Tooltip, componentName: DefaultComponentNames.MapMenu, flyoutId: `${DefaultComponentNames.MapMenu}_${scopedId.next()}`, parameters: widget.Extension };
3!
143
        case "Query":
207✔
144
            return makeCommand(widget, noToolbarLabels, DefaultCommands.Query);
9✔
145
        case "QuickPlot":
207✔
146
            return makeCommand(widget, noToolbarLabels, DefaultCommands.QuickPlot);
3✔
147
        case "Redline":
207✔
148
            return makeCommand(widget, noToolbarLabels, DefaultCommands.Redline);
9✔
149
        case "RefreshMap":
207✔
150
            return makeCommand(widget, noToolbarLabels, DefaultCommands.RefreshMap);
4✔
151
        //case "SaveMap":
152
        case "InvokeURL": //Commands with this name would've been registered beforehand
207✔
153
        case "Search":
207✔
154
            return { icon: widget.ImageUrl, spriteClass: widget.ImageClass, command: widget.Name, label: (noToolbarLabels ? null : widget.Label), tooltip: widget.Tooltip, parameters: widget.Extension };
15!
155
        case "SelectPolygon":
207✔
156
            return makeCommand(widget, noToolbarLabels, DefaultCommands.SelectPolygon);
4✔
157
        case "SelectRadius":
207✔
158
            return makeCommand(widget, noToolbarLabels, DefaultCommands.SelectRadius);
4✔
159
        //case "SelectRadiusValue":
160
        case "SelectWithin":
207✔
161
            return makeCommand(widget, noToolbarLabels, DefaultCommands.SelectWithin);
1✔
162
        case "Theme":
207✔
163
            return makeCommand(widget, noToolbarLabels, DefaultCommands.Theme);
6✔
164
        case "ViewOptions":
207✔
165
            return makeCommand(widget, noToolbarLabels, DefaultCommands.ViewerOptions);
4✔
166
        case "ZoomToSelection":
207!
167
            return makeCommand(widget, noToolbarLabels, DefaultCommands.ZoomToSelection);
×
168
        case "Measure":
207✔
169
            return makeCommand(widget, noToolbarLabels, DefaultCommands.Measure);
10✔
170
        case "Print":
207✔
171
            return makeCommand(widget, noToolbarLabels, DefaultCommands.Print);
2✔
172
        case "BasemapSwitcher":
207✔
173
            return { icon: widget.ImageUrl, spriteClass: widget.ImageClass, label: (noToolbarLabels ? null : widget.Label), tooltip: widget.Tooltip, componentName: DefaultComponentNames.BaseMapSwitcher, flyoutId: `${DefaultComponentNames.BaseMapSwitcher}_${scopedId.next()}`, parameters: widget.Extension };
2!
174
        case "InvokeScript":
207✔
175
            return { icon: widget.ImageUrl, spriteClass: widget.ImageClass, command: widget.Name, label: (noToolbarLabels ? null : widget.Label), tooltip: widget.Tooltip, parameters: widget.Extension };
12!
176
        default:
207✔
177
            return { error: tr("UNKNOWN_WIDGET", locale, { widget: widget.Type }) }
6✔
178
    }
207✔
179
}
207✔
180

181
/**
182
 * @hidden
183
 * 
184
 * @param isStateless 
185
 * @param items 
186
 * @param widgetsByKey 
187
 * @param locale 
188
 * @param noToolbarLabels 
189
 * @returns 
190
 */
191
export function convertFlexLayoutUIItems(isStateless: boolean, items: ContainerItem[], widgetsByKey: Dictionary<Widget>, locale: string, noToolbarLabels = false): (IFlyoutSpec | ISeparatorSpec | IUnknownCommandSpec | ICommandSpec)[] {
1✔
192
    const converted = items.map(item => {
33✔
193
        switch (item.Function) {
256✔
194
            case "Widget":
256✔
195
                {
219✔
196
                    const widget = widgetsByKey[item.Widget];
219✔
197
                    if (widget && isUIWidget(widget)) {
219✔
198
                        const cmd = convertWidget(widget, locale, noToolbarLabels);
207✔
199
                        if (isStateless && isCommandSpec(cmd) && !isSupportedCommandInStatelessMode(cmd.command)) {
207✔
200
                            console.warn(`The widget (${widget.Name}) references a command (${cmd.command}) that is not supported in stateless mode. This widget will always be disabled`);
19✔
201
                        }
19✔
202
                        return cmd;
207✔
203
                    }
207✔
204
                }
219✔
205
            case "Separator":
256✔
206
                return { isSeparator: true } as ISeparatorSpec;
37✔
207
            case "Flyout":
256✔
208
                return {
12✔
209
                    label: item.Label,
12✔
210
                    tooltip: item.Tooltip,
12✔
211
                    icon: item.ImageUrl,
12✔
212
                    spriteClass: item.ImageClass,
12✔
213
                    children: convertFlexLayoutUIItems(isStateless, item.Item, widgetsByKey, locale)
12✔
214
                } as IFlyoutSpec;
12✔
215
            default:
256!
216
                assertNever(item);
×
217
        }
256!
218
        return null;
×
219
    })
33✔
220
        .filter(i => i != null)
33✔
221
        .map(i => i as (IFlyoutSpec | ISeparatorSpec | IUnknownCommandSpec | ICommandSpec));
33✔
222
    return converted;
33✔
223
}
33✔
224

225
function tryTranslateImageUrlToSpriteClass(imageUrl: string): string | undefined {
37✔
226
    switch (imageUrl) {
37✔
227
        case "../stdicons/icon_invokeurl.gif":
37✔
228
            return SPRITE_INVOKE_URL;
5✔
229
        case "../stdicons/icon_invokescript.gif":
37!
230
            return SPRITE_INVOKE_SCRIPT;
×
231
    }
37✔
232
}
37✔
233

234
/**
235
 * @hidden
236
 * 
237
 * @param items 
238
 * @param cmdsByKey 
239
 * @param locale 
240
 * @param noToolbarLabels 
241
 * @returns 
242
 */
243
export function convertWebLayoutUIItems(items: UIItem[] | undefined, cmdsByKey: Dictionary<CommandDef>, locale: string, noToolbarLabels = true): (IFlyoutSpec | ISeparatorSpec | IUnknownCommandSpec | ICommandSpec)[] {
1✔
244
    const converted = (items || []).map(item => {
6!
245
        if (isCommandItem(item)) {
58✔
246
            const cmdDef: CommandDef = cmdsByKey[item.Command];
43✔
247
            if (!cmdDef) {
43!
248
                warn(`Invalid reference to command: ${item.Command}`);
×
249
                return { error: tr("UNKNOWN_COMMAND_REFERENCE", locale, { command: item.Command }) } as IUnknownCommandSpec;
×
250
            } else if (cmdDef.TargetViewer != "Dwf") {
43✔
251
                let icon: Partial<Pick<ICommandSpec, "icon" | "spriteClass">> = {};
38✔
252
                if (cmdDef.ImageURL) {
38✔
253
                    icon.spriteClass = tryTranslateImageUrlToSpriteClass(cmdDef.ImageURL);
37✔
254
                    if (!icon.spriteClass) {
37✔
255
                        icon.icon = cmdDef.ImageURL;
32✔
256
                    }
32✔
257
                }
37✔
258
                const commonParams: any = {};
38✔
259
                if (isTargetedCommand(cmdDef)) {
38✔
260
                    commonParams.Target = cmdDef.Target;
15✔
261
                    commonParams.TargetFrame = cmdDef.TargetFrame;
15✔
262
                }
15✔
263
                if (isBasicCommand(cmdDef)) {
38✔
264
                    let action: string = cmdDef.Action;
23✔
265
                    if (action == "ZoomRectangle") {
23✔
266
                        action = DefaultCommands.Zoom;
2✔
267
                    } else if (action == "FitToWindow") {
23✔
268
                        action = DefaultCommands.ZoomExtents;
2✔
269
                    } else if (action == "Refresh") {
21✔
270
                        action = DefaultCommands.RefreshMap;
1✔
271
                    }
1✔
272
                    return { command: action, label: (noToolbarLabels ? null : cmdDef.Label), tooltip: cmdDef.Tooltip, parameters: commonParams, ...icon };
23✔
273
                } else {
38✔
274
                    switch (cmdDef["@xsi:type"]) {
15✔
275
                        case "ViewOptionsCommandType":
15✔
276
                            return { command: DefaultCommands.ViewerOptions, label: (noToolbarLabels ? null : cmdDef.Label), tooltip: cmdDef.Tooltip, parameters: commonParams };
1!
277
                        case "MeasureCommandType":
15✔
278
                            return { command: DefaultCommands.Measure, label: (noToolbarLabels ? null : cmdDef.Label), tooltip: cmdDef.Tooltip, parameters: commonParams };
3✔
279
                        case "HelpCommandType":
15✔
280
                            return { command: DefaultCommands.Help, label: (noToolbarLabels ? null : cmdDef.Label), tooltip: cmdDef.Tooltip, parameters: commonParams };
1!
281
                        case "BufferCommandType":
15✔
282
                            return { command: DefaultCommands.Buffer, label: (noToolbarLabels ? null : cmdDef.Label), tooltip: cmdDef.Tooltip, parameters: commonParams };
3✔
283
                        case "SelectWithinCommandType":
15✔
284
                            return { command: DefaultCommands.SelectWithin, label: (noToolbarLabels ? null : cmdDef.Label), tooltip: cmdDef.Tooltip, parameters: commonParams };
1!
285
                        case "GetPrintablePageCommandType":
15✔
286
                            return { command: DefaultCommands.QuickPlot, label: (noToolbarLabels ? null : cmdDef.Label), tooltip: cmdDef.Tooltip, parameters: commonParams };
1!
287
                        default:
15✔
288
                            return { command: cmdDef.Name, label: (noToolbarLabels ? null : cmdDef.Label), tooltip: cmdDef.Tooltip, parameters: commonParams, ...icon };
5!
289
                    }
15✔
290
                }
15✔
291
            }
38✔
292
        } else if (isSeparatorItem(item)) {
58✔
293
            return { isSeparator: true } as ISeparatorSpec;
12✔
294
        } else if (isFlyoutItem(item)) {
15✔
295
            return {
3✔
296
                label: item.Label,
3✔
297
                tooltip: item.Tooltip,
3✔
298
                children: convertWebLayoutUIItems(item.SubItem, cmdsByKey, locale, false)
3✔
299
            } as IFlyoutSpec;
3✔
300
        } else {
3!
301
            assertNever(item);
×
UNCOV
302
        }
✔
303
        return null;
5✔
304
    })
6✔
305
        .filter(i => i != null)
6✔
306
        .map(i => i as (IFlyoutSpec | ISeparatorSpec | IUnknownCommandSpec | ICommandSpec));
6✔
307
    return converted;
6✔
308
}
6✔
309

310
function convertToCommandTarget(fusionCmdTarget: string): CommandTarget {
18✔
311
    //Treat empty/undefined target as new window
312
    if (strIsNullOrEmpty(fusionCmdTarget)) {
18!
313
        return "NewWindow";
×
UNCOV
314
    }
×
315
    switch (fusionCmdTarget) {
18✔
316
        case "SearchWindow":
18!
317
        case "InvokeUrlWindow":
18✔
318
            return "NewWindow";
2✔
319
        case "TaskPane":
18✔
320
            return "TaskPane";
16✔
321
        default:
18!
322
            return "SpecifiedFrame";
×
323
    }
18✔
324
}
18✔
325
export type CommandRegistrationFunc = (name: string, cmdDef: ICommand | IInvokeUrlCommand | ISearchCommand) => void;
326

327
export function parseWidgetsInAppDef(appDef: ApplicationDefinition, cmdRegister: CommandRegistrationFunc) {
1✔
328
    let taskPane: Widget | undefined;
3✔
329
    let viewSize: Widget | undefined;
3✔
330
    let hasLegend = false;
3✔
331
    let hasStatus = false;
3✔
332
    let hasNavigator = false;
3✔
333
    let hasSelectionPanel = false;
3✔
334
    let hasTaskBar = false;
3✔
335
    let initialTask: string;
3✔
336
    const isStatelessAppDef = isStateless(appDef);
3✔
337
    const widgetsByKey: Dictionary<Widget> = {};
3✔
338
    //Register any InvokeURL and Search commands. Also set capabilities along the way
339
    for (const widgetSet of appDef.WidgetSet) {
3✔
340
        for (const widget of widgetSet.Widget) {
3✔
341
            const cmd = widget.Extension;
211✔
342
            switch (widget.Type) {
211✔
343
                case "TaskPane":
211✔
344
                    taskPane = widget;
3✔
345
                    break;
3✔
346
                case "ViewSize":
211✔
347
                    viewSize = widget;
3✔
348
                    break;
3✔
349
                case "Legend":
211✔
350
                    hasLegend = true;
3✔
351
                    break;
3✔
352
                case "SelectionPanel":
211✔
353
                    hasSelectionPanel = true;
3✔
354
                    break;
3✔
355
                case "CursorPosition":
211✔
356
                case "SelectionInfo":
211✔
357
                    hasStatus = true;
6✔
358
                    break;
6✔
359
                case "Navigator":
211✔
360
                    hasNavigator = true;
3✔
361
                    break;
3✔
362
                case "Search":
211✔
363
                    cmdRegister(widget.Name, {
8✔
364
                        layer: cmd.Layer,
8✔
365
                        prompt: cmd.Prompt,
8✔
366
                        resultColumns: cmd.ResultColumns,
8✔
367
                        filter: cmd.Filter,
8✔
368
                        matchLimit: cmd.MatchLimit,
8✔
369
                        title: (cmd.Title || (isUIWidget(widget) ? widget.Label : undefined)),
8!
370
                        target: convertToCommandTarget(cmd.Target),
8✔
371
                        targetFrame: cmd.Target
8✔
372
                    });
8✔
373
                    if (isStatelessAppDef) {
8!
374
                        console.warn(`The search command (${widget.Name}) is not supported in stateless mode. This widget will always be disabled`);
×
UNCOV
375
                    }
×
376
                    break;
8✔
377
                case "InvokeURL":
211✔
378
                    cmdRegister(widget.Name, {
10✔
379
                        url: cmd.Url,
10✔
380
                        disableIfSelectionEmpty: cmd.DisableIfSelectionEmpty,
10✔
381
                        target: convertToCommandTarget(cmd.Target),
10✔
382
                        targetFrame: cmd.Target,
10✔
383
                        parameters: (cmd.AdditionalParameter || []).map((p: any) => {
10✔
384
                            return { name: p.Key, value: p.Value };
×
385
                        }),
10✔
386
                        title: isUIWidget(widget) ? widget.Label : undefined
10!
387
                    });/*
10✔
388
                        if (config.isStateless && !strStartsWith(cmd.Url, "component://")) {
389
                            console.warn(`The InvokeURL command (${widget.Name}) is not supported in stateless mode. This widget will always be disabled`);
390
                        }*/
391
                    break;
10✔
392
            }
211✔
393
            widgetsByKey[widget.Name] = widget;
211✔
394
        }
211✔
395
    }
3✔
396

397
    if (taskPane) {
3✔
398
        hasTaskBar = true; //Fusion flex layouts can't control the visiblity of this
3✔
399
        initialTask = taskPane.Extension.InitialTask || "server/TaskPane.html";
3✔
400
    } else {
3!
401
        initialTask = "server/TaskPane.html";
×
UNCOV
402
    }
×
403

404
    return {
3✔
405
        taskPane,
3✔
406
        viewSize,
3✔
407
        initialTask,
3✔
408
        hasLegend,
3✔
409
        hasStatus,
3✔
410
        hasNavigator,
3✔
411
        hasSelectionPanel,
3✔
412
        hasTaskBar,
3✔
413
        isStateless: isStatelessAppDef,
3✔
414
        widgetsByKey
3✔
415
    };
3✔
416
}
3✔
417

418
export function parseCommandsInWebLayout(webLayout: WebLayout, cmdRegister: CommandRegistrationFunc) {
1✔
419
    const cmdsByKey: Dictionary<CommandDef> = {};
1✔
420
    //Register any InvokeURL and Search commands
421
    for (const cmd of webLayout.CommandSet.Command) {
1✔
422
        if (isInvokeURLCommand(cmd)) {
33✔
423
            cmdRegister(cmd.Name, {
5✔
424
                url: cmd.URL,
5✔
425
                disableIfSelectionEmpty: cmd.DisableIfSelectionEmpty,
5✔
426
                target: cmd.Target,
5✔
427
                targetFrame: cmd.TargetFrame,
5✔
428
                parameters: (cmd.AdditionalParameter || []).map(p => {
5!
429
                    return { name: p.Key, value: p.Value };
×
430
                }),
5✔
431
                title: cmd.Label
5✔
432
            });
5✔
433
        } else if (isSearchCommand(cmd)) {
33!
434
            cmdRegister(cmd.Name, {
×
UNCOV
435
                layer: cmd.Layer,
×
UNCOV
436
                prompt: cmd.Prompt,
×
UNCOV
437
                target: cmd.Target,
×
UNCOV
438
                targetFrame: cmd.TargetFrame,
×
UNCOV
439
                resultColumns: cmd.ResultColumns,
×
UNCOV
440
                filter: cmd.Filter,
×
UNCOV
441
                matchLimit: cmd.MatchLimit,
×
UNCOV
442
                title: cmd.Label
×
UNCOV
443
            });
×
UNCOV
444
        }
×
445
        cmdsByKey[cmd.Name] = cmd;
33✔
446
    }
33✔
447
    return cmdsByKey;
1✔
448
}
1✔
449

450
/**
451
 * @hidden
452
 * 
453
 * @param tbConf 
454
 * @returns 
455
 */
456
export function prepareSubMenus(tbConf: Dictionary<ToolbarConf>): [PreparedSubMenuSet, boolean] {
1✔
457
    const prepared: PreparedSubMenuSet = {
×
UNCOV
458
        toolbars: {},
×
UNCOV
459
        flyouts: {}
×
UNCOV
460
    };
×
461
    let bFoundContextMenu = false;
×
462
    for (const key in tbConf) {
×
463
        if (key == WEBLAYOUT_CONTEXTMENU) {
×
464
            bFoundContextMenu = true;
×
UNCOV
465
        }
×
466

467
        //Special cases: Task pane and Context Menu. Transfer all to flyout
468
        if (key == WEBLAYOUT_TASKMENU || key == WEBLAYOUT_CONTEXTMENU) {
×
469
            const flyoutId = key;
×
470
            prepared.flyouts[flyoutId] = {
×
UNCOV
471
                children: tbConf[key].items
×
UNCOV
472
            }
×
UNCOV
473
        } else {
×
474
            prepared.toolbars[key] = {
×
UNCOV
475
                items: []
×
UNCOV
476
            };
×
477
            for (const item of tbConf[key].items) {
×
478
                //Special case: contextmenu is all inline
479
                if (isFlyoutSpec(item) && key != WEBLAYOUT_CONTEXTMENU) {
×
480
                    const flyoutId = `${item.label}_${scopedId.next()}`;
×
481
                    prepared.toolbars[key].items.push({
×
UNCOV
482
                        label: item.label,
×
UNCOV
483
                        tooltip: item.tooltip,
×
UNCOV
484
                        icon: item.icon,
×
UNCOV
485
                        spriteClass: item.spriteClass,
×
UNCOV
486
                        flyoutId: flyoutId
×
UNCOV
487
                    } as ICommandSpec);
×
488
                    prepared.flyouts[flyoutId] = {
×
UNCOV
489
                        children: item.children
×
UNCOV
490
                    }
×
UNCOV
491
                } else {
×
492
                    prepared.toolbars[key].items.push(item);
×
UNCOV
493
                }
×
UNCOV
494
            }
×
UNCOV
495
        }
×
UNCOV
496
    }
×
497
    return [prepared, bFoundContextMenu]
×
UNCOV
498
}
×
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc