Sfoglia il codice sorgente

Merge pull request #9107 from miguelvazq/XrefUpgrade

HPCC-12131 Xref Upgrade

Reviewed-By: Gordon Smith <gordon.smith@lexisnexis.com>
Reviewed-By: Richard Chapman <rchapman@hpccsystems.com>
Richard Chapman 8 anni fa
parent
commit
e4884ae92e

+ 52 - 0
esp/src/eclwatch/WsDFUXref.js

@@ -0,0 +1,52 @@
+/*##############################################################################
+#    HPCC SYSTEMS software Copyright (C) 2012 HPCC Systems®.
+#
+#    Licensed under the Apache License, Version 2.0 (the "License");
+#    you may not use this file except in compliance with the License.
+#    You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+#    Unless required by applicable law or agreed to in writing, software
+#    distributed under the License is distributed on an "AS IS" BASIS,
+#    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+#    See the License for the specific language governing permissions and
+#    limitations under the License.
+############################################################################## */
+define([
+    "hpcc/ESPRequest"
+], function (ESPRequest) {
+
+    return {
+        WUGetXref: function (params) {
+            return ESPRequest.send("WsDFUXRef", "DFUXRefList", params);
+        },
+        DFUXRefBuild: function (params) {
+            return ESPRequest.send("WsDFUXRef", "DFUXRefBuild", params);
+        },
+        DFUXRefUnusedFiles: function (params) {
+            return ESPRequest.send("WsDFUXRef", "DFUXRefUnusedFiles", params);
+        },
+        DFUXRefFoundFiles: function (params) {
+            return ESPRequest.send("WsDFUXRef", "DFUXRefFoundFiles", params);
+        },
+        DFUXRefOrphanFiles: function (params) {
+            return ESPRequest.send("WsDFUXRef", "DFUXRefOrphanFiles", params);
+        },
+        DFUXRefMessages: function (params) {
+            return ESPRequest.send("WsDFUXRef", "DFUXRefMessages", params);
+        },
+        DFUXRefCleanDirectories: function (params) {
+            return ESPRequest.send("WsDFUXRef", "DFUXRefCleanDirectories", params);
+        },
+        DFUXRefLostFiles: function (params) {
+            return ESPRequest.send("WsDFUXRef", "DFUXRefLostFiles", params);
+        },
+        DFUXRefDirectories: function (params) {
+            return ESPRequest.send("WsDFUXRef", "DFUXRefDirectories", params);
+        },
+        DFUXRefBuildCancel: function (params) {
+            return ESPRequest.send("WsDFUXRef", "DFUXRefBuildCancel", params);
+        }
+    };
+});

+ 178 - 0
esp/src/eclwatch/XrefDetailsWidget.js

@@ -0,0 +1,178 @@
+/*##############################################################################
+#   HPCC SYSTEMS software Copyright (C) 2012 HPCC Systems®.
+#
+#   Licensed under the Apache License, Version 2.0 (the "License");
+#   you may not use this file except in compliance with the License.
+#   You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+#   Unless required by applicable law or agreed to in writing, software
+#   distributed under the License is distributed on an "AS IS" BASIS,
+#   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+#   See the License for the specific language governing permissions and
+#   limitations under the License.
+############################################################################## */
+define([
+    "dojo/_base/declare",
+    "dojo/_base/lang",
+    "dojo/i18n",
+    "dojo/i18n!./nls/hpcc",
+    "dojo/dom",
+    "dojo/dom-form",
+    "dojo/dom-attr",
+    "dojo/request/iframe",
+    "dojo/dom-class",
+    "dojo/query",
+    "dojo/store/Memory",
+    "dojo/store/Observable",
+
+    "dijit/registry",
+
+    "dgrid/OnDemandGrid",
+    "dgrid/Keyboard",
+    "dgrid/Selection",
+    "dgrid/selector",
+    "dgrid/extensions/ColumnResizer",
+    "dgrid/extensions/DijitRegistry",
+
+    "hpcc/_TabContainerWidget",
+    "hpcc/ESPWorkunit",
+    "hpcc/ESPRequest",
+    "hpcc/TargetSelectWidget",
+    "hpcc/DelayLoadWidget",
+    "hpcc/InfoGridWidget",
+    "hpcc/WsWorkunits",
+    "hpcc/GridDetailsWidget",
+    "hpcc/WsDFUXref",
+
+    "dojo/text!../templates/XrefDetailsWidget.html",
+
+    "dijit/layout/BorderContainer",
+    "dijit/layout/TabContainer",
+    "dijit/layout/ContentPane",
+    "dijit/form/Form",
+    "dijit/form/Textarea",
+    "dijit/form/Button",
+    "dijit/form/DropDownButton",
+    "dijit/form/NumberTextBox",
+    "dijit/form/ValidationTextBox",
+    "dijit/form/Select",
+    "dijit/form/ToggleButton",
+    "dijit/Toolbar",
+    "dijit/ToolbarSeparator",
+    "dijit/TooltipDialog",
+    "dijit/TitlePane",
+    "dijit/form/TextBox",
+    "dijit/Dialog",
+    "dijit/form/SimpleTextarea",
+
+    "hpcc/TableContainer"
+], function (declare, lang, i18n, nlsHPCC, dom, domForm, domAttr, iframe, domClass, query, Memory, Observable,
+                registry,
+                OnDemandGrid, Keyboard, Selection, selector, ColumnResizer, DijitRegistry,
+                _TabContainerWidget, ESPWorkunit, ESPRequest, TargetSelectWidget, DelayLoadWidget, InfoGridWidget, WsWorkunits, GridDetailsWidget, WsDFUXref,
+                template) {
+    return declare("XrefDetailsWidget", [_TabContainerWidget], {
+        templateString: template,
+        baseClass: "XrefDetailsWidget",
+        i18n: nlsHPCC,
+
+        initalized: false,
+        loaded: false,
+        summaryWidget: null,
+        foundFilesWidget: null,
+        foundFilesWidgetLoaded: null,
+        orphanFilesWidget: null,
+        orphanFilesWidgetLoaded: null,
+        lostFilesWidget: null,
+        lostFilesWidgetLoaded: null,
+        directoriesWidget: null,
+        directoriesWidgetLoaded: null,
+        errorsWidget: null,
+        errorsWidgetLoaded: null,
+
+        postCreate: function (args) {
+            this.inherited(arguments);
+            this.summaryWidget = registry.byId(this.id + "_Summary");
+            this.foundFilesWidget = registry.byId(this.id + "_FoundFiles");
+            this.orphanFilesWidget = registry.byId(this.id + "_OrphanFiles");
+            this.lostFilesWidget = registry.byId(this.id + "_LostFiles");
+            this.directoriesWidget = registry.byId(this.id + "_Directories");
+            this.errorsWidget = registry.byId(this.id + "_Errors");
+        },
+
+        startup: function (args) {
+            this.inherited(arguments);
+        },
+
+        destroy: function (args) {
+            this.inherited(arguments);
+        },
+
+        //  Implementation  ---
+        init: function (params) {
+            if (this.inherited(arguments))
+                return;
+
+            if (params.Name) {
+                dom.byId(this.id + "Cluster").textContent = params.Name;
+                dom.byId(this.id + "LastRun").textContent = params.Modified;
+                dom.byId(this.id + "LastMessage").textContent = params.Status;
+            }
+            this.refreshActionState();
+        },
+
+        _onGenerate: function (arg) {
+            WsDFUXref.DFUXRefBuild({
+                request: {
+                    Cluster: this.params.Name
+                }
+            });
+        },
+
+        _onCancel: function (arg) {
+            WsDFUXref.DFUXRefBuildCancel({
+                request: {}
+            });
+            alert(this.i18n.AllQueuedItemsCleared);
+        },
+
+        initTab: function () {
+            var currSel = this.getSelectedChild();
+            if (currSel.id === this.widget._FoundFiles.id && !this.widget._FoundFiles.__hpcc_initalized) {
+                this.widget._FoundFiles.init({
+                    Name: this.params.Name
+                });
+            } else if (currSel.id === this.widget._OrphanFiles.id && !this.widget._OrphanFiles.__hpcc_initalized) {
+                this.widget._OrphanFiles.init({
+                    Name: this.params.Name
+                });
+            } else if (currSel.id === this.widget._LostFiles.id && !this.widget._LostFiles.__hpcc_initalized) {
+                this.widget._LostFiles.init({
+                    Name: this.params.Name
+                });
+            } else if (currSel.id === this.widget._Directories.id && !this.widget._Directories.__hpcc_initalized) {
+                this.widget._Directories.init({
+                    Name: this.params.Name
+                });
+            } else if (currSel.id === this.widget._Errors.id && !this.widget._Errors.__hpcc_initalized) {
+                this.widget._Errors.init({
+                    Name: this.params.Name
+                });
+            }
+        },
+
+        refreshActionState: function () {
+            var disabled = false;
+            if (this.params.Name === "SuperFiles") {
+                disabled = true;
+            }
+
+            this.foundFilesWidget = registry.byId(this.id + "_FoundFiles").set("disabled", disabled);
+            this.orphanFilesWidget = registry.byId(this.id + "_OrphanFiles").set("disabled", disabled);
+            this.lostFilesWidget = registry.byId(this.id + "_LostFiles").set("disabled", disabled);
+            this.directoriesWidget = registry.byId(this.id + "_Directories").set("disabled", disabled);;
+        }
+    });
+});

+ 136 - 0
esp/src/eclwatch/XrefDirectoriesWidget.js

@@ -0,0 +1,136 @@
+/*##############################################################################
+#    HPCC SYSTEMS software Copyright (C) 2012 HPCC Systems®.
+#
+#    Licensed under the Apache License, Version 2.0 (the "License");
+#    you may not use this file except in compliance with the License.
+#    You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+#    Unless required by applicable law or agreed to in writing, software
+#    distributed under the License is distributed on an "AS IS" BASIS,
+#    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+#    See the License for the specific language governing permissions and
+#    limitations under the License.
+############################################################################## */
+define([
+    "dojo/_base/declare",
+    "dojo/_base/lang",
+    "dojo/i18n",
+    "dojo/i18n!./nls/hpcc",
+    "dojo/_base/array",
+    "dojo/on",
+    "dojo/dom",
+    "dojo/dom-construct",
+    "dojo/dom-class",
+
+    "dijit/registry",
+    "dijit/form/ToggleButton",
+    "dijit/ToolbarSeparator",
+    "dijit/form/Button",
+
+    "hpcc/GridDetailsWidget",
+    "hpcc/WsDFUXref",
+    "hpcc/DelayLoadWidget",
+    "hpcc/ESPUtil",
+    "hpcc/XrefDetailsWidget",
+
+], function (declare, lang, i18n, nlsHPCC, arrayUtil, on, dom, domConstruct, domClass,
+                registry, ToggleButton, ToolbarSeparator, Button,
+                GridDetailsWidget, WsDFUXref, DelayLoadWidget, ESPUtil) {
+    return declare("XrefQueryWidget", [GridDetailsWidget], {
+        i18n: nlsHPCC,
+        gridTitle: nlsHPCC.title_DirectoriesFor + ":",
+        idProperty: "Name",
+
+        init: function (params) {
+            if (this.inherited(arguments))
+                return;
+            this._refreshActionState();
+            this.refreshGrid();
+
+            this.gridTab.set("title", this.i18n.title_DirectoriesFor + ":" + this.params.Name);
+        },
+
+        _onRefresh: function (event) {
+            this.refreshGrid();
+        },
+
+        createGrid: function (domID) {
+            var context = this;
+
+            this.openButton = registry.byId(this.id + "Open");
+            this.deleteDirectories = new Button({
+                id: this.id + "Delete",
+                disabled: false,
+                onClick: function (val) {
+                    if (confirm(context.i18n.DeleteDirectories)) {
+                        var selections = context.grid.getSelected();
+
+                        WsDFUXref.DFUXRefCleanDirectories({
+                            request: {
+                                Cluster: context.params.Name
+                            }
+                        }).then(function (response) {
+                            if (response) {
+                                context.refreshGrid();
+                            }
+                        })
+
+                    }
+                },
+                label: this.i18n.DeleteEmptyDirectories
+            }).placeAt(this.openButton.domNode, "after");
+            new ToolbarSeparator().placeAt(this.openButton.domNode, "after");
+
+            var retVal = new declare([ESPUtil.Grid(true, true)])({
+                store: this.store,
+                columns: {
+                    Name: {label: this.i18n.Directory, width:100, sortable: false},
+                    Num: {label: this.i18n.Files, width: 30, sortable: false},
+                    Size: {label: this.i18n.TotalSize, width: 30, sortable: false},
+                    MaxIP: {label: this.i18n.MaxNode, width: 30, sortable: false},
+                    MaxSize: {label: this.i18n.MaxSize, width: 30, sortable: false},
+                    MinIP: {label: this.i18n.MinNode, width: 30, sortable: false},
+                    MinSize: {label: this.i18n.MinSize, width: 30, sortable: false},
+                    SkewPositive: {label: this.i18n.SkewPositive, width: 30, sortable: true},
+                    SkewNegative: {label: this.i18n.SkewNegative, width: 30, sortable: true}
+                }
+            }, domID);
+
+            return retVal;
+        },
+
+        refreshGrid: function () {
+            var context = this;
+
+            WsDFUXref.DFUXRefDirectories({
+                request: {
+                    Cluster: this.params.Name
+                }
+            }).then(function (response) {
+                var results = [];
+                var newRows = [];
+                if (lang.exists("DFUXRefDirectoriesQueryResponse.DFUXRefDirectoriesQueryResult.Directory", response)) {
+                    results = response.DFUXRefDirectoriesQueryResponse.DFUXRefDirectoriesQueryResult.Directory;
+                }
+                arrayUtil.forEach(results, function (row, idx) {
+                   newRows.push({
+                        Name: row.Name,
+                        Num: row.Num,
+                        MinSize: row.MinSize,
+                        Size: row.Size,
+                        MaxIP: row.MaxIP,
+                        MaxSize: row.MaxSize,
+                        MinIP: row.MinIP,
+                        MinSize: row.MinSize,
+                        SkewPositive: row.SkewPositive,
+                        SkewNegative: row.SkewNegative
+                    });
+                });
+                context.store.setData(newRows);
+                context.grid.set("query", {});
+            });
+        }
+    });
+});

+ 121 - 0
esp/src/eclwatch/XrefErrorsWarningsWidget.js

@@ -0,0 +1,121 @@
+/*##############################################################################
+#    HPCC SYSTEMS software Copyright (C) 2012 HPCC Systems®.
+#
+#    Licensed under the Apache License, Version 2.0 (the "License");
+#    you may not use this file except in compliance with the License.
+#    You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+#    Unless required by applicable law or agreed to in writing, software
+#    distributed under the License is distributed on an "AS IS" BASIS,
+#    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+#    See the License for the specific language governing permissions and
+#    limitations under the License.
+############################################################################## */
+define([
+    "dojo/_base/declare",
+    "dojo/_base/lang",
+    "dojo/i18n",
+    "dojo/i18n!./nls/hpcc",
+    "dojo/_base/array",
+    "dojo/on",
+    "dojo/dom",
+    "dojo/dom-construct",
+    "dojo/dom-class",
+
+    "dijit/registry",
+    "dijit/form/ToggleButton",
+    "dijit/ToolbarSeparator",
+    "dijit/form/Button",
+
+    "hpcc/GridDetailsWidget",
+    "hpcc/WsDFUXref",
+    "hpcc/DelayLoadWidget",
+    "hpcc/ESPUtil",
+
+], function (declare, lang, i18n, nlsHPCC, arrayUtil, on, dom, domConstruct, domClass,
+                registry, ToggleButton, ToolbarSeparator, Button,
+                GridDetailsWidget, WsDFUXref, DelayLoadWidget, ESPUtil) {
+    return declare("XrefFoundFilesWidget", [GridDetailsWidget], {
+        i18n: nlsHPCC,
+        gridTitle: nlsHPCC.title_ErrorsWarnings,
+        idProperty: "Name",
+
+        init: function (params) {
+            if (this.inherited(arguments))
+                return;
+            this._refreshActionState();
+            this.refreshGrid();
+
+            this.gridTab.set("title", this.i18n.title_ErrorsWarnings + ":" + this.params.Name);
+        },
+
+        _onRefresh: function (event) {
+            this.refreshGrid();
+        },
+
+        createGrid: function (domID) {
+            this.openButton = registry.byId(this.id + "Open");
+
+            var retVal = new declare([ESPUtil.Grid(true, true)])({
+                store: this.store,
+                columns: {
+                    File: {label: this.i18n.File, width:100, sortable: false},
+                    Text: {label: this.i18n.Message, width: 100, sortable: false},
+                    Status: {label: this.i18n.Status, width: 10, sortable: true,
+                        renderCell: function (object, value, node, options) {
+                            switch (value) {
+                                case "Error":
+                                    domClass.add(node, "ErrorCell");
+                                    break;
+                                case "Warning":
+                                    domClass.add(node, "WarningCell");
+                                    break;
+                                case "Normal":
+                                    domClass.add(node, "NormalCell");
+                                    break;
+                            }
+                            node.innerText = value;
+                        }
+                    }
+                }
+            }, domID);
+
+            return retVal;
+        },
+
+        refreshGrid: function () {
+            var context = this;
+
+            WsDFUXref.DFUXRefMessages({
+                request: {
+                    Cluster: this.params.Name
+                }
+            }).then(function (response) {
+                var results = [];
+                var newRows = [];
+                if (lang.exists("DFUXRefMessagesQueryResponse.DFUXRefMessagesQueryResult", response)) {
+                    results = response.DFUXRefMessagesQueryResponse.DFUXRefMessagesQueryResult;
+                }
+                arrayUtil.forEach(results.Warning, function (row, idx) {
+                   newRows.push({
+                        File: row.File,
+                        Text: row.Text,
+                        Status: context.i18n.Warning
+                    });
+                });
+
+                arrayUtil.forEach(results.Error, function (row, idx) {
+                   newRows.push({
+                        File: row.File,
+                        Text: row.Text,
+                        Status: context.i18n.Error
+                    });
+                });
+                context.store.setData(newRows);
+                context.grid.set("query", {});
+            });
+        }
+    });
+});

+ 99 - 0
esp/src/eclwatch/XrefFoundFilesWidget.js

@@ -0,0 +1,99 @@
+/*##############################################################################
+#    HPCC SYSTEMS software Copyright (C) 2012 HPCC Systems®.
+#
+#    Licensed under the Apache License, Version 2.0 (the "License");
+#    you may not use this file except in compliance with the License.
+#    You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+#    Unless required by applicable law or agreed to in writing, software
+#    distributed under the License is distributed on an "AS IS" BASIS,
+#    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+#    See the License for the specific language governing permissions and
+#    limitations under the License.
+############################################################################## */
+define([
+    "dojo/_base/declare",
+    "dojo/_base/lang",
+    "dojo/i18n",
+    "dojo/i18n!./nls/hpcc",
+    "dojo/_base/array",
+    "dojo/on",
+    "dojo/dom",
+    "dojo/dom-construct",
+    "dojo/dom-class",
+
+    "dijit/registry",
+    "dijit/form/ToggleButton",
+    "dijit/ToolbarSeparator",
+    "dijit/form/Button",
+
+    "hpcc/GridDetailsWidget",
+    "hpcc/WsDFUXref",
+    "hpcc/DelayLoadWidget",
+    "hpcc/ESPUtil",
+
+], function (declare, lang, i18n, nlsHPCC, arrayUtil, on, dom, domConstruct, domClass,
+                registry, ToggleButton, ToolbarSeparator, Button,
+                GridDetailsWidget, WsDFUXref, DelayLoadWidget, ESPUtil) {
+    return declare("XrefFoundFilesWidget", [GridDetailsWidget], {
+        i18n: nlsHPCC,
+        gridTitle: nlsHPCC.title_FoundFilesFor,
+        idProperty: "Name",
+
+        init: function (params) {
+            if (this.inherited(arguments))
+                return;
+            this._refreshActionState();
+            this.refreshGrid();
+
+            this.gridTab.set("title", this.i18n.title_FoundFilesFor + ":" + this.params.Name);
+        },
+
+        _onRefresh: function (event) {
+            this.refreshGrid();
+        },
+
+        createGrid: function (domID) {
+
+            var retVal = new declare([ESPUtil.Grid(true, true)])({
+                store: this.store,
+                columns: {
+                    Name: {label: this.i18n.Name, width:100, sortable: false},
+                    Modified: {label: this.i18n.Modified, width: 30, sortable: true},
+                    Parts: {label: this.i18n.Parts, width: 30, sortable: true},
+                    Size: {label: this.i18n.Size, width: 30, sortable: true}
+                }
+            }, domID);
+
+            return retVal;
+        },
+
+        refreshGrid: function () {
+            var context = this;
+
+            WsDFUXref.DFUXRefFoundFiles({
+                request: {
+                    Cluster: this.params.Name
+                }
+            }).then(function (response) {
+                var results = [];
+                var newRows = [];
+                if (lang.exists("DFUXRefFoundFilesQueryResponse.DFUXRefFoundFilesQueryResult.File", response)) {
+                    results = response.DFUXRefFoundFilesQueryResponse.DFUXRefFoundFilesQueryResult.File;
+                }
+                arrayUtil.forEach(results, function (row, idx) {
+                   newRows.push({
+                        Name: row.Partmask,
+                        Modified: row.Modified,
+                        Parts: row.Numparts,
+                        Size: row.Size
+                    });
+                });
+                context.store.setData(newRows);
+                context.grid.set("query", {});
+            });
+        }
+    });
+});

+ 110 - 0
esp/src/eclwatch/XrefLostFilesWidget.js

@@ -0,0 +1,110 @@
+/*##############################################################################
+#    HPCC SYSTEMS software Copyright (C) 2012 HPCC Systems®.
+#
+#    Licensed under the Apache License, Version 2.0 (the "License");
+#    you may not use this file except in compliance with the License.
+#    You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+#    Unless required by applicable law or agreed to in writing, software
+#    distributed under the License is distributed on an "AS IS" BASIS,
+#    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+#    See the License for the specific language governing permissions and
+#    limitations under the License.
+############################################################################## */
+define([
+    "dojo/_base/declare",
+    "dojo/_base/lang",
+    "dojo/i18n",
+    "dojo/i18n!./nls/hpcc",
+    "dojo/_base/array",
+    "dojo/on",
+    "dojo/dom",
+    "dojo/dom-construct",
+    "dojo/dom-class",
+
+    "dijit/registry",
+    "dijit/form/ToggleButton",
+    "dijit/ToolbarSeparator",
+    "dijit/form/Button",
+
+    "dgrid/selector",
+
+    "hpcc/GridDetailsWidget",
+    "hpcc/WsDFUXref",
+    "hpcc/ESPWorkunit",
+    "hpcc/DelayLoadWidget",
+    "hpcc/ESPUtil",
+    "hpcc/XrefDetailsWidget",
+
+], function (declare, lang, i18n, nlsHPCC, arrayUtil, on, dom, domConstruct, domClass,
+                registry, ToggleButton, ToolbarSeparator, Button,
+                selector,
+                GridDetailsWidget, WsDFUXref, ESPWorkunit, DelayLoadWidget, ESPUtil, FilterDropDownWidget, XrefDetailsWidget) {
+    return declare("XrefFoundFilesWidget", [GridDetailsWidget], {
+        i18n: nlsHPCC,
+        gridTitle: nlsHPCC.title_LostFilesFor,
+        idProperty: "Name",
+
+        init: function (params) {
+            if (this.inherited(arguments))
+                return;
+            this._refreshActionState();
+            this.refreshGrid();
+
+            this.gridTab.set("title", this.i18n.title_LostFilesFor + ":" + this.params.Name);
+        },
+
+        _onRefresh: function (event) {
+            this.refreshGrid();
+        },
+
+        createGrid: function (domID) {
+
+            var retVal = new declare([ESPUtil.Grid(true, true)])({
+                store: this.store,
+                columns: {
+                    Name: {label: this.i18n.Name, width:100, sortable: false},
+                    Modified: {label: this.i18n.Modified, width: 30, sortable: true},
+                    Numparts: {label: this.i18n.TotalParts, width: 30, sortable: false},
+                    Size: {label:this.i18n.Size, width: 30, sortable: true},
+                    Partslost: {label:this.i18n.PartsLost, width: 30, sortable: true},
+                    Primarylost: {label: this.i18n.PrimaryLost, width: 30, sortable: false},
+                    Replicatedlost: {label: this.i18n.ReplicatedLost, width: 30, sortable: false}
+                }
+            }, domID);
+
+            return retVal;
+        },
+
+        refreshGrid: function () {
+            var context = this;
+
+            WsDFUXref.DFUXRefLostFiles({
+                request: {
+                    Cluster: this.params.Name
+                }
+            }).then(function (response) {
+                var results = [];
+                var newRows = [];
+                if (lang.exists("DFUXRefLostFilesQueryResponse.DFUXRefLostFilesQueryResult.File", response)) {
+                    results = response.DFUXRefLostFilesQueryResponse.DFUXRefLostFilesQueryResultFile
+                }
+                arrayUtil.forEach(results, function (row, idx) {
+                   newRows.push({
+                        Name: row.Name,
+                        Modified: row.Modified,
+                        Numparts: row.Numparts,
+                        Partslost: row.Partslost,
+                        Primarylost: row.Primarylost,
+                        Replicatedlost: row.Replicatedlost,
+                        Size: row.Size
+                    });
+                });
+                context.store.setData(newRows);
+                context.grid.set("query", {});
+            });
+        }
+    });
+});

+ 130 - 0
esp/src/eclwatch/XrefOrphanFilesWidget.js

@@ -0,0 +1,130 @@
+/*##############################################################################
+#    HPCC SYSTEMS software Copyright (C) 2012 HPCC Systems®.
+#
+#    Licensed under the Apache License, Version 2.0 (the "License");
+#    you may not use this file except in compliance with the License.
+#    You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+#    Unless required by applicable law or agreed to in writing, software
+#    distributed under the License is distributed on an "AS IS" BASIS,
+#    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+#    See the License for the specific language governing permissions and
+#    limitations under the License.
+############################################################################## */
+define([
+    "dojo/_base/declare",
+    "dojo/_base/lang",
+    "dojo/i18n",
+    "dojo/i18n!./nls/hpcc",
+    "dojo/_base/array",
+    "dojo/on",
+    "dojo/dom",
+    "dojo/dom-construct",
+    "dojo/dom-class",
+
+    "dijit/registry",
+    "dijit/form/ToggleButton",
+    "dijit/ToolbarSeparator",
+    "dijit/form/Button",
+
+    "dgrid/selector",
+
+    "hpcc/GridDetailsWidget",
+    "hpcc/WsDFUXref",
+    "hpcc/DelayLoadWidget",
+    "hpcc/ESPUtil",
+    "hpcc/FilterDropDownWidget",
+    "hpcc/XrefDetailsWidget",
+
+], function (declare, lang, i18n, nlsHPCC, arrayUtil, on, dom, domConstruct, domClass,
+                registry, ToggleButton, ToolbarSeparator, Button,
+                selector,
+                GridDetailsWidget, WsDFUXref, DelayLoadWidget, ESPUtil) {
+    return declare("XrefFoundFilesWidget", [GridDetailsWidget], {
+        i18n: nlsHPCC,
+        gridTitle: nlsHPCC.title_OrphanFilesFor,
+        idProperty: "Name",
+
+        init: function (params) {
+            if (this.inherited(arguments))
+                return;
+            this._refreshActionState();
+            this.refreshGrid();
+
+            this.gridTab.set("title", this.i18n.title_OrphanFilesFor + ":" + this.params.Name);
+        },
+
+        _onRefresh: function (event) {
+            this.refreshGrid();
+        },
+
+        createGrid: function (domID) {
+            var context = this;
+            this.openButton = registry.byId(this.id + "Open");
+            this.delete = new Button({
+                id: this.id + "Delete",
+                disabled: false,
+                onClick: function (val) {
+                    if (confirm(context.i18n.RunningServerStrain)) {
+                        var selections = context.grid.getSelected();
+                        WsDFUXref.DFUXRefBuild({
+                            request: {
+                                Cluster: selections[0].Name
+                            }
+                        }).then(function (response) {
+                            if (response) {
+                                context.refreshGrid();
+                            }
+                        });
+                    }
+
+                },
+                label: this.i18n.Delete
+            }).placeAt(this.openButton.domNode, "after");
+
+            var retVal = new declare([ESPUtil.Grid(true, true)])({
+                store: this.store,
+                selectionMode: "single",
+                allowSelectAll: false,
+                columns: {
+                    Name: {label: this.i18n.Name, width:100, sortable: false},
+                    Modified: {label: this.i18n.Modified, width: 30, sortable: false},
+                    PartsFound: {label: this.i18n.PartsFound, width: 30, sortable: false},
+                    TotalParts: {label: this.i18n.TotalParts, width: 30, sortable: true},
+                    Size: {label: this.i18n.Size, width: 30, sortable: true}
+                }
+            }, domID);
+
+            return retVal;
+        },
+
+        refreshGrid: function () {
+            var context = this;
+
+            WsDFUXref.DFUXRefOrphanFiles({
+                request: {
+                    Cluster: this.params.Name
+                }
+            }).then(function (response) {
+                var results = [];
+                var newRows = [];
+                if (lang.exists("DFUXRefOrphanFilesQueryResponse.DFUXRefOrphanFilesQueryResult.File", response)) {
+                    results = response.DFUXRefOrphanFilesQueryResponse.DFUXRefOrphanFilesQueryResult.File
+                }
+                arrayUtil.forEach(results, function (row, idx) {
+                   newRows.push({
+                        Name: row.Partmask,
+                        Modified: row.Modified,
+                        PartsFound: row.Partsfound,
+                        TotalParts: row.Numparts,
+                        Size: row.Size
+                    });
+                });
+                context.store.setData(newRows);
+                context.grid.set("query", {});
+            });
+        }
+    });
+});

+ 215 - 0
esp/src/eclwatch/XrefQueryWidget.js

