From c39243c66d5e20f08828770862576db1c0ceb9ab Mon Sep 17 00:00:00 2001
From: David E Jones
Date: Thu, 2 Feb 2023 16:10:20 -0800
Subject: [PATCH 01/25] On Login screen fix auto-focus of username field on
login tab by moving to trigger on tab set/change allowing auto focus on other
tabs, also if there is a username and 2nd factor required then auto focus on
that to save a click in that flow on login and change tabs
---
.../webroot/screen/webroot/Login.ftl | 41 ++++++++++++-------
1 file changed, 26 insertions(+), 15 deletions(-)
diff --git a/base-component/webroot/screen/webroot/Login.ftl b/base-component/webroot/screen/webroot/Login.ftl
index 7dcb811f0..43444317a 100644
--- a/base-component/webroot/screen/webroot/Login.ftl
+++ b/base-component/webroot/screen/webroot/Login.ftl
@@ -39,15 +39,15 @@
<#-- people know what to do
${ec.l10n.localize("Enter your username and password to sign in")}
-->
<#-- not needed for this request: -->
- disabled="disabled"#if>
- required="required" class="form-control top" id="login_form_username"
+ required="required" class="form-control top"
placeholder="${ec.l10n.localize("Username")}" aria-label="${ec.l10n.localize("Username")}">
<#-- secondFactorRequired will only be set if a user is pre-authenticated, and in that case password not required again -->
<#if secondFactorRequired>
-
+
<#else>
@@ -56,16 +56,16 @@
<#if expiredCredentials>
WARNING: Your password has expired
#if>
<#if passwordChangeRequired>
WARNING: Password change required
#if>
-
@@ -74,18 +74,19 @@
${ec.l10n.localize("Enter details to change your password")}
- disabled="disabled"#if>
+ required="required" class="form-control top"
placeholder="${ec.l10n.localize("Username")}" aria-label="${ec.l10n.localize("Username")}">
<#-- secondFactorRequired will only be set if a user is pre-authenticated, and in that case password not required again -->
<#if secondFactorRequired>
-
+
<#else>
+ placeholder="${ec.l10n.localize("Old Password")}" aria-label="${ec.l10n.localize("Old Password")}">
#if>
<#-- FUTURE: fancy JS to validate PW as it is entered or on blur -->
+ if (tabName === "login") { $("#login_form_code").focus(); }
+ else if (tabName === "change") { $("#change_form_code").focus(); }
+ else if (tabName === "reset") { $("#reset_form_username").focus(); }
+ <#else>
+ if (tabName === "login") { $("#login_form_username").focus(); }
+ else if (tabName === "change") { $("#change_form_username").focus(); }
+ else if (tabName === "reset") { $("#reset_form_username").focus(); }
+ #if>
});
$('a[href="' + (location.hash || '${initialTab!"#login"}') + '"]').tab('show');
})
From 8363a40eb777b956712bd78276a6f10ff87a087c Mon Sep 17 00:00:00 2001
From: David E Jones
Date: Fri, 3 Feb 2023 15:37:06 -0800
Subject: [PATCH 02/25] Add m-mermaid vue component for qvt render mode, use on
new StatusFlows screen in the tools app; the results when status items are
sorted in Mermaid JS are pretty good, might even be end-user useful but at
least here useful for devs
---
.../tools/screen/Tools/StatusFlows.xml | 96 +++++++++++++++++++
.../tools/screen/Tools/dashboard.xml | 5 +
.../screen/webroot/js/WebrootVue.qvt.js | 14 +++
3 files changed, 115 insertions(+)
create mode 100644 base-component/tools/screen/Tools/StatusFlows.xml
diff --git a/base-component/tools/screen/Tools/StatusFlows.xml b/base-component/tools/screen/Tools/StatusFlows.xml
new file mode 100644
index 000000000..6e5ddd108
--- /dev/null
+++ b/base-component/tools/screen/Tools/StatusFlows.xml
@@ -0,0 +1,96 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ${mermaidText}]]>
+ Only supported in the 'qvt' render mode, go to the same URL under /qapps (instead of /apps or /vapps)
',
+ mounted: function() {
+ var vm = this;
+ moqui.loadScript('https://cdnjs.cloudflare.com/ajax/libs/mermaid/9.3.0/mermaid.min.js', function(err) {
+ if (err) return;
+ mermaid.init(vm.config, vm.$refs.mermaid);
+ }, function() { return !!window.mermaid; });
+ }
+});
/* Lazy loading CK Editor wrapper component, based on https://github.com/ckeditor/ckeditor4-vue */
/* see https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_config.html */
Vue.component('m-ck-editor', {
From 417d16043e527a4c51bb1fbaea7fa5a2448ec041 Mon Sep 17 00:00:00 2001
From: David E Jones
Date: Fri, 3 Feb 2023 16:59:05 -0800
Subject: [PATCH 03/25] On StatusFlows screen add dialog with Mermaid JS text
to make it easier to grab for customization and use elsewhere like in docs
---
base-component/tools/screen/Tools/StatusFlows.xml | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/base-component/tools/screen/Tools/StatusFlows.xml b/base-component/tools/screen/Tools/StatusFlows.xml
index 6e5ddd108..311b60d81 100644
--- a/base-component/tools/screen/Tools/StatusFlows.xml
+++ b/base-component/tools/screen/Tools/StatusFlows.xml
@@ -66,8 +66,11 @@ along with this software (see the LICENSE.md file). If not, see
-
+
+
+
+ ${mermaidText}]]>Only supported in the 'qvt' render mode, go to the same URL under /qapps (instead of /apps or /vapps)]]>
From 88c21daef1ac29b42665128c36660ed0a0afb29a Mon Sep 17 00:00:00 2001
From: David E Jones
Date: Sat, 4 Feb 2023 04:47:49 -0800
Subject: [PATCH 04/25] Add ServiceLoadRunner screen, a qvue screen (/qapps
only) for managing the new Service LoadRunner and viewing results in real-ish
time
---
.../Tools/Service/ServiceLoadRunner.xml | 219 ++++++++++++++++++
.../tools/screen/Tools/dashboard.xml | 1 +
2 files changed, 220 insertions(+)
create mode 100644 base-component/tools/screen/Tools/Service/ServiceLoadRunner.xml
diff --git a/base-component/tools/screen/Tools/Service/ServiceLoadRunner.xml b/base-component/tools/screen/Tools/Service/ServiceLoadRunner.xml
new file mode 100644
index 000000000..5cd8527ea
--- /dev/null
+++ b/base-component/tools/screen/Tools/Service/ServiceLoadRunner.xml
@@ -0,0 +1,219 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
All delay, run, etc times in milliseconds (ms)
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Exec Index {{executorInfo.execIndex}}
+
Total Threads {{executorInfo.totalThreads}}
+
+
+
+
+
Service & Parameters
+
Target
+
Current
+
Run Delay
+
Ramp Delay
+
Run Count
+
Error Count
+
Time Average
+
Time Std Dev
+
Runs/Sec Avg
+
Runs/Sec Time
+
Busy Pct
+
Last Run
+
+
+
+
+
+
{{serviceInfo.serviceName}}
+
{{serviceInfo.parametersExpr}}
+
+
{{serviceInfo.targetThreads}}
+
{{serviceInfo.currentThreads}}
+
{{serviceInfo.runDelayMs}}
+
{{serviceInfo.rampDelayMs}}
+
{{serviceInfo.runCount}}
+
{{serviceInfo.errorCount}}
+
{{serviceInfo.timeAverage}}
+
{{serviceInfo.timeStdDev}}
+
{{serviceInfo.runsPerSecAvg}}
+
{{serviceInfo.runsPerSecTime}}
+
{{serviceInfo.busyPercent}}
+
{{serviceInfo.lastRunTimeStr}}
+
+
+
+
+
{{JSON.stringify(serviceInfo.lastResult)}}
+
+
+
+
+ ]]>Only supported in the 'qvt' render mode, go to the same URL under /qapps (instead of /apps or /vapps)
+ ]]>
+
+
diff --git a/base-component/tools/screen/Tools/dashboard.xml b/base-component/tools/screen/Tools/dashboard.xml
index 17b6a4f55..944e31c3b 100644
--- a/base-component/tools/screen/Tools/dashboard.xml
+++ b/base-component/tools/screen/Tools/dashboard.xml
@@ -31,6 +31,7 @@ along with this software (see the LICENSE.md file). If not, see
+
From a9b1fd32e6220cf72ec1123b68237ece76c4dc02 Mon Sep 17 00:00:00 2001
From: David E Jones
Date: Sat, 4 Feb 2023 13:31:27 -0800
Subject: [PATCH 05/25] On ServiceLoadRunner screen add stats for specific
artifact types, some number formatting improvements more needed
---
.../Tools/Service/ServiceLoadRunner.xml | 88 +++++++++++++++++--
.../webroot/screen/webroot/js/MoquiLib.js | 1 +
2 files changed, 80 insertions(+), 9 deletions(-)
diff --git a/base-component/tools/screen/Tools/Service/ServiceLoadRunner.xml b/base-component/tools/screen/Tools/Service/ServiceLoadRunner.xml
index 5cd8527ea..046fb714c 100644
--- a/base-component/tools/screen/Tools/Service/ServiceLoadRunner.xml
+++ b/base-component/tools/screen/Tools/Service/ServiceLoadRunner.xml
@@ -37,12 +37,13 @@ along with this software (see the LICENSE.md file). If not, see
lastResult:serviceInfo.lastResult, beginTime:serviceInfo.beginTime,
lastRunTime:serviceInfo.lastRunTime, lastRunTimeStr:(new Timestamp(serviceInfo.lastRunTime).toString()),
totalTime:serviceInfo.totalTime, totalSquaredTime:serviceInfo.totalSquaredTime,
+ minTime:serviceInfo.minTime, maxTime:serviceInfo.maxTime,
timeAverage:(serviceInfo.runCount ? serviceInfo.totalTime / serviceInfo.runCount : 0),
timeStdDev:(serviceInfo.totalSquaredTime && serviceInfo.runCount > 1 ?
Math.sqrt((serviceInfo.totalSquaredTime - ((serviceInfo.totalTime*serviceInfo.totalTime) / serviceInfo.runCount)).abs() / (serviceInfo.runCount - 1)) : null),
- runsPerSecAvg:runsPerSecAvg,
- runsPerSecTime:runsPerSecTime,
- busyPercent:(runsPerSecAvg ? 100*runsPerSecTime/runsPerSecAvg : 0)
+ runsPerSecAvg:runsPerSecAvg, runsPerSecTime:runsPerSecTime,
+ busyPercent:(runsPerSecAvg ? 100*runsPerSecTime/runsPerSecAvg : 0),
+ typeStats:objectToMap(serviceInfo.artifactTypeStats)
])
}
@@ -76,7 +77,7 @@ along with this software (see the LICENSE.md file). If not, see
-
All delay, run, etc times in milliseconds (ms)
+
All delay, run, etc times are in milliseconds (ms), rates in runs per second
@@ -96,7 +97,7 @@ along with this software (see the LICENSE.md file). If not, see
-
+
@@ -114,7 +115,9 @@ along with this software (see the LICENSE.md file). If not, see
Run Count
Error Count
Time Average
-
Time Std Dev
+
Std Dev
+
Min
+
Max
Runs/Sec Avg
Runs/Sec Time
Busy Pct
@@ -135,6 +138,8 @@ along with this software (see the LICENSE.md file). If not, see
{{serviceInfo.errorCount}}
{{serviceInfo.timeAverage}}
{{serviceInfo.timeStdDev}}
+
{{serviceInfo.minTime}}
+
{{serviceInfo.maxTime}}
{{serviceInfo.runsPerSecAvg}}
{{serviceInfo.runsPerSecTime}}
{{serviceInfo.busyPercent}}
@@ -142,11 +147,71 @@ along with this software (see the LICENSE.md file). If not, see
+
+ (runDelayMs as Integer) ?: 100, (rampDelayMs as Integer) ?: 500,
+ (timeBinLength as Integer) ?: 2000, (timeBinsKeep as Integer) ?: 20)
@@ -77,6 +82,8 @@ along with this software (see the LICENSE.md file). If not, see
+
All delay, run, etc times are in milliseconds (ms), rates in runs per second
-
+
-
+
-
+
+
+
+
+
@@ -103,6 +116,9 @@ along with this software (see the LICENSE.md file). If not, see
Exec Index {{executorInfo.execIndex}}
Total Threads {{executorInfo.totalThreads}}
+
Terminating {{executorInfo.terminating}}
+
Terminated {{executorInfo.terminated}}
+
Shutdown {{executorInfo.shutdown}}
@@ -112,6 +128,8 @@ along with this software (see the LICENSE.md file). If not, see
Current
Run Delay
Ramp Delay
+
Bin Length
+
Bins Keep
Run Count
Error Count
Time Average
@@ -134,6 +152,8 @@ along with this software (see the LICENSE.md file). If not, see
{{serviceInfo.currentThreads}}
{{serviceInfo.runDelayMs}}
{{serviceInfo.rampDelayMs}}
+
{{serviceInfo.timeBinLength}}
+
{{serviceInfo.timeBinsKeep}}
{{serviceInfo.runCount}}
{{serviceInfo.errorCount}}
{{serviceInfo.timeAverage}}
@@ -209,16 +229,27 @@ along with this software (see the LICENSE.md file). If not, see
+
+
From 75b80f8b7e6a885444bef6d8d94f1dee0715cfcc Mon Sep 17 00:00:00 2001
From: David E Jones
Date: Sun, 5 Feb 2023 17:29:35 -0800
Subject: [PATCH 11/25] Add link to Service LoadRunner on Tools Dashboard, and
on that screen check new permission, support run delay vary, add Average Run
Time chart (should have been the first, is the most basic), other small
changes
---
.../Tools/Service/ServiceLoadRunner.xml | 77 +++++++++++++------
.../tools/screen/Tools/dashboard.xml | 2 +-
2 files changed, 53 insertions(+), 26 deletions(-)
diff --git a/base-component/tools/screen/Tools/Service/ServiceLoadRunner.xml b/base-component/tools/screen/Tools/Service/ServiceLoadRunner.xml
index 4145dc908..04bd02da6 100644
--- a/base-component/tools/screen/Tools/Service/ServiceLoadRunner.xml
+++ b/base-component/tools/screen/Tools/Service/ServiceLoadRunner.xml
@@ -24,7 +24,7 @@ along with this software (see the LICENSE.md file). If not, see
@@ -102,12 +103,17 @@ along with this software (see the LICENSE.md file). If not, see
+
+
+
+
-
+
+
All delay, run, etc times are in milliseconds (ms), rates in runs per second
+
@@ -142,6 +154,7 @@ along with this software (see the LICENSE.md file). If not, see
Exec Index {{executorInfo.execIndex}}
Total Threads {{executorInfo.totalThreads}}
+
Active Threads {{executorInfo.activeThreads}}
Running {{executorInfo.running}}
@@ -204,15 +217,19 @@ along with this software (see the LICENSE.md file). If not, see
-
+
+
Average Run Time
+
+
+
Runs per Second
-
+
Entity Finds per Second
-
+
Entity Writes per Second
@@ -288,19 +305,22 @@ along with this software (see the LICENSE.md file). If not, see
data: function() { return {
// NOTE: regardless of defaults elsewhere these are the ones that show on the screen
newServiceInfo:{ serviceName:"", parametersExpr:"", targetThreads:"10",
- runDelayMs:"100", rampDelayMs:"500", timeBinLength:"2000", timeBinsKeep:"20" },
+ runDelayMs:"100", runDelayVaryMs:"5", rampDelayMs:"505", timeBinLength:"2000", timeBinsKeep:"20" },
serverStatus:{}, executorInfo:{running:false}, serviceInfos:[],
getInfoInterval:null, serverStatusInterval:null,
+ timeAvgChartConfig:{type:'line', data:{ labels:[], datasets:[] }},
runsPerSecAvgChartConfig:{type:'line', data:{ labels:[], datasets:[] }},
findsPerSecAvgChartConfig:{type:'line', data:{ labels:[], datasets:[] }},
writesPerSecAvgChartConfig:{type:'line', data:{ labels:[], datasets:[] }}
} },
methods: {
- setLocal: function(serviceName, parametersExpr, targetThreads, runDelayMs, rampDelayMs, timeBinLength, timeBinsKeep) {
+ setLocal: function(serviceName, parametersExpr, targetThreads, runDelayMs, runDelayVaryMs,
+ rampDelayMs, timeBinLength, timeBinsKeep) {
if (serviceName) this.newServiceInfo.serviceName = serviceName;
if (parametersExpr) this.newServiceInfo.parametersExpr = parametersExpr;
if (targetThreads) this.newServiceInfo.targetThreads = targetThreads;
if (runDelayMs) this.newServiceInfo.runDelayMs = runDelayMs;
+ if (runDelayVaryMs) this.newServiceInfo.runDelayVaryMs = runDelayVaryMs;
if (rampDelayMs) this.newServiceInfo.rampDelayMs = rampDelayMs;
if (timeBinLength) this.newServiceInfo.timeBinLength = timeBinLength;
if (timeBinsKeep) this.newServiceInfo.timeBinsKeep = timeBinsKeep;
@@ -370,35 +390,35 @@ along with this software (see the LICENSE.md file). If not, see
if (nostring) return over / under;
else return moqui.format(over / under, null, "bigdecimal");
},
- populateChartData: function(fieldName, serviceName, timeBinList, rpsDatasetsArray) {
+ populateChartData: function(fieldName, serviceName, timeBinList, datasetsArray) {
// NOTE: change moving average lengths here; consider making these user settable
var ma1Length = 7, ma2Length = 20;
- var rpsDataArray = [], rpsMa1DataArray = [], rpsMa2DataArray = [];
- var rpsMa1Cur = 0, rpsMa2Cur = 0;
+ var dataArray = [], ma1DataArray = [], ma2DataArray = [];
+ var ma1Cur = 0, ma2Cur = 0;
for (var tbi = 0; timeBinList && tbi < timeBinList.length; tbi++) {
var timeBin = timeBinList[tbi];
- rpsDataArray.push(timeBin[fieldName]);
+ dataArray.push(timeBin[fieldName]);
// for rolling moving average always add current
- rpsMa1Cur += timeBin[fieldName];
- rpsMa2Cur += timeBin[fieldName];
+ ma1Cur += timeBin[fieldName];
+ ma2Cur += timeBin[fieldName];
// for rolling moving average if more than ma periods subtract off the next one to drop
- if (tbi >= ma1Length) rpsMa1Cur -= timeBinList[tbi - ma1Length][fieldName];
- if (tbi >= ma2Length) rpsMa2Cur -= timeBinList[tbi - ma2Length][fieldName];
- rpsMa1DataArray.push(rpsMa1Cur / (tbi < ma1Length ? tbi+1 : ma1Length));
- rpsMa2DataArray.push(rpsMa2Cur / (tbi < ma2Length ? tbi+1 : ma2Length));
+ if (tbi >= ma1Length) ma1Cur -= timeBinList[tbi - ma1Length][fieldName];
+ if (tbi >= ma2Length) ma2Cur -= timeBinList[tbi - ma2Length][fieldName];
+ ma1DataArray.push(ma1Cur / (tbi < ma1Length ? tbi+1 : ma1Length));
+ ma2DataArray.push(ma2Cur / (tbi < ma2Length ? tbi+1 : ma2Length));
}
- rpsDatasetsArray.push({
+ datasetsArray.push({
backgroundColor:'rgba(49, 112, 143, 0.9)', borderColor:'rgba(49, 112, 143, 0.9)',
- label:serviceName, type:'line', fill:false, data:rpsDataArray
+ label:serviceName, type:'line', fill:false, data:dataArray
});
- rpsDatasetsArray.push({
+ datasetsArray.push({
backgroundColor:'rgba(100, 112, 70, 0.9)', borderColor:'rgba(100, 112, 70, 0.9)',
- label:serviceName + ' MA' + ma1Length, type:'line', fill:false, data:rpsMa1DataArray
+ label:serviceName + ' MA' + ma1Length, type:'line', fill:false, data:ma1DataArray
});
- rpsDatasetsArray.push({
+ datasetsArray.push({
backgroundColor:'rgba(100, 60, 143, 0.9)', borderColor:'rgba(100, 60, 143, 0.9)',
- label:serviceName + ' MA' + ma2Length, type:'line', fill:false, data:rpsMa2DataArray
+ label:serviceName + ' MA' + ma2Length, type:'line', fill:false, data:ma2DataArray
});
},
updateChartData: function() {
@@ -408,15 +428,22 @@ along with this software (see the LICENSE.md file). If not, see
this.serviceInfos[0].timeBinList.forEach(function (it) {
labelArray.push(moqui.format(it.beginTime, null, 'time')); });
+ var timeDatasetsArray = [];
var rpsDatasetsArray = [];
var efpsDatasetsArray = [];
var ewpsDatasetsArray = [];
var vm = this;
this.serviceInfos.forEach(function (it) {
+ vm.populateChartData("timeAverage", it.serviceName, it.timeBinList, timeDatasetsArray);
vm.populateChartData("runsPerSecAvg", it.serviceName, it.timeBinList, rpsDatasetsArray);
vm.populateChartData("entityFindsPerSec", it.serviceName, it.timeBinList, efpsDatasetsArray);
vm.populateChartData("entityWritePerSec", it.serviceName, it.timeBinList, ewpsDatasetsArray);
})
+ this.timeAvgChartConfig = {
+ type:'line', data:{ labels:labelArray, datasets:timeDatasetsArray },
+ options:{ legend:{display:false}, scales:{ xAxes:[{display:true}] },
+ maintainAspectRatio:false, animation:false }
+ };
this.runsPerSecAvgChartConfig = {
type:'line', data:{ labels:labelArray, datasets:rpsDatasetsArray },
options:{ legend:{display:false}, scales:{ xAxes:[{display:true}] },
diff --git a/base-component/tools/screen/Tools/dashboard.xml b/base-component/tools/screen/Tools/dashboard.xml
index 944e31c3b..ee6c23d2f 100644
--- a/base-component/tools/screen/Tools/dashboard.xml
+++ b/base-component/tools/screen/Tools/dashboard.xml
@@ -31,7 +31,7 @@ along with this software (see the LICENSE.md file). If not, see
-
+
From b0910b7e99d16a4d392acea39137e1bcea9c9ba5 Mon Sep 17 00:00:00 2001
From: Acetousk
Date: Tue, 7 Feb 2023 16:09:55 -0700
Subject: [PATCH 12/25] Create SqlScriptRunner.xml screen and add to
dashboard.xml
---
.../screen/Tools/Entity/SqlScriptRunner.xml | 91 +++++++++++++++++++
.../tools/screen/Tools/dashboard.xml | 11 ++-
2 files changed, 97 insertions(+), 5 deletions(-)
create mode 100644 base-component/tools/screen/Tools/Entity/SqlScriptRunner.xml
diff --git a/base-component/tools/screen/Tools/Entity/SqlScriptRunner.xml b/base-component/tools/screen/Tools/Entity/SqlScriptRunner.xml
new file mode 100644
index 000000000..3c5797440
--- /dev/null
+++ b/base-component/tools/screen/Tools/Entity/SqlScriptRunner.xml
@@ -0,0 +1,91 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/base-component/tools/screen/Tools/dashboard.xml b/base-component/tools/screen/Tools/dashboard.xml
index ee6c23d2f..222e29bf2 100644
--- a/base-component/tools/screen/Tools/dashboard.xml
+++ b/base-component/tools/screen/Tools/dashboard.xml
@@ -47,21 +47,21 @@ along with this software (see the LICENSE.md file). If not, see
+ text="${childResource.displayName ?: childResource.description ?: childResource.name} (${childResource.childMethods})"
+ url-type="plain" link-type="anchor" target-window="_blank"/>
+ target-window="_blank" text="${resource.displayName ?: resource.name} (${resource.childMethods})"
+ tooltip="${resource.description ?: ''}"/>
+ text="${masterEntityName}" link-type="anchor" target-window="_blank"/>
+ <#-- TODO: histItem.icon see https://v1.quasar.dev/vue-components/banner-->
{{histItem.time}}{{histItem.message}}
+
+
+
diff --git a/base-component/webroot/screen/webroot/js/WebrootVue.qvt.js b/base-component/webroot/screen/webroot/js/WebrootVue.qvt.js
index 7734983d7..c726b1061 100644
--- a/base-component/webroot/screen/webroot/js/WebrootVue.qvt.js
+++ b/base-component/webroot/screen/webroot/js/WebrootVue.qvt.js
@@ -141,9 +141,13 @@ moqui.handleAjaxError = function(jqXHR, textStatus, errorThrown, responseText) {
/* Override moqui.notifyGrowl */
moqui.notifyGrowl = function(jsonObj) {
if (!jsonObj) return;
- // TODO: jsonObj.link, jsonObj.icon
- moqui.webrootVue.$q.notify($.extend({}, moqui.notifyOptsInfo, { type:jsonObj.type, message:jsonObj.title }));
- moqui.webrootVue.addNotify(jsonObj.title, jsonObj.type);
+ // TODO: jsonObj.icon
+ moqui.webrootVue.$q.notify($.extend({}, moqui.notifyOptsInfo, { type:jsonObj.type, message:jsonObj.title,
+ actions: [
+ { label: 'View', color: 'white', handler: function () { moqui.webrootVue.setUrl(jsonObj.link); } }
+ ]
+ }));
+ moqui.webrootVue.addNotify(jsonObj.title, jsonObj.type, jsonObj.link, jsonObj.icon);
};
/* ========== component loading methods ========== */
@@ -2258,13 +2262,13 @@ moqui.webrootVue = new Vue({
this.urlListeners.push(urlListenerFunction);
},
- addNotify: function(message, type) {
+ addNotify: function(message, type, link, icon) {
var histList = this.notifyHistoryList.slice(0);
var nowDate = new Date();
var nh = nowDate.getHours(); if (nh < 10) nh = '0' + nh;
var nm = nowDate.getMinutes(); if (nm < 10) nm = '0' + nm;
// var ns = nowDate.getSeconds(); if (ns < 10) ns = '0' + ns;
- histList.unshift({message:message, type:type, time:(nh + ':' + nm)}); // + ':' + ns
+ histList.unshift({message:message, type:type, time:(nh + ':' + nm), link:link, icon:icon}); // + ':' + ns
while (histList.length > 25) { histList.pop(); }
this.notifyHistoryList = histList;
},
From 1e41d73322f1f65e77c43b6c9b8548cbfc0f5ece Mon Sep 17 00:00:00 2001
From: Acetousk
Date: Mon, 3 Apr 2023 12:33:04 -0600
Subject: [PATCH 14/25] Add sessionId field to list screen for debugging
---
base-component/tools/screen/System/Visit/VisitList.xml | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/base-component/tools/screen/System/Visit/VisitList.xml b/base-component/tools/screen/System/Visit/VisitList.xml
index 3ca3409e8..2297c13a8 100644
--- a/base-component/tools/screen/System/Visit/VisitList.xml
+++ b/base-component/tools/screen/System/Visit/VisitList.xml
@@ -43,6 +43,10 @@ along with this software (see the LICENSE.md file). If not, see
+
+
+
+
@@ -70,7 +74,7 @@ along with this software (see the LICENSE.md file). If not, see
-
+
From 9be2e9696adb205aa861f77a51fef1d33e467596 Mon Sep 17 00:00:00 2001
From: pandor4u <103976470+pandor4u@users.noreply.github.com>
Date: Tue, 11 Apr 2023 13:16:57 -0500
Subject: [PATCH 15/25] Changed header color to make it more obviously not
production
---
base-component/webroot/screen/webroot/css/WebrootVue.qvt.css | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/base-component/webroot/screen/webroot/css/WebrootVue.qvt.css b/base-component/webroot/screen/webroot/css/WebrootVue.qvt.css
index 99099e090..80e4ad1ba 100644
--- a/base-component/webroot/screen/webroot/css/WebrootVue.qvt.css
+++ b/base-component/webroot/screen/webroot/css/WebrootVue.qvt.css
@@ -21,7 +21,7 @@ h6, .text-h6 { font-size:1.0rem; line-height:1.0rem; letter-spacing:initial; mar
p { margin-bottom:8px; } /* orig 16px */
pre { text-wrap: normal; white-space: pre-line; word-wrap: normal; word-break: normal; }
-body.dev #top { background: #0c1b29!important; }
+body.dev #top { background: #5d5d5d!important; }
body.test #top { background: #224422!important; }
/* example for header that changes light and dark along with rest of screen:
From e7a6fe7628e8e41e498a28c0458ef43836679e8c Mon Sep 17 00:00:00 2001
From: pandor4u <103976470+pandor4u@users.noreply.github.com>
Date: Thu, 13 Apr 2023 13:15:15 -0500
Subject: [PATCH 16/25] Added Page Size to Log Viewer
---
base-component/tools/screen/System/LogViewer.xml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/base-component/tools/screen/System/LogViewer.xml b/base-component/tools/screen/System/LogViewer.xml
index fbd0ba730..8ec77b842 100644
--- a/base-component/tools/screen/System/LogViewer.xml
+++ b/base-component/tools/screen/System/LogViewer.xml
@@ -112,7 +112,7 @@ along with this software (see the LICENSE.md file). If not, see
-
+
From f7388127b23b5118227b2adab9187ff5b374c125 Mon Sep 17 00:00:00 2001
From: aabiabdallah
Date: Fri, 26 May 2023 15:50:41 -0500
Subject: [PATCH 17/25] In WebrootVue.qvt.css, updated rule for drawer
background to only come into effect in non-mobile layouts.
---
base-component/webroot/screen/webroot/css/WebrootVue.qvt.css | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/base-component/webroot/screen/webroot/css/WebrootVue.qvt.css b/base-component/webroot/screen/webroot/css/WebrootVue.qvt.css
index 80e4ad1ba..1791f7a61 100644
--- a/base-component/webroot/screen/webroot/css/WebrootVue.qvt.css
+++ b/base-component/webroot/screen/webroot/css/WebrootVue.qvt.css
@@ -38,7 +38,9 @@ body.test.body--dark #top { background:#224422!important; color:white; }
.body--dark .q-menu { background-color:black; }
.body--dark img.invertible { -webkit-filter: invert(90%); filter: invert(90%); }
-.q-dark, .q-card { background:transparent; }
+@media (min-width:576px) {
+ .q-dark, .q-card { background:transparent; }
+}
.q-card__actions h5 { font-size: 1.1rem; display:inline-block; margin-block-start:0; margin-block-end:0; }
.q-dialog .q-card { background-color:white; }
.body--dark .q-dialog .q-card { background-color:black; }
From 3c524a4f0c5ecb54d51fd61ccc8ea924b27c8d9b Mon Sep 17 00:00:00 2001
From: David E Jones
Date: Fri, 26 May 2023 16:42:33 -0500
Subject: [PATCH 18/25] In DefaultScreenMacros for vuet and qvt add paginate
support to section-include when included section is a section-iterate with
paginate=true; in qvt js don't show pagination widget if there is only one
result
---
.../webroot/screen/webroot/js/WebrootVue.qvt.js | 2 +-
template/screen-macro/DefaultScreenMacros.qvt.ftl | 9 +++++++++
template/screen-macro/DefaultScreenMacros.vuet.ftl | 9 +++++++++
3 files changed, 19 insertions(+), 1 deletion(-)
diff --git a/base-component/webroot/screen/webroot/js/WebrootVue.qvt.js b/base-component/webroot/screen/webroot/js/WebrootVue.qvt.js
index c726b1061..4a22cf090 100644
--- a/base-component/webroot/screen/webroot/js/WebrootVue.qvt.js
+++ b/base-component/webroot/screen/webroot/js/WebrootVue.qvt.js
@@ -1009,7 +1009,7 @@ Vue.component('m-form-paginate', {
name: "mFormPaginate",
props: { paginate:Object, formList:Object },
template:
- '
' +
+ '
' +
'' +
'' +
'' +
diff --git a/template/screen-macro/DefaultScreenMacros.qvt.ftl b/template/screen-macro/DefaultScreenMacros.qvt.ftl
index 3ec5cfc17..481f797e5 100644
--- a/template/screen-macro/DefaultScreenMacros.qvt.ftl
+++ b/template/screen-macro/DefaultScreenMacros.qvt.ftl
@@ -69,6 +69,15 @@ along with this software (see the LICENSE.md file). If not, see
#macro>
<#macro "section-include">
<#if sri.doBoundaryComments()>#if>
+ <#assign sectionNode = sri.getSectionIncludedNode(.node)>
+ <#if sectionNode["@paginate"]! == "true">
+ <#assign listName = sectionNode["@list"]>
+ <#assign listObj = context.get(listName)>
+ <#assign pagParms = Static["org.moqui.util.CollectionUtilities"].paginateParameters(listObj?size, listName, context)>
+
+ <#t> pageSize:${context[listName + "PageSize"]?c}, pageMaxIndex:${context[listName + "PageMaxIndex"]?c},
+ <#lt> pageRangeLow:${context[listName + "PageRangeLow"]?c}, pageRangeHigh:${context[listName + "PageRangeHigh"]?c} }">
+ #if>
${sri.renderSectionInclude(.node)}
<#if sri.doBoundaryComments()>#if>
#macro>
diff --git a/template/screen-macro/DefaultScreenMacros.vuet.ftl b/template/screen-macro/DefaultScreenMacros.vuet.ftl
index c3ea2ce00..50688ff75 100644
--- a/template/screen-macro/DefaultScreenMacros.vuet.ftl
+++ b/template/screen-macro/DefaultScreenMacros.vuet.ftl
@@ -67,6 +67,15 @@ along with this software (see the LICENSE.md file). If not, see
#macro>
<#macro "section-include">
<#if sri.doBoundaryComments()>#if>
+ <#assign sectionNode = sri.getSectionIncludedNode(.node)>
+ <#if sectionNode["@paginate"]! == "true">
+ <#assign listName = sectionNode["@list"]>
+ <#assign listObj = context.get(listName)>
+ <#assign pagParms = Static["org.moqui.util.CollectionUtilities"].paginateParameters(listObj?size, listName, context)>
+
+ <#t> pageSize:${context[listName + "PageSize"]?c}, pageMaxIndex:${context[listName + "PageMaxIndex"]?c},
+ <#lt> pageRangeLow:${context[listName + "PageRangeLow"]?c}, pageRangeHigh:${context[listName + "PageRangeHigh"]?c} }">
+ #if>
${sri.renderSectionInclude(.node)}
<#if sri.doBoundaryComments()>#if>
#macro>
From b1e3c16957db1df0c22b9f88f1b584472543b9fc Mon Sep 17 00:00:00 2001
From: David E Jones
Date: Tue, 13 Jun 2023 18:41:07 -0500
Subject: [PATCH 19/25] In WebrootVue.qvt.js add qLayoutMinHeight method to
calculate a full height, useful for certain types of screens with particular
or bottom instead of top focused layouts
---
.../webroot/screen/webroot/js/WebrootVue.qvt.js | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/base-component/webroot/screen/webroot/js/WebrootVue.qvt.js b/base-component/webroot/screen/webroot/js/WebrootVue.qvt.js
index 4a22cf090..908410a03 100644
--- a/base-component/webroot/screen/webroot/js/WebrootVue.qvt.js
+++ b/base-component/webroot/screen/webroot/js/WebrootVue.qvt.js
@@ -2417,6 +2417,14 @@ moqui.webrootVue = new Vue({
if (resp.loggedIn) {
this.reLoginPostLogin();
}
+ },
+ qLayoutMinHeight: function(offset) {
+ // "offset" is a Number (pixels) that refers to the total
+ // height of header + footer that occupies on screen,
+ // based on the QLayout "view" prop configuration
+
+ // this is actually what the default style-fn does in Quasar
+ return { minHeight: offset ? `calc(100vh - ${offset}px)` : '100vh' }
}
},
watch: {
From 0c2e1daacb7b203e95988c71a5f900075b675a77 Mon Sep 17 00:00:00 2001
From: David E Jones
Date: Thu, 27 Jul 2023 15:31:29 -0500
Subject: [PATCH 20/25] In qvt macros for form-list fix issue with
first/second/last row and hidden parameters
---
template/screen-macro/DefaultScreenMacros.qvt.ftl | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/template/screen-macro/DefaultScreenMacros.qvt.ftl b/template/screen-macro/DefaultScreenMacros.qvt.ftl
index 481f797e5..630262c0f 100644
--- a/template/screen-macro/DefaultScreenMacros.qvt.ftl
+++ b/template/screen-macro/DefaultScreenMacros.qvt.ftl
@@ -1135,11 +1135,11 @@ ${sri.renderIncludeScreen(.node["@location"], .node["@share-scope"]!)}
<#assign listName = formNode["@list"]>
<#assign isServerStatic = formInstance.isServerStatic(sri.getRenderMode())>
<#assign formDisabled = formListUrlInfo.disableLink>
+ <#assign hiddenParameterMap = sri.getFormHiddenParameters(formNode)>
+ <#assign hiddenParameterKeys = hiddenParameterMap.keySet()>
<#if isServerStatic><#-- client rendered, static -->
<#-- TODO: form-list server-static needs to be revisited still for Quasar -->
- <#assign hiddenParameterMap = sri.getFormHiddenParameters(formNode)>
- <#assign hiddenParameterKeys = hiddenParameterMap.keySet()>
<#t> :skip-form="${skipForm?c}" :skip-header="${skipHeader?c}" :header-form="${needHeaderForm?c}"
<#t> :header-dialog="${isHeaderDialog?c}" :saved-finds="${(formNode["@saved-finds"]! == "true")?c}"
From a7c0d844964c09b8a25b053bec0c38e3c909f168 Mon Sep 17 00:00:00 2001
From: David E Jones
Date: Sat, 29 Jul 2023 18:09:30 -0500
Subject: [PATCH 21/25] In qvt screen macros first pass on working support for
first, second, and last row forms
---
.../screen-macro/DefaultScreenMacros.qvt.ftl | 79 +++++++++----------
1 file changed, 37 insertions(+), 42 deletions(-)
diff --git a/template/screen-macro/DefaultScreenMacros.qvt.ftl b/template/screen-macro/DefaultScreenMacros.qvt.ftl
index 630262c0f..8c8bc28bd 100644
--- a/template/screen-macro/DefaultScreenMacros.qvt.ftl
+++ b/template/screen-macro/DefaultScreenMacros.qvt.ftl
@@ -1135,10 +1135,10 @@ ${sri.renderIncludeScreen(.node["@location"], .node["@share-scope"]!)}
<#assign listName = formNode["@list"]>
<#assign isServerStatic = formInstance.isServerStatic(sri.getRenderMode())>
<#assign formDisabled = formListUrlInfo.disableLink>
- <#assign hiddenParameterMap = sri.getFormHiddenParameters(formNode)>
- <#assign hiddenParameterKeys = hiddenParameterMap.keySet()>
<#if isServerStatic><#-- client rendered, static -->
+ <#assign hiddenParameterMap = sri.getFormHiddenParameters(formNode)>
+ <#assign hiddenParameterKeys = hiddenParameterMap.keySet()>
<#-- TODO: form-list server-static needs to be revisited still for Quasar -->
<#t> :skip-form="${skipForm?c}" :skip-header="${skipHeader?c}" :header-form="${needHeaderForm?c}"
@@ -1266,22 +1266,17 @@ ${sri.renderIncludeScreen(.node["@location"], .node["@share-scope"]!)}
#if>
<#-- first-row fields -->
<#if formListInfo.hasFirstRow()>
- <#-- TODO change to wrap row, use something like sri.makeFormListSingleMap() which eliminates use inline of hiddenParameterKeys, hiddenParameterMap -->
- <#t>${sri.pushSingleFormMapContext(formNode["@map-first-row"]!"")}
<#assign listEntryIndex = "first">
- <#assign firstUrlInstance = sri.makeUrlByType(formNode["@transition-first-row"], "transition", null, "false")>
-
- <#if orderByField?has_content>#if>
- <#list hiddenParameterKeys as hiddenParameterKey>#list>
- <#assign hiddenFieldList = formListInfo.getListFirstRowHiddenFieldList()>
- <#list hiddenFieldList as hiddenField><#recurse hiddenField["first-row-field"][0]/>#list>
-
- <#assign listEntryIndex = "">
- <#t>${sri.popContext()}<#-- context was pushed for the form so pop here at the end -->
+ <#if formListInfo.isFirstRowForm()>
+ <#assign firstRowMap = sri.getSingleFormMap(formNode["@map-first-row"]!"")>
+ <#assign firstUrlInstance = sri.makeUrlByType(formNode["@transition-first-row"], "transition", null, "false")>
+
+ #if>
<#t>${sri.pushSingleFormMapContext(formNode["@map-first-row"]!"")}
<#assign ownerForm = formId + "_first">
- <#assign listEntryIndex = "first">
+ <#assign fieldsJsName = "formProps.fields">