├── app
├── src
│ ├── auth
│ │ ├── login.html
│ │ ├── auth.html
│ │ ├── register.controller.js
│ │ ├── forgotpassword.controller.js
│ │ ├── login.controller.js
│ │ ├── forgotpassword.html
│ │ ├── loginform.html
│ │ └── register.html
│ ├── services
│ │ ├── preloaders
│ │ │ ├── css
│ │ │ │ └── slack.css
│ │ │ ├── zendesk.js
│ │ │ ├── utils
│ │ │ │ ├── spellcheck.js
│ │ │ │ └── zoom.js
│ │ │ ├── asana.js
│ │ │ ├── custom_app.js
│ │ │ ├── google_calendar.js
│ │ │ ├── jira.js
│ │ │ ├── hipchat.js
│ │ │ ├── freshdesk.js
│ │ │ ├── whatsapp.js
│ │ │ ├── closedotio.js
│ │ │ ├── hangouts.js
│ │ │ ├── gitter.js
│ │ │ ├── salesforce.js
│ │ │ ├── evernote.js
│ │ │ ├── pura.js
│ │ │ ├── confluence.js
│ │ │ ├── google_drive.js
│ │ │ └── bitbucket.js
│ │ ├── dynamicModal.html
│ │ ├── deleteProfile.html
│ │ ├── subscription.html
│ │ ├── testPreload.js
│ │ ├── myModalContent.html
│ │ ├── upgradeModal.html
│ │ ├── shareModal.html
│ │ ├── registerModal.html
│ │ └── referModal.html
│ ├── index
│ │ └── index.html
│ ├── home
│ │ ├── home.html
│ │ └── home.controller.js
│ ├── components
│ │ └── APIInterceptor.service.js
│ ├── app.js
│ ├── servicesList
│ │ └── servicesList.html
│ ├── notificationcenter
│ │ ├── notificationCenter.controller.js
│ │ └── notificationCenter.html
│ └── enabledServices
│ │ └── enabledServices.html
├── images
│ ├── logo.png
│ ├── cross.png
│ ├── 512x512.png
│ ├── loading.gif
│ ├── manageyum.png
│ ├── rolling.gif
│ ├── services
│ │ ├── vk.png
│ │ ├── asana.png
│ │ ├── grape.png
│ │ ├── hibox.png
│ │ ├── icq.png
│ │ ├── jira.png
│ │ ├── mysms.png
│ │ ├── pura.png
│ │ ├── skype.png
│ │ ├── slack.png
│ │ ├── wire.png
│ │ ├── discord.png
│ │ ├── github.png
│ │ ├── gitter.png
│ │ ├── groupme.png
│ │ ├── hipchat.png
│ │ ├── outlook.png
│ │ ├── todoist.png
│ │ ├── wechat.png
│ │ ├── zendesk.png
│ │ ├── basecamp.png
│ │ ├── chatwork.png
│ │ ├── ciscospark.png
│ │ ├── confluence.png
│ │ ├── coupleme.png
│ │ ├── dingtalk.png
│ │ ├── evernote.png
│ │ ├── flowdock.png
│ │ ├── freshdesk.png
│ │ ├── hangouts.png
│ │ ├── intercom.png
│ │ ├── irccloud.png
│ │ ├── linkedin.png
│ │ ├── mattermost.png
│ │ ├── messenger.png
│ │ ├── rocketchat.png
│ │ ├── salesforce.png
│ │ ├── steamchat.png
│ │ ├── teamwork.png
│ │ ├── telegram.png
│ │ ├── tweetdeck.png
│ │ ├── whatsapp.png
│ │ ├── wunderlist.png
│ │ ├── google_drive.png
│ │ ├── googlegmail.png
│ │ ├── googleinbox.png
│ │ ├── producthunt.png
│ │ ├── facebookpages.png
│ │ ├── google_calendar.png
│ │ ├── yahoomessenger.png
│ │ ├── defaultIntegration.png
│ │ ├── zendesk.svg
│ │ ├── helpscout.svg
│ │ ├── custom_app.svg
│ │ ├── twitter.svg
│ │ ├── asana.svg
│ │ ├── bitbucket.svg
│ │ ├── messenger.svg
│ │ ├── wire.svg
│ │ ├── gitter.svg
│ │ ├── outlook.svg
│ │ ├── trello.svg
│ │ ├── tweetdeck.svg
│ │ ├── mattermost.svg
│ │ ├── vk.svg
│ │ ├── linkedin.svg
│ │ ├── telegram.svg
│ │ ├── intercom.svg
│ │ ├── flowdock.svg
│ │ ├── wechat.svg
│ │ ├── groupme.svg
│ │ ├── whatsapp.svg
│ │ ├── hipchat.svg
│ │ ├── discord.svg
│ │ └── coupleme.svg
│ ├── windock
│ │ ├── win-dock-alert-1.png
│ │ ├── win-dock-alert-2.png
│ │ ├── win-dock-alert-3.png
│ │ ├── win-dock-alert-4.png
│ │ ├── win-dock-alert-5.png
│ │ ├── win-dock-alert-6.png
│ │ ├── win-dock-alert-7.png
│ │ ├── win-dock-alert-8.png
│ │ ├── win-dock-alert-9.png
│ │ ├── win-dock-alert.png
│ │ └── win-dock-alert-10.png
│ ├── facebook.svg
│ ├── close.svg
│ ├── add.svg
│ ├── edit.svg
│ ├── envelope.svg
│ ├── twitter.svg
│ ├── heart.svg
│ ├── notification_on.svg
│ ├── notification_off.svg
│ ├── applogo.svg
│ ├── clearcache.svg
│ ├── right-chevron.svg
│ └── cog.svg
├── fonts
│ ├── 1YwB1sO8YE1Lyjf12WNiUA.woff2
│ └── UyBMtLsHKBKXelqf4x7VRQ.woff2
├── package.json
├── helpers
│ ├── external_links.js
│ └── context_menu.js
└── app.html
├── .jshintrc
├── resources
├── osx
│ ├── _DS_Store
│ ├── icon.icns
│ ├── 256x256.png
│ ├── dmg-icon.icns
│ ├── dmg-background.png
│ ├── dmg-background@2x.png
│ └── dmg-background@2x.png.png
├── windows
│ ├── icon.ico
│ ├── _DS_Store
│ └── setup-icon.ico
└── icons
│ └── 512x512.png
├── config
├── env_test.json
├── env_production.json
└── env_development.json
├── gulpfile.js
├── src
├── menu
│ ├── file_menu_template.js
│ ├── window_menu_template.js
│ ├── dev_menu_template.js
│ ├── help_menu_template.js
│ ├── edit_menu_template.js
│ └── view_menu_template.js
├── hello_world
│ ├── hello_world.js
│ └── hello_world.spec.js
├── env.js
├── stylesheets
│ └── main.less
├── src
│ └── servicesList
│ │ ├── servicesList.html
│ │ └── servicesList.controller.js
├── app.js
└── helpers
│ └── window.js
├── tasks
├── utils.js
├── start.js
├── build_app.js
├── build_tests.js
└── bundle.js
├── .gitignore
├── .editorconfig
├── .travis.yml
├── scripts
├── travis-build.sh
└── istanbul-reporter.js
├── e2e
├── hello_world.e2e.js
└── utils.js
├── appveyor.yml
├── LICENSE
├── README.md
└── package.json
/app/src/auth/login.html:
--------------------------------------------------------------------------------
1 |
12 | // google 13 | // bing 14 | //
15 | 16 | (function () { 17 | 'use strict'; 18 | 19 | var shell = require('electron').shell; 20 | 21 | var supportExternalLinks = function (e) { 22 | var href; 23 | var isExternal = false; 24 | 25 | var checkDomElement = function (element) { 26 | if (element.nodeName === 'A') { 27 | href = element.getAttribute('href'); 28 | } 29 | if (element.classList.contains('js-external-link')) { 30 | isExternal = true; 31 | } 32 | if (href && isExternal) { 33 | shell.openExternal(href); 34 | e.preventDefault(); 35 | } else if (element.parentElement) { 36 | checkDomElement(element.parentElement); 37 | } 38 | }; 39 | 40 | checkDomElement(e.target); 41 | }; 42 | 43 | document.addEventListener('click', supportExternalLinks, false); 44 | }()); 45 | -------------------------------------------------------------------------------- /app/images/services/messenger.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /tasks/build_app.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var gulp = require('gulp'); 4 | var less = require('gulp-less'); 5 | var watch = require('gulp-watch'); 6 | var batch = require('gulp-batch'); 7 | var plumber = require('gulp-plumber'); 8 | var jetpack = require('fs-jetpack'); 9 | var bundle = require('./bundle'); 10 | var utils = require('./utils'); 11 | 12 | var projectDir = jetpack; 13 | var srcDir = jetpack.cwd('./src'); 14 | var destDir = jetpack.cwd('./app'); 15 | 16 | gulp.task('bundle', function () { 17 | return Promise.all([ 18 | bundle(srcDir.path('background.js'), destDir.path('background.js')), 19 | bundle(srcDir.path('app.js'), destDir.path('app.js')), 20 | ]); 21 | }); 22 | 23 | gulp.task('less', function () { 24 | return gulp.src(srcDir.path('stylesheets/main.less')) 25 | .pipe(plumber()) 26 | .pipe(less()) 27 | .pipe(gulp.dest(destDir.path('stylesheets'))); 28 | }); 29 | 30 | gulp.task('environment', function () { 31 | var configFile = 'config/env_' + utils.getEnvName() + '.json'; 32 | projectDir.copy(configFile, destDir.path('env.json'), { overwrite: true }); 33 | }); 34 | 35 | gulp.task('watch', function () { 36 | var beepOnError = function (done) { 37 | return function (err) { 38 | if (err) { 39 | utils.beepSound(); 40 | } 41 | done(err); 42 | }; 43 | }; 44 | 45 | watch('src/**/*.js', batch(function (events, done) { 46 | gulp.start('bundle', beepOnError(done)); 47 | })); 48 | watch('src/**/*.less', batch(function (events, done) { 49 | gulp.start('less', beepOnError(done)); 50 | })); 51 | }); 52 | 53 | gulp.task('build', ['bundle', 'less', 'environment']); 54 | -------------------------------------------------------------------------------- /app/images/services/wire.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /app/images/services/gitter.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /src/menu/edit_menu_template.js: -------------------------------------------------------------------------------- 1 | import { 2 | app, 3 | BrowserWindow 4 | } from 'electron'; 5 | 6 | export var editMenuTemplate = { 7 | label: 'Edit', 8 | submenu: [{ 9 | label: "Undo", 10 | accelerator: "CmdOrCtrl+Z", 11 | selector: "undo:" 12 | }, 13 | { 14 | label: "Redo", 15 | accelerator: "Shift+CmdOrCtrl+Z", 16 | selector: "redo:" 17 | }, 18 | { 19 | type: "separator" 20 | }, 21 | { 22 | label: "Cut", 23 | accelerator: "CmdOrCtrl+X", 24 | selector: "cut:" 25 | }, 26 | { 27 | label: "Copy", 28 | accelerator: "CmdOrCtrl+C", 29 | selector: "copy:" 30 | }, { 31 | label: "Copy Current Page URL", 32 | click: function(e, l) { 33 | console.log('Copy current page url'); 34 | BrowserWindow.getFocusedWindow().webContents.send('copyCurrentPageURL', { 35 | msg: 'hello from main process' 36 | }); 37 | } 38 | }, 39 | { 40 | label: "Clear Current Page Cache", 41 | click: function(e, l) { 42 | console.log('Clear current page cache'); 43 | BrowserWindow.getFocusedWindow().webContents.send('clearCache', { 44 | msg: 'hello from main process' 45 | }); 46 | } 47 | }, 48 | { 49 | label: "Paste", 50 | accelerator: "CmdOrCtrl+V", 51 | selector: "paste:" 52 | }, 53 | { 54 | label: "Select All", 55 | accelerator: "CmdOrCtrl+A", 56 | selector: "selectAll:" 57 | } 58 | ] 59 | }; 60 | -------------------------------------------------------------------------------- /app/helpers/context_menu.js: -------------------------------------------------------------------------------- 1 | // This gives you default context menu (cut, copy, paste) 2 | // in all input fields and textareas across your app. 3 | 4 | (function () { 5 | 'use strict'; 6 | 7 | var remote = require('electron').remote; 8 | var Menu = remote.Menu; 9 | var MenuItem = remote.MenuItem; 10 | 11 | var isAnyTextSelected = function () { 12 | return window.getSelection().toString() !== ''; 13 | }; 14 | 15 | var cut = new MenuItem({ 16 | label: "Cut", 17 | click: function () { 18 | document.execCommand("cut"); 19 | } 20 | }); 21 | 22 | var copy = new MenuItem({ 23 | label: "Copy", 24 | click: function () { 25 | document.execCommand("copy"); 26 | } 27 | }); 28 | 29 | var paste = new MenuItem({ 30 | label: "Paste", 31 | click: function () { 32 | document.execCommand("paste"); 33 | } 34 | }); 35 | 36 | var normalMenu = new Menu(); 37 | normalMenu.append(copy); 38 | 39 | var textEditingMenu = new Menu(); 40 | textEditingMenu.append(cut); 41 | textEditingMenu.append(copy); 42 | textEditingMenu.append(paste); 43 | 44 | document.addEventListener('contextmenu', function (e) { 45 | switch (e.target.nodeName) { 46 | case 'TEXTAREA': 47 | case 'INPUT': 48 | e.preventDefault(); 49 | textEditingMenu.popup(remote.getCurrentWindow()); 50 | break; 51 | default: 52 | if (isAnyTextSelected()) { 53 | e.preventDefault(); 54 | normalMenu.popup(remote.getCurrentWindow()); 55 | } 56 | } 57 | }, false); 58 | 59 | }()); 60 | -------------------------------------------------------------------------------- /app/images/services/outlook.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /app/images/services/trello.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /app/src/services/preloaders/asana.js: -------------------------------------------------------------------------------- 1 | require('./utils/spellcheck.js'); 2 | require('./utils/zoom.js'); 3 | 4 | 5 | const { ipcRenderer } = require('electron'); 6 | 7 | var notificationMap = {}; 8 | 9 | var service = null; 10 | 11 | 12 | 13 | function replacePopupWithRedirect() { 14 | var google_auth_button = $('google_auth_button'); 15 | if (google_auth_button) { 16 | var str = google_auth_button.getAttribute('onclick'); 17 | str = str.replace('false', 'true'); 18 | google_auth_button.setAttribute('onclick', str); 19 | } 20 | } 21 | 22 | function getMessages() { 23 | var title = document.title; 24 | var count_indirect = 0; 25 | if (service.custom_badges_conf && service.custom_badges_conf.length > 0) { 26 | if (title.startsWith('●')) { 27 | count_indirect = 1; 28 | } 29 | } 30 | ipcRenderer['sendToHost']('notification-count', { 31 | count: 0, 32 | count_indirect: count_indirect 33 | }) 34 | } 35 | 36 | 37 | function initIpcListener() { 38 | ipcRenderer.on('open-notification', function(event, args) { 39 | console.log('am called'); 40 | 41 | var notification = args; 42 | var onClickFn = notificationMap[notification.title] 43 | 44 | if (onClickFn) { 45 | console.log('inside notificationHandler') 46 | onClickFn(); 47 | } 48 | }); 49 | 50 | ipcRenderer.on('serviceUpdate', function(event, args) { 51 | service = args; 52 | }); 53 | } 54 | 55 | 56 | asana = { 57 | init: function(serviceConfig) { 58 | service = JSON.parse(serviceConfig); 59 | setInterval(getMessages, 1000); 60 | replacePopupWithRedirect(); 61 | initIpcListener(); 62 | console.log("asana preloader initialized"); 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Manageyum 2 | ============== 3 | 4 | 5 | # Quick start 6 | The only development dependency of this project is [Node.js](https://nodejs.org). So just make sure you have it installed. 7 | Then type few commands known to every Node developer... 8 | ``` 9 | git clone https://github.com/sivaramsi/manageyum.git 10 | cd manageyum 11 | npm install 12 | npm start 13 | ``` 14 | ... and boom! You have a running desktop application on your screen. 15 | 16 | 17 | ## Folders for application code 18 | 19 | The application is split between two main folders... 20 | 21 | `src` - this folder is intended for files which need to be transpiled or compiled (files which can't be used directly by electron). 22 | 23 | `app` - contains all static assets (put here images, css, html etc.) which don't need any pre-processing. 24 | 25 | The build process compiles all stuff from the `src` folder and puts it into the `app` folder, so after the build has finished, your `app` folder contains the full, runnable application. 26 | 27 | Treat `src` and `app` folders like two halves of one bigger thing. 28 | 29 | The drawback of this design is that `app` folder contains some files which should be git-ignored and some which shouldn't (see `.gitignore` file). But thanks to this two-folders split development builds are much (much!) faster. 30 | 31 | # Development 32 | 33 | ### Installation 34 | 35 | ``` 36 | npm install 37 | ``` 38 | It will also download Electron runtime and install dependencies for the second `package.json` file inside the `app` folder. 39 | 40 | ### Starting the app 41 | 42 | ``` 43 | npm start 44 | ``` 45 | 46 | ### Adding npm modules to your app 47 | 48 | Remember to add your dependencies to `app/package.json` file: 49 | ``` 50 | cd app 51 | npm install name_of_npm_module --save 52 | ``` 53 | 54 | # License 55 | 56 | Released under the MIT license. 57 | -------------------------------------------------------------------------------- /app/src/services/shareModal.html: -------------------------------------------------------------------------------- 1 |