diff --git a/.firebaserc b/.firebaserc new file mode 100644 index 0000000..bff1c9c --- /dev/null +++ b/.firebaserc @@ -0,0 +1,5 @@ +{ + "projects": { + "prod": "trello-snooze-8c244" + } +} \ No newline at end of file diff --git a/404.html b/404.html new file mode 100644 index 0000000..01ec007 --- /dev/null +++ b/404.html @@ -0,0 +1,81 @@ + + + + + Page Not Found + + + +

Page Not Found

+

This specified file was not found on this website. Please check the URL for mistakes and try again.

+

Why am I seeing this?

+

This page was generated by the Firebase Command-Line Interface. To modify it, edit the 404.html file in your project's configured public directory.

+ + + diff --git a/database.rules.json b/database.rules.json new file mode 100644 index 0000000..d2b8268 --- /dev/null +++ b/database.rules.json @@ -0,0 +1,6 @@ +{ + "rules": { + ".read": true, + ".write": true + } +} diff --git a/date-picker.css b/date-picker.css new file mode 100644 index 0000000..a68c79b --- /dev/null +++ b/date-picker.css @@ -0,0 +1,3 @@ +#snooze { + margin-top:15px; +} diff --git a/date-picker.html b/date-picker.html new file mode 100644 index 0000000..e4b40cb --- /dev/null +++ b/date-picker.html @@ -0,0 +1,18 @@ + + + + + + + + + + + + +
+

You have to authenticate yourself through the powerup settings

+
+ + + diff --git a/date-picker.js b/date-picker.js new file mode 100644 index 0000000..1e57313 --- /dev/null +++ b/date-picker.js @@ -0,0 +1,50 @@ +var Promise = TrelloPowerUp.Promise; +var t = TrelloPowerUp.iframe(); + +var now = moment.tz(moment.now().valueOf(),moment.tz.guess()) +var fixedFuture = now.add(1,'day').hour(8).minute(0).format() +var rightShit = moment(fixedFuture).format('YYYY-MM-DDTHH:mm') + +t.get('board', 'private', 'auth', null).then(function(auth) { + console.log(auth); + if(auth) { + document.getElementById('content').innerHTML ='

Pick a date

'; + document.getElementById('date').value = rightShit; + document.getElementById('snooze').addEventListener('click', function(){ + var time = document.getElementById('date').value + t.get('board', 'private', 'id', null).then(function(secret) { + var date = moment(time); + t.card('id').then(function(obj) { + $.ajax({ + method: "GET", + url: "https://trello-snooze-webhook.herokuapp.com/close?userid="+secret+"&id="+obj.id+"&unix="+date.valueOf(), + timeout:5500 + }) + .done(function( msg ) { + if(msg.error) { + if(msg.errorobj.status === 401) { + Trello.deauthorize(); + t.popup({ + title: "Authorize", + url: './settings.html' + }); + } + } else { + t.closePopup(); + } + }) + }) + }) + }) + } +}) + +document.getElementById('auth').addEventListener('click', function(){ + t.get('board', 'private', 'auth', null).then(function(auth) { + console.log("BOARD AUTH") + console.log(auth); + t.get('board', 'private', 'id', null).then(function(id) { + console.log(id); + }) + }) +}) diff --git a/firebase.json b/firebase.json new file mode 100644 index 0000000..dd6825b --- /dev/null +++ b/firebase.json @@ -0,0 +1,19 @@ +{ + "database": { + "rules": "database.rules.json" + }, + "hosting": { + "public": "./", + "headers": [ { + "source" : "**", + "headers" : [ { + "key" : "Access-Control-Allow-Origin", + "value" : "*" + } ] + } ], + "ignore" : [ + "server/*", + ".git/" + ] + } +} diff --git a/images/icon-gray.svg b/images/icon-gray.svg new file mode 100644 index 0000000..77774c9 --- /dev/null +++ b/images/icon-gray.svg @@ -0,0 +1,38 @@ + + + Layer 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/images/icon-white.svg b/images/icon-white.svg new file mode 100644 index 0000000..fa7329f --- /dev/null +++ b/images/icon-white.svg @@ -0,0 +1,38 @@ + + + Layer 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/images/logo-old.png b/images/logo-old.png new file mode 100644 index 0000000..788e4d7 Binary files /dev/null and b/images/logo-old.png differ diff --git a/images/logo.png b/images/logo.png new file mode 100644 index 0000000..8b3d9ec Binary files /dev/null and b/images/logo.png differ diff --git a/images/nps.svg b/images/nps.svg new file mode 100644 index 0000000..97a470e --- /dev/null +++ b/images/nps.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/index.html b/index.html new file mode 100644 index 0000000..1616d02 --- /dev/null +++ b/index.html @@ -0,0 +1,4 @@ + + + + diff --git a/manifest.json b/manifest.json new file mode 100644 index 0000000..690fc4f --- /dev/null +++ b/manifest.json @@ -0,0 +1,21 @@ +{ + "name": "Snooze Cards", + "details": "This power-up will allow you to hide Trello cards for a set amount of time then return to your list.", + "icon": { + "url": "./images/logo.png" + }, + "author": "Snorre Lothar von Gohren Edwin", + "capabilities": [ + "board-buttons", + "card-buttons", + "callback", + "card-badges", + "card-detail-badges", + "show-settings" + ], + "connectors": { + "iframe": { + "url": "./index.html" + } + } +} diff --git a/server/.gitignore b/server/.gitignore new file mode 100644 index 0000000..3c3629e --- /dev/null +++ b/server/.gitignore @@ -0,0 +1 @@ +node_modules diff --git a/server/Procfile b/server/Procfile new file mode 100644 index 0000000..09f379e --- /dev/null +++ b/server/Procfile @@ -0,0 +1 @@ +web: node schedule-card-task.js diff --git a/server/package.json b/server/package.json new file mode 100644 index 0000000..b33771b --- /dev/null +++ b/server/package.json @@ -0,0 +1,17 @@ +{ + "name": "server", + "version": "1.0.0", + "description": "backendserver for mye trellotask", + "main": "schedule-card-task.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "author": "Snorrre Lothar von Gohren Edwin (https://github.com/Snorlock)", + "license": "ISC", + "dependencies": { + "body-parser": "^1.15.2", + "express": "^4.14.0", + "firebase": "2.4.2", + "superagent": "^2.3.0" + } +} diff --git a/server/schedule-card-task.js b/server/schedule-card-task.js new file mode 100644 index 0000000..75ee9c3 --- /dev/null +++ b/server/schedule-card-task.js @@ -0,0 +1,111 @@ +var Express = require('express'); +// var Webtask = require('webtask-tools'); +var firebase = require('firebase'); +var bodyParser = require('body-parser'); +var request = require('superagent'); +var app = Express(); + +var myFirebaseRef = new Firebase(process.env.FIREBASEURL); +var timeoutlist = {}; +var appKey = process.env.APPKEY; + +var allowCrossDomain = function(req, res, next) { + res.header('Access-Control-Allow-Origin', '*'); + res.header('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE,OPTIONS'); + res.header('Access-Control-Allow-Headers', 'Content-Type, Authorization, Content-Length, X-Requested-With'); + + // intercept OPTIONS method + if ('OPTIONS' == req.method) { + res.send(200); + } + else { + next(); + } +}; + +app.use(allowCrossDomain); + +app.set('port', (process.env.PORT || 3000)); +app.use(bodyParser.json()); + +// GET +app.get('/', function (req, res) { + myFirebaseRef.child(req.query.id).set({ + token: req.query.value ? req.query.value : "" + }); + res.json({ id: req.query }); +}); + +app.get('/status', function (req, res) { + res.json({ timeouts: timeoutlist }) +}); + +app.get('/close', function (req, res) { + myFirebaseRef.child(req.query.userid).once('value') + .then(function(snapshot) { + console.log(snapshot.val().token) + closeCard(true, req.query.id, snapshot.val().token) + .end(function(err,response){ + if(err) { + console.log(err) + res.json({error:true, errorobj:err}) + } else { + console.log("setting inteervaltask") + postCommentOnCard(req.query.id, snapshot.val().token, 'Card have been archived by SnoozeCards powerup'); + setIntervalTask(req.query.id, snapshot.val().token, req.query.unix) + res.json({error:false}) + } + }) + }) +}); + +var setIntervalTask = function(cardId, token, unix) { + var now = new Date(); + var ms = unix-now.valueOf() + var timoutId = setTimeout(openCardAfterTimeoutExpiration, ms, cardId, token); + timeoutlist[cardId] = timoutId; +} + +var closeCard = function(closed, cardId, token) { + + return request('PUT', 'https://api.trello.com/1/cards/'+cardId+'/closed?key='+appKey+'&token='+token) + .set('Content-Type', 'application/json') + .send({ "value" : closed }) + +} + +var openCardAfterTimeoutExpiration = function(cardId, token) { + request('PUT', 'https://api.trello.com/1/cards/'+cardId+'/closed?key='+appKey+'&token='+token) + .set('Content-Type', 'application/json') + .send({ "value" : false }) + .end(function(err, response) { + if(err) { + console.log("Error on reopening the card"); + console.log(err); + postCommentOnCard(cardId, token, 'Card could not be woken up, because error'); + } else { + console.log("Card reopened"); + postCommentOnCard(cardId, token, 'Card have succesfully been woken up'); + } + }) +} + +var postCommentOnCard = function(cardId, token, message) { + request('POST', 'https://api.trello.com/1/cards/'+cardId+'/actions/comments?key='+appKey+'&token='+token) + .set('Content-Type', 'application/json') + .send({ "text" : message }) + .end(function(err, response) { + if(err) { + console.log("Fallback method did not work!!!!!") + console.log(err) + } else { + console.log("commented on card to keep it updated!") + } + }) +} + +app.listen(app.get('port'), function () { + console.log('Example app listening on port '+app.get('port')); +}); + +// module.exports = Webtask.fromExpress(app); diff --git a/settings.html b/settings.html new file mode 100644 index 0000000..fbd5d29 --- /dev/null +++ b/settings.html @@ -0,0 +1,15 @@ + + + + + + + + +
+

Authorize your account to be able to have the Snooze service hide and show cards for you

+ +
+ + + diff --git a/settings.js b/settings.js new file mode 100644 index 0000000..89f13cb --- /dev/null +++ b/settings.js @@ -0,0 +1,41 @@ +var Promise = TrelloPowerUp.Promise; +var t = TrelloPowerUp.iframe(); + +t.render(function(){ + +}); +console.log(Trello.authorized()) + +var authenticationSuccess = function() { + var secret = TrelloPowerUp.PostMessageIO.randomId(); + console.log("Successful authentication. Token is:" + Trello.token()); + $.ajax({ + method: "GET", + url: "https://trello-snooze-webhook.herokuapp.com?id="+secret+"&value="+Trello.token() + }) + .done(function( msg ) { + t.set('board', 'private', 'auth', 'true') + .then(function() { + t.set('board', 'private', 'id', secret) + .then(function() { + t.closePopup(); + }) + }) + }) +}; +var authenticationFailure = function() { + console.log("Failed authentication"); +}; + +document.getElementById('authorize').addEventListener('click', function(){ + Trello.authorize({ + type: "popup", + name: "SnoozeCards", + scope: { + read: true, + write: true }, + expiration: "never", + success: authenticationSuccess, + error: authenticationFailure + }); +}) diff --git a/snooze.js b/snooze.js new file mode 100644 index 0000000..18e646a --- /dev/null +++ b/snooze.js @@ -0,0 +1,39 @@ +TrelloPowerUp.initialize({ + 'card-buttons': function(t, card) { + return [ + // Button with a nested popup callback + { + icon: './images/logo.png', + text: "Snooze Card", + callback: function(t, card) { + return t.popup({ + title:"Choose date", + url:"./date-picker.html" + }) + } + }]; + }, + 'format-url': function(t, options) { + if(options.url.length > 20) { + return { + icon: './images/trello-icon.png' + + }; + } else { + throw t.NotHandled("Not a handled URL"); + } + }, + 'card-from-url': function(t, options) { + return { + name: 'All New Cards have this name', + desc: 'All New cards have this description' + }; + }, + 'show-settings': function(t, options) { + t.popup({ + title: "Authorize Account", + url: 'settings.html', + height: 250 + }); + } +});