This commit is contained in:
@@ -2,54 +2,65 @@
|
|||||||
@@@@@@@@@@@@@@@ ROADMAP STAGE 4 - REPORTING / DASHBOARD / KPI
|
@@@@@@@@@@@@@@@ ROADMAP STAGE 4 - REPORTING / DASHBOARD / KPI
|
||||||
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
|
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
|
||||||
|
|
||||||
todo: reporting "ZOMBIE" chrome processes on linux
|
|
||||||
open the shell into the docker container:
|
|
||||||
docker run -it [container_id] /bin/ash
|
|
||||||
run the "top" command and then print a report
|
|
||||||
each run generates 3 chrome processes
|
|
||||||
Many discussions about workarounds and stuff here:
|
|
||||||
https://github.com/hardkoded/puppeteer-sharp/issues/1489
|
|
||||||
https://github.com/puppeteer/puppeteer/issues/1825
|
|
||||||
https://github.com/Yelp/dumb-init
|
|
||||||
|
|
||||||
Ok, fixed it, but now it's a little slower and can crash if it hits the limits of the droplet i.e.
|
todo: pdf options UI and passthrough
|
||||||
Not sure what to do about that, maybe more timeouts in more places?
|
basically need to be able to select every option and send it through
|
||||||
What are the specs for the droplet?
|
options:
|
||||||
|
http://www.puppeteersharp.com/api/PuppeteerSharp.PdfOptions.html
|
||||||
todo: figure out how jsreport is launching headless chrome, i.e. which settings and flags etc
|
http://www.puppeteersharp.com/api/PuppeteerSharp.Page.html#PuppeteerSharp_Page_PdfAsync_System_String_PuppeteerSharp_PdfOptions_
|
||||||
https://github.com/puppeteer/puppeteer/blob/main/docs/api.md#puppeteerlaunchoptions
|
https://pptr.dev/#?product=Puppeteer&version=v5.3.0&show=api-pagepdfoptions
|
||||||
https://jsreport.net/learn/chrome-pdf
|
page numbers control
|
||||||
https://github.com/jsreport/jsreport-chrome-pdf/blob/master/lib/conversion.js
|
|
||||||
|
|
||||||
todo: look over this: https://github.com/puppeteer/puppeteer/issues/1834
|
|
||||||
todo: look at guidance for running puppeteer (js) on alpine docker here: https://github.com/puppeteer/puppeteer/blob/main/docs/troubleshooting.md#running-on-alpine
|
|
||||||
todo: test with generated huge data locally here in Windows, see what limits get hit and how it handles it
|
|
||||||
todo: document (or tell Joyce) about the troubleshooting section items here:
|
|
||||||
https://jsreport.net/learn/chrome-pdf
|
|
||||||
which may or may not apply in our case
|
|
||||||
|
|
||||||
todo: more timeouts for report rendering, Devops droplet is overwhelmed by 10k records of widgets using the customfields example report
|
|
||||||
symptom is super high cpu usage (100%) pegged and probably virtual memory usage as well
|
|
||||||
timeout is kind of a hard core way to work around this issue, maybe instead it should be looking at excessive cpu and memory usage?
|
|
||||||
The metrics don't catch it because it happens too quickly for the metrics lifecycle
|
|
||||||
|
|
||||||
I want it to be able to handle it gracefully without crashing
|
|
||||||
|
|
||||||
todo: look at metrics snapshot lifecycle, perhaps it should be shorter as it's missing 100% cpu pegging during big rendering on devops
|
|
||||||
|
|
||||||
todo: pdf page numbers control
|
|
||||||
Test this, it might do what we need as it has a template for pdf footer and page number is part of it
|
Test this, it might do what we need as it has a template for pdf footer and page number is part of it
|
||||||
http://www.puppeteersharp.com/api/PuppeteerSharp.PdfOptions.html
|
http://www.puppeteersharp.com/api/PuppeteerSharp.PdfOptions.html
|
||||||
look at jsreport what do they include in their pdf post processing parameters and capabilities
|
look at jsreport what do they include in their pdf post processing parameters and capabilities
|
||||||
need to add pdfkit or whatever it's called at the front.
|
need to add pdfkit or whatever it's called at the front.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
todo: document (or tell Joyce) about the troubleshooting section items here:
|
||||||
|
https://jsreport.net/learn/chrome-pdf
|
||||||
|
which may or may not apply in our case
|
||||||
|
|
||||||
|
|
||||||
|
//before getting into timeouts and shit make sure it's running as well as can be in docker
|
||||||
|
todo: look at guidance for running puppeteer (js) on alpine docker here: https://github.com/puppeteer/puppeteer/blob/main/docs/troubleshooting.md#running-on-alpine
|
||||||
|
how jsreport is launching headless chrome, i.e. which settings and flags etc
|
||||||
|
https://github.com/puppeteer/puppeteer/blob/main/docs/api.md#puppeteerlaunchoptions
|
||||||
|
https://jsreport.net/learn/chrome-pdf
|
||||||
|
https://github.com/jsreport/jsreport-chrome-pdf/blob/master/lib/conversion.js
|
||||||
|
(after looking at it, it's still a bit unclear, maybe not relevant as they seem to do a lot differently for that)
|
||||||
|
|
||||||
|
|
||||||
|
todo: look over this: https://github.com/puppeteer/puppeteer/issues/1834
|
||||||
|
|
||||||
todo: reporting load test
|
todo: reporting load test
|
||||||
test locally with 20k widgets, make it crash then determine what limits to set on it and properly return error when it's exceeded
|
test locally with 20k widgets, make it crash then determine what limits to set on it and properly return error when it's exceeded
|
||||||
right now it just says something about puppeteer and "crash"
|
right now it just says something about puppeteer and "crash"
|
||||||
|
|
||||||
|
|
||||||
|
todo: more timeouts for report rendering, hard kill after 30 seconds tops but adjustable interval maybe?
|
||||||
|
each process takes time in part, need to see which is taking which time the most and killable
|
||||||
|
i.e. run a huge report and see which exact step takes which time for each
|
||||||
|
we have the pre-render timing out maybe need more for each step where it's vulnerable to crashing / timing out
|
||||||
|
|
||||||
|
Devops droplet is overwhelmed by 10k records of widgets using the customfields example report
|
||||||
|
symptom is super high cpu usage (100%) pegged and probably virtual memory usage as well
|
||||||
|
timeout is kind of a hard core way to work around this issue, maybe instead it should be looking at excessive cpu and memory usage?
|
||||||
|
The metrics don't catch it because it happens too quickly for the metrics lifecycle
|
||||||
|
|
||||||
|
I want it to be able to handle it gracefully without crashing
|
||||||
|
Looks like jsreports has this issue too and they hard kill the process I think if necessary, but they actually re-use the same instance for reporting I think.
|
||||||
|
If it's not an issue then no need to resolve at the moment
|
||||||
|
|
||||||
|
|
||||||
todo: Need a setting that warns people about printing too much data, i.e. "That's a lot of data, are you sure you want to render that, it will be slow" or something to that effect
|
todo: Need a setting that warns people about printing too much data, i.e. "That's a lot of data, are you sure you want to render that, it will be slow" or something to that effect
|
||||||
|
|
||||||
|
|
||||||
|
todo: look at metrics snapshot lifecycle, perhaps it should be shorter as it's missing 100% cpu pegging during big rendering on devops
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
todo: Take a serious look at .net5 migration, it will almost certainly be better to do it now than down the road after a release
|
todo: Take a serious look at .net5 migration, it will almost certainly be better to do it now than down the road after a release
|
||||||
it also has many performance enhancements and nifty features like code analysis and warnings which might save me a lot of hassle
|
it also has many performance enhancements and nifty features like code analysis and warnings which might save me a lot of hassle
|
||||||
|
|
||||||
@@ -61,6 +72,18 @@ todo: look at what's coming on the radar before release in the big libs I'm usin
|
|||||||
|
|
||||||
todo: triage this stuff:
|
todo: triage this stuff:
|
||||||
|
|
||||||
|
todo: Direct report view URL doesn't work if already logged in due to code only being in login form
|
||||||
|
need to hijack the router before navigation to intercept special urls
|
||||||
|
https://test.helloayanova.com/widgets/499
|
||||||
|
localhost:8080/viewreport?oid=20000&rid=9
|
||||||
|
|
||||||
|
todo: wiki image helper, if select ok but haven't selected a attachment it errors out, ok should not be available until there is a valid image selected
|
||||||
|
todo: attach files drag and drop helper should be expanded to include the selection tab, not just the list tab
|
||||||
|
todo: .webp type not available to wiki image helper when attached
|
||||||
|
this is because it's not identified as an image when it's a .webp extension
|
||||||
|
add to image types list for MIME
|
||||||
|
|
||||||
|
|
||||||
todo: DataListFilter UI pretty shitty
|
todo: DataListFilter UI pretty shitty
|
||||||
error on duplicate
|
error on duplicate
|
||||||
how to make a new filter?
|
how to make a new filter?
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
export default {
|
export default {
|
||||||
version: "8.0.0-alpha.16",
|
version: "8.0.0-alpha.19",
|
||||||
copyright: "© 1999-2020, Ground Zero Tech-Works Inc."
|
copyright: "© 1999-2020, Ground Zero Tech-Works Inc."
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -686,9 +686,15 @@ export default {
|
|||||||
///////////////////////////////
|
///////////////////////////////
|
||||||
// On fieldValueChanged handler
|
// On fieldValueChanged handler
|
||||||
// This is required so that server errors can be cleared when input is changed
|
// This is required so that server errors can be cleared when input is changed
|
||||||
//
|
// formReference is an optional string name of the form ref property if alternative named form
|
||||||
fieldValueChanged(vm, ref) {
|
fieldValueChanged(vm, ref, formReference) {
|
||||||
let that = this;
|
let that = this;
|
||||||
|
let formControl = null;
|
||||||
|
if (formReference == undefined) {
|
||||||
|
formControl = vm.$refs.form;
|
||||||
|
} else {
|
||||||
|
formControl = vm.$refs[formReference];
|
||||||
|
}
|
||||||
//this is currently required to ensure that this method runs after all the broken rule checks have settled
|
//this is currently required to ensure that this method runs after all the broken rule checks have settled
|
||||||
Vue.nextTick(function() {
|
Vue.nextTick(function() {
|
||||||
//-------------
|
//-------------
|
||||||
@@ -738,7 +744,8 @@ export default {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//Update the form status
|
//Update the form status
|
||||||
let formValid = vm.$refs.form.validate();
|
let formValid = formControl.validate();
|
||||||
|
//let formValid = vm.$refs.form.validate();//##FORM REFERENCE
|
||||||
// console.log(
|
// console.log(
|
||||||
// "gzform:fieldValueChanged - form validity being set to ",
|
// "gzform:fieldValueChanged - form validity being set to ",
|
||||||
// formValid
|
// formValid
|
||||||
|
|||||||
@@ -22,6 +22,10 @@
|
|||||||
{{ $ay.t("ReportEditorProperties") }}
|
{{ $ay.t("ReportEditorProperties") }}
|
||||||
</v-btn>
|
</v-btn>
|
||||||
|
|
||||||
|
<v-btn value="pdfoptions">
|
||||||
|
{{ $ay.t("ReportPdfOptions") }}
|
||||||
|
</v-btn>
|
||||||
|
|
||||||
<v-btn value="template">
|
<v-btn value="template">
|
||||||
{{ $ay.t("ReportTemplate") }}
|
{{ $ay.t("ReportTemplate") }}
|
||||||
</v-btn>
|
</v-btn>
|
||||||
@@ -114,6 +118,25 @@
|
|||||||
</v-row>
|
</v-row>
|
||||||
</v-form>
|
</v-form>
|
||||||
</v-col>
|
</v-col>
|
||||||
|
|
||||||
|
<v-col cols="12" v-show="view == 'pdfoptions'">
|
||||||
|
<v-form ref="formPDF">
|
||||||
|
<v-row>
|
||||||
|
<v-col cols="12" sm="6" lg="4" xl="3">
|
||||||
|
<v-checkbox
|
||||||
|
v-model="obj.active"
|
||||||
|
:readonly="formState.readOnly"
|
||||||
|
:disabled="formState.readOnly"
|
||||||
|
:label="$ay.t('Active')"
|
||||||
|
ref="active"
|
||||||
|
:data-cy="!!$ay.dev ? 'active' : false"
|
||||||
|
:error-messages="form().serverErrors(this, 'active')"
|
||||||
|
@change="fieldValueChanged('active', 'formPDF')"
|
||||||
|
></v-checkbox>
|
||||||
|
</v-col>
|
||||||
|
</v-row>
|
||||||
|
</v-form>
|
||||||
|
</v-col>
|
||||||
</v-row>
|
</v-row>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
@@ -320,7 +343,20 @@ export default {
|
|||||||
Handlebars.registerHelper('loud', function (aString) {
|
Handlebars.registerHelper('loud', function (aString) {
|
||||||
return aString.toUpperCase()
|
return aString.toUpperCase()
|
||||||
})`,
|
})`,
|
||||||
renderType: 0
|
renderType: 0,
|
||||||
|
headerTemplate: null,
|
||||||
|
footerTemplate: null,
|
||||||
|
displayHeaderFooter: false,
|
||||||
|
paperFormat: 0,
|
||||||
|
landscape: false,
|
||||||
|
marginOptionsBottom: null,
|
||||||
|
marginOptionsLeft: null,
|
||||||
|
marginOptionsRight: null,
|
||||||
|
marginOptionsTop: null,
|
||||||
|
pageRanges: null,
|
||||||
|
preferCSSPageSize: false,
|
||||||
|
printBackground: false,
|
||||||
|
scale: 1
|
||||||
},
|
},
|
||||||
formState: {
|
formState: {
|
||||||
ready: false,
|
ready: false,
|
||||||
@@ -337,6 +373,16 @@ Handlebars.registerHelper('loud', function (aString) {
|
|||||||
rendering: false
|
rendering: false
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
/*{"data":{"id":10,"concurrency":19494847,"name":"test basic","active":true,"notes":"",
|
||||||
|
"roles":124927,"objectType":2,
|
||||||
|
"template":"<html>\n\n<body>\n\t{{#each ayReportData}}\n\t<h2>{{ Name }}</h2>\n\t<div>Notes: <span class='example'>{{ Notes }}</span></div>\n\t{{/each}}\n</body>\n\n</html>","style":".example {\n color: blue;\n}","jsPrerender":"async function ayPrepareData(reportData){ \n //this function (if present) is called with the report data \n //before the report is rendered\n //modify data as required here and return it to change the data before the report renders\n //see the help documentation for details\n return reportData;\n}","jsHelpers":"//Register custom Handlebars helpers here to use in your report script\n//https://handlebarsjs.com/guide/#custom-helpers\nHandlebars.registerHelper('loud', function (aString) {\n return aString.toUpperCase()\n})",
|
||||||
|
"renderType":0,
|
||||||
|
"headerTemplate":null,"footerTemplate":null,"displayHeaderFooter":false,
|
||||||
|
"paperFormat":0,"landscape":false,"marginOptionsBottom":null,
|
||||||
|
"marginOptionsLeft":null,"marginOptionsRight":null,
|
||||||
|
"marginOptionsTop":null,"pageRanges":null,"preferCSSPageSize":false,
|
||||||
|
"printBackground":false,"scale":1}}
|
||||||
|
*/
|
||||||
//WATCHERS
|
//WATCHERS
|
||||||
watch: {
|
watch: {
|
||||||
formState: {
|
formState: {
|
||||||
@@ -403,6 +449,9 @@ Handlebars.registerHelper('loud', function (aString) {
|
|||||||
case "properties":
|
case "properties":
|
||||||
//no state to save here
|
//no state to save here
|
||||||
break;
|
break;
|
||||||
|
case "pdfoptions":
|
||||||
|
//no state to save here
|
||||||
|
break;
|
||||||
case "template":
|
case "template":
|
||||||
vm.editData.template.state = currentState;
|
vm.editData.template.state = currentState;
|
||||||
break;
|
break;
|
||||||
@@ -427,6 +476,10 @@ Handlebars.registerHelper('loud', function (aString) {
|
|||||||
vm.view = "properties";
|
vm.view = "properties";
|
||||||
return;
|
return;
|
||||||
break;
|
break;
|
||||||
|
case "pdfoptions":
|
||||||
|
vm.view = "pdfoptions";
|
||||||
|
return;
|
||||||
|
break;
|
||||||
case "template":
|
case "template":
|
||||||
editor.setModel(vm.editData.template.model);
|
editor.setModel(vm.editData.template.model);
|
||||||
editor.restoreViewState(vm.editData.template.state);
|
editor.restoreViewState(vm.editData.template.state);
|
||||||
@@ -487,13 +540,13 @@ Handlebars.registerHelper('loud', function (aString) {
|
|||||||
form() {
|
form() {
|
||||||
return window.$gz.form;
|
return window.$gz.form;
|
||||||
},
|
},
|
||||||
fieldValueChanged(ref) {
|
fieldValueChanged(ref, formReference) {
|
||||||
if (
|
if (
|
||||||
this.formState.ready &&
|
this.formState.ready &&
|
||||||
!this.formState.loading &&
|
!this.formState.loading &&
|
||||||
!this.formState.readOnly
|
!this.formState.readOnly
|
||||||
) {
|
) {
|
||||||
window.$gz.form.fieldValueChanged(this, ref);
|
window.$gz.form.fieldValueChanged(this, ref, formReference);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
async getDataFromApi(recordId) {
|
async getDataFromApi(recordId) {
|
||||||
@@ -919,6 +972,7 @@ async function fetchTranslatedText(vm) {
|
|||||||
await window.$gz.translation.cacheTranslations([
|
await window.$gz.translation.cacheTranslations([
|
||||||
"ReportDesignReport",
|
"ReportDesignReport",
|
||||||
"ReportName",
|
"ReportName",
|
||||||
|
"ReportPdfOptions",
|
||||||
"ReportEditorProperties",
|
"ReportEditorProperties",
|
||||||
"ReportEditorData",
|
"ReportEditorData",
|
||||||
"ReportEditorMobileWarning",
|
"ReportEditorMobileWarning",
|
||||||
|
|||||||
Reference in New Issue
Block a user