@@ -0,0 +1,215 @@
+/*##############################################################################
+#    HPCC SYSTEMS software Copyright (C) 2012 HPCC Systems®.
+#
+#    Licensed under the Apache License, Version 2.0 (the "License");
+#    you may not use this file except in compliance with the License.
+#    You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+#    Unless required by applicable law or agreed to in writing, software
+#    distributed under the License is distributed on an "AS IS" BASIS,
+#    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+#    See the License for the specific language governing permissions and
+#    limitations under the License.
+############################################################################## */
+define([
+    "dojo/_base/declare",
+    "dojo/_base/lang",
+    "dojo/i18n",
+    "dojo/i18n!./nls/hpcc",
+    "dojo/_base/array",
+    "dojo/on",
+    "dojo/dom",
+    "dojo/dom-construct",
+    "dojo/dom-class",
+
+    "dijit/registry",
+    "dijit/form/ToggleButton",
+    "dijit/ToolbarSeparator",
+    "dijit/form/Button",
+
+    "dgrid/selector",
+
+    "hpcc/GridDetailsWidget",
+    "hpcc/WsDFUXref",
+    "hpcc/DelayLoadWidget",
+    "hpcc/ESPUtil"
+], function (declare, lang, i18n, nlsHPCC, arrayUtil, on, dom, domConstruct, domClass,
+                registry, ToggleButton, ToolbarSeparator, Button,
+                selector,
+                GridDetailsWidget, WsDFUXref, DelayLoadWidget, ESPUtil) {
+    return declare("XrefQueryWidget", [GridDetailsWidget], {
+        i18n: nlsHPCC,
+        gridTitle: nlsHPCC.XRef,
+        idProperty: "Name",
+
+        init: function (params) {
+            if (this.inherited(arguments))
+                return;
+            this._refreshActionState();
+            this.refreshGrid();
+            this.initTab();
+        },
+
+        initTab: function () {
+            var currSel = this.getSelectedChild();
+            if (currSel && !currSel.initalized) {
+                if (currSel.init) {
+                    currSel.init({
+                        Name: currSel.params.Name,
+                        Status: currSel.params.Status,
+                        Modified: currSel.params.Modified
+                    });
+                }
+            }
+        },
+
+        _onRefresh: function (event) {
+            this.refreshGrid();
+        },
+
+        createGrid: function (domID) {
+            var context = this;
+
+            this.openButton = registry.byId(this.id + "Open");
+
+            this.generate = new Button({
+                id: this.id + "Generate",
+                disabled: false,
+                onClick: function (val) {
+                    var selections = context.grid.getSelected();
+                    if (confirm(context.i18n.RunningServerStrain)) {
+                        for (var i = selections.length - 1; i >= 0; --i) {
+                            WsDFUXref.DFUXRefBuild({
+                                request: {
+                                    Cluster: selections[i].Name
+                                }
+                            })
+                        }
+                    }
+                    context.refreshGrid();
+                },
+                label: this.i18n.Generate
+            }).placeAt(this.openButton.domNode, "after");
+
+            this.cancel = new Button({
+                id: this.id + "Cancel",
+                disabled: false,
+                onClick: function (val) {
+                    if (confirm(context.i18n.CancelAllMessage)) {
+                        WsDFUXref.DFUXRefBuildCancel({
+                            request: {}
+                        })
+                    }
+                    context.refreshGrid();
+                },
+                label: this.i18n.CancelAll
+            }).placeAt(this.openButton.domNode, "after");
+
+            new ToolbarSeparator().placeAt(this.openButton.domNode, "after");
+            new ToolbarSeparator().placeAt(this.cancel.domNode, "after");
+
+            var retVal = new declare([ESPUtil.Grid(true, true)])({
+                store: this.store,
+                columns: {
+                    col1: selector({
+                        width: 10,
+                        selectorType: 'checkbox',
+                        label: ""
+                    }),
+                    Name: {label: this.i18n.Name, width:100, sortable: false,
+                        formatter: function (Name, idx) {
+                           return "<a href='#' class='dgrid-row-url'>" + Name + "</a>";
+                        }
+                    },
+                    Modified: {label: this.i18n.LastRun, width: 30, sortable: false},
+                    Status: {label: this.i18n.LastMessage, width: 30, sortable: false}
+                }
+            }, domID);
+
+            retVal.on(".dgrid-row-url:click", function (evt) {
+                if (context._onRowDblClick) {
+                    var item = retVal.row(evt).data;
+                    context._onRowDblClick(item);
+                }
+            });
+            retVal.on(".dgrid-row:dblclick", function (evt) {
+                if (context._onRowDblClick) {
+                    var item = retVal.row(evt).data;
+                    context._onRowDblClick(item);
+                }
+            });
+
+            return retVal;
+        },
+
+        _onOpen: function (event) {
+            var selections = this.grid.getSelected();
+            var firstTab = null;
+            for (var i = selections.length - 1; i >= 0; --i) {
+                var tab = this.ensurePane(selections[i].Name, {
+                    Name: selections[i].Name,
+                    Modified: selections[i].Modified,
+                    Status: selections[i].Status
+
+                });
+                if (i == 0) {
+                    firstTab = tab;
+                }
+            }
+            if (firstTab) {
+                this.selectChild(firstTab);
+            }
+        },
+
+        _onRowDblClick: function (item) {
+            var nameTab = this.ensurePane(item.Name, {
+                Name: item.Name,
+                Modified: item.Modified,
+                Status: item.Status
+            });
+            this.selectChild(nameTab);
+        },
+
+        refreshGrid: function () {
+            var context = this;
+
+            WsDFUXref.WUGetXref({
+                request: {}
+            }).then(function (response) {
+                var results = [];
+                var newRows = [];
+                if (lang.exists("DFUXRefListResponse.DFUXRefListResult.XRefNode", response)) {
+                    results = response.DFUXRefListResponse.DFUXRefListResult.XRefNode;
+                }
+                arrayUtil.forEach(results, function (row, idx) {
+                   newRows.push({
+                        Name: row.Name,
+                        Modified: row.Modified,
+                        Status: row.Status
+                    });
+                });
+                context.store.setData(newRows);
+                context.grid.set("query", {});
+            });
+        },
+
+        ensurePane: function (id, params) {
+            id = this.createChildTabID(id);
+            var retVal = registry.byId(id);
+            if (!retVal) {
+                var context = this;
+                retVal = new DelayLoadWidget({
+                    id: id,
+                    title: params.Name,
+                    closable: true,
+                    delayWidget: "XrefDetailsWidget",
+                    params: params
+                });
+                this.addChild(retVal, 1);
+            }
+            return retVal;
+        }
+    });
+});

+ 36 - 0
esp/src/eclwatch/nls/hpcc.js

