Html based Ver 1.0.4 (#10)
* Version 1.0.3 HTM-based New guid, many changes in R code, visual.ts, supports source to R code * small change to metadata updated dependencies and github link * Solved small bugs 1) forecastLength < 12000 2) empty data => empty plot * removed "_HTML" from name * changed PBIX * Ver 1.0.4 Changed "qua(r)ter" word . English typo * commented out DEBUG code * api 1.7.0 + changes due to Ignat * try to ignore * gitignore * remove .R* * removed out_files * removed out.html.tmp * remove out.html_files * Ver 1.0.4 almost ready PBIX, export , conf limits in GUI like ARIMA * Ver 1.0.4 * small * removed commented * package.json revert partially * ignore * small * ignore * whitespaces and package-lock.json * tslint * "powerbi-visuals-utils-dataviewutils": "1.2.0" * ignore pbiviz * _work remove * tslint
This commit is contained in:
Родитель
92d48d2e62
Коммит
3d7a5a6d39
|
@ -1,4 +1,5 @@
|
|||
node_modules
|
||||
node_modules/*
|
||||
.tmp
|
||||
dist
|
||||
.api
|
||||
|
@ -7,7 +8,6 @@ dist
|
|||
.tmp/*
|
||||
dist/*
|
||||
.tmp/drop/pbiviz.json
|
||||
.tmp/drop/pbiviz.json
|
||||
.tmp/drop/visual.js
|
||||
.tmp/precompile/src/visual.ts
|
||||
.tmp/drop/pbiviz.json
|
||||
|
@ -25,4 +25,8 @@ dist/PowerBI-visuals-forcasting-exp.pbiviz
|
|||
out.html.tmp
|
||||
out.html.*
|
||||
out.html_files/*
|
||||
out.html_files
|
||||
out.html_files
|
||||
dist/PowerBI-visuals-forcasting-exp.pbiviz
|
||||
assets/Presentation1.pptx
|
||||
assets/*_testing.pbix
|
||||
dist/PowerBI-visuals-forcasting-exp.pbiviz
|
|
@ -0,0 +1,13 @@
|
|||
{
|
||||
"version": "0.1.0",
|
||||
"configurations": [
|
||||
{
|
||||
"name": "Debugger",
|
||||
"type": "chrome",
|
||||
"request": "attach",
|
||||
"port": 9222,
|
||||
"sourceMaps": true,
|
||||
"webRoot": "${cwd}/"
|
||||
}
|
||||
]
|
||||
}
|
|
@ -0,0 +1,37 @@
|
|||
{
|
||||
"editor.tabSize": 4,
|
||||
"editor.insertSpaces": true,
|
||||
"files.eol": "\n",
|
||||
"files.watcherExclude": {
|
||||
"**/.git/objects/**": true,
|
||||
"**/node_modules/**": true,
|
||||
".tmp": true
|
||||
},
|
||||
"files.exclude": {
|
||||
".tmp": true
|
||||
},
|
||||
"search.exclude": {
|
||||
".tmp": true,
|
||||
"typings": true
|
||||
},
|
||||
"json.schemas": [
|
||||
{
|
||||
"fileMatch": [
|
||||
"/pbiviz.json"
|
||||
],
|
||||
"url": "./.api/v1.10.0/schema.pbiviz.json"
|
||||
},
|
||||
{
|
||||
"fileMatch": [
|
||||
"/capabilities.json"
|
||||
],
|
||||
"url": "./.api/v1.10.0/schema.capabilities.json"
|
||||
},
|
||||
{
|
||||
"fileMatch": [
|
||||
"/dependencies.json"
|
||||
],
|
||||
"url": "./.api/v1.10.0/schema.dependencies.json"
|
||||
}
|
||||
]
|
||||
}
|
Двоичный файл не отображается.
После Ширина: | Высота: | Размер: 29 KiB |
Двоичные данные
assets/forecast_custom_RV_HTML-based.pbix
Двоичные данные
assets/forecast_custom_RV_HTML-based.pbix
Двоичный файл не отображается.
|
@ -62,7 +62,7 @@
|
|||
},
|
||||
"settings_forecastPlot_params": {
|
||||
"displayName": "Forecasting settings",
|
||||
"description": "Basic decomposition models are: 1. Additive: x[t] = Trend + Seasonal + Random, 2. Multiplicative: x[t] = Trend * Seasonal * Random. Hybrid models are allowed. Any forbiden model combination will be replaced by `Automatic`",
|
||||
"description": "Basic decomposition models are: 1. Additive: x[t] = Trend + Seasonal + Remainder, 2. Multiplicative: x[t] = Trend * Seasonal * Remainder. Hybrid models are allowed. Any forbiden model combination will be replaced by `Automatic`",
|
||||
"properties": {
|
||||
|
||||
"forecastLength": {
|
||||
|
@ -72,7 +72,7 @@
|
|||
},
|
||||
|
||||
"errorType": {
|
||||
"displayName": "Error component",
|
||||
"displayName": "Remainder component",
|
||||
"type": {
|
||||
"enumeration": [
|
||||
{
|
||||
|
@ -201,34 +201,125 @@
|
|||
"show": {
|
||||
"type": {"bool": true}
|
||||
},
|
||||
"percentile": { "displayName": "Confidence", "type": { "numeric": true } },
|
||||
"upperConfIntervalFactor": {
|
||||
"displayName": "Upper interval factor",
|
||||
"description": "Upper Confidence = Confidence + (100 - Confidence)*UpperIntervalFactor ",
|
||||
"type": {
|
||||
"enumeration": [
|
||||
{
|
||||
"displayName": "0",
|
||||
"value": "0"
|
||||
},
|
||||
{
|
||||
"displayName": "0.5",
|
||||
"value": "0.5"
|
||||
},
|
||||
{
|
||||
"displayName": "0.75",
|
||||
"value": "0.75"
|
||||
},
|
||||
{
|
||||
"displayName": "0.9",
|
||||
"value": "0.9"
|
||||
},
|
||||
{
|
||||
"displayName": "0.95",
|
||||
"value": "0.95"
|
||||
}
|
||||
]
|
||||
}
|
||||
"confInterval1": {
|
||||
"displayName": "Confidence level",
|
||||
"description": "Select first confidence interval",
|
||||
"type": {
|
||||
"enumeration": [
|
||||
{
|
||||
"displayName": "0",
|
||||
"value": "0"
|
||||
},
|
||||
{
|
||||
"displayName": "0.2",
|
||||
"value": "0.2"
|
||||
},
|
||||
{
|
||||
"displayName": "0.4",
|
||||
"value": "0.4"
|
||||
},
|
||||
{
|
||||
"displayName": "0.5",
|
||||
"value": "0.5"
|
||||
},
|
||||
{
|
||||
"displayName": "0.75",
|
||||
"value": "0.75"
|
||||
},
|
||||
{
|
||||
"displayName": "0.8",
|
||||
"value": "0.8"
|
||||
},
|
||||
{
|
||||
"displayName": "0.9",
|
||||
"value": "0.9"
|
||||
},
|
||||
{
|
||||
"displayName": "0.95",
|
||||
"value": "0.95"
|
||||
},
|
||||
{
|
||||
"displayName": "0.975",
|
||||
"value": "0.975"
|
||||
},
|
||||
{
|
||||
"displayName": "0.98",
|
||||
"value": "0.98"
|
||||
},
|
||||
{
|
||||
"displayName": "0.99",
|
||||
"value": "0.99"
|
||||
},
|
||||
{
|
||||
"displayName": "0.995",
|
||||
"value": "0.995"
|
||||
},
|
||||
{
|
||||
"displayName": "0.999",
|
||||
"value": "0.999"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"confInterval2": {
|
||||
"displayName": "Confidence level #2",
|
||||
"description": "Select additional confidence interval",
|
||||
"type": {
|
||||
"enumeration": [
|
||||
{
|
||||
"displayName": "0",
|
||||
"value": "0"
|
||||
},
|
||||
{
|
||||
"displayName": "0.2",
|
||||
"value": "0.2"
|
||||
},
|
||||
{
|
||||
"displayName": "0.4",
|
||||
"value": "0.4"
|
||||
},
|
||||
{
|
||||
"displayName": "0.5",
|
||||
"value": "0.5"
|
||||
},
|
||||
{
|
||||
"displayName": "0.75",
|
||||
"value": "0.75"
|
||||
},
|
||||
{
|
||||
"displayName": "0.8",
|
||||
"value": "0.8"
|
||||
},
|
||||
{
|
||||
"displayName": "0.9",
|
||||
"value": "0.9"
|
||||
},
|
||||
{
|
||||
"displayName": "0.95",
|
||||
"value": "0.95"
|
||||
},
|
||||
{
|
||||
"displayName": "0.975",
|
||||
"value": "0.975"
|
||||
},
|
||||
{
|
||||
"displayName": "0.98",
|
||||
"value": "0.98"
|
||||
},
|
||||
{
|
||||
"displayName": "0.99",
|
||||
"value": "0.99"
|
||||
},
|
||||
{
|
||||
"displayName": "0.995",
|
||||
"value": "0.995"
|
||||
},
|
||||
{
|
||||
"displayName": "0.999",
|
||||
"value": "0.999"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -276,10 +367,56 @@
|
|||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"settings_export_params": {
|
||||
"displayName": "Export data",
|
||||
"description": "Export result of clustering",
|
||||
"properties": {
|
||||
"show": {
|
||||
"type": {
|
||||
"bool": true
|
||||
}
|
||||
},
|
||||
"limitExportSize": {
|
||||
"displayName": "Maximum exported rows",
|
||||
"description": "Limit number of rows",
|
||||
"type": {
|
||||
"enumeration": [{
|
||||
"displayName": "1000",
|
||||
"value": "1000"
|
||||
},
|
||||
{
|
||||
"displayName": "10000",
|
||||
"value": "10000"
|
||||
},
|
||||
{
|
||||
"displayName": "50000",
|
||||
"value": "50000"
|
||||
},
|
||||
{
|
||||
"displayName": "unlimited",
|
||||
"value": "100000"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"method": {
|
||||
"displayName": "Method",
|
||||
"description": "Method",
|
||||
"type": {
|
||||
"enumeration": [{
|
||||
"displayName": "copy to clipboard",
|
||||
"value": "copy"
|
||||
},
|
||||
{
|
||||
"displayName": "download (only service)",
|
||||
"value": "download"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
},
|
||||
"suppressDefaultTitle": true
|
||||
}
|
|
@ -39,6 +39,11 @@
|
|||
"name": "XML",
|
||||
"displayName": "XML",
|
||||
"url": "https://cran.r-project.org/web/packages/XML/index.html"
|
||||
},
|
||||
{
|
||||
"name": "caTools",
|
||||
"displayName": "caTools",
|
||||
"url": "https://cran.r-project.org/web/packages/caTools/index.html"
|
||||
}
|
||||
|
||||
]
|
||||
|
|
Двоичный файл не отображается.
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"name": "visual",
|
||||
"scripts": {
|
||||
"postinstall": "pbiviz update 1.7.0",
|
||||
"postinstall": "pbiviz update 1.10.0",
|
||||
"pbiviz": "pbiviz",
|
||||
"package": "pbiviz package",
|
||||
"lint": "tslint -r \"node_modules/tslint-microsoft-contrib\" \"+(src)/**/*.ts\"",
|
||||
|
@ -10,6 +10,7 @@
|
|||
"devDependencies": {
|
||||
"tslint": "^4.4.2",
|
||||
"tslint-microsoft-contrib": "^4.0.0",
|
||||
"powerbi-visuals-tools": "1.7.1"
|
||||
"powerbi-visuals-tools": "1.10.0",
|
||||
"powerbi-visuals-utils-dataviewutils": "1.2.0"
|
||||
}
|
||||
}
|
||||
}
|
13
pbiviz.json
13
pbiviz.json
|
@ -4,12 +4,12 @@
|
|||
"displayName": "Forecasting",
|
||||
"guid": "PBI_CV_8EDDC07B_EE79_4418_A84C_D73897C0E21F_HTML",
|
||||
"visualClassName": "Visual",
|
||||
"version": "1.0.3",
|
||||
"description": "<span>Time series forecasting is the use of a model to predict future values based on previously observed values. Current visual implements well known exponential smoothing method for the forecasting. The prediction is based on trend and seasonality modeling. You can control the algorithm parameters and the visual attributes to suit your needs.<br/><br/><span style='font-style:italic'>Service prerequisites:</span> R-powered custom visual is used in service seamlessly<br/><br /><span style='font-style:italic'>Desktop prerequisites:</span> To run R scripts in Power BI Desktop, you must separately install R on your local computer.<br />You can download and install R for free from the <a href='https://mran.revolutionanalytics.com/download/'>Revolution Open download page</a> or the <a href='https://cran.r-project.org/bin/windows/base/'>CRAN Repository</a><br /><br /> <span style='font-style:italic'> R package dependencies(auto-installed): </span> graphics, scales, forecast, zoo, ggplot2, htmlWidgets, XML, plotly <br /><br /> <span style='font-style:italic'> Supports R versions: </span> R 3.3.1, R 3.3.0, MRO 3.3.1, MRO 3.3.0, MRO 3.2.2 <br /></span>",
|
||||
"version": "1.0.4",
|
||||
"description": "<span>Time series forecasting is the use of a model to predict future values based on previously observed values. Current visual implements well known exponential smoothing method for the forecasting. The prediction is based on trend and seasonality modeling. You can control the algorithm parameters and the visual attributes to suit your needs.<br/><br/><span style='font-style:italic'>Service prerequisites:</span> R-powered custom visual is used in service seamlessly<br/><br /><span style='font-style:italic'>Desktop prerequisites:</span> To run R scripts in Power BI Desktop, you must separately install R on your local computer.<br />You can download and install R for free from the <a href='https://mran.revolutionanalytics.com/download/'>Revolution Open download page</a> or the <a href='https://cran.r-project.org/bin/windows/base/'>CRAN Repository</a><br /><br /> <span style='font-style:italic'> R package dependencies(auto-installed): </span> graphics, scales, forecast, zoo, ggplot2, htmlWidgets, XML, plotly <br /><br /> <span style='font-style:italic'> Supports R versions: </span> R 3.3.1, R 3.3.0, R 3.4.1, MRO 3.3.1, MRO 3.3.0, MRO 3.2.2 <br /></span>",
|
||||
"supportUrl": "http://community.powerbi.com/",
|
||||
"gitHubUrl": "https://github.com/microsoft/PowerBI-visuals-forcasting-exp"
|
||||
},
|
||||
"apiVersion": "1.7.0",
|
||||
"apiVersion": "1.10.0",
|
||||
"author": {
|
||||
"name": "Microsoft",
|
||||
"email": "pbicvsupport@microsoft.com"
|
||||
|
@ -17,8 +17,11 @@
|
|||
"assets": {
|
||||
"icon": "assets/icon.png"
|
||||
},
|
||||
"externalJS": [],
|
||||
"externalJS": [
|
||||
"node_modules/powerbi-visuals-utils-dataviewutils/lib/index.js"
|
||||
],
|
||||
"style": "style/visual.less",
|
||||
"capabilities": "capabilities.json",
|
||||
"dependencies": "dependencies.json"
|
||||
"dependencies": "dependencies.json",
|
||||
"stringResources": []
|
||||
}
|
||||
|
|
|
@ -115,5 +115,14 @@ FindSrcReplacement <- function(str)
|
|||
str = paste('https://cdn.plot.ly/plotly-', verstr,'.min.js', sep='')
|
||||
return(str)
|
||||
}
|
||||
#ReadFullFileReplaceString
|
||||
ReadFullFileReplaceString <- function(fnameIn, fnameOut, sourceString,targetString)
|
||||
{
|
||||
if(!file.exists(fnameIn))
|
||||
return(NULL)
|
||||
|
||||
tx <- readLines(fnameIn)
|
||||
tx2 <- gsub(pattern = sourceString, replace = targetString, x = tx)
|
||||
writeLines(tx2, con = fnameOut)
|
||||
}
|
||||
#################################################
|
||||
|
||||
|
|
158
script.r
158
script.r
|
@ -29,21 +29,11 @@
|
|||
source('./r_files/flatten_HTML.r')
|
||||
|
||||
############### Library Declarations ###############
|
||||
libraryRequireInstall("ggplot2");
|
||||
libraryRequireInstall("ggplot2")
|
||||
libraryRequireInstall("plotly")
|
||||
libraryRequireInstall("caTools")
|
||||
####################################################
|
||||
|
||||
#DEBUG
|
||||
# fileRda = "C:/Users/boefraty/projects/PBI/R/tempData.Rda"
|
||||
# if(file.exists(dirname(fileRda)))
|
||||
# {
|
||||
# if(Sys.getenv("RSTUDIO")!="")
|
||||
# load(file= fileRda)
|
||||
# else
|
||||
# save(list = ls(all.names = TRUE), file=fileRda)
|
||||
# }
|
||||
|
||||
|
||||
Sys.setlocale("LC_ALL","English") # Internationalization
|
||||
|
||||
############ User Parameters #########
|
||||
|
@ -106,20 +96,34 @@ drawConfidenceLevels = TRUE
|
|||
if(exists("settings_conf_params_show"))
|
||||
drawConfidenceLevels = settings_conf_params_show
|
||||
|
||||
|
||||
lowerConfInterval = 0.8
|
||||
if (exists("settings_conf_params_percentile"))
|
||||
{
|
||||
lowerConfInterval = as.numeric(settings_conf_params_percentile)/100
|
||||
if(is.na(lowerConfInterval))
|
||||
lowerConfInterval = 0.8
|
||||
|
||||
lowerConfInterval = max(min(lowerConfInterval,0.99),0)
|
||||
##PBI_PARAM: Confidence level
|
||||
#Type:enum, Default:"0.8", Range:NA, PossibleValues:0, 0.5 etc, Remarks: NA
|
||||
confInterval1 = 0.8
|
||||
if(exists("settings_conf_params_confInterval1"))
|
||||
{
|
||||
confInterval1 = as.numeric(settings_conf_params_confInterval1)
|
||||
}
|
||||
|
||||
upperConfInterval = 0.98
|
||||
if (exists("settings_conf_params_upperConfIntervalFactor"))
|
||||
{ upperConfInterval = lowerConfInterval+(1-lowerConfInterval)*as.numeric(settings_conf_params_upperConfIntervalFactor)}
|
||||
|
||||
##PBI_PARAM: Confidence level
|
||||
#Type:enum, Default:"0.95", Range:NA, PossibleValues:0, 0.5 etc, Remarks: NA
|
||||
confInterval2 = 0.95
|
||||
if(exists("ssettings_conf_params_confInterval2"))
|
||||
{
|
||||
confInterval2 = as.numeric(settings_conf_params_confInterval2)
|
||||
}
|
||||
|
||||
|
||||
if(confInterval1 > confInterval2)
|
||||
{#switch places
|
||||
temp = confInterval1
|
||||
confInterval1 = confInterval2
|
||||
confInterval2 = temp
|
||||
}
|
||||
|
||||
lowerConfInterval = confInterval1
|
||||
upperConfInterval = confInterval2
|
||||
|
||||
|
||||
if(drawConfidenceLevels==FALSE)
|
||||
lowerConfInterval=upperConfInterval=0
|
||||
|
@ -164,6 +168,23 @@ cexSub = 0.75
|
|||
if(exists("settings_additional_params_textSize"))
|
||||
cexSub = as.numeric(settings_additional_params_textSize)/12
|
||||
|
||||
##PBI_PARAM: export out data to HTML?
|
||||
#Type:logical, Default:FALSE, Range:NA, PossibleValues:NA, Remarks: NA
|
||||
keepOutData = FALSE
|
||||
if(exists("settings_export_params_show"))
|
||||
keepOutData = settings_export_params_show
|
||||
|
||||
##PBI_PARAM: method of export interface
|
||||
#Type: string , Default:"copy", Range:NA, PossibleValues:"copy", "download", Remarks: NA
|
||||
exportMethod = "copy"
|
||||
if(exists("settings_export_params_method"))
|
||||
exportMethod = settings_export_params_method
|
||||
|
||||
##PBI_PARAM: limit the out table exported
|
||||
#Type: string , Default:1000, Range:NA, PossibleValues:"1000", "10000", Inf, Remarks: NA
|
||||
limitExportSize = 1000
|
||||
if(exists("settings_export_params_limitExportSize"))
|
||||
limitExportSize = as.numeric(settings_export_params_limitExportSize)
|
||||
|
||||
###############Internal parameters definitions#################
|
||||
|
||||
|
@ -376,6 +397,65 @@ getAngleXlabels = function(mylabels)
|
|||
|
||||
}
|
||||
|
||||
ConvertDF64encoding = function (df, withoutEncoding = FALSE)
|
||||
{
|
||||
header_row <- paste(names(df), collapse=", ")
|
||||
tab <- apply(df, 1, function(x)paste(x, collapse=", "))
|
||||
|
||||
if(withoutEncoding){
|
||||
text <- paste(c(header_row, tab), collapse="\n")
|
||||
x <- text
|
||||
}
|
||||
else
|
||||
{
|
||||
text <- paste(c(header_row, tab), collapse="\n")
|
||||
x <- caTools::base64encode(text)
|
||||
}
|
||||
return(x)
|
||||
}
|
||||
|
||||
|
||||
KeepOutDataInHTML = function(df, htmlFile = 'out.html', exportMethod = "copy", limitExportSize = 1000)
|
||||
{
|
||||
if(nrow(df)>limitExportSize)
|
||||
df = df[1:limitExportSize,]
|
||||
|
||||
outDataString64 = ConvertDF64encoding(df)
|
||||
|
||||
linkElem = '\n<a href="" download="data.csv" style="position: absolute; top:0px; left: 0px; z-index: 20000;" id = "mydataURL">export</a>\n'
|
||||
updateLinkElem = paste('<script>\n link_element = document.getElementById("mydataURL");link_element.href = outDataString64href;', '\n</script> ', sep =' ')
|
||||
var64 = paste('<script> outDataString64 ="', outDataString64, '"; </script>', sep ="")
|
||||
var64href = paste('<script> outDataString64href ="data:;base64,', outDataString64, '"; </script>', sep ="")
|
||||
|
||||
buttonElem = '<button style="position: absolute; top:0px; left: 0px; z-index: 20000;" onclick="myFunctionCopy(1)">copy to clipboard</button>'
|
||||
funcScript = '<script>
|
||||
function myFunctionCopy(is64)
|
||||
{
|
||||
const el = document.createElement("textarea");
|
||||
if(is64)
|
||||
{
|
||||
el.value = atob(outDataString64);
|
||||
}
|
||||
else
|
||||
{
|
||||
el.value = outDataStringPlane;
|
||||
}
|
||||
document.body.appendChild(el);
|
||||
el.select();
|
||||
document.execCommand("copy");
|
||||
document.body.removeChild(el);};
|
||||
</script>'
|
||||
|
||||
if(exportMethod == "copy")
|
||||
endOfBody = paste(var64,funcScript, buttonElem,'\n</body>',sep ="")
|
||||
else#"download"
|
||||
endOfBody = paste(linkElem,var64, var64href,updateLinkElem,'\n</body>',sep ="")
|
||||
|
||||
ReadFullFileReplaceString('out.html', 'out.html', '</body>', endOfBody)
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
###############Upfront input correctness validations (where possible)#################
|
||||
|
||||
|
@ -592,7 +672,29 @@ p <- config(p, staticPlot = FALSE, editable = FALSE, sendData = FALSE, showLink
|
|||
displaylogo = FALSE, collaborate = FALSE, cloud=FALSE)
|
||||
|
||||
internalSaveWidget(p, 'out.html')
|
||||
####################################################
|
||||
#display in R studio
|
||||
# if(Sys.getenv("RSTUDIO")!="")
|
||||
# print(p)
|
||||
|
||||
# resolve bug in plotly (margin of 40 px)
|
||||
ReadFullFileReplaceString('out.html', 'out.html', ',"padding":40,', ',"padding":0,')
|
||||
|
||||
if(keepOutData)
|
||||
{
|
||||
padNA1 = rep(NA,length(x_full))
|
||||
padNA2 = rep(NA,length(f_full))
|
||||
if(!exists("lower1"))
|
||||
lower1 = lower2 = upper1 = upper2 = padNA2;
|
||||
|
||||
|
||||
lower1 = c(padNA1,lower1)
|
||||
lower2 = c(padNA1,lower2)
|
||||
upper1 = c(padNA1,upper1)
|
||||
upper2 = c(padNA1,upper2)
|
||||
|
||||
exportDF = data.frame(Date = as.character(c(x_full,f_full)),Value = c(y1,y2),
|
||||
lower1 = lower1,
|
||||
lower2 = lower2,
|
||||
upper1 = upper1,
|
||||
upper2 = upper2)
|
||||
colnames(exportDF)[c(1,2)] = c(labTime,labValue)
|
||||
|
||||
KeepOutDataInHTML(df = exportDF, htmlFile = 'out.html', exportMethod = exportMethod, limitExportSize = limitExportSize)
|
||||
}
|
||||
|
|
|
@ -1,29 +1,24 @@
|
|||
module powerbi.extensibility.visual {
|
||||
"use strict";
|
||||
let injectorCounter: number = 0;
|
||||
|
||||
export function ResetInjector() : void {
|
||||
export function ResetInjector(): void {
|
||||
injectorCounter = 0;
|
||||
}
|
||||
|
||||
export function injectorReady() : boolean {
|
||||
export function injectorReady(): boolean {
|
||||
return injectorCounter === 0;
|
||||
}
|
||||
|
||||
export function ParseElement(el: HTMLElement , target: HTMLElement) : Node[]
|
||||
{
|
||||
export function ParseElement(el: HTMLElement, target: HTMLElement): Node[] {
|
||||
let arr: Node[] = [];
|
||||
if (!el || !el.hasChildNodes())
|
||||
return
|
||||
|
||||
let nodes = el.children;
|
||||
for (var i=0; i<nodes.length; i++)
|
||||
{
|
||||
let tempNode: HTMLElement;
|
||||
if (nodes.item(i).nodeName.toLowerCase() === 'script'){
|
||||
if (!el || !el.hasChildNodes()) {
|
||||
return;
|
||||
}
|
||||
let nodes: HTMLCollection = el.children;
|
||||
for (let i: number = 0; i < nodes.length; i++) {
|
||||
let tempNode: HTMLElement;
|
||||
if (nodes.item(i).nodeName.toLowerCase() === "script") {
|
||||
tempNode = createScriptNode(nodes.item(i));
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
tempNode = <HTMLElement>nodes.item(i).cloneNode(true);
|
||||
}
|
||||
target.appendChild(tempNode);
|
||||
|
@ -31,33 +26,32 @@ module powerbi.extensibility.visual {
|
|||
}
|
||||
return arr;
|
||||
}
|
||||
|
||||
function createScriptNode(refNode: Element): HTMLElement{
|
||||
let script = document.createElement('script');
|
||||
let attr = refNode.attributes;
|
||||
for (var i=0; i<attr.length; i++)
|
||||
{
|
||||
script.setAttribute(attr[i].name, attr[i].textContent);
|
||||
|
||||
if (attr[i].name.toLowerCase() === 'src') {
|
||||
// waiting only for src to finish loading
|
||||
function createScriptNode(refNode: Element): HTMLElement {
|
||||
let script: HTMLScriptElement = document.createElement("script");
|
||||
let attr: NamedNodeMap = refNode.attributes;
|
||||
for (let i: number = 0; i < attr.length; i++) {
|
||||
script.setAttribute(attr[i].name, attr[i].textContent);
|
||||
if (attr[i].name.toLowerCase() === "src") {
|
||||
// waiting only for src to finish loading - async opetation
|
||||
injectorCounter++;
|
||||
script.onload = function() {
|
||||
injectorCounter--;
|
||||
script.onload = () => {
|
||||
injectorCounter--;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
script.innerHTML = refNode.innerHTML;
|
||||
script.innerHTML = refNode.innerHTML;
|
||||
return script;
|
||||
}
|
||||
|
||||
export function RunHTMLWidgetRenderer(): void {
|
||||
let intervalVar = window.setInterval(() => {
|
||||
// rendering HTML which was created by HTMLWidgets package
|
||||
// wait till all tje script elements are loaded
|
||||
let intervalVar: number = window.setInterval(() => {
|
||||
if (injectorReady()) {
|
||||
window.clearInterval(intervalVar);
|
||||
if (window.hasOwnProperty('HTMLWidgets') && window['HTMLWidgets'].staticRender) {
|
||||
window['HTMLWidgets'].staticRender();
|
||||
if (window.hasOwnProperty("HTMLWidgets") && window["HTMLWidgets"].staticRender) {
|
||||
window["HTMLWidgets"].staticRender();
|
||||
}
|
||||
}
|
||||
}, 100);
|
||||
|
|
|
@ -1,149 +0,0 @@
|
|||
module powerbi.extensibility.visual {
|
||||
/**
|
||||
* Gets property value for a particular object.
|
||||
*
|
||||
* @function
|
||||
* @param {DataViewObjects} objects - Map of defined objects.
|
||||
* @param {string} objectName - Name of desired object.
|
||||
* @param {string} propertyName - Name of desired property.
|
||||
* @param {T} defaultValue - Default value of desired property.
|
||||
*/
|
||||
export function getValue<T>(objects: DataViewObjects, objectName: string, propertyName: string, defaultValue: T ): T {
|
||||
if (objects) {
|
||||
let object = objects[objectName];
|
||||
if (object) {
|
||||
let property: T = <T>object[propertyName];
|
||||
if (property !== undefined) {
|
||||
return property;
|
||||
}
|
||||
}
|
||||
}
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets property value for a particular object.
|
||||
*
|
||||
* @function
|
||||
* @param {DataViewObjects} objects - Map of defined objects.
|
||||
* @param {string} objectName - Name of desired object.
|
||||
* @param {string} propertyName - Name of desired property.
|
||||
* @param {T} defaultValue - Default value of desired property.
|
||||
*/
|
||||
export function getValueMinMax<T>(objects: DataViewObjects, objectName: string, propertyName: string, defaultValue: T, minVal: T, maxVal: T ): T {
|
||||
if (objects) {
|
||||
let object = objects[objectName];
|
||||
if (object) {
|
||||
let property: T = <T>object[propertyName];
|
||||
if (property < minVal) {
|
||||
return minVal;
|
||||
}
|
||||
if (property > maxVal) {
|
||||
return maxVal;
|
||||
}
|
||||
if (property !== undefined) {
|
||||
return property;
|
||||
}
|
||||
}
|
||||
}
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Gets property value for a particular object.
|
||||
*
|
||||
* @function
|
||||
* @param {DataViewObjects} objects - Map of defined objects.
|
||||
* @param {string} objectName - Name of desired object.
|
||||
* @param {string} propertyName - Name of desired property.
|
||||
* @param {T} defaultValue - Default value of desired property.
|
||||
*/
|
||||
export function getValueNumberMinMax(objects: DataViewObjects, objectName: string, propertyName: string, defaultValue: number, minValue: number, maxValue: number ) {
|
||||
if (objects) {
|
||||
let object = objects[objectName];
|
||||
if (object) {
|
||||
let property = object[propertyName];
|
||||
if (property !== undefined) {
|
||||
if (property > maxValue) {
|
||||
return maxValue;
|
||||
}
|
||||
if (property < minValue) {
|
||||
return minValue;
|
||||
}
|
||||
return property;
|
||||
}
|
||||
}
|
||||
}
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Gets conditional property value for a particular object of type string
|
||||
*
|
||||
* @function
|
||||
* @param {string} inVal - current value of parameter
|
||||
* @param {string} contrVal - control value
|
||||
* @param {string} contrVal2Compare - specific string to be compared with contrVal
|
||||
* @param {boolean} logic - true / false "logic"
|
||||
* @param {string} outValIfCondTrue - output value if comparison (contrVal == contrVal2Compare) comes out as "logic"
|
||||
*/
|
||||
export function ifStringReturnString(inVal: string, contrVal: string, contrVal2Compare: string, outValIfCondTrue: string, logic: boolean, applyNow: boolean) {
|
||||
if (applyNow && contrVal === contrVal2Compare && logic === true)
|
||||
return outValIfCondTrue;
|
||||
|
||||
if (applyNow && contrVal !== contrVal2Compare && logic === false)
|
||||
return outValIfCondTrue;
|
||||
|
||||
return inVal;
|
||||
}
|
||||
|
||||
export function ifStringReturnStringClustersMethod(numClustersMethods: string, numOfClusters: string) {
|
||||
if (numOfClusters !== "auto")
|
||||
return "None";
|
||||
|
||||
if (numOfClusters === "auto" && numClustersMethods === "None")
|
||||
return "fast";
|
||||
|
||||
return numClustersMethods;
|
||||
}
|
||||
|
||||
export function inMinMax(a: number, mi: number, ma: number) {
|
||||
if (a < mi)
|
||||
return mi;
|
||||
if (a > ma)
|
||||
return ma;
|
||||
return a;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Gets property value for a particular object in a category.
|
||||
*
|
||||
* @function
|
||||
* @param {DataViewCategoryColumn} category - List of category objects.
|
||||
* @param {number} index - Index of category object.
|
||||
* @param {string} objectName - Name of desired object.
|
||||
* @param {string} propertyName - Name of desired property.
|
||||
* @param {T} defaultValue - Default value of desired property.
|
||||
*/
|
||||
export function getCategoricalObjectValue<T>(category: DataViewCategoryColumn, index: number, objectName: string, propertyName: string, defaultValue: T): T {
|
||||
let categoryObjects = category.objects;
|
||||
|
||||
if (categoryObjects) {
|
||||
let categoryObject: DataViewObject = categoryObjects[index];
|
||||
if (categoryObject) {
|
||||
let object = categoryObject[objectName];
|
||||
if (object) {
|
||||
let property: T = <T>object[propertyName];
|
||||
if (property !== undefined) {
|
||||
return property;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return defaultValue;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,71 @@
|
|||
/*
|
||||
* Power BI Visualizations
|
||||
*
|
||||
* Copyright (c) Microsoft Corporation
|
||||
* All rights reserved.
|
||||
* MIT License
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the ""Software""), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
module powerbi.extensibility.visual {
|
||||
"use strict";
|
||||
import DataViewObjectsParser = powerbi.extensibility.utils.dataview.DataViewObjectsParser;
|
||||
export function inMinMax(a: number, mi: number, ma: number) {
|
||||
if (a < mi)
|
||||
return mi;
|
||||
if (a > ma)
|
||||
return ma;
|
||||
return a;
|
||||
}
|
||||
export class VisualSettings extends DataViewObjectsParser {
|
||||
public settings_forecastPlot_params: SettingsForecastPlotParams = new SettingsForecastPlotParams();
|
||||
public settings_conf_params: SettingsConfParams = new SettingsConfParams();
|
||||
public settings_graph_params: SettingsGraphParams = new SettingsGraphParams();
|
||||
public settings_additional_params: SettingsAdditionalParams = new SettingsAdditionalParams();
|
||||
public settings_export_params: SettingsExportParams = new SettingsExportParams();
|
||||
}
|
||||
export class SettingsForecastPlotParams {
|
||||
public forecastLength: number = 10;
|
||||
public seasonType: string = "Automatic";
|
||||
public errorType: string = "Automatic";
|
||||
public trendType: string = "Automatic";
|
||||
public dampingType: string = "Automatic";
|
||||
public targetSeason: string = "Automatic";
|
||||
}
|
||||
export class SettingsConfParams {
|
||||
public show: boolean = true;
|
||||
public confInterval1: string = "0.8";
|
||||
public confInterval2: string = "0.95";
|
||||
}
|
||||
export class SettingsGraphParams {
|
||||
public dataCol: string = "orange";
|
||||
public forecastCol: string = "red";
|
||||
public percentile: number = 40;
|
||||
public weight: number = 10;
|
||||
}
|
||||
export class SettingsAdditionalParams {
|
||||
public showInfo: boolean = true;
|
||||
public textSize: number = 10;
|
||||
}
|
||||
export class SettingsExportParams {
|
||||
public show: boolean = false;
|
||||
public limitExportSize: string = "10000";
|
||||
public method: string = "copy";
|
||||
}
|
||||
}
|
295
src/visual.ts
295
src/visual.ts
|
@ -24,153 +24,72 @@
|
|||
* THE SOFTWARE.
|
||||
*/
|
||||
module powerbi.extensibility.visual {
|
||||
"use strict";
|
||||
|
||||
// in order to improve the performance, one can update the <head> only in the initial rendering.
|
||||
// in order to improve the performance, one can update the <head> only in the initial rendering.
|
||||
// set to 'true' if you are using different packages to create the widgets
|
||||
const updateHTMLHead: boolean = false;
|
||||
const renderVisualUpdateType: number[] = [VisualUpdateType.Resize, VisualUpdateType.ResizeEnd, VisualUpdateType.Resize + VisualUpdateType.ResizeEnd];
|
||||
|
||||
|
||||
interface VisualSettingsForecastPlotParams {
|
||||
show: boolean;
|
||||
forecastLength: number;
|
||||
seasonType: string;
|
||||
errorType: string;
|
||||
trendType: string;
|
||||
dampingType: string;
|
||||
targetSeason: string;
|
||||
}
|
||||
|
||||
interface VisualSettingsConfParams {
|
||||
show: boolean;
|
||||
percentile: number;
|
||||
upperConfIntervalFactor: string;
|
||||
}
|
||||
interface VisualGraphParams {
|
||||
show: boolean;
|
||||
dataCol: string;
|
||||
forecastCol: string;
|
||||
percentile: number;
|
||||
weight: number;
|
||||
}
|
||||
interface VisualAdditionalParams {
|
||||
show: boolean;
|
||||
// showWarnings: boolean;
|
||||
showInfo: boolean;
|
||||
textSize: number;
|
||||
}
|
||||
|
||||
const renderVisualUpdateType: number[] = [
|
||||
VisualUpdateType.Resize,
|
||||
VisualUpdateType.ResizeEnd,
|
||||
VisualUpdateType.Resize + VisualUpdateType.ResizeEnd
|
||||
];
|
||||
|
||||
export class Visual implements IVisual {
|
||||
// private imageDiv: HTMLDivElement;
|
||||
// private imageElement: HTMLImageElement;
|
||||
//HTML
|
||||
private rootElement: HTMLElement;
|
||||
private headNodes: Node[];
|
||||
private bodyNodes: Node[];
|
||||
|
||||
|
||||
|
||||
|
||||
private settings_forecastPlot_params: VisualSettingsForecastPlotParams;
|
||||
private settings_conf_params: VisualSettingsConfParams;
|
||||
private settings_graph_params: VisualGraphParams;
|
||||
private settings_additional_params: VisualAdditionalParams;
|
||||
private settings: VisualSettings;
|
||||
|
||||
public constructor(options: VisualConstructorOptions) {
|
||||
// HTML
|
||||
if(options && options.element)
|
||||
if (options && options.element) {
|
||||
this.rootElement = options.element;
|
||||
|
||||
}
|
||||
this.headNodes = [];
|
||||
this.bodyNodes = [];
|
||||
|
||||
// default parameters
|
||||
this.settings_forecastPlot_params = <VisualSettingsForecastPlotParams>{
|
||||
|
||||
forecastLength: 10,
|
||||
// forecastDate: "9/25/2010 11:00:00 PM",
|
||||
seasonType: "Automatic",
|
||||
errorType: "Automatic",
|
||||
trendType: "Automatic",
|
||||
dampingType: "Automatic",
|
||||
targetSeason: "Automatic"
|
||||
};
|
||||
|
||||
this.settings_conf_params = <VisualSettingsConfParams>{
|
||||
show: true,
|
||||
percentile: 80,
|
||||
upperConfIntervalFactor: "0.5",
|
||||
};
|
||||
|
||||
this.settings_graph_params = <VisualGraphParams>{
|
||||
|
||||
dataCol: "orange",
|
||||
forecastCol: "red",
|
||||
percentile: 40,
|
||||
weight: 10
|
||||
|
||||
};
|
||||
|
||||
this.settings_additional_params = <VisualAdditionalParams>{
|
||||
|
||||
// showWarnings: false,
|
||||
showInfo: true,
|
||||
textSize: 10
|
||||
};
|
||||
}
|
||||
|
||||
public update(options: VisualUpdateOptions) {
|
||||
if (!options || !options.type || !options.viewport)
|
||||
public update(options: VisualUpdateOptions): void {
|
||||
if (!options ||
|
||||
!options.type ||
|
||||
!options.viewport ||
|
||||
!options.dataViews ||
|
||||
options.dataViews.length === 0 ||
|
||||
!options.dataViews[0]) {
|
||||
return;
|
||||
|
||||
let dataViews: DataView[] = options.dataViews;
|
||||
if (!dataViews || dataViews.length === 0)
|
||||
return;
|
||||
|
||||
let dataView: DataView = dataViews[0];
|
||||
if (!dataView || !dataView.metadata)
|
||||
return;
|
||||
|
||||
this.updateObjects(dataView.metadata.objects);
|
||||
|
||||
}
|
||||
const dataView: DataView = options.dataViews[0];
|
||||
this.settings = Visual.parseSettings(dataView);
|
||||
let payloadBase64: string = null;
|
||||
if (dataView.scriptResult && dataView.scriptResult.payloadBase64) {
|
||||
payloadBase64 = dataView.scriptResult.payloadBase64;
|
||||
}
|
||||
|
||||
if (renderVisualUpdateType.indexOf(options.type) === -1) {
|
||||
if (payloadBase64) {
|
||||
this.injectCodeFromPayload(payloadBase64);
|
||||
}
|
||||
} else {
|
||||
this.onResizing(options.viewport);
|
||||
}
|
||||
|
||||
this.onResizing(options.viewport);
|
||||
}
|
||||
|
||||
// HTML
|
||||
public onResizing(finalViewport: IViewport): void {
|
||||
public onResizing(finalViewport: IViewport): void {
|
||||
/* add code to handle resizing of the view port */
|
||||
}
|
||||
|
||||
private injectCodeFromPayload(payloadBase64: string): void {
|
||||
// Inject HTML from payload, created in R
|
||||
private injectCodeFromPayload(payloadBase64: string): void {
|
||||
// inject HTML from payload, created in R
|
||||
// the code is injected to the 'head' and 'body' sections.
|
||||
// if the visual was already rendered, the previous DOM elements are cleared
|
||||
|
||||
ResetInjector();
|
||||
|
||||
if (!payloadBase64)
|
||||
return
|
||||
|
||||
if (!payloadBase64) {
|
||||
return;
|
||||
}
|
||||
// create 'virtual' HTML, so parsing is easier
|
||||
let el: HTMLHtmlElement = document.createElement('html');
|
||||
let el: HTMLHtmlElement = document.createElement("html");
|
||||
try {
|
||||
el.innerHTML = window.atob(payloadBase64);
|
||||
} catch (err) {
|
||||
return;
|
||||
}
|
||||
|
||||
// if 'updateHTMLHead == false', then the code updates the header data only on the 1st rendering
|
||||
// this option allows loading and parsing of large and recurring scripts only once.
|
||||
if (updateHTMLHead || this.headNodes.length === 0) {
|
||||
|
@ -178,154 +97,94 @@ module powerbi.extensibility.visual {
|
|||
let tempNode: Node = this.headNodes.pop();
|
||||
document.head.removeChild(tempNode);
|
||||
}
|
||||
let headList: NodeListOf<HTMLHeadElement> = el.getElementsByTagName('head');
|
||||
let headList: NodeListOf<HTMLHeadElement> = el.getElementsByTagName("head");
|
||||
if (headList && headList.length > 0) {
|
||||
let head: HTMLHeadElement = headList[0];
|
||||
this.headNodes = ParseElement(head, document.head);
|
||||
}
|
||||
}
|
||||
|
||||
// update 'body' nodes, under the rootElement
|
||||
while (this.bodyNodes.length > 0) {
|
||||
let tempNode: Node = this.bodyNodes.pop();
|
||||
this.rootElement.removeChild(tempNode);
|
||||
}
|
||||
let bodyList: NodeListOf<HTMLBodyElement> = el.getElementsByTagName('body');
|
||||
let bodyList: NodeListOf<HTMLBodyElement> = el.getElementsByTagName("body");
|
||||
if (bodyList && bodyList.length > 0) {
|
||||
let body: HTMLBodyElement = bodyList[0];
|
||||
this.bodyNodes = ParseElement(body, this.rootElement);
|
||||
}
|
||||
|
||||
RunHTMLWidgetRenderer();
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* This function gets called by the update function above. You should read the new values of the properties into
|
||||
* your settings object so you can use the new value in the enumerateObjectInstances function below.
|
||||
*
|
||||
* Below is a code snippet demonstrating how to expose a single property called "lineColor" from the object called "settings"
|
||||
* This object and property should be first defined in the capabilities.json file in the objects section.
|
||||
* In this code we get the property value from the objects (and have a default value in case the property is undefined)
|
||||
*/
|
||||
public updateObjects(objects: DataViewObjects) {
|
||||
/*this.settings = <VisualSettings>{
|
||||
lineColor: getFillValue(object, 'settings', 'lineColor', "#333333")
|
||||
};*/
|
||||
|
||||
this.settings_forecastPlot_params = <VisualSettingsForecastPlotParams>{
|
||||
//show: getValue<boolean>(dataView.metadata.objects, 'settings_forecastPlot_params', 'show', false),
|
||||
forecastLength: getValue<number>(objects, 'settings_forecastPlot_params', 'forecastLength', 10),
|
||||
// forecastDate: getValue<string>(dataView.metadata.objects, 'settings_forecastPlot_params', 'forecastDate', "9/25/2010 11:00:00 PM"),
|
||||
seasonType: getValue<string>(objects, 'settings_forecastPlot_params', 'seasonType', "Automatic"),
|
||||
errorType: getValue<string>(objects, 'settings_forecastPlot_params', 'errorType', "Automatic"),
|
||||
trendType: getValue<string>(objects, 'settings_forecastPlot_params', 'trendType', "Automatic"),
|
||||
dampingType: getValue<string>(objects, 'settings_forecastPlot_params', 'dampingType', "Automatic"),
|
||||
targetSeason: getValue<string>(objects, 'settings_forecastPlot_params', 'targetSeason', "Automatic")
|
||||
};
|
||||
|
||||
|
||||
this.settings_conf_params = <VisualSettingsConfParams>{
|
||||
show: getValue<boolean>( objects, 'settings_conf_params', 'show', true),
|
||||
percentile: getValue<number>( objects, 'settings_conf_params', 'percentile', 80),
|
||||
upperConfIntervalFactor: getValue<string>( objects, 'settings_conf_params', 'upperConfIntervalFactor', "0.5"),
|
||||
|
||||
};
|
||||
this.settings_graph_params = <VisualGraphParams>{
|
||||
// show: getValue<boolean>( objects, 'settings_graph_params', 'show', false),
|
||||
dataCol: getValue<string>( objects, 'settings_graph_params', 'dataCol', "orange"),
|
||||
forecastCol: getValue<string>( objects, 'settings_graph_params', 'forecastCol', "red"),
|
||||
percentile: getValue<number>( objects, 'settings_graph_params', 'percentile', 40),
|
||||
weight: getValue<number>( objects, 'settings_graph_params', 'weight', 10),
|
||||
|
||||
};
|
||||
this.settings_additional_params = <VisualAdditionalParams>{
|
||||
|
||||
//show: getValue<boolean>( objects, 'settings_additional_params', 'show', false),
|
||||
// showWarnings: getValue<boolean>( objects, 'settings_additional_params', 'showWarnings', false),
|
||||
showInfo: getValue<boolean>( objects, 'settings_additional_params', 'showInfo', true),
|
||||
textSize: getValue<number>( objects, 'settings_additional_params', 'textSize', 10)
|
||||
}
|
||||
private static parseSettings(dataView: DataView): VisualSettings {
|
||||
return VisualSettings.parse(dataView) as VisualSettings;
|
||||
}
|
||||
|
||||
|
||||
|
||||
//This function gets called for each of the objects defined in the capabilities files and allows you to select which of the
|
||||
//objects and properties you want to expose to the users in the property pane.
|
||||
public enumerateObjectInstances(options: EnumerateVisualObjectInstancesOptions): VisualObjectInstanceEnumeration {
|
||||
let objectName = options.objectName;
|
||||
let objectEnumeration = [];
|
||||
|
||||
switch (objectName) {
|
||||
case 'settings_forecastPlot_params':
|
||||
if (this.settings_forecastPlot_params.trendType !== "None") {
|
||||
objectEnumeration.push({
|
||||
objectName: objectName,
|
||||
properties: {
|
||||
|
||||
|
||||
forecastLength: Math.round(inMinMax(this.settings_forecastPlot_params.forecastLength,1,12000)),
|
||||
trendType: this.settings_forecastPlot_params.trendType,
|
||||
dampingType: this.settings_forecastPlot_params.dampingType,
|
||||
errorType: this.settings_forecastPlot_params.errorType,
|
||||
seasonType: this.settings_forecastPlot_params.seasonType,
|
||||
targetSeason: this.settings_forecastPlot_params.targetSeason
|
||||
},
|
||||
selector: null
|
||||
});
|
||||
if (this.settings.settings_forecastPlot_params.trendType !== "None") {
|
||||
objectEnumeration.push({
|
||||
objectName: objectName,
|
||||
properties: {
|
||||
forecastLength: Math.round(inMinMax(this.settings.settings_forecastPlot_params.forecastLength, 1, 12000)),
|
||||
trendType: this.settings.settings_forecastPlot_params.trendType,
|
||||
dampingType: this.settings.settings_forecastPlot_params.dampingType,
|
||||
errorType: this.settings.settings_forecastPlot_params.errorType,
|
||||
seasonType: this.settings.settings_forecastPlot_params.seasonType,
|
||||
targetSeason: this.settings.settings_forecastPlot_params.targetSeason
|
||||
},
|
||||
selector: null
|
||||
});
|
||||
}
|
||||
else {
|
||||
objectEnumeration.push({
|
||||
objectName: objectName,
|
||||
properties: {
|
||||
|
||||
|
||||
forecastLength: Math.round(inMinMax(this.settings_forecastPlot_params.forecastLength,1,100000)),
|
||||
trendType: this.settings_forecastPlot_params.trendType,
|
||||
errorType: this.settings_forecastPlot_params.errorType,
|
||||
seasonType: this.settings_forecastPlot_params.seasonType,
|
||||
},
|
||||
selector: null
|
||||
});
|
||||
objectName: objectName,
|
||||
properties: {
|
||||
forecastLength: Math.round(inMinMax(this.settings.settings_forecastPlot_params.forecastLength, 1, 100000)),
|
||||
trendType: this.settings.settings_forecastPlot_params.trendType,
|
||||
errorType: this.settings.settings_forecastPlot_params.errorType,
|
||||
seasonType: this.settings.settings_forecastPlot_params.seasonType,
|
||||
},
|
||||
selector: null
|
||||
});
|
||||
}
|
||||
break;
|
||||
|
||||
case 'settings_conf_params':
|
||||
objectEnumeration.push({
|
||||
objectName: objectName,
|
||||
properties: {
|
||||
show: this.settings_conf_params.show,
|
||||
percentile: inMinMax(this.settings_conf_params.percentile, 0, 99),
|
||||
upperConfIntervalFactor: this.settings_conf_params.upperConfIntervalFactor
|
||||
show: this.settings.settings_conf_params.show,
|
||||
confInterval1: this.settings.settings_conf_params.confInterval1,
|
||||
confInterval2: this.settings.settings_conf_params.confInterval2
|
||||
},
|
||||
selector: null
|
||||
});
|
||||
break;
|
||||
|
||||
case 'settings_graph_params':
|
||||
objectEnumeration.push({
|
||||
objectName: objectName,
|
||||
properties: {
|
||||
|
||||
dataCol: this.settings_graph_params.dataCol,
|
||||
forecastCol: this.settings_graph_params.forecastCol,
|
||||
percentile: this.settings_graph_params.percentile,
|
||||
weight: inMinMax(this.settings_graph_params.weight, 1,50)
|
||||
|
||||
dataCol: this.settings.settings_graph_params.dataCol,
|
||||
forecastCol: this.settings.settings_graph_params.forecastCol,
|
||||
percentile: this.settings.settings_graph_params.percentile,
|
||||
weight: inMinMax(this.settings.settings_graph_params.weight, 1, 50)
|
||||
|
||||
},
|
||||
selector: null
|
||||
});
|
||||
break;
|
||||
|
||||
case 'settings_additional_params':
|
||||
if (this.settings_additional_params.showInfo === true) {
|
||||
if (this.settings.settings_additional_params.showInfo === true) {
|
||||
objectEnumeration.push({
|
||||
|
||||
objectName: objectName,
|
||||
properties: {
|
||||
|
||||
// showWarnings: this.settings_additional_params.showWarnings,
|
||||
showInfo: this.settings_additional_params.showInfo,
|
||||
textSize: this.settings_additional_params.textSize
|
||||
showInfo: this.settings.settings_additional_params.showInfo,
|
||||
textSize: this.settings.settings_additional_params.textSize
|
||||
},
|
||||
selector: null
|
||||
});
|
||||
|
@ -335,18 +194,24 @@ module powerbi.extensibility.visual {
|
|||
|
||||
objectName: objectName,
|
||||
properties: {
|
||||
|
||||
// showWarnings: this.settings_additional_params.showWarnings,
|
||||
showInfo: this.settings_additional_params.showInfo,
|
||||
|
||||
showInfo: this.settings.settings_additional_params.showInfo,
|
||||
},
|
||||
selector: null
|
||||
});
|
||||
|
||||
}
|
||||
break;
|
||||
case 'settings_export_params':
|
||||
objectEnumeration.push({
|
||||
objectName: objectName,
|
||||
properties: {
|
||||
show: this.settings.settings_export_params.show,
|
||||
limitExportSize: this.settings.settings_export_params.limitExportSize,
|
||||
method: this.settings.settings_export_params.method
|
||||
},
|
||||
selector: null
|
||||
});
|
||||
break;
|
||||
};
|
||||
|
||||
return objectEnumeration;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,9 +8,10 @@
|
|||
"out": "./.tmp/build/visual.js"
|
||||
},
|
||||
"files": [
|
||||
".api/v1.7.0/PowerBI-visuals.d.ts",
|
||||
".api/v1.10.0/PowerBI-visuals.d.ts",
|
||||
"src/htmlInjectionUtility.ts",
|
||||
"src/objectEnumerationUtility.ts",
|
||||
"node_modules/powerbi-visuals-utils-dataviewutils/lib/index.d.ts",
|
||||
"src/settings.ts",
|
||||
"src/visual.ts"
|
||||
]
|
||||
}
|
||||
|
|
|
@ -63,11 +63,7 @@
|
|||
"no-document-write": true,
|
||||
"no-exec-script": true,
|
||||
"no-function-constructor-with-string-args": true,
|
||||
"no-http-string": [
|
||||
true,
|
||||
"http://www.example.com/?.*",
|
||||
"http://www.examples.com/?.*"
|
||||
],
|
||||
"no-http-string": [true, "http://www.example.com/?.*", "http://www.examples.com/?.*"],
|
||||
"no-inner-html": true,
|
||||
"no-octal-literal": true,
|
||||
"no-reserved-keywords": true,
|
||||
|
@ -80,4 +76,4 @@
|
|||
"react-iframe-missing-sandbox": true,
|
||||
"react-no-dangerous-html": true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче