├── Example
└── MasterScriptTemplate.xlsx
├── LICENSE
├── README.md
├── build
├── MasterScript.zip
└── archive
│ ├── MasterScript_1_0_0.zip
│ ├── MasterScript_1_0_1.zip
│ ├── MasterScript_1_0_2.zip
│ ├── MasterScript_1_1_0.zip
│ ├── MasterScript_1_1_1.zip
│ └── MasterScript_1_1_2.zip
└── src
├── MasterScript.css
├── MasterScript.js
├── MasterScript.qext
├── definition.js
├── dialog-template.ng.html
├── template.ng.html
└── wbfolder.wbl
/Example/MasterScriptTemplate.xlsx:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AnalyticsEarth/MasterScript/2eec061dc159d5b1eee885b98ad1f9dca1331a9f/Example/MasterScriptTemplate.xlsx
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2017 Steven Pressland
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # MasterScript
2 |
3 | MasterScript is a utility to easily import Qlik Sense master items from an external table via the Qlik application data model. For those situation where a bulk load of master items is necessary to load a business data dictionary to your application, then MasterScript is the tool for you!
4 |
5 | ## How to get started?
6 | 1. Install the extension via QMC
7 | 1. Load your metadata in the format outlined below to your application data model
8 | 1. Add the MasterScript extension to your application sheet
9 | 1. Open MasterScript
10 | 1. Click "Import Master Items"
11 | 1. Check the status
12 | 1. Delete the MasterScript extension from your application sheet
13 | 1. Build your application
14 |
15 | ## Loading metadata
16 | The metadata required by the extension must be in a pre-defined format, the easiest way to load this is with the sample spreadsheet which has all the required column headers in a single table. It is also possible to use the data transformation capabilities in Qlik Sense to convert to this format once loaded in a different structure.
17 |
18 | The format is designed for ease of manual completion in a spreadsheet, hence the flat nature of the data structure.
19 |
20 | The fields have a "_" prefix so this can be combined with the ___set HidePrefix = '\_'___ option
21 |
22 | ### The data format
23 | * _MasterItemID
24 | * A unique ID for the master item, this will be used to apply updates, so the name of a master item can be changed
25 | * _MasterItemType
26 | * A value of either "Measure" or "Dimension"
27 | * _MasterItemName
28 | * The name for the master item, this will be displayed in the master items panel
29 | * _MasterItemDescription
30 | * The contents for the Description field seen when creating a master item
31 | * _MasterItemColor
32 | * The HEX code to define the master items color. Must be in the format of "#000000"
33 | * _MasterItemTags
34 | * A list of tags to be applied to the master item. tags should be listed using the ";" as a delimiter
35 | * _MasterItemLabel
36 | * The label expression to be displayed on chart axis when using the master item (Qlik Sense September 2017 Onwards)
37 | * _MasterItemExpression1
38 | * The Field name or expression for the measure or dimension
39 | * _MasterItemExpression(2...n)
40 | * Additional fields, when required for a Drill-down Dimension should be added as extra columns using a sequential number in the field title
41 |
42 | ## Once Imported
43 | When you have imported, the extension can be deleted, you can also remove the data table from your script too. If you need to update the master items, just load the extension again (if you have deleted it from the sheet) and update from the source data.
44 |
45 | The master items will be updated based upon the _MasterItemID column.
46 |
47 | There are no dependencies in your app for the extension, or when you share the application for the recipient server to have MasterScript installed. This is just used to importing master items.
48 |
--------------------------------------------------------------------------------
/build/MasterScript.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AnalyticsEarth/MasterScript/2eec061dc159d5b1eee885b98ad1f9dca1331a9f/build/MasterScript.zip
--------------------------------------------------------------------------------
/build/archive/MasterScript_1_0_0.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AnalyticsEarth/MasterScript/2eec061dc159d5b1eee885b98ad1f9dca1331a9f/build/archive/MasterScript_1_0_0.zip
--------------------------------------------------------------------------------
/build/archive/MasterScript_1_0_1.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AnalyticsEarth/MasterScript/2eec061dc159d5b1eee885b98ad1f9dca1331a9f/build/archive/MasterScript_1_0_1.zip
--------------------------------------------------------------------------------
/build/archive/MasterScript_1_0_2.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AnalyticsEarth/MasterScript/2eec061dc159d5b1eee885b98ad1f9dca1331a9f/build/archive/MasterScript_1_0_2.zip
--------------------------------------------------------------------------------
/build/archive/MasterScript_1_1_0.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AnalyticsEarth/MasterScript/2eec061dc159d5b1eee885b98ad1f9dca1331a9f/build/archive/MasterScript_1_1_0.zip
--------------------------------------------------------------------------------
/build/archive/MasterScript_1_1_1.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AnalyticsEarth/MasterScript/2eec061dc159d5b1eee885b98ad1f9dca1331a9f/build/archive/MasterScript_1_1_1.zip
--------------------------------------------------------------------------------
/build/archive/MasterScript_1_1_2.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AnalyticsEarth/MasterScript/2eec061dc159d5b1eee885b98ad1f9dca1331a9f/build/archive/MasterScript_1_1_2.zip
--------------------------------------------------------------------------------
/src/MasterScript.css:
--------------------------------------------------------------------------------
1 | /* CSS */
2 |
3 | .qv-object-aeRWizard > .qv-object-nav{
4 | display: none;
5 | }
6 |
7 | .extensionFrame {
8 | height:100%;
9 | width:100%;
10 | display:table;
11 | min-width:207px;
12 | min-height:118px;
13 | }
14 |
15 | .inputPlaceholderSheet {
16 | text-align: center;
17 | font-weight: bold;
18 | font-size: 1.1em;
19 | padding: 5px;
20 | height:100%;
21 | display:table-cell;
22 | vertical-align:middle;
23 | text-align:center;
24 | }
25 |
26 | .placeholderIconSheet {
27 | font-size: 20px;
28 | padding-bottom: 5px;
29 | }
30 |
31 | .placeholderButtonSheet {
32 | margin-top: 5px;
33 | }
34 |
35 | .wizarddialog {
36 | min-width: 900px;
37 | max-width: 900px;
38 | min-height: 90%;
39 | max-height: 90%;
40 | }
41 |
42 | .warningLeft {
43 | float: left;
44 | clear: none;
45 | font-weight: bold;
46 | font-size: 1.1em;
47 | padding: 5px;
48 | }
49 |
50 |
51 | .column1 {
52 | width:25%;
53 | float:left;
54 | clear:none;
55 | }
56 |
57 | .column2 {
58 | width:10%;
59 | float:left;
60 | clear:none;
61 | }
62 |
63 | .column3 {
64 | width:17%;
65 | float:left;
66 | clear:none;
67 | }
68 |
69 | .column4 {
70 | width:10%;
71 | float:left;
72 | clear:none;
73 | text-align: center;
74 | }
75 |
76 | .column5 {
77 | width:10%;
78 | float:left;
79 | clear:none;
80 | font-weight: bold;
81 | text-align: center;
82 | }
83 |
84 | .topButton {
85 | float:right;
86 | margin-left:10px;
87 | }
88 |
89 | .topTitle {
90 | float: left;
91 | }
92 |
93 | .colorDisc {
94 | width:16px;
95 | height: 16px;
96 | border-radius: 8px;
97 | margin:0 auto;
98 | border:1px solid #CCCCCC;
99 | }
100 |
101 | .fieldoval {
102 | background-color: #E6E6E6;
103 | border-radius: 10px;
104 | padding-left:9px;
105 | padding-right: 9px;
106 | padding-top: 1px;
107 | padding-bottom: 1px;
108 | border: 1px solid #CCCCCC;
109 | float:left;
110 | clear:both;
111 | margin: 1px 0;
112 | }
113 |
114 | .rowHeight {
115 | padding-top: 10px;
116 | padding-bottom: 10px;
117 | }
118 |
119 | .hidden {
120 | display: none;
121 | }
122 |
123 | .errorList {
124 | clear: both;
125 | width: 100%;
126 | margin-top: 40px;
127 | box-sizing: border-box;
128 | }
129 |
130 | .errorList li {
131 | font-weight: bold;
132 | list-style-type: none;
133 | border-radius: 5px;
134 | margin-bottom: 5px;
135 | background-color: #f05555;
136 | padding-left:10px;
137 | padding-right: 10px;
138 | color: #ffffff;
139 | }
140 |
--------------------------------------------------------------------------------
/src/MasterScript.js:
--------------------------------------------------------------------------------
1 | define( [ "qlik",
2 | 'text!./template.ng.html',
3 | './definition',
4 | 'text!./dialog-template.ng.html',
5 | 'css!./MasterScript.css',
6 | 'util'
7 | ],
8 | function ( qlik, template, definition, dialogTemplate, cssStyle, Util) {
9 | 'use strict';
10 | return {
11 | support : {
12 | snapshot: false,
13 | export: false,
14 | exportData : false
15 | },
16 | template: template,
17 | definition: definition,
18 | paint: function ($element,layout){
19 |
20 | layout.navmode = qlik.navigation.getMode();
21 | //console.log($element);
22 |
23 | if(layout.navmode == 'analysis'){
24 | $("#launchButton").removeClass("hidden").addClass("hidden");
25 | }else{
26 | $("#launchButton").removeClass("hidden");
27 | }
28 |
29 | },
30 | controller: ['$scope','luiDialog', function ( $scope, luiDialog) {
31 |
32 |
33 | //console.log($scope);
34 |
35 | $scope.processButton = function($event){
36 |
37 | $scope.openWizard();
38 | };
39 |
40 |
41 | /* This function opens the dialog window when the openWizard() function
42 | is called */
43 | $scope.openWizard = function(){
44 | luiDialog.show({
45 | template: dialogTemplate,
46 | input: {
47 | selectedKey: '',
48 | wizardName: '',
49 | showKey: false,
50 | wizardList: $scope.wizardList,
51 | appModel: $scope.component.model.app,
52 | layout: $scope.layout,
53 | isLoading: false,
54 | enableVizBuild: true,
55 | previewEnabled: false,
56 | buttonState: 0,
57 | buttonTitle: 'Preview Master Items',
58 | buttonIcon: 'view',
59 | warningMessage: '',
60 | masterScriptListInternal: [],
61 | tableReady: false
62 | },
63 | controller: ['$scope', function( $scope ) {
64 | //console.log($scope);
65 |
66 | /* Get current Qlik App and field list */
67 | var app = qlik.currApp(this);
68 |
69 | //app.getList("FieldList", function(reply){
70 | app.createGenericObject({
71 | qFieldListDef:{
72 | qShowHidden:true
73 | }}, function(reply){
74 | //console.log("Field List");
75 | //console.log(reply);
76 | $scope.input.fieldList = reply.qFieldList.qItems.filter(a => a.qName.substring(0,11) == '_MasterItem').map(a => a.qName);
77 | //console.log($scope.input.fieldList);
78 |
79 | if(typeof $scope.input.fieldList != 'undefined'){
80 | var rowCount = Math.floor(10000 / ($scope.input.fieldList.length + 1));
81 | //console.log(rowCount);
82 | $scope.input.masterScriptList = app.createTable(
83 | $scope.input.fieldList,
84 | [{qDef:{qLabel:"_KeyCount",qDef:"count(TOTAL <_MasterItemID> _MasterItemID)"}}],
85 | {rows:rowCount}
86 | );
87 |
88 | var listener = function() {
89 |
90 | $scope.processItems();
91 | };
92 | $scope.input.masterScriptList.OnData.bind( listener ); //bind the listener
93 | $scope.input.tableReady = true;
94 | }
95 |
96 | });
97 |
98 |
99 | /* Set the default tab and create the function which will allow for
100 | the tab to be changed in code */
101 | $scope.tabs = 'tab1';
102 | $scope.make_tab_active = function(tabid) {
103 | $scope.tabs = 'tab'+tabid;
104 | //console.log($scope.tabs);
105 | }
106 |
107 | //$scope.make_tab_active(1);
108 |
109 |
110 | $scope.updateDimList = function(){
111 | var list = {
112 | qInfo: {
113 | qId: "",
114 | qType: "DimensionList"
115 | },
116 | qDimensionListDef: {
117 | qType: 'dimension',
118 | qData: {grouping: '/qDim/qGrouping'}
119 | }
120 | };
121 |
122 | $scope.input.appModel.createSessionObject(list).then((data) => {
123 | $scope.input.dimListObj = data;
124 | $scope.refreshDimList(data);
125 | });
126 | };
127 |
128 | $scope.refreshDimList = function(dimListObj){
129 | dimListObj.getLayout().then((dataLayout) => {
130 | //console.log("Refresh Dim List");
131 | //console.log(dataLayout);
132 | $scope.input.dimList = dataLayout.qDimensionList.qItems;
133 | $scope.processItems();
134 |
135 | });
136 | };
137 |
138 | $scope.updateMesList = function(){
139 | var list = {
140 | qInfo: {
141 | qId: "",
142 | qType: "MeasureList"
143 | },
144 | qMeasureListDef: {
145 | qType: 'measure',
146 | qData: {grouping: '/qMeasure/qGrouping'}
147 | }
148 | };
149 |
150 | $scope.input.appModel.createSessionObject(list).then((data) => {
151 | $scope.input.mesListObj = data;
152 | $scope.refreshMesList(data);
153 | });
154 | };
155 |
156 | $scope.refreshMesList = function(mesListObj){
157 | mesListObj.getLayout().then((dataLayout) => {
158 | //console.log("Refresh Dim List");
159 | //console.log(dataLayout);
160 | $scope.input.mesList = dataLayout.qMeasureList.qItems;
161 | $scope.processItems();
162 | });
163 | };
164 |
165 | $scope.updateDimList();
166 | $scope.updateMesList();
167 |
168 | //console.log("Session Object");
169 | //console.log($scope.input.DimListObj);
170 |
171 |
172 |
173 |
174 |
175 |
176 |
177 |
178 | $scope.process = function(){
179 | //console.log("Process Click");
180 |
181 | $scope.createItems(true);
182 |
183 | };
184 |
185 | $scope.createItems = function(shouldCreate){
186 | var p = [];
187 | $scope.input.masterScriptListInternal.forEach(function(row) {
188 | //console.log(row);
189 |
190 | if(row.rowType == "Dimension"){
191 | var a = $scope.createDimension(row, shouldCreate);
192 | p.push(a);
193 | }
194 | if(row.rowType == "Measure"){
195 | var a = $scope.createMeasure(row, shouldCreate);
196 | //console.log(a);
197 | p.push(a);
198 | }
199 | });
200 |
201 | Promise.all(p).then(values => {
202 | $scope.refreshDimList($scope.input.dimListObj);
203 | $scope.refreshMesList($scope.input.mesListObj);
204 |
205 | });
206 |
207 | };
208 |
209 | $scope.processItems = function(){
210 | if($scope.input.tableReady && $scope.input.masterScriptList.colCount > 1){
211 | var table = $scope.input.masterScriptList;
212 | //console.log(table);
213 | var iDCol = table.getColByName('_MasterItemID');
214 | var typeCol = table.getColByName('_MasterItemType');
215 | var nameCol = table.getColByName('_MasterItemName');
216 | var descCol = table.getColByName('_MasterItemDescription');
217 | var colorCol = table.getColByName('_MasterItemColor');
218 | var tagCol = table.getColByName('_MasterItemTags');
219 | var countCol = table.getColByName('_KeyCount');
220 | var labelExpCol = table.getColByName('_MasterItemLabel');
221 | //console.log("Accumulate Column: " + accumulateCol);
222 |
223 |
224 |
225 | $scope.input.masterScriptList.rows.forEach(function(row, rowNum) {
226 | //console.log(row);
227 | var error = false;
228 | var errors = [];
229 | var fieldsList = [];
230 |
231 | if(row.cells[countCol].qNum > 1){
232 | error = true;
233 | errors.push("Duplicate _MasterItemID Found");
234 | }
235 |
236 | if(row.cells[countCol].qNum == 0){
237 | error = true;
238 | errors.push("Missing _MasterItemID Value");
239 | }
240 |
241 | for(var i = 1; i <= 10; i++)
242 | {
243 | var expCol = table.getColByName('_MasterItemExpression'+i);
244 | var cell = row.cells[expCol];
245 | if(cell && cell.qElemNumber >= 0){
246 | fieldsList.push(cell.qText);
247 | }
248 | }
249 |
250 | var idValue;
251 | if(typeof row.cells[iDCol] != 'undefined'){
252 | idValue = row.cells[iDCol].qText;
253 | }
254 |
255 | if(idValue == '-'){
256 | //idValue = row.cells[nameCol].qText;
257 | error = true;
258 | errors.push('No _MasterItemID - Add MasterItemID to source data');
259 | }
260 |
261 | var descValue;
262 | if(typeof row.cells[descCol] != 'undefined'){
263 | descValue = row.cells[descCol].qText;
264 | }
265 | if(descValue == '-'){
266 | descValue = '';
267 | }
268 |
269 |
270 | var tagsList = [];
271 | if(typeof row.cells[tagCol] != 'undefined'){
272 | tagsList = row.cells[tagCol].qText.split(";");
273 | tagsList = tagsList.filter(a => a !== '-');
274 | tagsList.push(idValue);
275 | }
276 |
277 | var rowDisplay;
278 | if(typeof row.cells[typeCol] != 'undefined'){
279 | rowDisplay = row.cells[typeCol].qText;
280 | }
281 |
282 | var labelExp = '';
283 | if(typeof row.cells[labelExpCol] != 'undefined'){
284 | labelExp = row.cells[labelExpCol].qText;
285 | if(labelExp == '-'){
286 | labelExp = '';
287 | }
288 | }
289 |
290 | if(!(rowDisplay == 'Dimension' || rowDisplay == 'Measure')){
291 | error = true;
292 | errors.push("_MasterItemType does not match either 'Dimension' or 'Measure'")
293 | }
294 |
295 |
296 | if(fieldsList.length > 1 && rowDisplay == "Dimension"){
297 | rowDisplay = "Drill-down Dimension"
298 | }
299 | var prevProcessed = 'Pending';
300 | if(typeof $scope.input.masterScriptListInternal[rowNum] != 'undefined'){
301 | prevProcessed = $scope.input.masterScriptListInternal[rowNum].processed;
302 | }
303 |
304 | var itemData = {
305 | rowNumber:rowNum,
306 | rowType: row.cells[typeCol].qText,
307 | rowDisplayType: rowDisplay,
308 | displayName: row.cells[nameCol].qText,
309 | description: descValue,
310 | color: row.cells[colorCol].qText,
311 | labelExpression: labelExp,
312 | fields: fieldsList,
313 | tags: tagsList,
314 | msId: idValue,
315 | status: "Pending",
316 | processed: prevProcessed,
317 | error: error,
318 | errors: errors
319 | };
320 |
321 | if(itemData.error){
322 | itemData.status = "Error";
323 | itemData.processed = "";
324 | }
325 |
326 | $scope.input.masterScriptListInternal[rowNum] = itemData;
327 | $scope.checkDim(itemData);
328 | $scope.checkMes(itemData);
329 |
330 | });
331 | }
332 |
333 |
334 | //console.log("Complete");
335 | //console.log($scope.input.masterScriptListInternal);
336 |
337 | };
338 |
339 | $scope.checkDim = function(t){
340 | if(!t.error){
341 | var check = false;
342 | $scope.input.dimList.forEach(function(dim){
343 | //console.log(dim);
344 |
345 | if(t.msId == dim.qMeta.masterScriptId){
346 | //console.log("Dim Already Exists: " + t.msId + " " + dim.qMeta.masterScriptId);
347 | t.qId = dim.qInfo.qId;
348 | check = true;
349 | //console.log(t);
350 | }
351 | });
352 | if(t.rowType == "Dimension"){
353 | if(check){
354 | t.status = "Exists";
355 | }else{
356 | t.status = "Not Created";
357 | }
358 | }
359 | }
360 | return check;
361 | };
362 |
363 | $scope.checkMes = function(t){
364 | if(!t.error){
365 | var check = false;
366 | $scope.input.mesList.forEach(function(mes){
367 | //console.log(dim);
368 |
369 | if(t.msId == mes.qMeta.masterScriptId){
370 | //console.log("Measure Already Exists: " + t.msId + " " + mes.qMeta.masterScriptId);
371 | t.qId = mes.qInfo.qId;
372 | check = true;
373 | }
374 | });
375 | if(t.rowType == "Measure"){
376 | if(check){
377 | t.status = "Exists";
378 | }else{
379 | t.status = "Not Created";
380 | }
381 | }
382 |
383 | }
384 | return check;
385 | };
386 |
387 |
388 | /* Create Dimension */
389 | $scope.createDimension = function(t, shouldCreate){
390 | var group = "N";
391 | if(t.fields.length > 1) group = "H";
392 |
393 | var colorBlock = {}
394 |
395 | if(t.color != "-"){
396 | colorBlock = {
397 | baseColor: {
398 | color: t.color,
399 | index: -1
400 | }
401 | };
402 | }
403 | var dimJSON =
404 | {
405 | qInfo: {
406 | qType: "dimension"
407 | },
408 | qDim: {
409 | qGrouping: group,
410 | qFieldDefs: t.fields,
411 | qFieldLabels: t.fields,
412 | title:t.displayName,
413 | qLabelExpression:t.labelExpression,
414 | coloring: colorBlock
415 | },
416 | qMetaDef: {
417 | title:t.displayName,
418 | description:t.description,
419 | tags:t.tags,
420 | masterScriptId:t.msId
421 | }
422 | };
423 |
424 | if(!t.error){
425 | if($scope.checkDim(t)){
426 | if(shouldCreate){
427 | return $scope.input.appModel.getDimension(t.qId).then((data) => {
428 | data.setProperties(dimJSON);
429 | t.processed = "Updated";
430 | });
431 | }
432 | }else{
433 | if(shouldCreate){
434 | return $scope.input.appModel.createDimension(dimJSON).then((data) => {
435 | t.processed = "Created";
436 | });
437 | }
438 | }
439 | }
440 | };
441 |
442 | /* Create Measure */
443 | $scope.createMeasure = function(t, shouldCreate){
444 | var colorBlock = {}
445 |
446 | if(t.color != "-"){
447 | colorBlock = {
448 | baseColor: {
449 | color: t.color,
450 | index: -1
451 | }
452 | };
453 | }
454 |
455 | var mesJSON =
456 | {
457 | qInfo: {
458 | qType: "measure"
459 | },
460 | qMeasure: {
461 | qLabel:t.displayName,
462 | qGrouping: "N",
463 | qDef: t.fields[0],
464 | qExpressions:[],
465 | qActiveExpression: 0,
466 | qLabelExpression:t.labelExpression,
467 | coloring:colorBlock
468 | },
469 | qMetaDef: {
470 | title:t.displayName,
471 | description:t.description,
472 | tags:t.tags,
473 | masterScriptId:t.msId
474 | }
475 | };
476 |
477 | if(!t.error){
478 | if($scope.checkMes(t)){
479 | //console.log("Updating: "+ t.qId);
480 | return $scope.input.appModel.getMeasure(t.qId).then((data) => {
481 | //console.log("Updating Measure");
482 | //console.log(data);
483 | data.setProperties(mesJSON);
484 | t.processed = "Updated";
485 | });
486 | }else{
487 | if(shouldCreate){
488 | return $scope.input.appModel.createMeasure(mesJSON).then((data) => {
489 | t.processed = "Created";
490 | });
491 | }
492 | }
493 | }
494 | };
495 | }]
496 | });
497 | }
498 | }]
499 | };
500 | });
501 |
--------------------------------------------------------------------------------
/src/MasterScript.qext:
--------------------------------------------------------------------------------
1 | {
2 | "name": "MasterScript",
3 | "description": "Create Master Items from a table in your data model",
4 | "type": "visualization",
5 | "version": "1.1.3",
6 | "icon": "library",
7 | "author": "Steven Pressland",
8 | "homepage": "https://github.com/AnalyticsEarth/MasterScript",
9 | "keywords": "qlik-sense, visualization, Master Items",
10 | "license": "",
11 | "repository": "",
12 | "dependencies": {
13 | "qlik-sense": ">=3.0.x"
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/src/definition.js:
--------------------------------------------------------------------------------
1 | define( [], function () {
2 | 'use strict';
3 |
4 | // Appearance section
5 | var appearanceSection = {
6 | uses: "settings",
7 | items: {
8 | general: {
9 | items:{
10 | showTitles:{
11 | defaultValue: false
12 | }
13 | }
14 | }
15 | }
16 | };
17 |
18 |
19 |
20 | // *****************************************************************************
21 | // Main properties panel definition
22 | // Only what is defined here is returned from properties.js
23 | // *****************************************************************************
24 | return {
25 | type: "items",
26 | component: "accordion",
27 | items: {
28 | appearance: appearanceSection
29 | }
30 | };
31 | });
32 |
--------------------------------------------------------------------------------
/src/dialog-template.ng.html:
--------------------------------------------------------------------------------
1 |
8 |
38 |
32 |
34 |