@@ -32,6 +32,7 @@ define({root:
     AllowFull: "<center>Allow<br>Full</center>",
     AllowRead: "<center>Allow<br>Read</center>",
     AllowWrite: "<center>Allow<br>Write</center>",
+    AllQueuedItemsCleared: "All Queued items have been cleared. The current running job will continue to execute.",
     ANY: "ANY",
     Append: "Append",
     Apply: "Apply",
@@ -48,6 +49,8 @@ define({root:
     BlobPrefix: "BLOB Prefix",
     Bottom: "Bottom",
     Cancel: "Cancel",
+    CancelAll: "Cancel All",
+    CancelAllMessage: "Abort running jobs and clear queue. Do you wish to continue?",
     CheckAllNodes: "Check All Nodes",
     CheckFilePermissions: "Check File Permissions",
     CheckSingleNode: "Check Single Node",
@@ -96,6 +99,8 @@ define({root:
     Defaults: "Defaults",
     Delete: "Delete",
     Deleted: "Deleted",
+    DeleteEmptyDirectories: "Delete empty directories?",
+    DeleteDirectories: "Remove empty directories. Do you wish to continue?",
     DeleteSelectedFiles: "Delete Selected Files?",
     DeleteSelectedGroups: "Delete selected group(s)?",
     DeleteSelectedPermissions: "Delete selected permission(s)?",
@@ -119,6 +124,7 @@ define({root:
     Details: "Details",
     DFUServerName: "DFU Server Name",
     DFUWorkunit: "DFU Workunit",
+    Directories: "Directories",
     Directory: "Directory",
     DisableScopeScans: "Disable Scope Scans",
     DisableScopeScanConfirm: "Are you sure you want to disable Scope Scans?  Changes will revert to configuration settings on DALI reboot.",
@@ -198,10 +204,13 @@ define({root:
     Format: "Format",
     Forums: "Forums",
     Forward: "Forward",
+    FoundFile: "Found File",
+    FoundFileMessage: "A found file has all of its parts on disk that are not referenced in the Dali server. All the file parts are accounted for so they can be added back to the Dali server. They can also be deleted from the cluster, if required.",
     FromDate: "From Date",
     FromSizes: "From Sizes",
     FromTime: "From Time",
     FullName: "Full Name",
+    Generate: "Generate",
     Graph: "Graph",
     Graphs: "Graphs",
     GraphView: "Graph View",
@@ -250,10 +259,12 @@ define({root:
     Largest: "Largest",
     LargestFile: "Largest File",
     LargestSize: "Largest Size",
+    LastMessage: "Last Message",
     LastName: "Last Name",
     LastNDays: "Last N Days",
     LastNHours: "Last N Hours",
     LastNRows: "Last N Rows",
+    LastRun: "Last Run",
     LegacyForm: "Legacy Form",
     LDAPWarning: "<b>LDAP Services Error:</b>  'Too Many Users' - Please use a Filter.",
     LibrariesUsed: "Libraries Used",
@@ -279,6 +290,9 @@ define({root:
     Log: "Log",
     Logs: "Logs",
     log_analysis_1: "log_analysis_1*",
+    LostFile: "Lost File",
+    LostFile2: "Lost Files",
+    LostFileMessage: "A logical file that is missing at least one file part on both the primary and replicated locations in storage. The logical file is still referenced in the Dali server. Deleting the file removes the reference from the Dali server and any remaining parts on disk.",
     Low: "Low",
     ManagedBy: "Managed By",
     ManagedByPlaceholder: "CN=HPCCAdmin,OU=users,OU=hpcc,DC=MyCo,DC=local",
@@ -288,12 +302,16 @@ define({root:
     Mappings: "Mappings",
     Mask: "Mask",
     Max: "Max",
+    MaxNode: "Max Node",
+    MaxSize: "Max Size",
     MaximumNumberOfSlaves: "Slave Number",
     MaxRecordLength: "Max Record Length",
     MemberOf: "Member Of",
     Members: "Members",
     Message: "Message",
     Min: "Min",
+    MinNode: "Min Node",
+    MinSize: "Min Size",
     Missing: "Missing",
     MixedNodeStates: "Mixed Node States",
     Modified: "Modified",
@@ -346,6 +364,9 @@ define({root:
     Operations: "Operations",
     Options: "Options",
     OriginalFile: "Original File",
+    OrphanFile: "Orphan Files",
+    OrphanFile2: "Orphan File",
+    OrphanMessage: "An orphan file has partial file parts on disk. However, a full set of parts is not available to construct a complete logical file. This no reference to these file parts in the Dali server.",
     Outputs: "Outputs",
     Overview: "Overview",
     Overwrite: "Overwrite",
@@ -358,7 +379,10 @@ define({root:
     PackagesNoQuery: "Packages without matching queries",
     ParameterXML: "Parameter XML",
     Part: "Part",
+    PartMask: "Part Mask",
     Parts: "Parts",
+    PartsFound: "Parts Found",
+    PartsLost: "Parts Lost",
     Password: "Password",
     PasswordExpiration: "Password Expiration",
     PasswordOpenZAP: "Password to open ZAP (optional)",
@@ -389,6 +413,7 @@ define({root:
     PrefixPlaceholder: "filename{:length}, filesize{:[B|L][1-8]}",
     PreserveCompression: "Preserve Compression",
     Preview: "Preview",
+    PrimaryLost: "Primary Lost",
     PrimaryMonitoring: "Primary Monitoring",
     Priority: "Priority",
     Process: "Process",
@@ -441,6 +466,7 @@ define({root:
     RenderedSVG: "Rendered SVG",
     RenderSVG: "Render SVG",
     Replicate: "Replicate",
+    ReplicatedLost: "Replicated Lost",
     ReplicateOffset: "Replicate Offset",
     RepresentsASubset: "represent a subset of the total number of matches. Using a correct filter may reduce the number of matches.",
     RequestSchema: "Request Schema",
@@ -467,6 +493,7 @@ define({root:
     RowPath: "Row Path",
     RowTag: "Row Tag",
     RoxieCluster: "Roxie Cluster",
+    RunningServerStrain: "Running this process may take a long time and will put a heavy strain on the servers. Do you wish to continue?",
     Sample: "Sample",
     SampleRequest: "Sample Request",
     SampleResponse: "Sample Response",
@@ -485,6 +512,8 @@ define({root:
     ShowSVG: "Show SVG",
     Size: "Size",
     Skew: "Skew",
+    SkewNegative: "Skew(-)",
+    SkewPositive: "Skew(+)",
     SLA: "SLA",
     Slaves: "Slaves",
     SlaveLogs: "Slave Logs",
@@ -558,12 +587,15 @@ define({root:
     title_AvailableGroupPermissions: "Available Group Permissions",
     title_ClusterInfo: "Groups",
     title_CodeGeneratorPermissions: "Code Generator Permissions",
+    title_DirectoriesFor: "Directories for",
     title_DFUQuery: "Logical Files",
     title_DFUWUDetails: "DFU Workunit",
     title_DiskUsage: "Disk Usage",
     title_ECLPlayground: "ECL Playground",
+    title_ErrorsWarnings: "Errors/Warnings for",
     title_EventScheduleWorkunit: "Event Scheduler",
     title_FileScopeDefaultPermissions: "Default permissions of files",
+    title_FoundFilesFor: "Found files for",
     title_GetDFUWorkunits: "DFU Workunits",
     title_Graph: "Graph",
     title_GraphPage: "title",
@@ -581,7 +613,9 @@ define({root:
     title_LZBrowse: "Landing Zones",
     title_MemberOf: "Member Of",
     title_Members: "Members",
+    title_LostFilesFor: "Lost files for",
     title_LibrariesUsed: "Libraries Used",
+    title_OrphanFilesFor: "Orphan files for",
     title_Permissions: "Permissions",
     title_QuerySetDetails: "Query Details",
     title_QuerySetErrors: "Errors",
@@ -608,6 +642,7 @@ define({root:
     Top: "Top",
     Topology: "Topology",
     ToSizes: "To Sizes",
+    TotalParts: "Total Parts",
     TotalSize: "Total Size",
     TotalClusterTime: "Total Cluster Time",
     TransitionGuide: "Transition Guide",
@@ -648,6 +683,7 @@ define({root:
     ViewByScope: "View By Scope",
     Views: "Views",
     Visualize: "Visualize",
+    Warning: "Warning",
     Warnings: "Warning(s)",
     WarnOldGraphControl: "Warning:  Old Graph Control",
     What: "What",

+ 1 - 1
esp/src/eclwatch/templates/HPCCPlatformFilesWidget.html

@@ -10,7 +10,7 @@
             </div>
             <div id="${id}_Workunits" title="${i18n.Workunits}" data-dojo-props="delayWidget: 'GetDFUWorkunitsWidget'" data-dojo-type="DelayLoadWidget">
             </div>
-            <div id="${id}_XRef" title="${i18n.XRef}" style="padding: 0px; border:0px; border-color:none; overflow: hidden" data-dojo-type="dijit.layout.ContentPane">
+            <div id="${id}_Xref" title="${i18n.XRef}" data-dojo-props="delayWidget: 'XrefQueryWidget'" data-dojo-type="DelayLoadWidget">
             </div>
         </div>
     </div>

+ 52 - 0
esp/src/eclwatch/templates/XrefDetailsWidget.html

@@ -0,0 +1,52 @@
+<div class="${baseClass}">
+    <div id="${id}BorderContainer" class="${baseClass}BorderContainer" style="width: 100%; height: 100%;" data-dojo-type="dijit.layout.BorderContainer">
+        <div id="${id}TabContainer" data-dojo-props="region: 'center', tabPosition: 'top'" style="width: 100%; height: 100%" data-dojo-type="dijit.layout.TabContainer">
+            <div id="${id}_Summary" style="width: 100%; height: 100%" data-dojo-props="title:'${i18n.Summary}'" data-dojo-type="dijit.layout.BorderContainer">
+                <div id="${id}Toolbar" class="topPanel" data-dojo-props="region: 'top'" data-dojo-type="dijit.Toolbar">
+                    <div id="${id}Generate" data-dojo-attach-event="onClick:_onGenerate" data-dojo-type="dijit.form.Button">${i18n.Generate}</div>
+                    <div id="${id}CancelAll" data-dojo-attach-event="onClick:_onCancel" data-dojo-type="dijit.form.Button">${i18n.CancelAll}</div>
+                    <div id="${id}NewPage" class="right" data-dojo-attach-event="onClick:_onNewPage" data-dojo-props="iconClass:'iconNewPage', showLabel:false" data-dojo-type="dijit.form.Button">${i18n.OpenInNewPage}</div>
+                </div>
+                <div data-dojo-props="region: 'center'" data-dojo-type="dijit.layout.ContentPane">
+                    <h2>
+                        <img src="${dojoConfig.urlInfo.resourcePath}/img/cluster.png" />&nbsp;<span id="${id}Cluster" class="bold">${i18n.Cluster}</span>
+                    </h2>
+                    <form id="${id}SummaryForm">
+                        <ul>
+                            <li>
+                                <label class="Prompt" for="${id}LastRun">${i18n.LastRun}:</label>
+                                <div id="${id}LastRun"></div>
+                            </li>
+                            <li>
+                                <label class="Prompt" for="${id}LastMessage">${i18n.LastMessage}:</label>
+                                <div id="${id}LastMessage"></div>
+                            </li>
+                            <li>
+                                <label class="Prompt" for="${id}FoundFile">${i18n.FoundFile}:</label>
+                                <div id="${id}FoundFile">${i18n.FoundFileMessage}</div>
+                            </li>
+                            <li>
+                                <label class="Prompt" for="${id}OrphanFile">${i18n.OrphanFile2}:</label>
+                                <div id="${id}OrphanFile">${i18n.OrphanMessage}</div>
+                            </li>
+                            <li>
+                                <label class="Prompt" for="${id}LostFile">${i18n.LostFile}:</label>
+                                <div id="${id}LostFile">${i18n.LostFileMessage}</div>
+                            </li>
+                        </ul>
+                    </form>
+                </div>
+            </div>
+            <div id="${id}_FoundFiles" title="${i18n.FoundFile}" data-dojo-props="delayWidget: 'XrefFoundFilesWidget'" data-dojo-type="DelayLoadWidget">
+            </div>
+            <div id="${id}_OrphanFiles" title="${i18n.OrphanFile}" data-dojo-props="delayWidget: 'XrefOrphanFilesWidget'" data-dojo-type="DelayLoadWidget">
+            </div>
+            <div id="${id}_LostFiles" title="${i18n.LostFile}" data-dojo-props="delayWidget: 'XrefLostFilesWidget'" data-dojo-type="DelayLoadWidget">
+            </div>
+            <div id="${id}_Directories" title="${i18n.Directories}" data-dojo-props="delayWidget: 'XrefDirectoriesWidget'" data-dojo-type="DelayLoadWidget">
+            </div>
+            <div id="${id}_Errors" title="${i18n.ErrorWarnings}" data-dojo-props="delayWidget: 'XrefErrorsWarningsWidget'" data-dojo-type="DelayLoadWidget">
+            </div>
+        </div>
+    </div>
+</div>

+ 8 - 0
esp/src/eclwatch/templates/XrefQueryWidget.html

@@ -0,0 +1,8 @@
+<div class="${baseClass}">
+    <div id="${id}BorderContainer" class="${baseClass}BorderContainer" style="width: 100%; height: 100%" data-dojo-props="splitter: false" data-dojo-type="dijit.layout.BorderContainer">
+        <div id="${id}GridCP" style="padding: 0px; border:0px; border-color:none" data-dojo-props="region: 'center'" data-dojo-type="dijit.layout.ContentPane">
+            <div id="${id}Grid">
+            </div>
+        </div>
+    </div>
+</div>