瀏覽代碼

Merge pull request #5874 from wangkx/h11166

 HPCC-11166 Separate Validate Package page to two, etc

Reviewed-By: Anthony Fishbeck <anthony.fishbeck@lexisnexis.com>
Reviewed-By: Gordon Smith <gordon.smith@lexisnexis.com>
Reviewed-By: Richard Chapman <rchapman@hpccsystems.com>
Richard Chapman 11 年之前
父節點
當前提交
9c67629858

+ 4 - 1
esp/services/ws_packageprocess/ws_packageprocessService.cpp

@@ -350,7 +350,10 @@ void getPkgInfo(const char *target, const char *process, StringBuffer &info)
     Owned<IPropertyTree> tree = createPTree("PackageMaps");
     Owned<IPropertyTree> pkgSetRegistry = getPkgSetRegistry(process, true);
     if (!pkgSetRegistry)
-        throw MakeStringException(PKG_DALI_LOOKUP_ERROR, "Unable to retrieve package information from dali for process %s", (process && *process) ? process : "*");
+    {
+        toXML(tree, info);
+        return;
+    }
     StringBuffer xpath("PackageMap[@active='1']");
     if (target && *target)
         xpath.appendf("[@querySet='%s']", target);

+ 3 - 0
esp/src/eclwatch/ECLSourceWidget.js

@@ -85,6 +85,9 @@ define([
                     mode = "xml";
                 }
 
+                if (params.readOnly !== undefined)
+                    this.readOnly = params.readOnly;
+
                 this.editor = CodeMirror.fromTextArea(document.getElementById(this.id + "EclCode"), {
                     tabMode: "indent",
                     matchBrackets: true,

+ 35 - 10
esp/src/eclwatch/PackageMapQueryWidget.js

@@ -38,6 +38,7 @@ define([
     "dojo/data/ItemFileWriteStore",
 
     "hpcc/_TabContainerWidget",
+    "hpcc/DelayLoadWidget",
     "hpcc/PackageMapDetailsWidget",
     "hpcc/PackageMapValidateWidget",
     "hpcc/WsPackageMaps",
@@ -57,7 +58,7 @@ define([
 ], function (declare, lang, i18n, nlsHPCC, arrayUtil, dom, domConstruct, domForm, ObjectStore, on, topic,
     _LayoutWidget, _TemplatedMixin, _WidgetsInTemplateMixin, registry,
     Uploader, FileUploader, EnhancedGrid, Pagination, IndirectSelection, ItemFileWriteStore,
-    _TabContainerWidget, PackageMapDetailsWidget, PackageMapValidateWidget,
+    _TabContainerWidget, DelayLoadWidget, PackageMapDetailsWidget, PackageMapValidateWidget,
     WsPackageMaps, ESPPackageProcess, SFDetailsWidget,
     template) {
     return declare("PackageMapQueryWidget", [_TabContainerWidget, _LayoutWidget, _TemplatedMixin, _WidgetsInTemplateMixin], {
@@ -75,6 +76,8 @@ define([
         processFilters: null,
         addPackageMapDialog: null,
         validateTab: null,
+        validateTabInitialized: false,
+        params: null,
 
         buildRendering: function (args) {
             this.inherited(arguments);
@@ -133,6 +136,11 @@ define([
 
         _onChangeTarget: function (event) {
             this.updateProcessSelections(this.processSelect, this.processesToList, this.targetSelect.getValue());
+            this.refreshGrid();
+        },
+
+        _onChangeProcess: function (event) {
+            this.refreshGrid();
         },
 
         _onChangeAddProcessMapTarget: function (event) {
@@ -330,6 +338,7 @@ define([
                         context.processFilters = response.ProcessFilters.Item;
                     }
                     context.initPackagesGrid();
+                    context.initTabs();
                 },
                 error: function (errMsg, errStack) {
                     context.showErrors(errMsg, errStack);
@@ -397,17 +406,34 @@ define([
                 return;
 
             this.initalized = true;
+            this.params = params;
+            this.getSelections();
+        },
 
-            this.validateTab = new PackageMapValidateWidget({
-                id: this.id + "_ValidatePackageMap",
-                title: this.i18n.ValidatePackageMap,
-                params: params
-            });
-            //this.tabMap[this.id + "_ValidatePackageMap"] = this.validateTab;
-            this.tabContainer.addChild(this.validateTab, 1);
+        initTabs: function() {
+            this.params.targets = this.targets;
+            if (!this.validateTabInitialized) {
+                this.validateTabInitialized = true;
+                this.validateTab = this.initValidateTab("ValidatePackageMap", {
+                    title: "Validate Package Map",
+                    params: this.params
+                });
+            }
 
             this.tabContainer.selectChild(this.packagesTab);
-            this.getSelections();
+        },
+
+        initValidateTab: function (id, params) {
+            id = this.createChildTabID(id);
+            var retVal = new DelayLoadWidget({
+                id: id,
+                title: params.title,
+                closable: false,
+                delayWidget: "PackageMapValidateWidget",
+                params: params
+            });
+            this.tabContainer.addChild(retVal, 1);
+            return retVal;
         },
 
         initPackagesGrid: function() {
@@ -430,7 +456,6 @@ define([
             ]);
             var objStore = ESPPackageProcess.CreatePackageMapQueryObjectStore();
             this.packagesGrid.setStore(objStore);
-            this.packagesGrid.setQuery(this.getFilter());
 
             var context = this;
             this.packagesGrid.on("RowDblClick", function (evt) {

+ 240 - 0
esp/src/eclwatch/PackageMapValidateContentWidget.js

@@ -0,0 +1,240 @@
+/*##############################################################################
+#    HPCC SYSTEMS software Copyright (C) 2014 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/query",
+    "dojo/topic",
+    "dijit/registry",
+
+    "hpcc/_Widget",
+    "hpcc/ECLSourceWidget",
+    "hpcc/WsPackageMaps",
+
+    "dojo/text!../templates/PackageMapValidateContentWidget.html",
+
+    "dijit/layout/BorderContainer",
+    "dijit/layout/TabContainer",
+    "dijit/layout/ContentPane",
+    "dijit/form/Button"
+], function (declare, lang, i18n, nlsHPCC, dom, query, topic, registry,
+                _Widget, EclSourceWidget, WsPackageMaps,
+                template) {
+    return declare("PackageMapValidateContentWidget", [_Widget], {
+        templateString: template,
+        baseClass: "PackageMapValidateContentWidget",
+        i18n: nlsHPCC,
+
+        initalized: false,
+        targets: null,
+
+        targetSelectControl: null,
+        processSelectControl: null,
+        selectFileControl: null,
+        validateButton: null,
+        editorControl: null,
+        resultControl: null,
+
+        constructor: function() {
+            this.processes = new Array();
+        },
+
+        buildRendering: function (args) {
+            this.inherited(arguments);
+        },
+
+        startup: function (args) {
+            this.inherited(arguments);
+        },
+
+        resize: function (args) {
+            this.inherited(arguments);
+            this.borderContainer.resize();
+        },
+
+        layout: function (args) {
+            this.inherited(arguments);
+        },
+
+        getTitle: function () {
+            return this.i18n.ValidatePackageContent;
+        },
+
+        postCreate: function (args) {
+            this.inherited(arguments);
+            this.borderContainer = registry.byId(this.id + "BorderContainer");
+            this.targetSelectControl = registry.byId(this.id + "TargetSelect");
+            this.processSelectControl = registry.byId(this.id + "ProcessSelect");
+            this.validateButton = registry.byId(this.id + "ValidateBtn");
+        },
+
+        //  Init  ---
+        init: function (params) {
+            if (this.initalized)
+                return;
+
+            this.initalized = true;
+            if (params.targets !== undefined)
+                this.initSelections(params.targets);
+
+            this.editorControl = registry.byId(this.id + "Source");
+            this.editorControl.init(params);
+            this.editorControl.setText(this.i18n.LoadPackageContentHere);
+            this.initResultDisplay();
+
+            var context = this;
+            this.selectFileControl = document.getElementById(this.id + "SelectFile");
+            this.selectFileControl.addEventListener('change', function(event) {
+                var reader = new FileReader();
+                reader.onload = function(e){
+                    context.editorControl.setText(e.target.result);
+                };
+                reader.readAsText(event.target.files[0]);
+            }, false);
+        },
+
+        initSelections: function (targets) {
+            this.targets = targets;
+            if (this.targets.length > 0) {
+                var defaultTarget = 0;
+                for (var i = 0; i < this.targets.length; ++i) {
+                    if ((defaultTarget === 0) && (this.targets[i].Type === 'roxie'))
+                        defaultTarget = i; //first roxie
+                    this.targetSelectControl.options.push({label: this.targets[i].Name, value: this.targets[i].Name});
+                }
+                this.targetSelectControl.set("value", this.targets[defaultTarget].Name);
+                if (this.targets[defaultTarget].Processes !== undefined)
+                    this.updateProcessSelections(this.targets[defaultTarget], '');
+            }
+        },
+
+        updateProcessSelections: function (target, targetName) {
+            this.processSelectControl.removeOption(this.processSelectControl.getOptions());
+            if (target !== null)
+                this.addProcessSelections(target.Processes.Item);
+            else {
+                for (var i = 0; i < this.targets.length; ++i) {
+                    var target = this.targets[i];
+                    if ((target.Processes !== undefined) && (targetName === target.Name)) {
+                        this.addProcessSelections(target.Processes.Item);
+                        break;
+                    }
+                }
+            }
+            this.processSelectControl.options.push({label: this.i18n.ANY, value: 'ANY' });
+            this.processSelectControl.set("value", '');
+        },
+
+        addProcessSelections: function (processes) {
+            this.processes.length = 0;
+
+            if (processes.length < 1)
+                return;
+            for (var i = 0; i < processes.length; ++i) {
+                var process = processes[i];
+                if ((this.processes !== null) && (this.processes.indexOf(process) !== -1))
+                    continue;
+                this.processes.push(process);
+                this.processSelectControl.options.push({label: process, value: process});
+            }
+        },
+
+        initResultDisplay: function () {
+            this.resultControl = registry.byId(this.id + "Result");
+            this.resultControl.init({sourceMode: 'text/plain', readOnly: true});
+            this.resultControl.setText(this.i18n.ValidateResultHere);
+        },
+
+        //  action
+        _onChangeTarget: function (event) {
+            this.targetSelected  = this.targetSelectControl.getValue();
+            this.updateProcessSelections(null, this.targetSelected);
+        },
+
+        _onLoadBtnClicked: function (event) {
+            this.selectFileControl.click();
+        },
+
+        _onValidate: function (evt) {
+            var content = this.editorControl.getText();
+            if (content === '') {
+                alert(this.i18n.PackageContentNotSet);
+                return;
+            }
+            var request = { target: this.targetSelectControl.getValue() };
+            request['content'] = content;
+
+            var context = this;
+            this.resultControl.setText("");
+            this.validateButton.set("disabled", true);
+            WsPackageMaps.validatePackage(request, {
+                load: function (response) {
+                    var responseText = context.validateResponseToText(response);
+                    if (responseText === '')
+                        context.resultControl.setText(context.i18n.Empty);
+                    else {
+                        responseText = context.i18n.ValidateResult + responseText;
+                        context.resultControl.setText(responseText);
+                    }
+                    context.validateButton.set("disabled", false);
+                },
+                error: function (errMsg, errStack) {
+                    context.showErrors(errMsg, errStack);
+                    context.validateButton.set("disabled", false);
+                }
+            });
+        },
+
+        validateResponseToText: function (response) {
+            var text = "";
+            if (!lang.exists("Errors", response) || (response.Errors.length < 1))
+                text += this.i18n.NoErrorFound;
+            else
+                text = this.addArrayToText(this.i18n.Errors, response.Errors, text);
+            if (!lang.exists("Warnings", response) || (response.Warnings.length < 1))
+                text += this.i18n.NoWarningFound;
+            else
+                text = this.addArrayToText(this.i18n.Warnings, response.Warnings, text);
+
+            text += "\n";
+            text = this.addArrayToText(this.i18n.QueriesNoPackage, response.queries.Unmatched, text);
+            text = this.addArrayToText(this.i18n.PackagesNoQuery, response.packages.Unmatched, text);
+            text = this.addArrayToText(this.i18n.FilesNoPackage, response.files.Unmatched, text);
+            return text;
+        },
+
+        addArrayToText: function (arrayTitle, arrayItems, text) {
+            if ((arrayItems.Item !== undefined) && (arrayItems.Item.length > 0)) {
+                text += arrayTitle + ":\n";
+                for (i=0;i<arrayItems.Item.length;i++)
+                    text += "  " + arrayItems.Item[i] + "\n";
+                text += "\n";
+            }
+            return text;
+        },
+
+        showErrors: function (errMsg, errStack) {
+            topic.publish("hpcc/brToaster", {
+                Severity: "Error",
+                Source: errMsg,
+                Exceptions: [{ Message: errStack }]
+            });
+        }
+    });
+});

+ 148 - 98
esp/src/eclwatch/PackageMapValidateWidget.js

@@ -19,72 +19,82 @@ define([
     "dojo/i18n",
     "dojo/i18n!./nls/hpcc",
     "dojo/dom",
-    "dojo/dom-attr",
-    "dojo/dom-class",
+    "dojo/query",
     "dojo/topic",
-
-    "dijit/layout/_LayoutWidget",
-    "dijit/_TemplatedMixin",
-    "dijit/_WidgetsInTemplateMixin",
     "dijit/registry",
 
+    "hpcc/_Widget",
+    "hpcc/_TabContainerWidget",
+    "hpcc/DelayLoadWidget",
+    "hpcc/ECLSourceWidget",
     "hpcc/WsPackageMaps",
 
     "dojo/text!../templates/PackageMapValidateWidget.html",
 
-    "dijit/form/Form",
-    "dijit/form/Button",
-    "dijit/form/RadioButton",
-    "dijit/form/Select",
-    "dijit/form/SimpleTextarea"
-], function (declare, lang, i18n, nlsHPCC, dom, domAttr, domClass, topic,
-    _LayoutWidget, _TemplatedMixin, _WidgetsInTemplateMixin, registry,
-    WsPackageMaps, template) {
-    return declare("PackageMapValidateWidget", [_LayoutWidget, _TemplatedMixin, _WidgetsInTemplateMixin], {
+    "dijit/layout/BorderContainer",
+    "dijit/layout/TabContainer",
+    "dijit/layout/ContentPane",
+    "dijit/form/Button"
+], function (declare, lang, i18n, nlsHPCC, dom, query, topic, registry,
+                _Widget, _TabContainerWidget, DelayLoadWidget, EclSourceWidget, WsPackageMaps,
+                template) {
+    return declare("PackageMapValidateWidget", [_TabContainerWidget], {
         templateString: template,
         baseClass: "PackageMapValidateWidget",
         i18n: nlsHPCC,
-        validateForm: null,
-        targetSelect: null,
-        packageContent: null,
-        validateResult: null,
-        validateButton: null,
-        targets: null,
-        processes: new Array(),
+
         initalized: false,
+        targets: null,
 
-        buildRendering: function (args) {
-            this.inherited(arguments);
+        targetSelectControl: null,
+        processSelectControl: null,
+        validateButton: null,
+        editorControl: null,
+        resultControl: null,
+
+        validatePackageMapContentWidget: null,
+        validatePackageMapContentWidgetLoaded: false,
+
+        constructor: function() {
+            this.processes = new Array();
         },
 
-        postCreate: function (args) {
+        buildRendering: function (args) {
             this.inherited(arguments);
-            this.validateForm = registry.byId(this.id + "ValidatePM");
-            this.targetSelect = registry.byId(this.id + "TargetSelect");
-            this.processSelect = registry.byId(this.id + "ProcessSelect");
-            this.packageContent = registry.byId(this.id + "Package");
-            this.validateButton = registry.byId(this.id + "Validate");
-            this.validateResult = registry.byId(this.id + "ValidateResult");
         },
 
         startup: function (args) {
             this.inherited(arguments);
         },
 
-        resize: function (args) {
+        destroy: function (args) {
             this.inherited(arguments);
         },
 
-        layout: function (args) {
+        getTitle: function () {
+            return this.i18n.ValidateActivePackageMap;
+        },
+
+        postCreate: function (args) {
             this.inherited(arguments);
+            this.targetSelectControl = registry.byId(this.id + "TargetSelect");
+            this.processSelectControl = registry.byId(this.id + "ProcessSelect");
+            this.validateButton = registry.byId(this.id + "ValidateBtn");
+            this.validatePackageMapContentWidget = registry.byId(this.id + "_ValidatePackageMapContent");
         },
 
-        init: function (params, targets) {
+        //  init this page
+        init: function (params) {
             if (this.initalized)
                 return;
+
             this.initalized = true;
-            this.validateResult.set('style', 'visibility:hidden');
-            this.initSelections(targets);
+            if (params.params.targets !== undefined)
+                this.initSelections(params.params.targets);
+
+            this.editorControl = registry.byId(this.id + "Source");
+            this.editorControl.init(params);
+            this.initResultDisplay();
         },
 
         initSelections: function (targets) {
@@ -92,98 +102,110 @@ define([
             if (this.targets.length > 0) {
                 var defaultTarget = 0;
                 for (var i = 0; i < this.targets.length; ++i) {
-                    if ((defaultTarget == 0) && (this.targets[i].Type == 'roxie'))
+                    if ((defaultTarget === 0) && (this.targets[i].Type === 'roxie'))
                         defaultTarget = i; //first roxie
-                    this.targetSelect.options.push({label: this.targets[i].Name, value: this.targets[i].Name});
+                    this.targetSelectControl.options.push({label: this.targets[i].Name, value: this.targets[i].Name});
+                }
+                this.targetSelectControl.set("value", this.targets[defaultTarget].Name);
+                if (this.targets[defaultTarget].Processes !== undefined)
+                    this.updateProcessSelections(this.targets[defaultTarget], '');
+            }
+        },
+
+        updateProcessSelections: function (target, targetName) {
+            this.processSelectControl.removeOption(this.processSelectControl.getOptions());
+            if (target !== null)
+                this.addProcessSelections(target.Processes.Item);
+            else {
+                for (var i = 0; i < this.targets.length; ++i) {
+                    var target = this.targets[i];
+                    if ((target.Processes !== undefined) && (targetName === target.Name)) {
+                        this.addProcessSelections(target.Processes.Item);
+                        break;
+                    }
                 }
-                this.targetSelect.set("value", this.targets[defaultTarget].Name);
-                if (this.targets[defaultTarget].Processes != undefined)
-                    this.updateProcessSelections(this.targets[defaultTarget].Name);
             }
+            this.processSelectControl.options.push({label: this.i18n.ANY, value: 'ANY' });
+            this.processSelectControl.set("value", '');
         },
 
         addProcessSelections: function (processes) {
+            this.processes.length = 0;
             for (var i = 0; i < processes.length; ++i) {
                 var process = processes[i];
-                if ((this.processes != null) && (this.processes.indexOf(process) != -1))
+                if ((this.processes !== null) && (this.processes.indexOf(process) !== -1))
                     continue;
                 this.processes.push(process);
-                this.processSelect.options.push({label: process, value: process});
+                this.processSelectControl.options.push({label: process, value: process});
             }
         },
 
-        updateProcessSelections: function (targetName) {
-            this.processSelect.removeOption(this.processSelect.getOptions());
-            for (var i = 0; i < this.targets.length; ++i) {
-                var target = this.targets[i];
-                if ((target.Processes != undefined) && ((targetName == '') || (targetName == target.Name)))
-                    this.addProcessSelections(target.Processes.Item);
-            }
-            this.processSelect.options.push({label: this.i18n.ANY, value: 'ANY' });
-            this.processSelect.set("value", '');
+        initResultDisplay: function () {
+            this.resultControl = registry.byId(this.id + "Result");
+            this.resultControl.init({sourceMode: 'text/plain', readOnly: true});
+            this.resultControl.setText(this.i18n.ValidateResultHere);
         },
 
-        addArrayToText: function (arrayTitle, arrayItems, text) {
-            if ((arrayItems.Item != undefined) && (arrayItems.Item.length > 0)) {
-                text += arrayTitle + ":\n";
-                for (i=0;i<arrayItems.Item.length;i++)
-                    text += "  " + arrayItems.Item[i] + "\n";
-                text += "\n";
+        //  init tab
+        initTab: function () {
+            var currSel = this.getSelectedChild();
+            if (!this.validatePackageMapContentWidgetLoaded && (currSel.id === this.validatePackageMapContentWidget.id)) {
+                this.validatePackageMapContentWidgetLoaded = true;
+                this.validatePackageMapContentWidget.init({
+                    targets: this.targets
+                });
             }
-            return text;
         },
 
-        validateResponseToText: function (response) {
-            var text = "";
-            if (!lang.exists("Errors", response) || (response.Errors.length < 1))
-                text += this.i18n.NoErrorFound;
-            else
-                text = this.addArrayToText(this.i18n.Errors, response.Errors, text);
-            if (!lang.exists("Warnings", response) || (response.Warnings.length < 1))
-                text += this.i18n.Warnings;
-            else
-                text = this.addArrayToText(this.i18n.Warnings, response.Warnings, text);
-
-            text += "\n";
-            text = this.addArrayToText(this.i18n.QueriesNoPackage, response.queries.Unmatched, text);
-            text = this.addArrayToText(this.i18n.PackagesNoQuery, response.packages.Unmatched, text);
-            text = this.addArrayToText(this.i18n.FilesNoPackage, response.files.Unmatched, text);
-            return text;
+        //  action
+        _onChangeTarget: function (event) {
+            this.targetSelected  = this.targetSelectControl.getValue();
+            this.updateProcessSelections(null, this.targetSelected);
         },
 
-        _onChangeTarget: function (event) {
-            this.processes.length = 0;
-            this.targetSelected  = this.targetSelect.getValue();
-            this.updateProcessSelections(this.targetSelected);
-        },
-
-        _onValidate: function (event) {
-            var request = { target: this.targetSelect.getValue() };
-            var type = this.validateForm.attr('value').ValidateType;
-            if (type == 'ActivePM') {
-                request['active'] = true;
-                request['process'] = this.processSelect.getValue();
-            } else {
-                var content = this.packageContent.getValue();
-                if (content == '') {
-                    alert(this.i18n.PackageContentNotSet);
-                    return;
+        _onChangeProcess: function (event) {
+            var process = this.processSelectControl.getValue();
+            if (process === 'ANY')
+                process = '*';
+
+            var context = this;
+            this.editorControl.setText('');
+            WsPackageMaps.getPackage({
+                    target: this.targetSelectControl.getValue(),
+                    process: process
+                }, {
+                load: function (content) {
+                    if (content !== '') {
+                        context.editorControl.setText(content);;
+                    }
+                },
+                error: function (errMsg, errStack) {
+                    context.showErrors(errMsg, errStack);
                 }
-                request['content'] = content;
+            });
+        },
+
+        _onValidate: function (evt) {
+            var content = this.editorControl.getText();
+            if (content === '') {
+                alert(this.i18n.PackageContentNotSet);
+                return;
             }
+            var request = { target: this.targetSelectControl.getValue() };
+            request['content'] = content;
+
             var context = this;
-            this.validateResult.setValue("");
+            this.resultControl.setText("");
             this.validateButton.set("disabled", true);
             WsPackageMaps.validatePackage(request, {
                 load: function (response) {
                     var responseText = context.validateResponseToText(response);
-                    if (responseText == '')
-                        context.validateResult.setValue(context.i18n.Empty);
+                    if (responseText === '')
+                        context.resultControl.setText(context.i18n.Empty);
                     else {
                         responseText = context.i18n.ValidateResult + responseText;
-                        context.validateResult.setValue(responseText);
+                        context.resultControl.setText(responseText);
                     }
-                    context.validateResult.set('style', 'visibility:visible');
                     context.validateButton.set("disabled", false);
                 },
                 error: function (errMsg, errStack) {
@@ -193,6 +215,34 @@ define([
             });
         },
 
+        validateResponseToText: function (response) {
+            var text = "";
+            if (!lang.exists("Errors", response) || (response.Errors.length < 1))
+                text += this.i18n.NoErrorFound;
+            else
+                text = this.addArrayToText(this.i18n.Errors, response.Errors, text);
+            if (!lang.exists("Warnings", response) || (response.Warnings.length < 1))
+                text += this.i18n.NoWarningFound;
+            else
+                text = this.addArrayToText(this.i18n.Warnings, response.Warnings, text);
+
+            text += "\n";
+            text = this.addArrayToText(this.i18n.QueriesNoPackage, response.queries.Unmatched, text);
+            text = this.addArrayToText(this.i18n.PackagesNoQuery, response.packages.Unmatched, text);
+            text = this.addArrayToText(this.i18n.FilesNoPackage, response.files.Unmatched, text);
+            return text;
+        },
+
+        addArrayToText: function (arrayTitle, arrayItems, text) {
+            if ((arrayItems.Item !== undefined) && (arrayItems.Item.length > 0)) {
+                text += arrayTitle + ":\n";
+                for (var i=0;i<arrayItems.Item.length;i++)
+                    text += "  " + arrayItems.Item[i] + "\n";
+                text += "\n";
+            }
+            return text;
+        },
+
         showErrors: function (errMsg, errStack) {
             topic.publish("hpcc/brToaster", {
                 Severity: "Error",

+ 26 - 0
esp/src/eclwatch/WsPackageMaps.js

@@ -58,6 +58,32 @@ define([
             return false;
         },
 
+        getPackage: function (params, callback) {
+            var request = {
+                Target: params.target,
+                Process: params.process
+            };
+
+            var context = this;
+            return ESPRequest.send("WsPackageProcess", "GetPackage", {
+                request: request,
+                load: function (response) {
+                    if (context.checkExceptions(callback, response) &&
+                        context.checkStatus(callback, lang.exists("GetPackageResponse.status", response),
+                        response.GetPackageResponse.status))
+                    {
+                        if (!lang.exists("GetPackageResponse.Info", response))
+                            callback.load(i18n.NoContent);
+                        else
+                            callback.load(response.GetPackageResponse.Info);
+                    }
+                },
+                error: function (err) {
+                    context.errorMessageCallback(callback, err.message, err.stack);
+                }
+            });
+        },
+
         getPackageMapById: function (params, callback) {
             var request = {
                 PackageMapId: params.packageMap

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

@@ -202,6 +202,8 @@ define({root:
     Line: "Line",
     LineTerminators: "Line Terminators",
     Links: "Links",
+    LoadPackageContentHere: "(Load package content here)",
+    LoadPackageFromFile: "Load Package from a file",
     Loading: "Loading...",
     LoadingCachedLayout: "Loading Cached Layout...",
     LoadingData: "Loading Data...",
@@ -491,8 +493,11 @@ define({root:
     Users: "Users",
     UseSingleConnection: "Use Single Connection",
     Validate: "Validate",
+    ValidateActivePackageMap: "Validate Active Package Map",
+    ValidatePackageContent: "Validate Package Content",
     ValidatePackageMap: "Validate Package Map",
     ValidateResult: "=====Validate Result=====\n\n",
+    ValidateResultHere: "(Validation result)",
     Value: "Value",
     Variable: "Variable",
     Variables: "Variables",

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

@@ -8,7 +8,7 @@
                     </div>
                     <span data-dojo-type="dijit.ToolbarSeparator"></span>
                     <b>${i18n.Process}:</b>
-                    <div id="${id}ProcessSelect" name="ProcessSelect" style="width: 8em;" data-dojo-type="dijit.form.Select">
+                    <div id="${id}ProcessSelect" name="ProcessSelect" style="width: 8em;" data-dojo-attach-event="onChange:_onChangeProcess" data-dojo-type="dijit.form.Select">
                     </div>
                     <span data-dojo-type="dijit.ToolbarSeparator"></span>
                     <!--b>Process Filter:</b>

+ 21 - 0
esp/src/eclwatch/templates/PackageMapValidateContentWidget.html

@@ -0,0 +1,21 @@
+<div class="${baseClass}">
+    <div id="${id}BorderContainer" class="${baseClass}BorderContainer" style="width: 100%; height: 100%" data-dojo-type="dijit.layout.BorderContainer">
+        <div id="${id}SubmitPane" class="topPanel" data-dojo-props="region: 'top'" data-dojo-type="dijit.layout.ContentPane">
+            <div style="display: inline-block; vertical-align: middle">
+                <label for="${id}TargetSelect">${i18n.Target}</label>
+                <div id="${id}TargetSelect" name="TargetSelect" style="width: 8em;" data-dojo-attach-event="onChange:_onChangeTarget" data-dojo-type="dijit.form.Select">
+                </div>
+                <label for="${id}ProcessSelect">${i18n.Process}</label>
+                <div id="${id}ProcessSelect" name="ProcessSelect" style="width: 8em;" data-dojo-type="dijit.form.Select">
+                </div>
+                <button id="${id}LoadBtn" data-dojo-attach-event="onClick:_onLoadBtnClicked" data-dojo-type="dijit.form.Button">${i18n.LoadPackageFromFile}</button>
+                <button id="${id}ValidateBtn" data-dojo-attach-event="onClick:_onValidate" data-dojo-type="dijit.form.Button">${i18n.Validate}</button>
+                <div style='height: 0px;width:0px; overflow:hidden;'><input id="${id}SelectFile" type="file"/></div>
+            </div>
+        </div>
+        <div id="${id}Source" class="centerPanel" data-dojo-props="region: 'center'" data-dojo-type="ECLSourceWidget">
+        </div>
+        <div id="${id}Result" title="${i18n.Results}" style="width: 480px;" data-dojo-props="minSize:120, region: 'right', splitter:true" data-dojo-type="ECLSourceWidget">
+        </div>
+    </div>
+</div>

+ 21 - 41
esp/src/eclwatch/templates/PackageMapValidateWidget.html

@@ -1,45 +1,25 @@
 <div class="${baseClass}">
-    <div id="${id}ValidatePM" data-dojo-id="${id}ValidatePM" data-dojo-type="dijit.form.Form" encType="multipart/form-data" action="" method="">
-        <table id="${id}ValidatePMTable">
-            <tr>
-                <td width="140px"><b>${i18n.Target}:</b></td>
-                <td>
-                    <div id="${id}TargetSelect" name="TargetSelect" style="width: 8em;" data-dojo-attach-event="onChange:_onChangeTarget" data-dojo-type="dijit.form.Select">
+    <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}_ValidateActivePackageMap" style="width: 100%; height: 100%" data-dojo-props="title:'${i18n.ValidateActivePackageMap}'" data-dojo-type="dijit.layout.BorderContainer">
+                <div id="${id}SubmitPane" class="topPanel" data-dojo-props="region: 'top'" data-dojo-type="dijit.layout.ContentPane">
+                    <div style="display: inline-block; vertical-align: middle">
+                        <label for="${id}TargetSelect">${i18n.Target}</label>
+                        <div id="${id}TargetSelect" name="TargetSelect" style="width: 8em;" data-dojo-attach-event="onChange:_onChangeTarget" data-dojo-type="dijit.form.Select">
+                        </div>
+                        <label for="${id}ProcessSelect">${i18n.Process}</label>
+                        <div id="${id}ProcessSelect" name="ProcessSelect" style="width: 8em;" data-dojo-attach-event="onChange:_onChangeProcess" data-dojo-type="dijit.form.Select">
+                        </div>
+                        <button id="${id}ValidateBtn" data-dojo-attach-event="onClick:_onValidate" data-dojo-type="dijit.form.Button">${i18n.Validate}</button>
                     </div>
-                </td>
-            </tr>
-            <tr>
-                <td width="140px"><b>${i18n.Process}:</b></td>
-                <td>
-                    <div id="${id}ProcessSelect" name="ProcessSelect" style="width: 8em;" data-dojo-type="dijit.form.Select">
-                    </div>
-                </td>
-            </tr>
-            <tr>
-                <td><b>${i18n.Validate}:</b></td>
-                <td>
-                    <input name="ValidateType" id="ActivePM"  value="ActivePM" type="radio" data-dojo-type="dijit.form.RadioButton" checked/>${i18n.ActivePackageMap}
-                    <input name="ValidateType" id="PMContent"  value="PMContent"type="radio" data-dojo-type="dijit.form.RadioButton"/>${i18n.PackageContent}
-                </td>
-            </tr>
-            <tr>
-                <td valign='top'><b>${i18n.PackageContent}:</b></td>
-                <td>
-                    <textarea id="${id}Package" name="${id}Package" data-dojo-type="dijit.form.SimpleTextarea" rows="15" cols="80" style="width:100%;height:80%;"></textarea>
-                </td>
-            </tr>
-            <tr>
-                <td/>
-                <td>
-                    <div id="${id}Validate" data-dojo-attach-event="onClick:_onValidate" data-dojo-type="dijit.form.Button">${i18n.Validate}</div>
-                </td>
-            </tr>
-            <tr>
-                <td/>
-                <td>
-                    <textarea id="${id}ValidateResult" data-dojo-type="dijit.form.SimpleTextarea" rows="15" cols="100"></textarea>
-                </td>
-            </tr>
-        </table>
+                </div>
+                <div id="${id}Source" class="centerPanel" data-dojo-props="region: 'center'" data-dojo-type="ECLSourceWidget">
+                </div>
+                <div id="${id}Result" title="${i18n.Results}" style="width: 480px;" data-dojo-props="minSize:120, region: 'right', splitter:true" data-dojo-type="ECLSourceWidget">
+                </div>
+            </div>
+            <div id="${id}_ValidatePackageMapContent" title="${i18n.ValidatePackageContent}" data-dojo-props="delayWidget: 'PackageMapValidateContentWidget'" data-dojo-type="DelayLoadWidget">
+            </div>
+        </div>
     </div>
 </div>