Skip to content

Instantly share code, notes, and snippets.

@theredpea
Last active October 1, 2018 21:10
Show Gist options
  • Save theredpea/d99b3f5ce69a7afa8a3f24cc33e6bdda to your computer and use it in GitHub Desktop.
Save theredpea/d99b3f5ce69a7afa8a3f24cc33e6bdda to your computer and use it in GitHub Desktop.
listitems extension
<!doctype html>
<html><head>
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<title>Qlik Sense: Mashup</title>
<meta charset="utf-8">
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
<meta name="HandheldFriendly" content="True">
<meta name="MobileOptimized" content="320">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0, user-scalable=no">
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-status-bar-style" content="black">
<meta http-equiv="cleartype" content="on">
<link rel="stylesheet" href="../../resources/autogenerated/qlik-styles.css">
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
<script src="../../resources/assets/external/requirejs/require.js"></script>
<script src="listitems.js"></script>
<style>
article.qvobject
{
position:absolute;
overflow: hidden;
padding: 10px;
}
</style>
</head>
<body style="overflow:auto;">
<div class="container-fluid">
<div class="row">
<div class="col-md-12">
<div class="selector-content"></div>
</div>
</div>
<div class="row">
<div class="col-md-12">
<p>Qlik Sense data model documentation generator.</p>
<button class="btn btn-danger" style="margin:0 10px 10px 0;">Generate Docs View</button>
<button class="btn btn-warning" style="margin:0 10px 10px 0;">Generate Docs HTML</button>
<button class="btn btn-info" style="margin:0 10px 10px 0;">Generate Docs as CSV</button>
<div class="doc-html">
<textarea style="width:0; height:0;" name="dochtml"></textarea>
</div>
<div class="doc-gen"></div>
</div>
</div>
</div>
</body></html>
/*
* Basic Mashup template with absolute positioning
* @owner Enter you name here (xxx)
*/
/*
* Fill in host and port for Qlik engine
*/
var prefix = window.location.pathname.substr( 0, window.location.pathname.toLowerCase().lastIndexOf( "/extensions" ) + 1 );
var config = {
host: window.location.hostname,
prefix: prefix,
port: window.location.port,
isSecure: window.location.protocol === "https:"
};
require.config( {
baseUrl: ( config.isSecure ? "https://" : "http://" ) + config.host + (config.port ? ":" + config.port: "") + config.prefix + "resources"
} );
require( ["js/qlik"], function ( qlik ) {
qlik.setOnError( function ( error ) {
alert( error.message );
} );
var app = {};
var global = qlik.getGlobal(config);
//get list of available apps
global.getAppList(function(appList){
var appSelectHTML = "<select id='app-selr'>";
$.each(appList, function(key, value) {
appSelectHTML += '<option value="'+value.qDocId+'">'+ value.qDocName +'</option>'
// appSelectHTML += value.qDocName + '('+ value.qDocId ') ';
});
appSelectHTML += "</select>";
$('.selector-content').html(appSelectHTML+'<button class="btn btn-primary" style="margin:20px 10px 10px 10px;">Connect to app</button>');
$('.btn-primary').on('click', openApp);
//alert(appSelectHTML);
});
//callbacks -- inserted here --
//open apps -- inserted here --
var app = {};
var csvString = "";
$('.btn-info').on('click', generateDocs);
$('.btn-warning').on('click',true, generateDocs);
$('.btn-danger').on('click',false, generateDocs);
//get objects -- inserted here --
//app.getObject('QV01','prgzES');
//create cubes and lists -- inserted here --
function openApp() {
if( $('#app-selr option:selected').val().indexOf('.qvf') > -1 || $('#app-selr option:selected').val().indexOf('.QVF') > -1) {
var appNameOrId = $('#app-selr option:selected').html();
} else {
var appNameOrId = $('#app-selr option:selected').val();
}
console.log("opening", appNameOrId);
app = qlik.openApp(appNameOrId, config);
}
function generateDocs(event) {
var asHTML = event.data;
if(typeof(app) !== 'object') {
alert("App not connected!");
}
app.createGenericObject({
qMeasureListDef: {
qType: 'measure',
qData: {
title: '/qMetaDef/title',
expr: '/qMeasure/qDef'
}
},
qDimensionListDef: {
qType: 'dimension',
qData: {
title: '/qMetaDef/title',
expr: '/qDim'
}
}
}).then(model => {
if(typeof(asHTML)==='undefined') {
//title row
csvString = '"title","description","exprssion/fields","tags","type","number"\r\n';
model.layout.qMeasureList.qItems.forEach(makeCSV, measOrDim);
model.layout.qDimensionList.qItems.forEach(makeCSV, measOrDim);
console.log(csvString);
$('.doc-html textarea').html(csvString);
$('.doc-html textarea').css({"width":"100%", "height":"500px"});
} else {
console.log(model.layout);
var measOrDim = { measOrDimsHTML : ""};
var mainHTML = "";
//model.layout.qMeasureList.qItems.forEach(makePanels);
//makePanels will build measOrDimsHTML
//The second argument measOrDim will be the value of "this" inside the callback function
model.layout.qMeasureList.qItems.forEach(makePanels, measOrDim);
mainHTML += measOrDim.measOrDimsHTML;
measOrDim.measOrDimsHTML = "";
model.layout.qDimensionList.qItems.forEach(makePanels, measOrDim);
mainHTML += measOrDim.measOrDimsHTML;
console.log(mainHTML)
//window.document.body.textContent = measuresHTML;
if(asHTML) {
$('.doc-html textarea').html('<div class="row" >' + mainHTML + '</div>');
$('.doc-html textarea').css({"width":"100%", "height":"500px"});
} else {
$('.doc-gen').html('<div class="row" style="padding:45px;">' + mainHTML + '</div>');
}
}
});
}
function makeCSV(measOrDim, measOrDimIndex) {
if(measOrDim.qMeta.tags.length) {
var theTags = '';
measOrDim.qMeta.tags.forEach(function(tag, tagIndex) {
theTags += tag;
if(measOrDim.qMeta.tags.length-1 !== tagIndex) {
theTags += ', ';
}
});
} else {
var theTags = 'No tags';
}
if(typeof(measOrDim.qData.expr) === 'string') {
//measure use this logic
var expressionOrFields = measOrDim.qData.expr;
} else if (typeof(measOrDim.qData.expr) === 'object') {
//dimensions use this logic
// We need to get all the fields for this dimension, we will collect them into a list like this: "field1, field2,...etc" and store this in expressionOrFields, we will not escape these double quotes because they this is its own field in our CSV
var expressionOrFields = '';
measOrDim.qData.expr.qFieldDefs.forEach(function(field, fieldIndex) {
expressionOrFields += field;
//if we are not on the last iteration, add a comma
if(measOrDim.qData.expr.qFieldDefs.length-1 !== fieldIndex) {
expressionOrFields += ', ';
}
});
expressionOrFields += '';
} else {
var expressionOrFields = "// No expression/fields found";
}
var measOrDimsCSV = '"' + measOrDim.qMeta.title.replace(/"/g,'""') + '","' + measOrDim.qMeta.description.replace(/"/g,'""') + '","' + expressionOrFields.replace(/"/g,'""') + '","' + theTags.replace(/"/g,'""') + '","' + measOrDim.qInfo.qType.replace(/"/g,'""') + '","' + (measOrDimIndex+1) + '"\r\n';
csvString += measOrDimsCSV;
}
function makePanels(measOrDim, measOrDimIndex) {
if(measOrDim.qMeta.tags.length) {
var tagsHtml = makeTags(measOrDim.qMeta.tags);
} else {
var tagsHtml = 'No tags';
}
if(typeof(measOrDim.qData.expr) === 'string') {
var expressionOrFields = measOrDim.qData.expr
var panelClass = "info";
} else if (typeof(measOrDim.qData.expr) === 'object') {
var expressionOrFields = getFields(measOrDim.qData.expr);
var panelClass = "success";
} else {
var expressionOrFields = "// No expression/fields found";
}
var measOrDimPanel = '\
<div class="col col-md-12">\
<div class="panel panel-'+panelClass+'">\
<div class="panel-heading">'+measOrDim.qMeta.title+'</div>\
<div class="panel panel-body">\
<p>Description:'+measOrDim.qMeta.description+'</p>\
<p class="bg-'+panelClass+' text-warning" style="padding:15px;">\
Expression:<br/>\
<strong>'+expressionOrFields+'</strong>\
</p>\
<p>'+tagsHtml+'</p>\
</div>\
<div class="panel-footer"><span class="q-lib-item-count-footer">'+ measOrDim.qInfo.qType + " " + (measOrDimIndex+1) + '</span></div>\
</div>\
</div>';
this.measOrDimsHTML += measOrDimPanel;
}
function makeTags(tagArray) {
var localHtml = '';
tagArray.forEach(function(tag, tagIndex) {
localHtml += '<button class="btn btn-success" style="margin:0 10px 10px 0;">' + tag + '</button>';
//if(tagArray.length === tagIndex-1) {}
});
return localHtml;
}
function getFields(fieldObject) {
var localHtml = '';
fieldObject.qFieldDefs.forEach(function(field, fieldIndex) {
localHtml += '[' + field + '] ';
//if(tagArray.length === tagIndex-1) {}
});
return localHtml;
}
} );
{"type":"mashup","name":"listitems","description":"Basic mashup template with absolute positioning","author":"","homepage":"","keywords":"qlik-sense, visualization, mashup","license":"","repository":"","dependencies":{"qlik-sense":">=1.0.x"}}
listitems.qext;
listitems.html;
listitems.js
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment