Skip to content
Merged

Rc #473

Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions Jenkinsfile
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,9 @@ pipeline {
}
}
post {
always {
jiraSendBuildInfo site: 'kanocomputing.atlassian.net'
}
regression {
script {
email.notifyCulprits()
Expand Down
4 changes: 2 additions & 2 deletions config/default.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,15 +13,15 @@
"EXTENSIONS": [{
"TYPE": "FILE_TYPE_ASSOCIATION",
"NAME": "make-art",
"LOGO": "assets/kano-draw-windows.png",
"LOGO": "icon/kano-draw-windows.png",
"DISPLAY_NAME": "Make Art",
"SUPPORTED_FILE_TYPES": [{
"CONTENT_TYPE": "text/draw",
"FILE_TYPE": ".draw"
}]
}]
},
"BACKGROUND_COLOR": "#51555c",
"BACKGROUND_COLOR": "#333333",
"CONFIG": {
"DEBUG_LEVEL" : 1,
"PRODUCTION" : false,
Expand Down
201 changes: 10 additions & 191 deletions ga.js

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions kit-app-shell.conf.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ module.exports = {
'./assets/sounds/**/*',
'./assets/summercamp/**/*',
'./assets/*.png',
'./icon/*.png',
'./www/css/**/*',
'./www/directive/**/*',
'./www/fonts/**/*',
Expand Down
9 changes: 8 additions & 1 deletion lib/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -56,8 +56,10 @@ app.run(['$rootScope', '$window', '$location', '_config', ($rootScope, $window,
* Updates the user and loggedIn state in the $rootScope
*/
$rootScope.updateUser = function (user) {
$rootScope.user = user;
if (user) {
const { avatar } = user;
const parsed = new URL(avatar);
user.avatar = `${parsed.origin}/${user.id}/vanilla/head.png`;
$rootScope.loggedIn = true;
if (user.admin_level > 0) {
$rootScope.loadUserProfile(user.id);
Expand All @@ -66,6 +68,7 @@ app.run(['$rootScope', '$window', '$location', '_config', ($rootScope, $window,
} else {
$rootScope.loggedIn = false;
}
$rootScope.user = user;
prepareGamification(api.client, user ? user.id : 'anonymous', 'anonymous')
.then((gamificationClient) => {
$rootScope.gamification = gamificationClient;
Expand Down Expand Up @@ -204,6 +207,10 @@ app.run(['$rootScope', '$window', '$location', '_config', ($rootScope, $window,
var redirection = route.$$route ? route.$$route.redirectTo : null;
$rootScope.basePath = path ? path.split('/')[1] : '';
if (path && !redirection) {
if (window.gtag) {
window.gtag(
'config', window.GA_MEASUREMENT_ID, { page_path: window.location.pathname });
}
Telemetry.trackPageView({ page: window.location.pathname });
}
});
Expand Down
34 changes: 28 additions & 6 deletions lib/directive/display.js
Original file line number Diff line number Diff line change
@@ -1,20 +1,22 @@
"use strict";
import i18n from '../i18n.js';
import app from '../app.js';
import session from '../language/session.js';
import fileUtil from '../util/file.js';
import { throttle } from '../util/throttle.js';
var firstRender = true, THROTTLE_MS, VALIDATE_DELAY, config;

import language from '../language/index.js';
import { setWallpaper } from '../platform/uwp/wallpaper.js';
import { isUWP } from '../platform/index.js';
import notify from '../api/notify.js';
import { renderWallpaper } from '../wallpaper/render-wallpaper.js';
import { saveFile } from '../platform/uwp/file-picker.js';

var firstRender = true, THROTTLE_MS, VALIDATE_DELAY, config;

/*
* Display directive
*
* Handles live updatingm execution of code and rendering coming from its model
*/


app.directive('display', ['$window', '$rootScope', '_config', function ($window, $rootScope, _config) {
config = $rootScope.cfg;
THROTTLE_MS = config.OFFLINE ? 1000 : 1;
Expand All @@ -35,6 +37,18 @@ app.directive('display', ['$window', '$rootScope', '_config', function ($window,
var timer, win = angular.element($window),
loadInput = element.find('input')[0];

scope.setWallpaper = () => {
const width = window.screen.availWidth;
const height = window.screen.availHeight;
const wallpaperCanvas = renderWallpaper(scope.source, width, height);
setWallpaper(wallpaperCanvas).then(() => {
notify.message('Wallpaper updated', 'success');
});
};


scope.canSetWallapper = () => isUWP();

// Attach workspace to scope
scope.workspace = workspaceCtl || null;
/*
Expand Down Expand Up @@ -271,7 +285,15 @@ app.directive('display', ['$window', '$rootScope', '_config', function ($window,

blob = new Blob([scope.source], { type: 'text/plain' });

fileUtil.downloadBlob(blob, 'creation.draw');
if (isUWP()) {
saveFile(blob, 'creation.draw')
.then(() => {
notify.message('Creation saved', 'success');
});
} else {
fileUtil.downloadBlob(blob, 'creation.draw');
}


$rootScope.gamification.trigger({ name: 'make-art-code-written', detail: { count: scope.source.split('\n').length } });
};
Expand Down
2 changes: 1 addition & 1 deletion lib/directive/export-modal.js
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ app.directive('exportModal', ['$rootScope', '$routeParams', '_config', ($rootSco
return;
}

if (!$rootScope.user.attributes.consent) {
if (('consent' in $rootScope.user.attributes) && !$rootScope.user.attributes.consent) {
notify.message('Ask your parents to check their email. \nCurrently, you cannot publish your creations.', 'fail');
scope.close();
return;
Expand Down
7 changes: 5 additions & 2 deletions lib/language/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -64,9 +64,11 @@ function run(code, settings) {
};
}

const post = compiled.js.replace(/\(\)\s?=>/, 'function ()');

// Evaluate compiled JavaScript in build context
try {
evalInContext.bind({})(compiled.js);
evalInContext.bind({})(post);
} catch (err) {
// Trace back error location from compiled source map
var jsLoc = getErrorLocation(err),
Expand Down Expand Up @@ -209,7 +211,7 @@ function evalInContext(code) {
${code}
}`);

const runner = fn()
const runner = fn();

runner(...values);
}
Expand All @@ -220,4 +222,5 @@ export default {
checkValidity: checkValidity,
evalInContext: evalInContext,
cursorPosition: () => session.pos,
getBackground: () => session.settings.bg,
};
5 changes: 5 additions & 0 deletions lib/platform/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
export function isUWP() {
return ('Windows' in window);
}

export default { isUWP };
24 changes: 24 additions & 0 deletions lib/platform/uwp/file-picker.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import { blobToString } from '../../util/file.js';

export function saveFile(blob, filename) {
const savePicker = new Windows.Storage.Pickers.FileSavePicker();
savePicker.SuggestedStartLocation = Windows.Storage.Pickers.PickerLocationId.DocumentsLibrary;
// Dropdown of file types the user can save the file as
savePicker.fileTypeChoices.insert('Make Art Creation', ['.draw']);
// Default file name if the user does not type one in or select a file to replace
savePicker.suggestedFileName = filename;

return savePicker.pickSaveFileAsync()
.then((file) => {
if (!file) {
throw new Error('Could not save file: User cancelled');
}
// Prevent updates to the remote version of the file until
// we finish making changes and call CompleteUpdatesAsync.
Windows.Storage.CachedFileManager.deferUpdates(file);

return blobToString(blob)
.then((contents) => Windows.Storage.FileIO.writeTextAsync(file, contents))
.then(() => Windows.Storage.CachedFileManager.completeUpdatesAsync(file));
});
}
29 changes: 29 additions & 0 deletions lib/platform/uwp/wallpaper.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
function saveWallpaper(canvas) {
const { Storage } = window.Windows;
const blob = canvas.msToBlob();
const input = blob.msDetachStream();
return Storage.ApplicationData.current.localFolder.createFileAsync('wallpaper.png', Storage.CreationCollisionOption.generateUniqueName)
.then(f => f.openAsync(Storage.FileAccessMode.readWrite)
.then((stream) => {
const output = stream.getOutputStreamAt(0);
return Storage.Streams.RandomAccessStream.copyAsync(input, output)
.then(() => stream.flushAsync())
.then(() => {
output.close();
stream.close();
return f;
});
}));
}

export function setWallpaper(canvas) {
const { System } = window.Windows;
const { UserProfilePersonalizationSettings } = System.UserProfile;
return saveWallpaper(canvas)
.then((f) => {
const profileSettings = UserProfilePersonalizationSettings.current;
return profileSettings.trySetWallpaperImageAsync(f);
});
}

export default { setWallpaper };
19 changes: 17 additions & 2 deletions lib/util/file.js
Original file line number Diff line number Diff line change
Expand Up @@ -56,8 +56,23 @@ function downloadBlob(blob, filename) {
document.body.removeChild(link);
}

export function blobToString(blob) {
return new Promise((resolve) => {
const reader = new FileReader();

// This fires after the blob has been read/loaded.
reader.addEventListener('loadend', (e) => {
const text = e.srcElement.result;
resolve(text);
});

// Start reading the blob as text.
reader.readAsText(blob);
});
}

export default {
dataURItoBlob : dataURItoBlob,
downloadBlob : downloadBlob
dataURItoBlob,
downloadBlob,
blobToString,
};
23 changes: 23 additions & 0 deletions lib/wallpaper/render-wallpaper.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import language from '../language/index.js';

export function renderWallpaper(code, width, height) {
const size = Math.min(width, height);
const renderSettings = {};
renderSettings.canvas = document.createElement('canvas');
renderSettings.canvas.width = size;
renderSettings.canvas.height = size;
renderSettings.ctx = renderSettings.canvas.getContext('2d');
renderSettings.width = 500;
renderSettings.height = 500;
renderSettings.ratio = size / 500;
language.run(code, renderSettings);
const bg = language.getBackground();
const finalCanvas = document.createElement('canvas');
finalCanvas.width = width;
finalCanvas.height = height;
const ctx = finalCanvas.getContext('2d');
ctx.fillStyle = bg || '#ffffff';
ctx.fillRect(0, 0, width, height);
ctx.drawImage(renderSettings.canvas, (width - size) / 2, (height - size) / 2);
return finalCanvas;
}
1 change: 1 addition & 0 deletions locales/en/directive.json
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
{
"set_wallpaper": "set as wallpaper",
"save_to_gallery": "save to gallery",
"save_drawing": "save drawing",
"title": "Title",
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "draw",
"version": "1.1.0",
"version": "1.2.0",
"description": "App to learn programming using a basic CoffeeScript drawing API",
"main": "index.js",
"scripts": {
Expand Down
23 changes: 15 additions & 8 deletions styles/elements/display.styl
Original file line number Diff line number Diff line change
Expand Up @@ -48,16 +48,22 @@ display
background #f5f5f5

.actions
position relative
padding-bottom 20px
padding-top 10px
display flex
flex-direction row
align-items center
justify-content space-around
padding 20px 0
text-align center

&.challenge
.position-indicator
position absolute
left 16px

.position-indicator
width 100px
text-align left
display inline-block
margin 7px 15px
position absolute
left 0
font-weight bold
font-size 13px
text-transform uppercase
Expand All @@ -81,12 +87,10 @@ display
.action
smooth-font()
display inline-block
margin 0 15px
text-transform uppercase
font-size 14px
font-weight bold
position relative
top 4px
cursor pointer

&.action-share
Expand All @@ -97,6 +101,9 @@ display

&.action-reset
color color-grey-light

&.action-set-wallpaper
color color-red

&.action-load
color color-orange
Expand Down
1 change: 1 addition & 0 deletions terraform/main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@ module "prod" {
source = "[email protected]:KanoComputing/kes-terraform-modules//modules/aws/s3-cloudfront-website"

fqdn = "art-prod.kano.me"
aliases = ["art.kano.me"]
ssl_certificate_arn = "${aws_acm_certificate_validation.cert.certificate_arn}"
allowed_ips = "${local.cf_ips}"

Expand Down
25 changes: 15 additions & 10 deletions terraform/route53.tf
Original file line number Diff line number Diff line change
Expand Up @@ -3,29 +3,34 @@

resource "aws_acm_certificate" "cert" {
provider = "aws.cloudfront"
domain_name = "*.${var.domain}"
domain_name = "art.kano.me"

subject_alternative_names = ["art-dev.kano.me", "art-staging.kano.me", "art-prod.kano.me"]
validation_method = "DNS"
lifecycle {
create_before_destroy = true
}
}

resource "aws_route53_record" "cert_validation" {
provider = "aws.main"
name = "${aws_acm_certificate.cert.domain_validation_options.0.resource_record_name}"
type = "${aws_acm_certificate.cert.domain_validation_options.0.resource_record_type}"
zone_id = "${data.aws_route53_zone.main.id}"
records = ["${aws_acm_certificate.cert.domain_validation_options.0.resource_record_value}"]
ttl = 60
lifecycle {
count = "4"

provider = "aws.cloudfront"
zone_id = "${element(data.aws_route53_zone.main.*.id, 0)}"

name = "${lookup(aws_acm_certificate.cert.domain_validation_options[count.index], "resource_record_name")}"
type = "${lookup(aws_acm_certificate.cert.domain_validation_options[count.index], "resource_record_type")}"
records = ["${lookup(aws_acm_certificate.cert.domain_validation_options[count.index], "resource_record_value")}"]
ttl = 60

lifecycle {
create_before_destroy = true
}
}

resource "aws_acm_certificate_validation" "cert" {
provider = "aws.cloudfront"
certificate_arn = "${aws_acm_certificate.cert.arn}"
validation_record_fqdns = ["${aws_route53_record.cert_validation.fqdn}"]
validation_record_fqdns = ["${aws_route53_record.cert_validation.*.fqdn}"]
lifecycle {
create_before_destroy = true
}
Expand Down
Loading