Skip to content

Commit

Permalink
Merge pull request #1 from withdave/dev
Browse files Browse the repository at this point in the history
Merge in dev for v2.0
  • Loading branch information
withdave authored Aug 10, 2019
2 parents 8f7b901 + cfd5a8d commit 86238dd
Show file tree
Hide file tree
Showing 13 changed files with 182 additions and 58 deletions.
11 changes: 11 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# General
.DS_Store
.AppleDouble
.LSOverride

# Icon must end with two \r
Icon


# Thumbnails
._*
Binary file removed AppIconBuilder.zip
Binary file not shown.
37 changes: 33 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,41 @@ The requirements for a Qlik Sense App Icon are:

This has been packaged as an extension, so just upload it under extensions in the QMC, then navigate to /extensions/AppIconBuilder/AppIconBuilder.html to create some icons.

Note that prior to use, you'll need to configure the background image, and optionally font colours and sizes.
Example implementation:
![Default configuration, with a green logo generated](screenshot.png)

Note that prior to use, you'll need to configure the background image, and optionally font colours and sizes in config.json.

# Configuration

As of v2.0, configuration is via a config.json file. Two templates are included by default:
* qlik_green - uses a partially green background image with white app name text
* qlik_white - uses a fully white background image with dark text

# To do

Current backlog:
* Add config for source image (source, scaling, opacity) or for a single colour background
* Add config for app name (font, colour, size, location)
* Add wrapping for app names
* Add word splitting for app names with words longer than the full width (currently these overflow)
* Add handling for transparent background images
* Add integration with QRS API for auto generation, and to allow pushing into a defined content library

# Done

* Initial version (v1.0)
* Add config for source image (source, scaling, opacity) or for a single colour background (v2.0)
* Add config for app name (font, colour, size, location) (v2.0)
* Add wrapping for app names (v2.0)

# Updates

## v2.0 (dev)

* Moved to using releases
* Tidied up readme and other files around the extension
* Introduced "templates". These are be defined in config.json so that the user can then select between different themes
* Changed file naming so that all alphanumeric characters are permitted in the download file name
* Added some limited error output

## v1.0

* Initial version
Binary file added screenshot.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added src/.DS_Store
Binary file not shown.
Binary file added src/AppIconBuilder/.DS_Store
Binary file not shown.
27 changes: 19 additions & 8 deletions src/AppIconBuilder/AppIconBuilder.html
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<meta name="description" content="">
<meta name="author" content="withdave">
<title>Qlik Sense Icon Generator</title>
<title>Qlik Sense App Icon Builder</title>

<!-- Bootstrap core CSS -->
<link href="css/bootstrap.min.css" rel="stylesheet">
Expand Down Expand Up @@ -37,8 +37,13 @@
<main role="main" class="container">

<div class="qsi-header">
<h1>Qlik Sense App Icon Generator</h1>
<p class="lead">This tool is designed to help you produce standardised, repeatable app icons.</p>
<h1>Qlik Sense App Icon Builder v2.0</h1>
<p class="lead">This tool is designed to help you produce standardised, consistent app icons.</p>
</div>

<div id="qsi-error" class="alert alert-danger" role="alert">
<!-- Error placeholder -->
Error: Please check the console log and ensure javascript is enabled.
</div>

<div class="row">
Expand All @@ -60,8 +65,10 @@ <h3>Icon Config</h3>
</select>
</div>
<div class="qsi-formgroup">
<label for="qsi-bgalpha">Background Alpha (decimal between 0-1)</label>
<input type="text" name="qsi-bgalpha" id="qsi-bgalpha" value="1" class="form-control" />
<label for="qsi-template">Template</label>
<select name="qsi-template" id="qsi-template" class="form-control">
<!-- Populated by config.json file -->
</select>
</div>
<p><button type="submit" class="btn btn-primary">Generate Icon</button></p>
</form>
Expand All @@ -81,9 +88,13 @@ <h3>Generated Icon</h3>
<h3>Tool configuration</h3>
<p>To use this tool effectively:</p>
<ul>
<li>Create a background image of ratio 8:5 (optionally of size 164x108 to match the size the image is rescaled for the Hub, or alternatively of size 190x116 to match the size the image is rescaled to in-app) and store this in the mashup directory as "icon_background.png".</li>
<li>Set the default opacity for the background image, by changing the default value in this HTML file. By default this is fully opaque (1).</li>
<li>Change the default app types, if needed. The defaults are "Dashboard", "Transform", "Extract" and "Trigger" to signify the purpose of the application the icon is being generated for.</li>
<li>Create a background image of 164x108px (as per Qlik help this should be ratio 8:5, however this doesn't
match to match the size the image is rescaled for the Hub, or alternatively of size 190x116 to match the
size the image is rescaled to in-app) and store this in the mashup directory as "icon_background.png".</li>
<li>Set the default opacity for the background image, by changing the default value in this HTML file. By
default this is fully opaque (1).</li>
<li>Change the default app types, if needed. The defaults are "N/A" (blank), "Dashboard", "Transform",
"Extract" and "Trigger" to signify the purpose of the application the icon is being generated for.</li>
</ul>
</div>
</div>
Expand Down
Binary file added src/AppIconBuilder/backgrounds/.DS_Store
Binary file not shown.
Binary file added src/AppIconBuilder/backgrounds/qlik_green.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
File renamed without changes
50 changes: 50 additions & 0 deletions src/AppIconBuilder/config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
{
"templates": {
"qlik_green": {
"background": {
"image": "qlik_green.png",
"imageAlpha": 1,
"colour": "#009844"
},
"appName": {
"font": "Sans-Serif",
"fontSize": 14,
"colour": "#fff",
"align": "left",
"locX": 10,
"locY": 27
},
"appType": {
"font": "Sans-Serif",
"fontSize": 8,
"colour": "#333",
"align": "left",
"locX": 10,
"locY": 96
}
},
"qlik_white": {
"background": {
"image": "qlik_white.png",
"imageAlpha": 1,
"colour": "#fff"
},
"appName": {
"font": "Sans-Serif",
"fontSize": 14,
"colour": "#333",
"align": "left",
"locX": 10,
"locY": 27
},
"appType": {
"font": "Sans-Serif",
"fontSize": 8,
"colour": "#333",
"align": "left",
"locX": 10,
"locY": 96
}
}
}
}
99 changes: 69 additions & 30 deletions src/AppIconBuilder/js/script.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,34 @@
// withdave
// 27/07/2019
// Simple script to build icons the right size for Qlik Sense
// Update reminder: Readme (change log and version), version on HTML H1

// Primary page functions
(function ($) {

// Create a variable to hold the loaded configuration within the parent function
var templateList;

// Hide javascript error as we initialise
$("div#qsi-error").hide();

// Load config from config.json
$.getJSON('config.json', function (data) {
// Just in case we want to take a peek
// console.log(data);
}).done(function (data) {
// Assign object to templateList
templateList = data;
// Populate the template with options
$.each(data.templates, function (template) {
$("<option>").attr("value", template).text(template).appendTo("#qsi-template");
console.log("Recognised template: " + template);
});
}).fail(function () {
console.error("App Icon Builder: Error loading configuration - it's likely that the config.json file isn't structured correctly.")
$("div#qsi-error").show();
$("div#qsi-error").html("Error: There was an error loading config.json. Please check the file and refresh this page.");
});

// Logic to wrap app name text
// Sourced from https://www.html5canvastutorials.com/tutorials/html5-canvas-wrap-text-tutorial/
function wrapText(context, text, x, y, maxWidth, lineHeight) {
Expand All @@ -31,15 +55,40 @@
$("#qsi-config").on("submit", function (e) {
e.preventDefault();

// Get app icon config
// We'd better load that config!
// Determine which config has been selected
// There's no error checking so if the config is invalid it'll error or look odd
var iconTemplate = $("#qsi-template").val();

console.log(templateList.templates[iconTemplate].appName);

// Get app icon config from the form
var appName = $("#qsi-appname").val();
var fileName = "AppIcon_" + appName.replace(/[^a-zA-Z]+/g, "");
var fileName = "AppIcon_" + appName.replace(/[^a-zA-Z0-9]+/g, "");
var appType = $("#qsi-apptype").val().toUpperCase();
var backGroundAlpha = Number($("#qsi-bgalpha").val());

// Now do some in-app config
var appNameSize = 16;
var appTypeSize = 8;
// Get app icon config from the relevant JSON config
// Background
var backgroundAlpha = templateList.templates[iconTemplate].background.imageAlpha;
var backgroundColour = templateList.templates[iconTemplate].background.colour;
var backgroundImg = new Image();
backgroundImg.src = "backgrounds/" + templateList.templates[iconTemplate].background.image;

// App Name
var appNameFont = templateList.templates[iconTemplate].appName.font;
var appNameSize = templateList.templates[iconTemplate].appName.fontSize;
var appNameColour = templateList.templates[iconTemplate].appName.colour;
var appNameAlign = templateList.templates[iconTemplate].appName.align;
var appNameLocX = templateList.templates[iconTemplate].appName.locX;
var appNameLocY = templateList.templates[iconTemplate].appName.locY;

// App type
var appTypeFont = templateList.templates[iconTemplate].appType.font;
var appTypeSize = templateList.templates[iconTemplate].appType.fontSize;
var appTypeColour = templateList.templates[iconTemplate].appType.colour;
var appTypeAlign = templateList.templates[iconTemplate].appType.align;
var appTypeLocX = templateList.templates[iconTemplate].appType.locX;
var appTypeLocY = templateList.templates[iconTemplate].appType.locY;

// Get canvas
var canvas = document.getElementById("qsi-canvas");
Expand All @@ -48,20 +97,12 @@
// Draw a full background on the canvas
context.beginPath();
context.rect(0, 0, canvas.width, canvas.height);
context.fillStyle = "white";
context.fillStyle = backgroundColour;
context.fill();

// Set the background alpha value to 1 if it's not a numeric value
if (isNaN(backGroundAlpha)) {
var backGroundAlpha = 1;
} else {
var backGroundAlpha = Math.min(Math.abs(backGroundAlpha), 1);
};

console.log("Generating icon with name [" + appName + "] and type [" + appType + "]. Background alpha [" + backGroundAlpha + "], filename [" + fileName + "]");
console.log("Generating icon with name [" + appName + "] and type [" + appType + "] with template [" + iconTemplate + "].");

// Prep for background image and load it in
var backgroundImg = new Image();
backgroundImg.onload = function () {

// Work out the aspect ratio of the canvas and draw the background image this size in the centre
Expand All @@ -71,40 +112,38 @@
var centreShift_x = (canvas.width - backgroundImg.width * ratio) / 2;
var centreShift_y = (canvas.height - backgroundImg.height * ratio) / 2;
context.clearRect(0, 0, canvas.width, canvas.height);
context.globalAlpha = backGroundAlpha;
context.globalAlpha = backgroundAlpha;
context.drawImage(backgroundImg, 0, 0, backgroundImg.width, backgroundImg.height,
centreShift_x, centreShift_y, backgroundImg.width * ratio, backgroundImg.height * ratio);
context.globalAlpha = 1;

// Overlay the text for App Name
context.font = appNameSize + "pt Sans-Serif";
context.fillStyle = '#333';
var locationY = 27;
var locationX = 10;
var maxWidth = canvas.width - (locationX * 2);
context.font = appNameSize + "pt " + appNameFont;
context.textAlign = appNameAlign;
context.fillStyle = appNameColour;
var maxWidth = canvas.width - (appNameLocX * 2);
var lineHeight = appNameSize + 8;
wrapText(context, appName, locationX, locationY, maxWidth, lineHeight);
wrapText(context, appName, appNameLocX, appNameLocY, maxWidth, lineHeight);

// Overlay the text for App Type
context.font = appTypeSize + "pt Sans-Serif";
context.fillStyle = '#333';
context.fillText(appType, 10, 96);
context.font = appTypeSize + "pt " + appTypeFont;
context.textAlign = appTypeAlign;
context.fillStyle = appTypeColour;
context.fillText(appType, appTypeLocX, appTypeLocY);

// Now enable the download button and set the name of the button to the icon filename
$("#qsiDownload").prop('disabled', false);
$("#qsiDownload").text("Download [" + fileName + ".png]");

};

// Specify path to background image
backgroundImg.src = "icon_background.png";
});

// Logic to download canvas
$("#qsiDownload").on("click", function () {

// This should be refactored
var fileNameStart = $("#qsiDownload").text().indexOf("_")+1;
var fileNameStart = $("#qsiDownload").text().indexOf("_") + 1;
var fileNameLen = Math.max($("#qsiDownload").text().indexOf(".") - 1 - $("#qsiDownload").text().indexOf("_"), 0);
console.log("Loading filename from position " + fileNameStart + " for " + fileNameLen + " characters.");

Expand Down
16 changes: 0 additions & 16 deletions src/AppIconBuilder/readme.md

This file was deleted.

0 comments on commit 86238dd

Please sign in to comment.