├── .editorconfig ├── .gitignore ├── LICENSE ├── README.md ├── TODO.txt └── client ├── .bowerrc ├── app ├── app-module-config.js ├── app.js ├── blocks │ ├── endpoint │ │ ├── endpoint-config-service.js │ │ └── endpoint-module.js │ └── exception │ │ ├── exception-module-config.js │ │ ├── exception-module.js │ │ └── stacktrace-factory.js ├── components │ └── angular-ui-fabric │ │ └── src │ │ ├── ui-fabric-canvas-service.js │ │ ├── ui-fabric-config-service.js │ │ ├── ui-fabric-directive.js │ │ ├── ui-fabric-factory.js │ │ ├── ui-fabric-module-config.js │ │ ├── ui-fabric-module.js │ │ ├── ui-fabric-shape-service.js │ │ ├── ui-fabric-text-service.js │ │ ├── ui-fabric-utils-service.js │ │ └── ui-fabric-window-factory.js ├── data │ ├── containers.json │ ├── font-families.json │ ├── font-sizes.json │ ├── paper-sizes.json │ ├── shapes.json │ └── themes.json ├── help │ ├── angular-fabric │ │ ├── example │ │ │ ├── angular-fabric-codepen.txt │ │ │ ├── example.css │ │ │ ├── example.html │ │ │ ├── example.js │ │ │ └── example.less │ │ ├── fabric-canvas.js │ │ ├── fabric-constants.js │ │ ├── fabric-directive.js │ │ ├── fabric-dirty-status.js │ │ ├── fabric-module.js │ │ ├── fabric-utilities.js │ │ └── fabric-window.js │ ├── container-config-service.js │ ├── format-shape-config-service.js │ ├── hello-world-controller.js │ ├── main-module-config.js │ ├── resize-directive.js │ ├── shape-config-service.js │ ├── temp.html │ └── temp.js ├── locales │ ├── de.json │ ├── en.json │ └── pl.json └── main │ ├── content-resize-directive.js │ ├── main-controller.js │ ├── main-module.js │ ├── models │ ├── containers-model.js │ ├── font-families-model.js │ ├── font-sizes-model.js │ ├── paper-sizes-model.js │ ├── shapes-model.js │ └── themes-model.js │ └── templates │ ├── content.html │ ├── format-diagram.html │ ├── format-shape.html │ ├── header.html │ ├── layout.html │ ├── menubar.html │ ├── sidebar-left.html │ ├── sidebar-right.html │ └── toolbar.html ├── bower.json ├── content ├── css │ └── styles.css └── images │ ├── logical-security-zone-model-diagram.png │ ├── my-2d-diagram-editor-1.png │ ├── my-2d-diagram-editor-2.png │ ├── my-2d-diagram-editor-3.png │ ├── my-2d-diagram-editor-4-english.png │ ├── my-2d-diagram-editor-4-german.png │ ├── my-2d-diagram-editor-4-polish.png │ ├── my-2d-diagram-editor-5-english.png │ ├── my-2d-diagram-editor-6.png │ ├── my-2d-diagram-editor-7.png │ ├── my-2d-diagram-editor-draw-connector-with-arrow.png │ ├── my-2d-diagram-editor-formatting-shapes.png │ ├── my-2d-diagram-editor-interactivity.png │ ├── my-2d-diagram-editor-with-connections-2.png │ ├── my-2d-diagram-editor-with-connections.png │ ├── my-2d-diagram-editor-with-ports-2.png │ ├── my-2d-diagram-editor-with-ports-3.png │ ├── my-2d-diagram-editor-with-ports-4.png │ ├── my-2d-diagram-editor-with-ports.png │ └── my-2d-diagram-editor-with-toobar.png ├── favicon.ico ├── gulp-config.json ├── gulpfile.js ├── index.html └── package.json /.editorconfig: -------------------------------------------------------------------------------- 1 | # http://editorconfig.org 2 | root = true 3 | 4 | [*] 5 | indent_style = space 6 | indent_size = 2 7 | end_of_line = lf 8 | charset = utf-8 9 | trim_trailing_whitespace = true 10 | insert_final_newline = true 11 | 12 | [*.md] 13 | trim_trailing_whitespace = false 14 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Ignore Visual Studio Project # 2 | ################### 3 | *.user 4 | *.gpState 5 | *.suo 6 | bin 7 | obj 8 | /packages 9 | 10 | # Ignore Node & Bower 11 | ################### 12 | node_modules 13 | /modular/client/build 14 | /modular/build 15 | bower_components 16 | **/test/coverage 17 | /reports 18 | 19 | 20 | # mongo db 21 | ################### 22 | #Don't commit Mongo Database files 23 | *.lock 24 | *.0 25 | *.1 26 | *.ns 27 | journal 28 | 29 | # Ignore Web Storm # 30 | .idea 31 | 32 | # Compiled source # 33 | ################### 34 | *.com 35 | *.class 36 | *.dll 37 | *.exe 38 | *.o 39 | *.so 40 | report/ 41 | 42 | # Packages # 43 | ############ 44 | # it's better to unpack these files and commit the raw source 45 | # git has its own built in compression methods 46 | *.7z 47 | *.dmg 48 | *.gz 49 | *.iso 50 | *.jar 51 | *.rar 52 | *.tar 53 | *.xap 54 | *.zip 55 | 56 | # Logs and databases # 57 | ###################### 58 | *.log 59 | *.sql 60 | *.sqlite 61 | # *.sdf 62 | *.mdf 63 | *.ldf 64 | 65 | # OS generated files # 66 | ###################### 67 | .DS_Store* 68 | ehthumbs.db 69 | Icon? 70 | Thumbs.db 71 | packages 72 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2016 Rob Ferguson 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 | 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # my-2d-diagram-editor 2 | A browser-based 2D diagram editor, built using AngularJS, AngularUI and Fabric.js. 3 | 4 | ![screenshot](https://github.com/Robinyo/my-2d-diagram-editor/blob/master/client/content/images/my-2d-diagram-editor-7.png) 5 | 6 | Formatting shapes and containers: 7 | 8 | ![screenshot](https://github.com/Robinyo/my-2d-diagram-editor/blob/master/client/content/images/my-2d-diagram-editor-formatting-shapes.png) 9 | 10 | Interactivity: 11 | 12 | ![screenshot](https://github.com/Robinyo/my-2d-diagram-editor/blob/master/client/content/images/my-2d-diagram-editor-interactivity.png) 13 | 14 | How to highlight ports: 15 | 16 | ![screenshot](https://github.com/Robinyo/my-2d-diagram-editor/blob/master/client/content/images/my-2d-diagram-editor-with-ports.png) 17 | 18 | How to draw connections: 19 | 20 | ![screenshot](https://github.com/Robinyo/my-2d-diagram-editor/blob/master/client/content/images/my-2d-diagram-editor-draw-connector-with-arrow.png) 21 | 22 | How to update connections: 23 | 24 | ![screenshot](https://github.com/Robinyo/my-2d-diagram-editor/blob/master/client/content/images/my-2d-diagram-editor-with-ports-4.png) 25 | 26 | A sample Logical Security Zone Model diagram: 27 | 28 | ![screenshot](https://github.com/Robinyo/my-2d-diagram-editor/blob/master/client/content/images/logical-security-zone-model-diagram.png) 29 | 30 | #### Copyright & License 31 | 32 | Copyright (c) 2015-2017 Rob Ferguson - Released under the MIT license. 33 | 34 | -------------------------------------------------------------------------------- /TODO.txt: -------------------------------------------------------------------------------- 1 | 2 | https://github.com/johnpapa/angular-styleguide 3 | 4 | Exception Handling 5 | 6 | Use a decorator, at config time using the $provide service, on the $exceptionHandler service to perform custom 7 | actions when exceptions occur. 8 | 9 | Why?: Provides a consistent way to handle uncaught Angular exceptions for development-time or run-time. 10 | 11 | Note: Another option is to override the service instead of using a decorator. This is a fine option, but if you 12 | want to keep the default behavior and extend it a decorator is recommended. 13 | 14 | decorators 15 | 16 | /* recommended */ 17 | angular 18 | .module('blocks.exception') 19 | .config(exceptionConfig); 20 | 21 | exceptionConfig.$inject = ['$provide']; 22 | 23 | function exceptionConfig($provide) { 24 | $provide.decorator('$exceptionHandler', extendExceptionHandler); 25 | } 26 | 27 | extendExceptionHandler.$inject = ['$delegate', 'toastr']; 28 | 29 | function extendExceptionHandler($delegate, toastr) { 30 | return function(exception, cause) { 31 | $delegate(exception, cause); 32 | var errorData = { 33 | exception: exception, 34 | cause: cause 35 | }; 36 | /** 37 | * Could add the error to a service's collection, 38 | * add errors to $rootScope, log errors to remote web server, 39 | * or log locally. Or throw hard. It is entirely up to you. 40 | * throw exception; 41 | */ 42 | toastr.error(exception.msg, errorData); 43 | }; 44 | } 45 | 46 | Exception Catchers 47 | 48 | Create a factory that exposes an interface to catch and gracefully handle exceptions. 49 | 50 | Why?: Provides a consistent way to catch exceptions that may be thrown in your code (e.g. during XHR calls 51 | or promise failures). 52 | 53 | Note: The exception catcher is good for catching and reacting to specific exceptions from calls that you know may 54 | throw one. For example, when making an XHR call to retrieve data from a remote web service and you want to catch any exceptions from that service and react uniquely. 55 | 56 | /* recommended */ 57 | angular 58 | .module('blocks.exception') 59 | .factory('exception', exception); 60 | 61 | exception.$inject = ['logger']; 62 | 63 | function exception(logger) { 64 | var service = { 65 | catcher: catcher 66 | }; 67 | return service; 68 | 69 | function catcher(message) { 70 | return function(reason) { 71 | logger.error(message, reason); 72 | }; 73 | } 74 | } 75 | 76 | Route Errors 77 | 78 | [Style Y112] 79 | 80 | Handle and log all routing errors using $routeChangeError. 81 | 82 | Why?: Provides a consistent way to handle all routing errors. 83 | 84 | Why?: Potentially provides a better user experience if a routing error occurs and you route them to a 85 | friendly screen with more details or recovery options. 86 | 87 | /* recommended */ 88 | var handlingRouteChangeError = false; 89 | 90 | function handleRoutingErrors() { 91 | /** 92 | * Route cancellation: 93 | * On routing error, go to the dashboard. 94 | * Provide an exit clause if it tries to do it twice. 95 | */ 96 | $rootScope.$on('$routeChangeError', 97 | function(event, current, previous, rejection) { 98 | if (handlingRouteChangeError) { return; } 99 | handlingRouteChangeError = true; 100 | var destination = (current && (current.title || 101 | current.name || current.loadedTemplateUrl)) || 102 | 'unknown target'; 103 | var msg = 'Error routing to ' + destination + '. ' + 104 | (rejection.msg || ''); 105 | 106 | /** 107 | * Optionally log using a custom service or $log. 108 | * (Don't forget to inject custom service) 109 | */ 110 | logger.warning(msg, [current]); 111 | 112 | /** 113 | * On routing error, go to another route/state. 114 | */ 115 | $location.path('/'); 116 | 117 | } 118 | ); 119 | } 120 | -------------------------------------------------------------------------------- /client/.bowerrc: -------------------------------------------------------------------------------- 1 | { 2 | "directory": "bower_components" 3 | } 4 | -------------------------------------------------------------------------------- /client/app/app-module-config.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | 3 | 'use strict'; 4 | 5 | angular.module('app') 6 | .config(configModule); 7 | 8 | /* 9 | * Use $inject to manually identify your dependencies for Angular components. 10 | * This technique mirrors the technique used by ng-annotate, for automating the creation of minification safe 11 | * dependencies. If ng-annotate detects injection has already been made, it will not duplicate it. 12 | */ 13 | 14 | configModule.$inject = ['$provide', '$logProvider', '$tooltipProvider', '$translateProvider', '$stateProvider', '$urlRouterProvider']; 15 | 16 | function configModule($provide, $logProvider, $tooltipProvider, $translateProvider, $stateProvider, $urlRouterProvider) { 17 | 18 | // configExceptionHandler($provide); 19 | configLogging($provide, $logProvider); 20 | configBootstrapUI($tooltipProvider); 21 | configTranslations($translateProvider); 22 | configRoutes($stateProvider, $urlRouterProvider); 23 | } 24 | 25 | /* 26 | 27 | function configExceptionHandler($provide) { 28 | $provide.decorator('$exceptionHandler', extendExceptionHandler); 29 | } 30 | 31 | extendExceptionHandler.$inject = ['$delegate', 'stackTrace']; 32 | 33 | function extendExceptionHandler($delegate, stackTrace) { 34 | 35 | return function(exception, cause) { 36 | 37 | // Pass off the error to the default error handler on the AngularJS logger. 38 | // This will output the error to the console (and let the application 39 | // keep running normally for the user). 40 | 41 | $delegate(exception, cause); 42 | 43 | // Bespoke Exception Handling ... 44 | 45 | // var errorMessage = exception.toString(); 46 | 47 | var callback = function(stackframes) { 48 | var stringifiedStack = stackframes.map(function(sf) { 49 | return sf.toString(); 50 | }).join('\n'); 51 | console.log(stringifiedStack); 52 | }; 53 | 54 | var errback = function(err) { console.log(err.message); }; 55 | 56 | stackTrace.fromError(exception).then(callback).catch(errback); 57 | }; 58 | 59 | } 60 | 61 | */ 62 | 63 | function configLogging($provide, $logProvider) { 64 | 65 | var environment = 'development'; 66 | // var environment = 'production'; 67 | 68 | if (environment === 'production') { 69 | 70 | // Disable log, info, warn and debug messages 71 | 72 | $provide.decorator('$log', ['$delegate', function ($delegate) { 73 | $delegate.log = angular.noop; 74 | return $delegate; 75 | }]); 76 | 77 | $provide.decorator('$log', ['$delegate', function ($delegate) { 78 | $delegate.info = angular.noop; 79 | return $delegate; 80 | }]); 81 | 82 | $provide.decorator('$log', ['$delegate', function ($delegate) { 83 | $delegate.warn = angular.noop; 84 | return $delegate; 85 | }]); 86 | 87 | $logProvider.debugEnabled(false); 88 | 89 | } else { 90 | 91 | // $logProvider.debugEnabled(false); 92 | 93 | console.log('my-2d-diagram-editor - environment = ' + environment); 94 | console.log('my-2d-diagram-editor - log, info, warn, debug and error messages are enabled'); 95 | 96 | } 97 | } 98 | 99 | function configBootstrapUI($tooltipProvider) { 100 | $tooltipProvider.options({ placement: 'bottom' }); 101 | } 102 | 103 | function configTranslations($translateProvider) { 104 | 105 | $translateProvider 106 | .useStaticFilesLoader({ 107 | prefix: 'app/locales/', 108 | suffix: '.json' 109 | }) 110 | .registerAvailableLanguageKeys(['en', 'pl', 'de'], { 111 | 'en' : 'en', 'en_GB': 'en', 'en_US': 'en', 112 | 'pl' : 'pl', 'pl_PL': 'pl', 113 | 'de' : 'de', 'de_DE': 'de', 'de_CH': 'de' 114 | }) 115 | .preferredLanguage('en') 116 | .fallbackLanguage('en') 117 | .determinePreferredLanguage() 118 | .useSanitizeValueStrategy('escapeParameters'); 119 | } 120 | 121 | function configRoutes($stateProvider, $urlRouterProvider) { 122 | 123 | /* 124 | * Routes allow you to define ways to navigate to specific states within your application. 125 | * They also allow you to define configuration options for each specific route, such as 126 | * which template and controller to use. 127 | */ 128 | 129 | $stateProvider 130 | .state('home', { 131 | url: '/', 132 | templateUrl: 'app/main/templates/layout.html', 133 | controller: 'MainController', 134 | controllerAs: 'main' 135 | /* 136 | resolve: { 137 | moviesPrepService: moviesPrepService 138 | } 139 | */ 140 | }); 141 | 142 | /* 143 | * Use $inject to manually identify your route resolver dependencies for Angular components. 144 | * This technique breaks out the anonymous function for the route resolver, making it easier to read. 145 | * $inject statement can easily precede the resolver to handle making any dependencies minification safe. 146 | */ 147 | 148 | /* 149 | moviesPrepService.$inject = ['movieService']; 150 | function moviesPrepService(movieService) { 151 | return movieService.getMovies(); 152 | } 153 | */ 154 | 155 | $urlRouterProvider.otherwise('/'); 156 | } 157 | 158 | })(); 159 | 160 | // https://developers.google.com/web/tools/chrome-devtools/ 161 | // https://developer.chrome.com/devtools/docs/blackboxing 162 | 163 | -------------------------------------------------------------------------------- /client/app/app.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | 3 | /* 4 | * Wrap Angular components in an Immediately Invoked Function Expression (IIFE). 5 | * An IIFE removes variables from the global scope. This helps prevent variables and function declarations 6 | * from living longer than expected in the global scope, which also helps avoid variable collisions. 7 | */ 8 | 9 | 'use strict'; 10 | 11 | /* 12 | * Declare a new module called 'app', and list its dependencies. 13 | * Modules serve as containers to help you organise code within your AngularJS application. 14 | * Modules can contain sub-modules, making it easy to compose functionality as needed. 15 | */ 16 | 17 | angular.module('app', [ 18 | 19 | 'app.main' 20 | 21 | // app.components 22 | // app.feature1 23 | // app.feature2 24 | ]); 25 | 26 | })(); 27 | 28 | // $log.info('service.canvas: ' + JSON.stringify(['e', service.canvas], null, '\t')); 29 | 30 | -------------------------------------------------------------------------------- /client/app/blocks/endpoint/endpoint-config-service.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | 3 | 'use strict'; 4 | 5 | /* 6 | * Use camelCase when naming services and factories. 7 | */ 8 | 9 | angular.module('blocks.endpoint') 10 | // .constant('CURRENT_BACKEND', 'node') 11 | // .constant('CURRENT_BACKEND', 'firebase') 12 | .service('EndpointConfigService', EndpointConfigService); 13 | 14 | /* 15 | * Use $inject to manually identify your dependencies for Angular components. 16 | * This technique mirrors the technique used by ng-annotate, for automating the creation of minification safe 17 | * dependencies. If ng-annotate detects injection has already been made, it will not duplicate it. 18 | */ 19 | 20 | EndpointConfigService.$inject = ['$log']; 21 | 22 | function EndpointConfigService($log) { 23 | 24 | var service = this; 25 | var CURRENT_BACKEND = 'gulpWebServer'; 26 | // var CURRENT_BACKEND = 'httpServer'; 27 | // var CURRENT_BACKEND = 'node'; 28 | 29 | // $log.debug('EndpointConfigService - endpoint: ' + CURRENT_BACKEND); 30 | 31 | var endpointMap = { 32 | gulpWebServer: { URI: 'http://localhost:8001/', root: 'app/data/', format: '.json'}, 33 | httpServer: { URI: 'http://127.0.0.1:8080/', root: 'app/data/', format: '.json'}, 34 | node: { URI: 'http://localhost:3000/', root: 'app/data/', format: '.json'}, 35 | firebase: { URI: 'https://my-2d-diagram-editor.firebaseio.com/', root: 'app/data/', format: '.json' } 36 | }; 37 | 38 | var currentEndpoint = endpointMap[CURRENT_BACKEND]; 39 | var backend = CURRENT_BACKEND; 40 | 41 | service.getUrl = function(model) { 42 | // $log.debug('URI: ' + currentEndpoint.URI + currentEndpoint.root + model + currentEndpoint.format); 43 | return currentEndpoint.URI + currentEndpoint.root + model + currentEndpoint.format; 44 | }; 45 | 46 | } 47 | 48 | })(); 49 | 50 | /* 51 | 52 | https://github.com/indexzero/http-server 53 | 54 | cd ~/opt/WebStorm/projects/my-2d-diagram-editor/client 55 | http-server 56 | 57 | */ 58 | -------------------------------------------------------------------------------- /client/app/blocks/endpoint/endpoint-module.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | 3 | /* 4 | * Wrap Angular components in an Immediately Invoked Function Expression (IIFE). 5 | * An IIFE removes variables from the global scope. This helps prevent variables and function declarations 6 | * from living longer than expected in the global scope, which also helps avoid variable collisions. 7 | */ 8 | 9 | 'use strict'; 10 | 11 | /* 12 | * Declare a new module called 'blocks.endpoint', and list its dependencies. 13 | * Modules serve as containers to help you organise code within your AngularJS application. 14 | * Modules can contain sub-modules, making it easy to compose functionality as needed. 15 | */ 16 | 17 | angular.module('blocks.endpoint', []); 18 | 19 | })(); 20 | 21 | -------------------------------------------------------------------------------- /client/app/blocks/exception/exception-module-config.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | 3 | 'use strict'; 4 | 5 | angular.module('blocks.exception') 6 | .config(configExceptionHandler); 7 | 8 | /* 9 | * Use $inject to manually identify your dependencies for Angular components. 10 | * This technique mirrors the technique used by ng-annotate, for automating the creation of minification safe 11 | * dependencies. If ng-annotate detects injection has already been made, it will not duplicate it. 12 | */ 13 | 14 | configExceptionHandler.$inject = ['$provide']; 15 | 16 | function configExceptionHandler($provide) { 17 | $provide.decorator('$exceptionHandler', extendExceptionHandler); 18 | } 19 | 20 | extendExceptionHandler.$inject = ['$delegate', 'stackTrace']; 21 | 22 | function extendExceptionHandler($delegate, stackTrace) { 23 | 24 | return function(exception, cause) { 25 | 26 | // Pass off the error to the default error handler on the AngularJS logger. 27 | // This will output the error to the console (and let the application 28 | // keep running normally for the user). 29 | 30 | $delegate(exception, cause); 31 | 32 | // Bespoke Exception Handling ... 33 | 34 | // var errorMessage = exception.toString(); 35 | 36 | var callback = function(stackframes) { 37 | var stringifiedStack = stackframes.map(function(sf) { 38 | return sf.toString(); 39 | }).join('\n'); 40 | console.log(stringifiedStack); 41 | }; 42 | 43 | var errback = function(err) { console.log(err.message); }; 44 | 45 | stackTrace.fromError(exception).then(callback).catch(errback); 46 | }; 47 | 48 | } 49 | 50 | })(); 51 | 52 | // https://developers.google.com/web/tools/chrome-devtools/ 53 | // https://developer.chrome.com/devtools/docs/blackboxing 54 | 55 | -------------------------------------------------------------------------------- /client/app/blocks/exception/exception-module.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | 3 | /* 4 | * Wrap Angular components in an Immediately Invoked Function Expression (IIFE). 5 | * An IIFE removes variables from the global scope. This helps prevent variables and function declarations 6 | * from living longer than expected in the global scope, which also helps avoid variable collisions. 7 | */ 8 | 9 | 'use strict'; 10 | 11 | /* 12 | * Declare a new module called 'blocks.exception', and list its dependencies. 13 | * Modules serve as containers to help you organise code within your AngularJS application. 14 | * Modules can contain sub-modules, making it easy to compose functionality as needed. 15 | */ 16 | 17 | angular.module('blocks.exception', []); 18 | 19 | })(); 20 | 21 | -------------------------------------------------------------------------------- /client/app/blocks/exception/stacktrace-factory.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | 3 | angular.module('blocks.exception') 4 | .factory('stackTrace', stackTrace); 5 | 6 | stackTrace.$inject = ['$window']; 7 | 8 | function stackTrace($window) { 9 | return $window.StackTrace; 10 | } 11 | 12 | })(); 13 | 14 | -------------------------------------------------------------------------------- /client/app/components/angular-ui-fabric/src/ui-fabric-canvas-service.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | 3 | 'use strict'; 4 | 5 | angular.module('ui.fabric') 6 | .service('fabricCanvas', fabricCanvas); 7 | 8 | /* 9 | * Use $inject to manually identify your dependencies for Angular components. 10 | * This technique mirrors the technique used by ng-annotate, for automating the creation of minification safe 11 | * dependencies. If ng-annotate detects injection has already been made, it will not duplicate it. 12 | */ 13 | 14 | fabricCanvas.$inject = ['$log', '$rootScope', 'fabricConfig', 'fabricWindow']; 15 | 16 | /** 17 | * @name fabricCanvas 18 | * @desc Creates a Canvas 19 | * @param {Object} [$log] 20 | * @param {Object} [$rootScope] 21 | * @param {Object} [fabricConfig] 22 | * @param {Object} [fabricWindow] 23 | * @return {Object} Returns the new fabricCanvas object 24 | * 25 | * @fires canvas:created 26 | * 27 | */ 28 | function fabricCanvas($log, $rootScope, fabricConfig, fabricWindow) { 29 | 30 | var service = this; 31 | 32 | service.canvasId = null; 33 | service.canvas = null; 34 | service.element = null; 35 | 36 | service.canvasDefaults = null; 37 | 38 | service.init = function () { 39 | 40 | $log.debug('fabricCanvas - init()'); 41 | 42 | service.canvasDefaults = fabricConfig.getCanvasDefaults(); 43 | // service.canvasDefaults = angular.copy(fabricConfig.getCanvasDefaults()); 44 | }; 45 | 46 | var createId = function() { 47 | return Math.floor(Math.random() * 10000); 48 | }; 49 | 50 | service.setElement = function(element) { 51 | service.element = element; 52 | // $rootScope.$broadcast('canvas:element:selected'); 53 | }; 54 | 55 | service.createCanvas = function(options) { 56 | 57 | options = options || service.canvasDefaults; 58 | 59 | // $log.debug('options: ' + JSON.stringify(['e', options], null, '\t')); 60 | 61 | service.canvasId = 'fabric-canvas-' + createId(); 62 | service.element.attr('id', service.canvasId); 63 | service.canvas = new fabricWindow.Canvas(service.canvasId, options); 64 | $rootScope.$broadcast('canvas:created'); 65 | 66 | return service.canvas; 67 | }; 68 | 69 | service.getCanvas = function() { 70 | return service.canvas; 71 | }; 72 | 73 | service.init(); 74 | 75 | return service; 76 | 77 | } 78 | 79 | })(); 80 | 81 | // { selection: false, width: 600, height: 600 } 82 | // { width: 600, height: 600, backgroundColor: '#DCDCDC' } 83 | 84 | // $log.debug('service.element: ' + JSON.stringify(['e', service.element], null, '\t')); 85 | -------------------------------------------------------------------------------- /client/app/components/angular-ui-fabric/src/ui-fabric-config-service.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | 3 | 'use strict'; 4 | 5 | angular.module('ui.fabric') 6 | .service('fabricConfig', fabricConfig); 7 | 8 | /* 9 | * Use $inject to manually identify your dependencies for Angular components. 10 | * This technique mirrors the technique used by ng-annotate, for automating the creation of minification safe 11 | * dependencies. If ng-annotate detects injection has already been made, it will not duplicate it. 12 | */ 13 | 14 | // fabricConfig.$inject = ['']; 15 | 16 | function fabricConfig() { 17 | 18 | var service = this; 19 | 20 | // 'Portrait (8.5 x 11)' 21 | // 'Landscape (11 x 8.5)' 22 | 23 | const PORTRAIT_WIDTH = 1510; 24 | const PORTRAIT_HEIGHT = 1947; 25 | const LANDSCAPE_WIDTH = 1510; 26 | const LANDSCAPE_HEIGHT = 1947; 27 | 28 | const CANVAS_WIDTH = LANDSCAPE_WIDTH; 29 | const CANVAS_HEIGHT = LANDSCAPE_HEIGHT; 30 | 31 | const GRID_SIZE = 50; 32 | 33 | const CORNER_SIZE = 10; 34 | const ROTATING_POINT_OFFSET = 40; 35 | 36 | const STROKE_WIDTH = 1; 37 | 38 | const RECT_WIDTH = 300; 39 | const RECT_HEIGHT = 300; 40 | 41 | const FONT_SIZE = 12; 42 | const FONT_WEIGHT = 'normal'; 43 | const FONT_FAMILY = 'Tahoma'; 44 | 45 | const ARROW_HEAD_LENGTH = 15; 46 | 47 | var canvasDefaults = { 48 | backgroundColor: '#ffffff', 49 | grid: { 50 | show: true, 51 | size: GRID_SIZE, 52 | snapTo: false 53 | }, 54 | height: CANVAS_HEIGHT, 55 | originalHeight: CANVAS_HEIGHT, 56 | originalWidth: CANVAS_WIDTH, 57 | selection: true, 58 | width: CANVAS_WIDTH 59 | }; 60 | 61 | var objectDefaults = { 62 | borderColor: 'rgba(102,153,255,0.75)', 63 | centerTransform: true, 64 | cornerColor: 'rgba(102,153,255,0.5)', 65 | cornerSize: CORNER_SIZE, 66 | hasBorders: true, 67 | hasRotatingPoint: true, 68 | padding: 0, 69 | rotatingPointOffset: ROTATING_POINT_OFFSET, 70 | selectable: true, 71 | transparentCorners: true 72 | }; 73 | 74 | var lineDefaults = angular.extend({ 75 | stroke: 'BLACK', 76 | strokeWidth: STROKE_WIDTH 77 | }, objectDefaults); 78 | 79 | var rectDefaults = angular.extend({ 80 | fill: 'GRAY', 81 | height: RECT_HEIGHT, 82 | left: GRID_SIZE * 2, 83 | opacity: 0.7, 84 | top: GRID_SIZE * 2, 85 | width: RECT_WIDTH 86 | }, objectDefaults); 87 | 88 | var triangleDefaults = angular.extend({ 89 | // angle: angle, 90 | fill: 'BLUE', 91 | height: GRID_SIZE, 92 | left: GRID_SIZE, 93 | originX: 'center', 94 | originY: 'center', 95 | top: GRID_SIZE, 96 | width: GRID_SIZE 97 | }, objectDefaults); 98 | 99 | var textDefaults = angular.extend({ 100 | fill: 'BLACK', 101 | fontFamily: FONT_FAMILY, 102 | fontSize: FONT_SIZE, 103 | fontWeight: FONT_WEIGHT, 104 | left: GRID_SIZE, 105 | originX: 'left', 106 | originY: 'top', 107 | scaleX: 1, 108 | scaleY: 1, 109 | textAlign: 'left', 110 | top: GRID_SIZE 111 | }, objectDefaults); 112 | 113 | var gridLineDefaults = { 114 | stroke: 'LIGHTGRAY' 115 | }; 116 | 117 | var controlDefaults = { 118 | selectable: true, 119 | stroke: 'LIGHTBLUE', 120 | strokeWidth: STROKE_WIDTH 121 | }; 122 | 123 | // 124 | // Connectors (a line) are not selectable (but the arrows on either end are). 125 | // 126 | 127 | var connectorDefaults = { 128 | selectable: false, 129 | stroke: 'BLACK', 130 | strokeWidth: 2 // STROKE_WIDTH 131 | }; 132 | 133 | // 134 | // Arrows (a triangle) 135 | // 136 | 137 | var arrowDefaults = angular.extend({ 138 | // angle: angle, 139 | fill: 'BLACK', 140 | hasControls: false, 141 | height: ARROW_HEAD_LENGTH, 142 | left: GRID_SIZE, 143 | originX: 'center', 144 | originY: 'center', 145 | top: GRID_SIZE, 146 | width: ARROW_HEAD_LENGTH 147 | }, objectDefaults); 148 | 149 | arrowDefaults.hasRotatingPoint = false; 150 | arrowDefaults.selectable = false; 151 | 152 | // 153 | // RectWithText (a Node or a Container) 154 | // 155 | 156 | // const RECT_WITH_TEXT_FONT_SIZE = 18; 157 | const RECT_WITH_TEXT_FONT_SIZE = '18'; 158 | const RECT_WITH_TEXT_FONT_WEIGHT = 'normal'; 159 | const RECT_WITH_TEXT_WIDTH = 100; 160 | const RECT_WITH_TEXT_HEIGHT = 100; 161 | 162 | var rectWithTextDefaults = angular.extend({ 163 | fillStyle: 'BLACK', 164 | fontFamily: FONT_FAMILY, 165 | fontSize: RECT_WITH_TEXT_FONT_SIZE, // option element can only hold string type as its value 166 | fontWeight: RECT_WITH_TEXT_FONT_WEIGHT, 167 | originX: 'left', 168 | originY: 'top', 169 | scaleX: 1, 170 | scaleY: 1, 171 | textXAlign: 'center', // left, right, center, start, end 172 | textYAlign: 'middle', // top, bottom, middle 173 | textBaseline: 'middle' // top, bottom, middle, alphabetic, hanging 174 | }, rectDefaults); 175 | 176 | rectWithTextDefaults.width = RECT_WITH_TEXT_WIDTH; 177 | rectWithTextDefaults.height = RECT_WITH_TEXT_HEIGHT; 178 | 179 | service.getCanvasDefaults = function() { 180 | return canvasDefaults; 181 | }; 182 | 183 | service.getLineDefaults = function() { 184 | return lineDefaults; 185 | }; 186 | 187 | service.getRectDefaults = function() { 188 | return rectDefaults; 189 | }; 190 | 191 | service.getTriangleDefaults = function() { 192 | return triangleDefaults; 193 | }; 194 | 195 | service.getTextDefaults = function() { 196 | return textDefaults; 197 | }; 198 | 199 | service.getGridLineDefaults = function() { 200 | return gridLineDefaults; 201 | }; 202 | 203 | service.getControlDefaults = function() { 204 | return controlDefaults; 205 | }; 206 | 207 | service.getConnectorDefaults = function() { 208 | return connectorDefaults; 209 | }; 210 | 211 | service.getArrowDefaults = function() { 212 | return arrowDefaults; 213 | }; 214 | 215 | service.getRectWithTextDefaults = function() { 216 | return rectWithTextDefaults; 217 | }; 218 | 219 | return service; 220 | 221 | } 222 | 223 | })(); 224 | 225 | // LIGHTGRAY #D3D3D3 RGB(211, 211, 211) 226 | 227 | // http://htmlcolorcodes.com/color-names/ 228 | -------------------------------------------------------------------------------- /client/app/components/angular-ui-fabric/src/ui-fabric-directive.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | 3 | 'use strict'; 4 | 5 | angular.module('ui.fabric') 6 | .directive('fabric', fabric); 7 | 8 | /* 9 | * Use $inject to manually identify your dependencies for Angular components. 10 | * This technique mirrors the technique used by ng-annotate, for automating the creation of minification safe 11 | * dependencies. If ng-annotate detects injection has already been made, it will not duplicate it. 12 | */ 13 | 14 | fabric.$inject = ['$log', 'fabricCanvas']; 15 | 16 | function fabric($log, fabricCanvas) { 17 | return { 18 | 19 | restrict: 'A', 20 | scope: { 21 | options: '=' 22 | }, 23 | link: function link(scope, element) { 24 | 25 | $log.debug('fabric - link()'); 26 | 27 | var options = scope.options; 28 | 29 | // var options = scope.options || angular.copy(fabricService.getCanvasDefaults()); 30 | // $log.info('options: ' + JSON.stringify(['e', options], null, '\t')); 31 | 32 | fabricCanvas.setElement(element); 33 | fabricCanvas.createCanvas(options); 34 | 35 | } 36 | 37 | /* 38 | 39 | controller: function($scope, $element) { 40 | $log.info('fabric - controller()'); 41 | } 42 | 43 | */ 44 | }; 45 | } 46 | 47 | })(); 48 | 49 | // Note: "Best Practice: Directives should clean up after themselves. You can use element.on('$destroy', ...) or 50 | // scope.$on('$destroy', ...) to run a clean-up function when the directive is removed" ... 51 | -------------------------------------------------------------------------------- /client/app/components/angular-ui-fabric/src/ui-fabric-module-config.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | 3 | 'use strict'; 4 | 5 | angular.module('ui.fabric') 6 | .config(configModule); 7 | 8 | /* 9 | * Use $inject to manually identify your dependencies for Angular components. 10 | * This technique mirrors the technique used by ng-annotate, for automating the creation of minification safe 11 | * dependencies. If ng-annotate detects injection has already been made, it will not duplicate it. 12 | */ 13 | 14 | configModule.$inject = ['$provide', '$logProvider']; 15 | 16 | function configModule($provide, $logProvider) { 17 | 18 | } 19 | 20 | })(); 21 | 22 | -------------------------------------------------------------------------------- /client/app/components/angular-ui-fabric/src/ui-fabric-module.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | 3 | /* 4 | * Wrap Angular components in an Immediately Invoked Function Expression (IIFE). 5 | * An IIFE removes variables from the global scope. This helps prevent variables and function declarations 6 | * from living longer than expected in the global scope, which also helps avoid variable collisions. 7 | */ 8 | 9 | 'use strict'; 10 | 11 | /* 12 | * Declare a new module called 'ui.fabric', and list its dependencies. 13 | * Modules serve as containers to help you organise code within your AngularJS application. 14 | * Modules can contain sub-modules, making it easy to compose functionality as needed. 15 | */ 16 | 17 | angular.module('ui.fabric', []); 18 | 19 | })(); 20 | -------------------------------------------------------------------------------- /client/app/components/angular-ui-fabric/src/ui-fabric-shape-service.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | 3 | 'use strict'; 4 | 5 | angular.module('ui.fabric') 6 | .service('fabricShape', fabricShape); 7 | 8 | /* 9 | * Use $inject to manually identify your dependencies for Angular components. 10 | * This technique mirrors the technique used by ng-annotate, for automating the creation of minification safe 11 | * dependencies. If ng-annotate detects injection has already been made, it will not duplicate it. 12 | */ 13 | 14 | fabricShape.$inject = ['$log', 'fabricConfig', 'fabricWindow']; 15 | 16 | function fabricShape($log, fabricConfig, fabricWindow) { 17 | 18 | var service = this; 19 | 20 | $log.debug('fabricShape'); 21 | 22 | service.init = function () { 23 | 24 | $log.debug('fabricShape - init()'); 25 | 26 | service.gridLineDefaults = fabricConfig.getGridLineDefaults(); 27 | service.lineDefaults = fabricConfig.getLineDefaults(); 28 | service.rectDefaults = fabricConfig.getRectDefaults(); 29 | service.rectWithTextDefaults = fabricConfig.getRectWithTextDefaults(); 30 | service.triangleDefaults = fabricConfig.getTriangleDefaults(); 31 | 32 | }; 33 | 34 | // 35 | // Shapes: Circle, Ellipse, Line, Polygon, Polyline, Rect and Triangle. 36 | // 37 | 38 | /** 39 | * @name gridLine 40 | * @desc Creates a new Line object 41 | * @param {Array} [points] An array of points (where each point is an object with x and y) 42 | * @param {Object} [options] A configuration object, defaults to gridLineDefaults 43 | * @return {Object} Returns the new Line object 44 | */ 45 | service.gridLine = function(points, options) { 46 | 47 | $log.debug('fabricShape - gridLine()'); 48 | 49 | options = options || service.gridLineDefaults; 50 | 51 | // $log.debug('points: ' + JSON.stringify(['e', points], null, '\t')); 52 | 53 | return new fabricWindow.Line(points, options); 54 | }; 55 | 56 | /** 57 | * @name line 58 | * @desc Creates a new Line object 59 | * @param {Array} [points] An array of points (where each point is an object with x and y) 60 | * @param {Object} [options] A configuration object, defaults to lineDefaults 61 | * @return {Object} Returns the new Line object 62 | */ 63 | service.line = function(points, options) { 64 | 65 | $log.debug('fabricShape - line()'); 66 | 67 | options = options || service.lineDefaults; 68 | 69 | // $log.debug('points: ' + JSON.stringify(['e', points], null, '\t')); 70 | 71 | return new fabricWindow.Line(points, options); 72 | }; 73 | 74 | /** 75 | * @name rect 76 | * @desc Creates a new Rect object 77 | * @param {Object} [options] A configuration object, defaults to rectDefaults 78 | * @return {Object} Returns the new Rect object 79 | */ 80 | service.rect = function(options) { 81 | 82 | $log.debug('fabricShape - rect()'); 83 | 84 | options = options || service.rectDefaults; 85 | 86 | return new fabricWindow.Rect(options); 87 | 88 | // var object = new fabricWindow.Rect(options); 89 | // return object; 90 | }; 91 | 92 | /** 93 | * @name triangle 94 | * @desc Creates a new Triangle object 95 | * @param {Object} [options] A configuration object, defaults to triangleDefaults 96 | * @return {Object} Returns the new Triangle object 97 | */ 98 | service.triangle = function(options) { 99 | 100 | $log.debug('fabricShape - triangle()'); 101 | 102 | options = options || service.triangleDefaults; 103 | 104 | // $log.debug('options: ' + JSON.stringify(['e', options], null, '\t')); 105 | 106 | return new fabricWindow.Triangle(options); 107 | }; 108 | 109 | /** 110 | * @name rectWithText 111 | * @desc Creates a new RectWithText object 112 | * @param {String} [text] A configuration object, defaults to rectWithTextDefaults 113 | * @return {Object} Returns the new RectWithText object 114 | */ 115 | service.rectWithText = function(text, options) { 116 | 117 | $log.debug('fabricShape - rectWithText()'); 118 | 119 | text = text || 'New Text'; 120 | options = options || service.rectWithTextDefaults; 121 | 122 | return new RectWithText(text, options); 123 | }; 124 | 125 | var RectWithText = fabricWindow.util.createClass(fabricWindow.Rect, { 126 | 127 | type: 'rectWithText', 128 | 129 | text: '', 130 | 131 | fillStyle: '', 132 | fontFamily: '', 133 | fontSize: '', 134 | fontWeight: '', 135 | // lineHeight: 1.16, 136 | textXAlign: '', 137 | textYAlign: '', 138 | textBaseline: '', 139 | // textDecoration: '', 140 | // fontStyle: '', 141 | 142 | // TODO: Tried to move this from main-controller.js - had some issues ??? 143 | 144 | // id: '', 145 | // connectors: { fromPort: [], fromLine: [], fromArrow: [], toPort: [], toLine: [], toArrow: [], otherObject: [] }, 146 | 147 | initialize: function(text, options) { 148 | 149 | this.callSuper('initialize', options); 150 | 151 | this.set('text', text); 152 | for (var prop in options) { 153 | this.set(prop, options[prop]); 154 | } 155 | }, 156 | 157 | fromObject: function(object) { 158 | return new RectWithText(object); 159 | }, 160 | 161 | toObject: function() { 162 | return fabric.util.object.extend(this.callSuper('toObject'), { 163 | text: this.get('text') 164 | }); 165 | }, 166 | 167 | _render: function(ctx) { 168 | 169 | this.callSuper('_render', ctx); 170 | 171 | var x = 0; 172 | var y = 0; 173 | 174 | // top, bottom, middle 175 | 176 | switch (this.textYAlign) { 177 | 178 | case 'top': 179 | y = -(this.height / 2) + parseInt(this.fontSize, 10); 180 | break; 181 | 182 | case 'bottom': 183 | y = (this.height / 2) - parseInt(this.fontSize, 10); 184 | break; 185 | 186 | case 'middle': 187 | y = 0; 188 | break; 189 | 190 | default: 191 | $log.debug('RectWithText - textYAlign: ' + this.textYAlign); 192 | break; 193 | 194 | } 195 | 196 | // See Fabric's Text class line 19356 re support for multi-line text 197 | 198 | ctx.fillStyle = this.fillStyle; 199 | ctx.font = this.fontWeight + ' ' + this.fontSize + 'px ' + this.fontFamily; // 'bold 20px Tahoma'; 200 | ctx.textAlign = this.textXAlign; 201 | ctx.textBaseline = this.textBaseline; 202 | 203 | ctx.fillText(this.text, x, y); 204 | 205 | // $log.debug('fabricShape - ctx.font: ' + ctx.font.toLocaleString()); 206 | }, 207 | 208 | toString: function() { 209 | return '#'; 211 | } 212 | 213 | }); 214 | 215 | /** 216 | * @name connector 217 | * @desc Creates a new Connector object 218 | * @param {Array} [points] Array of points, e.g., [0, 0, 0, 0] 219 | * @param {Object} [options] A configuration object, defaults to lineDefaults 220 | * @return {Object} Returns the new Connector object 221 | */ 222 | service.connector = function(points, options) { 223 | 224 | $log.debug('fabricShape - connector()'); 225 | 226 | options = options || service.lineDefaults; 227 | 228 | return new Connector(points, options); 229 | }; 230 | 231 | var Connector = fabricWindow.util.createClass(fabricWindow.Line, { 232 | 233 | type: 'connector', 234 | 235 | initialize: function(points, options) { 236 | this.callSuper('initialize', points, options); 237 | 238 | }, 239 | 240 | fromObject: function(object) { 241 | return new Connector(object); 242 | 243 | }, 244 | 245 | toObject: function() { 246 | return fabric.util.object.extend(this.callSuper('toObject'), { 247 | 248 | }); 249 | }, 250 | 251 | _render: function(ctx) { 252 | this.callSuper('_render', ctx); 253 | 254 | }, 255 | 256 | toString: function() { 257 | return '#'; 258 | 259 | } 260 | 261 | }); 262 | 263 | service.init(); 264 | 265 | return service; 266 | 267 | } 268 | 269 | })(); 270 | 271 | -------------------------------------------------------------------------------- /client/app/components/angular-ui-fabric/src/ui-fabric-text-service.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | 3 | 'use strict'; 4 | 5 | angular.module('ui.fabric') 6 | .service('fabricText', fabricText); 7 | 8 | /* 9 | * Use $inject to manually identify your dependencies for Angular components. 10 | * This technique mirrors the technique used by ng-annotate, for automating the creation of minification safe 11 | * dependencies. If ng-annotate detects injection has already been made, it will not duplicate it. 12 | */ 13 | 14 | fabricText.$inject = ['$log', 'fabricConfig', 'fabricWindow']; 15 | 16 | function fabricText($log, fabricConfig, fabricWindow) { 17 | 18 | var service = this; 19 | 20 | service.textDefaults = null; 21 | 22 | $log.debug('fabricText'); 23 | 24 | service.init = function () { 25 | 26 | $log.debug('fabricText - init()'); 27 | 28 | service.textDefaults = fabricConfig.getTextDefaults(); 29 | }; 30 | 31 | // 32 | // Text 33 | // 34 | 35 | /** 36 | * @name text 37 | * @desc Adds a Text object to the canvas 38 | * @param {String} [text] - The text to render on the canvas 39 | * @param {Object} [options] A configuration object, defaults to textDefaults 40 | */ 41 | service.text = function(text, options) { 42 | 43 | $log.debug('fabricText - text()'); 44 | 45 | text = text || 'New Text'; 46 | options = options || service.textDefaults; 47 | 48 | return new fabricWindow.Text(text, options); 49 | }; 50 | 51 | service.init(); 52 | 53 | return service; 54 | 55 | } 56 | 57 | })(); 58 | 59 | // $log.debug('service.canvas: ' + JSON.stringify(['e', service.canvas], null, '\t')); 60 | 61 | -------------------------------------------------------------------------------- /client/app/components/angular-ui-fabric/src/ui-fabric-utils-service.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | 3 | 'use strict'; 4 | 5 | angular.module('ui.fabric') 6 | .service('fabricUtils', fabricUtils); 7 | 8 | /* 9 | * Use $inject to manually identify your dependencies for Angular components. 10 | * This technique mirrors the technique used by ng-annotate, for automating the creation of minification safe 11 | * dependencies. If ng-annotate detects injection has already been made, it will not duplicate it. 12 | */ 13 | 14 | fabricUtils.$inject = ['$log']; 15 | 16 | function fabricUtils($log) { 17 | 18 | var service = this; 19 | 20 | $log.debug('fabricUtils'); 21 | 22 | service.init = function () { 23 | $log.debug('fabricUtils - init()'); 24 | }; 25 | 26 | // See: _findTargetCorner() 27 | 28 | service.findTargetPort = function(object) { 29 | 30 | var points = new Array(4); 31 | var port = object.__corner; 32 | 33 | $log.debug('findTargetPort - port: ' + object.__corner); 34 | 35 | switch (port) { 36 | 37 | case 'mt': 38 | points = [ 39 | object.left + (object.width / 2), object.top, 40 | object.left + (object.width / 2), object.top 41 | ]; 42 | break; 43 | case 'mr': 44 | points = [ 45 | object.left + object.width, object.top + (object.height / 2), 46 | object.left + object.width, object.top + (object.height / 2) 47 | ]; 48 | break; 49 | case 'mb': 50 | points = [ 51 | object.left + (object.width / 2), object.top + object.height, 52 | object.left + (object.width / 2), object.top + object.height 53 | ]; 54 | break; 55 | case 'ml': 56 | points = [ 57 | object.left, object.top + (object.height / 2), 58 | object.left, object.top + (object.height / 2) 59 | ]; 60 | break; 61 | 62 | default: 63 | $log.error('findTargetPort() - service.fromObject.__corner === undefined'); 64 | break; 65 | } 66 | 67 | return points 68 | 69 | }; 70 | 71 | // Clockwise 72 | 73 | service.getNextTargetPort = function(port) { 74 | 75 | $log.debug('getNextTargetPort - port: ' + port); 76 | 77 | var nextPort = 'mt'; 78 | 79 | switch (port) { 80 | case 'mt': 81 | nextPort = 'mr'; 82 | break; 83 | case 'mr': 84 | nextPort = 'mb'; 85 | break; 86 | case 'mb': 87 | nextPort = 'ml'; 88 | break; 89 | case 'ml': 90 | nextPort = 'mt'; 91 | break; 92 | default: 93 | $log.error('getNextTargetPort() - port === undefined'); 94 | break; 95 | } 96 | 97 | $log.debug('getNextTargetPort - port: ' + port + ' nextPort: ' + nextPort); 98 | 99 | return nextPort; 100 | 101 | }; 102 | 103 | service.getPortCenterPoint = function(object, port) { 104 | 105 | $log.debug('getPortCenterPoint - port: ' + port); 106 | 107 | var x1 = 0; 108 | var y1 = 0; 109 | 110 | switch (port) { 111 | 112 | case 'mt': 113 | x1 = object.left + (object.width / 2); 114 | y1 = object.top; 115 | break; 116 | 117 | case 'mr': 118 | x1 = object.left + object.width; 119 | y1 = object.top + (object.height / 2); 120 | break; 121 | 122 | case 'mb': 123 | x1 = object.left + (object.width / 2); 124 | y1 = object.top + object.height; 125 | break; 126 | case 'ml': 127 | x1 = object.left; 128 | y1 = object.top + (object.height / 2); 129 | break; 130 | 131 | default: 132 | $log.error('getPortCenterPoint() - port === undefined'); 133 | break; 134 | } 135 | 136 | return { 137 | 'x1': x1, 'y1': y1, 138 | 'x2': x1, 'y2': y1 139 | } 140 | }; 141 | 142 | service.init(); 143 | 144 | return service; 145 | 146 | } 147 | 148 | })(); 149 | 150 | /* 151 | 152 | 153 | return { 154 | x1: x1, y1: y1, 155 | x2: x1, y2: y1 156 | } 157 | 158 | return { 159 | 'x1': x1, 'y1': y1, 160 | 'x2': x1, 'y2': y1 161 | } 162 | 163 | // $log.debug('x1: ' + x1 + ' y1: ' + y1 + ' x2: ' + x2 + ' y2: ' + y2); 164 | 165 | */ 166 | 167 | 168 | -------------------------------------------------------------------------------- /client/app/components/angular-ui-fabric/src/ui-fabric-window-factory.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | 3 | angular.module('ui.fabric') 4 | .factory('fabricWindow', fabricWindow); 5 | 6 | /* 7 | * Use $inject to manually identify your dependencies for Angular components. 8 | * This technique mirrors the technique used by ng-annotate, for automating the creation of minification safe 9 | * dependencies. If ng-annotate detects injection has already been made, it will not duplicate it. 10 | */ 11 | 12 | fabricWindow.$inject = ['$window']; 13 | 14 | // fabric.js must be included in your application's host file 'index.html' 15 | // For example: 16 | // We need to wrap it in a service so that we don't reference global objects inside AngularJS components. 17 | 18 | function fabricWindow($window) { 19 | return $window.fabric; 20 | } 21 | 22 | })(); 23 | -------------------------------------------------------------------------------- /client/app/data/containers.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "id" : 1, 4 | "name" : "CONTROLLED_ZONE", 5 | "value" : "Controlled Zone", 6 | "src" : "http://placehold.it/32x32/E3F09B", 7 | "backgroundColor" : "#E3F09B" 8 | }, 9 | { 10 | "id" : 2, 11 | "name" : "RESTRICTED_ZONE", 12 | "value" : "Restricted Zone", 13 | "src" : "http://placehold.it/32x32/F7D08A", 14 | "backgroundColor" : "#F7D08A" 15 | }, 16 | { 17 | "id" : 3, 18 | "name" : "SECURED_ZONE", 19 | "value" : "Secured Zone", 20 | "src" : "http://placehold.it/32x32/87B6A7", 21 | "backgroundColor" : "#87B6A7" 22 | }, 23 | { 24 | "id" : 4, 25 | "name" : "PARTNER_ZONE", 26 | "value" : "Partner Zone", 27 | "src" : "http://placehold.it/32x32/F79F79", 28 | "backgroundColor" : "#F79F79" 29 | }, 30 | { 31 | "id" : 5, 32 | "name" : "MANAGEMENT_ZONE", 33 | "value" : "Management Zone", 34 | "src" : "http://placehold.it/32x32/5B5941", 35 | "backgroundColor" : "#5B5941" 36 | } 37 | ] 38 | -------------------------------------------------------------------------------- /client/app/data/font-families.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "id" : 1, 4 | "name" : "HELVETICA", 5 | "value" : "Helvetica" 6 | }, 7 | { 8 | "id" : 2, 9 | "name" : "TAHOMA", 10 | "value" : "Tahoma" 11 | }, 12 | { 13 | "id" : 3, 14 | "name" : "VERDANA", 15 | "value" : "Verdana" 16 | } 17 | ] 18 | -------------------------------------------------------------------------------- /client/app/data/font-sizes.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "id" : 1, 4 | "name" : "EIGHT", 5 | "value" : "8" 6 | }, 7 | { 8 | "id" : 2, 9 | "name" : "TEN", 10 | "value" : "10" 11 | }, 12 | { 13 | "id" : 3, 14 | "name" : "TWELVE", 15 | "value" : "12" 16 | }, 17 | { 18 | "id" : 4, 19 | "name" : "FOURTEEN", 20 | "value" : "14" 21 | }, 22 | { 23 | "id" : 5, 24 | "name" : "SIXTEEN", 25 | "value" : "16" 26 | }, 27 | { 28 | "id" : 6, 29 | "name" : "EIGHTEEN", 30 | "value" : "18" 31 | }, 32 | { 33 | "id" : 7, 34 | "name" : "TWENTY", 35 | "value" : "20" 36 | } 37 | ] 38 | -------------------------------------------------------------------------------- /client/app/data/paper-sizes.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "id" : 1, 4 | "name" : "A3", 5 | "value" : "A3 (297mm x 420mm)" 6 | }, 7 | { 8 | "id" : 2, 9 | "name" : "A4", 10 | "value" : "A4 (210mm x 297mm)" 11 | }, 12 | { 13 | "id" : 3, 14 | "name" : "A5", 15 | "value" : "A5 (148mm x 210mm)" 16 | } 17 | ] 18 | -------------------------------------------------------------------------------- /client/app/data/shapes.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "id" : 1, 4 | "name" : "NODE", 5 | "value" : "Node", 6 | "src" : "content/images/icons/32x32/light-gray.png", 7 | "backgroundColor" : "GRAY" 8 | } 9 | ] 10 | -------------------------------------------------------------------------------- /client/app/data/themes.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "id" : 1, 4 | "name" : "COOLORS", 5 | "value" : "Coolors (coolors.co)" 6 | } 7 | ] 8 | -------------------------------------------------------------------------------- /client/app/help/angular-fabric/example/angular-fabric-codepen.txt: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | CodePen - AngularJS and FabricJS 9 | 10 | 11 | 12 | 13 | 14 | 15 | 91 | 92 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | clouddueling/angular-fabric 105 | 106 |
107 |
108 |
109 |
110 |
111 | 112 |
113 |
114 | Image and shape do not work due to codepen cross-origin. 115 |
116 |
117 | 122 | 123 | 128 | 129 | 134 | 135 | 140 | 141 | 146 |
147 | 148 |
149 |
150 |
151 | 152 |
153 |
154 | 155 |
156 |
157 | 158 |
159 |
160 | 163 |
164 |
165 |
166 | 167 |
168 | 173 | 174 | 179 |
180 |
181 |
182 | 183 |
184 | 185 |
186 |
187 | 188 | 189 |
190 | 191 |
192 | 193 |
194 | 197 | 198 |
199 |
200 |
201 |
202 | 203 | 204 |
205 | 206 |
207 | 208 | 209 |
210 | 211 | 214 |
215 |
216 |
217 |
218 | 219 |
220 | 221 |
222 |
223 | 224 | Preset Sizes 225 | 226 | 227 | 232 |
233 |
234 |
235 | 236 |
237 | 238 |
239 |
240 |
241 |
242 |
243 |

244 | 245 |

246 | 247 |

248 | 249 | 250 |

251 | 252 |

253 | 254 | 255 |

256 | 257 |
258 | 261 | 262 | 265 | 266 | 269 |
270 | 271 |
272 | 273 |
274 | 277 | 278 | 281 | 282 | 285 | 286 | 289 |
290 | 291 |
292 | 293 | 308 |
309 | 310 |
311 |
312 | 315 | 316 |
317 |
318 |
319 | 320 |
321 |
322 | 327 |
328 |
329 | 330 |
331 |
332 | 335 |
336 |
337 | 338 |
339 |
340 | 341 |
342 |
343 | 344 |
345 |
346 | 349 | 350 | 353 | 354 | 357 |
358 |
359 | 360 |
361 | 362 |
363 |
364 | 367 | 368 | 371 | 372 | 375 | 376 | 379 |
380 |
381 | 382 |
383 | 384 | 387 |
388 |
389 | 390 |
391 |
392 |
393 | 394 |
395 |
396 |
397 |
398 |
399 |
400 | 401 | 402 | 403 | 404 | 405 | 406 | 407 | 408 | 409 | 410 | 411 | 412 | 413 | 414 | 464 | 465 | 466 | 471 | 472 | 473 | 474 | 475 | 476 | -------------------------------------------------------------------------------- /client/app/help/angular-fabric/example/example.css: -------------------------------------------------------------------------------- 1 | body { 2 | padding: 10px; 3 | } 4 | .image-builder-container { 5 | position: relative; 6 | } 7 | .image-builder-container .image-builder { 8 | background: #cacaca; 9 | box-sizing: border-box; 10 | border: 1px solid #cacaca; 11 | min-height: 460px; 12 | text-align: center; 13 | position: relative; 14 | overflow-x: scroll; 15 | overflow-y: hidden; 16 | width: auto; 17 | } 18 | .image-builder-container .image-builder .image-cover { 19 | left: 0; 20 | right: 0; 21 | bottom: 0; 22 | top: 0; 23 | position: absolute; 24 | z-index: 2; 25 | } 26 | .image-builder-container .image-builder .fabric-container { 27 | background: white; 28 | border-radius: 1px; 29 | box-shadow: 0 1px 4px -1px rgba(0, 0, 0, 0.4); 30 | display: inline-block; 31 | margin: 50px; 32 | position: relative; 33 | vertical-align: middle; 34 | z-index: 0; 35 | } 36 | .image-builder-container .image-loading { 37 | background: rgba(255, 255, 255, 0.4); 38 | position: absolute; 39 | top: 0; 40 | bottom: 0; 41 | left: 0; 42 | right: 0; 43 | z-index: 1; 44 | } 45 | .image-builder-container .image-loading .loading-indicator { 46 | background: white; 47 | background-image: url(/images/squareLoader.gif); 48 | background-repeat: no-repeat; 49 | background-position: center; 50 | border-radius: 10px; 51 | box-shadow: 0 1px 3px rgba(0, 0, 0, 0.2); 52 | margin: 300px auto 0; 53 | height: 160px; 54 | width: 160px; 55 | } 56 | .image-builder-container .object-controls-container { 57 | position: relative; 58 | } 59 | .image-builder-container .object-controls-container .object-controls { 60 | position: absolute; 61 | z-index: 1; 62 | background: white; 63 | left: -250px; 64 | top: 0px; 65 | padding: 5px; 66 | width: 240px; 67 | } 68 | .image-builder-container .object-controls-container .object-controls textarea { 69 | font-size: 12px; 70 | } 71 | .object-font-family-preview { 72 | text-transform: capitalize; 73 | } 74 | -------------------------------------------------------------------------------- /client/app/help/angular-fabric/example/example.html: -------------------------------------------------------------------------------- 1 |
2 |
3 |
6 |
7 |
8 | 9 |
10 |
11 |
12 | 17 | 18 | 23 | 24 | 31 |
32 | 33 | 41 |
42 |
43 | 44 |
45 |
46 |
47 | 57 | 58 | 65 | 66 | 73 | 74 | 81 | 82 | 91 | 92 | 101 |
102 | 103 |
104 | 105 | 112 | 113 | 114 | 119 |
120 | 121 |
122 | 129 | 130 | 137 |
138 |
139 |
140 | 141 |
142 |
143 | 144 | 149 | 150 | 151 | 157 | 158 | 164 | 165 |
166 | 167 | Preset Sizes 168 | 169 | 170 | 177 |
178 |
179 |
180 | 181 |
182 |
185 |
186 |
187 |
188 |
189 | 194 |
195 |
196 | 197 |
198 |
199 |

200 | 201 | 205 |

206 |
207 |
208 | 209 |
210 |
211 |

212 | 213 | 218 |

219 |
220 |
221 | 222 |
223 | 229 | 230 | 236 | 237 | 243 |
244 | 245 |
246 | 247 |
248 | 254 | 255 | 261 | 262 | 268 | 269 | 275 |
276 | 277 |
278 | 279 | 302 |
303 | 304 |
305 |
306 | 312 | 317 |
318 |
319 |
320 | 321 |
322 |
323 | 331 |
332 |
333 | 334 |
335 |
336 | 342 |
343 |
344 | 345 |
348 |
349 | 354 |
355 |
356 | 357 |
358 |
359 | 364 | 365 | 370 | 371 | 376 |
377 |
378 | 379 |
380 |
381 | 386 | 387 | 392 | 393 | 398 | 399 | 404 |
405 |
406 | 407 |
408 | 414 |
415 |
416 |
417 | 418 |
421 |
422 | 423 |
424 |
425 |
426 |
427 | -------------------------------------------------------------------------------- /client/app/help/angular-fabric/example/example.js: -------------------------------------------------------------------------------- 1 | angular.module('example', [ 2 | 'common.fabric', 3 | 'common.fabric.utilities', 4 | 'common.fabric.constants' 5 | ]) 6 | 7 | .controller('ExampleCtrl', ['$scope', '$www', 'Modal', 'Fabric', 'FabricConstants', 'ImagesConstants', 'Keypress', function($scope, $www, Modal, Fabric, FabricConstants, ImagesConstants, Keypress) { 8 | 9 | $scope.fabric = {}; 10 | $scope.ImagesConstants = ImagesConstants; 11 | $scope.FabricConstants = FabricConstants; 12 | 13 | // 14 | // Creating Canvas Objects 15 | // ================================================================ 16 | $scope.addShape = function(path) { 17 | $scope.fabric.addShape('/lib/svg/' + path + '.svg'); 18 | Modal.close(); 19 | }; 20 | 21 | $scope.addImage = function(image) { 22 | $scope.fabric.addImage('/image?image=' + image + '&size=full'); 23 | Modal.close(); 24 | }; 25 | 26 | $scope.addImageUpload = function(data) { 27 | var obj = angular.fromJson(data); 28 | $scope.addImage(obj.filename); 29 | Modal.close(); 30 | }; 31 | 32 | // 33 | // Editing Canvas Size 34 | // ================================================================ 35 | $scope.selectCanvas = function() { 36 | $scope.canvasCopy = { 37 | width: $scope.fabric.canvasOriginalWidth, 38 | height: $scope.fabric.canvasOriginalHeight 39 | }; 40 | }; 41 | 42 | $scope.setCanvasSize = function() { 43 | $scope.fabric.setCanvasSize($scope.canvasCopy.width, $scope.canvasCopy.height); 44 | $scope.fabric.setDirty(true); 45 | Modal.close(); 46 | delete $scope.canvasCopy; 47 | }; 48 | 49 | $scope.updateCanvas = function() { 50 | var json = $scope.fabric.getJSON(); 51 | 52 | $www.put('/api/canvas/' + $scope.canvasId, { 53 | json: json 54 | }).success(function() { 55 | $scope.fabric.setDirty(false); 56 | }); 57 | }; 58 | 59 | // 60 | // Init 61 | // ================================================================ 62 | $scope.init = function() { 63 | $scope.fabric = new Fabric({ 64 | JSONExportProperties: FabricConstants.JSONExportProperties, 65 | textDefaults: FabricConstants.textDefaults, 66 | shapeDefaults: FabricConstants.shapeDefaults, 67 | json: $scope.main.selectedPage.json 68 | }); 69 | }; 70 | 71 | $scope.$on('canvas:created', $scope.init); 72 | 73 | Keypress.onSave(function() { 74 | $scope.updatePage(); 75 | }); 76 | 77 | }]); 78 | -------------------------------------------------------------------------------- /client/app/help/angular-fabric/example/example.less: -------------------------------------------------------------------------------- 1 | body { 2 | padding: 10px; 3 | } 4 | 5 | .image-builder-container { 6 | position: relative; 7 | 8 | .image-builder { 9 | background: #cacaca; 10 | box-sizing: border-box; 11 | border: 1px solid #cacaca; 12 | min-height: 460px; 13 | text-align: center; 14 | position: relative; 15 | overflow-x: scroll; 16 | overflow-y: hidden; 17 | width: auto; 18 | 19 | .image-cover { 20 | left: 0; 21 | right: 0; 22 | bottom: 0; 23 | top: 0; 24 | position: absolute; 25 | z-index: 2; 26 | } 27 | 28 | .fabric-container { 29 | background: white; 30 | border-radius: 1px; 31 | box-shadow: 0 1px 4px -1px rgba(0, 0, 0, .4); 32 | display: inline-block; 33 | margin: 50px; 34 | position: relative; 35 | vertical-align: middle; 36 | z-index: 0; 37 | } 38 | } 39 | 40 | .image-loading { 41 | background: rgba(255, 255, 255, .4); 42 | position: absolute; 43 | top: 0; 44 | bottom: 0; 45 | left: 0; 46 | right: 0; 47 | z-index: 1; 48 | 49 | .loading-indicator { 50 | background: white; 51 | background-image: url(/images/squareLoader.gif); 52 | background-repeat: no-repeat; 53 | background-position: center; 54 | border-radius: 10px; 55 | box-shadow: 0 1px 3px rgba(0, 0, 0, .2); 56 | margin: 300px auto 0; 57 | height: 160px; 58 | width: 160px; 59 | } 60 | } 61 | 62 | .object-controls-container { 63 | position: relative; 64 | 65 | .object-controls { 66 | position: absolute; 67 | z-index: 1; 68 | background: white; 69 | left: -250px; 70 | top: 0px; 71 | padding: 5px; 72 | width: 240px; 73 | 74 | textarea { 75 | font-size: 12px; 76 | } 77 | } 78 | } 79 | } 80 | 81 | .object-font-family-preview { 82 | text-transform: capitalize; 83 | } 84 | -------------------------------------------------------------------------------- /client/app/help/angular-fabric/fabric-canvas.js: -------------------------------------------------------------------------------- 1 | angular.module('common.fabric.canvas', [ 2 | 'common.fabric.window' 3 | ]) 4 | 5 | .service('FabricCanvas', ['FabricWindow', '$rootScope', function(FabricWindow, $rootScope) { 6 | 7 | var self = { 8 | canvasId: null, 9 | element: null, 10 | canvas: null 11 | }; 12 | 13 | function createId() { 14 | return Math.floor(Math.random() * 10000); 15 | } 16 | 17 | self.setElement = function(element) { 18 | self.element = element; 19 | $rootScope.$broadcast('canvas:element:selected'); 20 | }; 21 | 22 | self.createCanvas = function() { 23 | self.canvasId = 'fabric-canvas-' + createId(); 24 | self.element.attr('id', self.canvasId); 25 | self.canvas = new FabricWindow.Canvas(self.canvasId); 26 | $rootScope.$broadcast('canvas:created'); 27 | 28 | return self.canvas; 29 | }; 30 | 31 | self.getCanvas = function() { 32 | return self.canvas; 33 | }; 34 | 35 | self.getCanvasId = function() { 36 | return self.canvasId; 37 | }; 38 | 39 | return self; 40 | 41 | }]); 42 | -------------------------------------------------------------------------------- /client/app/help/angular-fabric/fabric-constants.js: -------------------------------------------------------------------------------- 1 | angular.module('common.fabric.constants', []) 2 | 3 | .service('FabricConstants', [function() { 4 | 5 | var objectDefaults = { 6 | rotatingPointOffset: 40, 7 | padding: 0, 8 | borderColor: 'rgba(102,153,255,0.75)', 9 | cornerColor: 'rgba(102,153,255,0.5)', 10 | cornerSize: 10, 11 | transparentCorners: true, 12 | hasRotatingPoint: true, 13 | centerTransform: true 14 | }; 15 | 16 | return { 17 | 18 | presetSizes: [ 19 | { 20 | name: 'Portrait (8.5 x 11)', 21 | height: 1947, 22 | width: 1510 23 | }, 24 | { 25 | name: 'Landscape (11 x 8.5)', 26 | width: 1947, 27 | height: 1510 28 | }, 29 | { 30 | name: 'Business Card (3.5 x 2)', 31 | height: 368, 32 | width: 630 33 | }, 34 | { 35 | name: 'Postcard (6 x 4)', 36 | height: 718, 37 | width: 1068 38 | }, 39 | { 40 | name: 'Content/Builder Product Thumbnail', 41 | height: 400, 42 | width: 760 43 | }, 44 | { 45 | name: 'Badge', 46 | height: 400, 47 | width: 400 48 | }, 49 | { 50 | name: 'Facebook Profile Picture', 51 | height: 300, 52 | width: 300 53 | }, 54 | { 55 | name: 'Facebook Cover Picture', 56 | height: 315, 57 | width: 851 58 | }, 59 | { 60 | name: 'Facebook Photo Post (Landscape)', 61 | height: 504, 62 | width: 403 63 | }, 64 | { 65 | name: 'Facebook Photo Post (Horizontal)', 66 | height: 1008, 67 | width: 806 68 | }, 69 | { 70 | name: 'Facebook Full-Width Photo Post', 71 | height: 504, 72 | width: 843 73 | } 74 | ], 75 | 76 | fonts: [ 77 | { name: 'Arial' }, 78 | { name: 'Lora' }, 79 | { name: 'Croissant One' }, 80 | { name: 'Architects Daughter' }, 81 | { name: 'Emblema One' }, 82 | { name: 'Graduate' }, 83 | { name: 'Hammersmith One' }, 84 | { name: 'Oswald' }, 85 | { name: 'Oxygen' }, 86 | { name: 'Krona One' }, 87 | { name: 'Indie Flower' }, 88 | { name: 'Courgette' }, 89 | { name: 'Gruppo' }, 90 | { name: 'Ranchers' } 91 | ], 92 | 93 | shapeCategories: [ 94 | { 95 | name: 'Popular Shapes', 96 | shapes: [ 97 | 'arrow6', 98 | 'bubble4', 99 | 'circle1', 100 | 'rectangle1', 101 | 'star1', 102 | 'triangle1' 103 | ] 104 | }, 105 | { 106 | name: 'Simple Shapes', 107 | shapes: [ 108 | 'circle1', 109 | 'heart1', 110 | 'rectangle1', 111 | 'triangle1', 112 | 'star1', 113 | 'star2', 114 | 'star3', 115 | 'square1' 116 | ] 117 | }, 118 | { 119 | name: 'Arrows & Pointers', 120 | shapes: [ 121 | 'arrow1', 122 | 'arrow9', 123 | 'arrow3', 124 | 'arrow6' 125 | ] 126 | }, 127 | { 128 | name: 'Bubbles & Balloons', 129 | shapes: [ 130 | 'bubble5', 131 | 'bubble4' 132 | ] 133 | }, 134 | { 135 | name: 'Check Marks', 136 | shapes: [ 137 | 138 | ] 139 | }, 140 | { 141 | name: 'Badges', 142 | shapes: [ 143 | 'badge1', 144 | 'badge2', 145 | 'badge4', 146 | 'badge5', 147 | 'badge6' 148 | ] 149 | } 150 | ], 151 | 152 | JSONExportProperties: [ 153 | 'height', 154 | 'width', 155 | 'background', 156 | 'objects', 157 | 158 | 'originalHeight', 159 | 'originalWidth', 160 | 'originalScaleX', 161 | 'originalScaleY', 162 | 'originalLeft', 163 | 'originalTop', 164 | 165 | 'lineHeight', 166 | 'lockMovementX', 167 | 'lockMovementY', 168 | 'lockScalingX', 169 | 'lockScalingY', 170 | 'lockUniScaling', 171 | 'lockRotation', 172 | 'lockObject', 173 | 'id', 174 | 'isTinted', 175 | 'filters' 176 | ], 177 | 178 | windowDefaults: { 179 | padding: 0, 180 | rotatingPointOffset: 40, 181 | transparentCorners: true 182 | }, 183 | 184 | canvasDefaults: { 185 | backgroundColor: '#ffffff', 186 | selection: false, 187 | width: 800, 188 | height: 800, 189 | originalWidth: 800, 190 | originalHeight: 800, 191 | grid: { 192 | show: true, 193 | snapTo: true 194 | } 195 | }, 196 | 197 | shapeDefaults: angular.extend({ 198 | fill: '#0088cc' 199 | }, objectDefaults), 200 | 201 | rectDefaults: angular.extend({ 202 | left: 0, 203 | top: 0, 204 | width: 300, 205 | height: 300, 206 | fill: '#FFFF00', 207 | opacity: 0.7 208 | }, objectDefaults), 209 | 210 | textDefaults: angular.extend({ 211 | left: 0, 212 | top: 0, 213 | originX: 'left', 214 | originY: 'top', 215 | scaleX: 1, 216 | scaleY: 1, 217 | fontFamily: 'Tahoma', 218 | fontSize: 12, 219 | fontWeight: 'normal', 220 | fill: '#454545', 221 | textAlign: 'left' 222 | }, objectDefaults) 223 | 224 | }; 225 | 226 | }]); 227 | -------------------------------------------------------------------------------- /client/app/help/angular-fabric/fabric-directive.js: -------------------------------------------------------------------------------- 1 | angular.module('common.fabric.directive', [ 2 | 'common.fabric.canvas' 3 | ]) 4 | 5 | .directive('fabric', ['$timeout', 'FabricCanvas', '$window', function($timeout, FabricCanvas, $window) { 6 | 7 | return { 8 | scope: { 9 | fabric: '=' 10 | }, 11 | controller: function($scope, $element) { 12 | FabricCanvas.setElement($element); 13 | FabricCanvas.createCanvas(); 14 | 15 | // Continue rendering the canvas until the user clicks 16 | // to avoid the "calcOffset" bug upon load. 17 | $('body').on('click', 'canvas', function() { 18 | if ($scope.fabric.setUserHasClickedCanvas) { 19 | $scope.fabric.setUserHasClickedCanvas(true); 20 | } 21 | }); 22 | 23 | // 24 | // Watching Controller Variables 25 | // ============================================================ 26 | $scope.$watch('fabric.canvasBackgroundColor', function(newVal) { 27 | if ($scope.fabric.setCanvasBackgroundColor) { 28 | $scope.fabric.setCanvasBackgroundColor(newVal); 29 | } 30 | }); 31 | 32 | $scope.$watch('fabric.selectedObject.text', function(newVal) { 33 | if (typeof newVal === 'string') { 34 | $scope.fabric.setText(newVal); 35 | $scope.fabric.render(); 36 | } 37 | }); 38 | 39 | $scope.$watch('fabric.selectedObject.fontSize', function(newVal) { 40 | if (typeof newVal === 'string' || typeof newVal === 'number') { 41 | $scope.fabric.setFontSize(newVal); 42 | $scope.fabric.render(); 43 | } 44 | }); 45 | 46 | $scope.$watch('fabric.selectedObject.lineHeight', function(newVal) { 47 | if (typeof newVal === 'string' || typeof newVal === 'number') { 48 | $scope.fabric.setLineHeight(newVal); 49 | $scope.fabric.render(); 50 | } 51 | }); 52 | 53 | $scope.$watch('fabric.selectedObject.textAlign', function(newVal) { 54 | if (typeof newVal === 'string') { 55 | $scope.fabric.setTextAlign(newVal); 56 | $scope.fabric.render(); 57 | } 58 | }); 59 | 60 | $scope.$watch('fabric.selectedObject.fontFamily', function(newVal) { 61 | if (typeof newVal === 'string' && newVal) { 62 | $scope.fabric.setFontFamily(newVal); 63 | $scope.fabric.render(); 64 | } 65 | }); 66 | 67 | $scope.$watch('fabric.selectedObject.opacity', function(newVal) { 68 | if (typeof newVal === 'string' || typeof newVal === 'number') { 69 | $scope.fabric.setOpacity(newVal); 70 | $scope.fabric.render(); 71 | } 72 | }); 73 | 74 | $scope.$watch('fabric.selectedObject.fill', function(newVal) { 75 | if (typeof newVal === 'string') { 76 | $scope.fabric.setFill(newVal); 77 | $scope.fabric.render(); 78 | } 79 | }); 80 | 81 | $scope.$watch('fabric.selectedObject.tint', function(newVal) { 82 | if (typeof newVal === 'string') { 83 | $scope.fabric.setTint(newVal); 84 | $scope.fabric.render(); 85 | } 86 | }); 87 | } 88 | }; 89 | 90 | }]); 91 | -------------------------------------------------------------------------------- /client/app/help/angular-fabric/fabric-dirty-status.js: -------------------------------------------------------------------------------- 1 | angular.module('common.fabric.dirtyStatus', []) 2 | 3 | .service('FabricDirtyStatus', ['$window', function($window) { 4 | 5 | var self = { 6 | dirty: false 7 | }; 8 | 9 | function checkSaveStatus() { 10 | if (self.isDirty()) { 11 | return "Oops! You have unsaved changes.\n\nPlease save before leaving so you don't lose any work."; 12 | } 13 | } 14 | 15 | self.endListening = function() { 16 | $window.onbeforeunload = null; 17 | $window.onhashchange = null; 18 | }; 19 | 20 | self.startListening = function() { 21 | $window.onbeforeunload = checkSaveStatus; 22 | $window.onhashchange = checkSaveStatus; 23 | }; 24 | 25 | self.isDirty = function() { 26 | return self.dirty; 27 | }; 28 | 29 | self.setDirty = function(value) { 30 | self.dirty = value; 31 | }; 32 | 33 | return self; 34 | 35 | }]); 36 | -------------------------------------------------------------------------------- /client/app/help/angular-fabric/fabric-utilities.js: -------------------------------------------------------------------------------- 1 | angular.module('common.fabric.utilities', []) 2 | 3 | .directive('parentClick', ['$timeout', function($timeout) { 4 | return { 5 | scope: { 6 | parentClick: '&' 7 | }, 8 | link: function(scope, element) { 9 | element.mousedown(function() { 10 | $timeout(function() { 11 | scope.parentClick(); 12 | }); 13 | }) 14 | .children() 15 | .mousedown(function(e) { 16 | e.stopPropagation(); 17 | }); 18 | } 19 | }; 20 | }]) 21 | 22 | // ReferenceError: $ is not defined 23 | // http://stackoverflow.com/questions/30773161/angularjs-referenceerror-is-not-defined 24 | // jqLite doesn't work with selectors 25 | 26 | .factory('Keypress', [function() { 27 | var self = {}; 28 | 29 | self.onSave = function(cb) { 30 | $(document).keydown(function(event) { 31 | // If Control or Command key is pressed and the S key is pressed 32 | // run save function. 83 is the key code for S. 33 | if((event.ctrlKey || event.metaKey) && event.which === 83) { 34 | // Save Function 35 | event.preventDefault(); 36 | 37 | cb(); 38 | 39 | return false; 40 | } 41 | }); 42 | }; 43 | 44 | return self; 45 | }]) 46 | 47 | .filter('reverse', [function() { 48 | return function(items) { 49 | if (items) { 50 | return items.slice().reverse(); 51 | } 52 | }; 53 | }]); 54 | -------------------------------------------------------------------------------- /client/app/help/angular-fabric/fabric-window.js: -------------------------------------------------------------------------------- 1 | angular.module('common.fabric.window', []) 2 | 3 | .factory('FabricWindow', ['$window', function($window) { 4 | 5 | return $window.fabric; 6 | 7 | }]); 8 | -------------------------------------------------------------------------------- /client/app/help/container-config-service.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | 3 | 'use strict'; 4 | 5 | /* 6 | * Use camelCase when naming services and factories. 7 | */ 8 | 9 | angular.module('app.main') 10 | .service('containerConfig', containerConfig); 11 | 12 | /* 13 | * Use $inject to manually identify your dependencies for Angular components. 14 | * This technique mirrors the technique used by ng-annotate, for automating the creation of minification safe 15 | * dependencies. If ng-annotate detects injection has already been made, it will not duplicate it. 16 | */ 17 | 18 | // containerConfig.$inject = ['']; 19 | 20 | function containerConfig() { 21 | 22 | var service = this; 23 | 24 | const CONTROLLED_ZONE_ID = 0; 25 | const RESTRICTED_ZONE_ID = 1; 26 | const SECURED_ZONE_ID = 2; 27 | const PARTNER_ZONE_ID = 3; 28 | const MANAGEMENT_ZONE_ID = 4; 29 | 30 | var containers = [ 31 | { 32 | "id" : CONTROLLED_ZONE_ID, 33 | "name" : "CONTROLLED_ZONE", 34 | "value" : "Controlled Zone", 35 | // "src" : "content/images/icons/32x32/yellow.png", 36 | "src" : "http://placehold.it/32x32/E3F09B", 37 | "backgroundColor" : "#E3F09B" // YELLOW 38 | }, 39 | { 40 | "id" : RESTRICTED_ZONE_ID, 41 | "name" : "RESTRICTED_ZONE", 42 | "value" : "Restricted Zone", 43 | // "src" : "content/images/icons/32x32/light-sea-green.png", 44 | "src" : "http://placehold.it/32x32/F7D08A", 45 | "backgroundColor" : "#F7D08A" // LIGHTGREEN 46 | }, 47 | { 48 | "id" : SECURED_ZONE_ID, 49 | "name" : "SECURED_ZONE", 50 | "value" : "Secured Zone", 51 | // "src" : "content/images/icons/32x32/dark-sea-green.png", 52 | "src" : "http://placehold.it/32x32/87B6A7", 53 | "backgroundColor" : "#87B6A7" // GREEN 54 | }, 55 | { 56 | "id" : PARTNER_ZONE_ID, 57 | "name" : "PARTNER_ZONE", 58 | "value" : "Partner Zone", 59 | // "src" : "content/images/icons/32x32/light-salmon.png", 60 | "src" : "http://placehold.it/32x32/F79F79", 61 | "backgroundColor" : "#F79F79" // LIGHTSALMON 62 | }, 63 | { 64 | "id" : MANAGEMENT_ZONE_ID, 65 | "name" : "MANAGEMENT_ZONE", 66 | "value" : "Management Zone", 67 | // "src" : "content/images/icons/32x32/dodger-blue.png", 68 | "src" : "http://placehold.it/32x32/5B5941", 69 | "backgroundColor" : "#5B5941" // DODGERBLUE 70 | } 71 | ]; 72 | 73 | service.getContainers = function() { 74 | return containers; 75 | }; 76 | 77 | service.getContainer = function(id) { 78 | return containers[id]; 79 | }; 80 | 81 | } 82 | 83 | })(); 84 | 85 | /* 86 | 87 | // http://www.awwwards.com/trendy-web-color-palettes-and-material-design-color-schemes-tools.html 88 | // http://htmlcolorcodes.com/color-names/ 89 | "src" : "http://placehold.it/32x32/FFFF00", // YELLOW 90 | 91 | */ 92 | -------------------------------------------------------------------------------- /client/app/help/format-shape-config-service.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | 3 | 'use strict'; 4 | 5 | /* 6 | * Use camelCase when naming services and factories. 7 | */ 8 | 9 | angular.module('app.main') 10 | .service('formatShapeConfig', formatShapeConfig); 11 | 12 | /* 13 | * Use $inject to manually identify your dependencies for Angular components. 14 | * This technique mirrors the technique used by ng-annotate, for automating the creation of minification safe 15 | * dependencies. If ng-annotate detects injection has already been made, it will not duplicate it. 16 | */ 17 | 18 | // formatShapeConfig.$inject = ['']; 19 | 20 | function formatShapeConfig() { 21 | 22 | var service = this; 23 | 24 | const HELVETICA_ID = 0; 25 | const TAHOMA_ID = 1; 26 | const VERDANA_ID = 2; 27 | 28 | var fontFamilies = [ 29 | { 30 | "id" : HELVETICA_ID, 31 | "name" : "HELVETICA", 32 | "value" : "Helvetica" 33 | }, 34 | { 35 | "id" : TAHOMA_ID, 36 | "name" : "TAHOMA", 37 | "value" : "Tahoma" 38 | }, 39 | { 40 | "id" : VERDANA_ID, 41 | "name" : "VERDANA", 42 | "value" : "Verdana" 43 | } 44 | ]; 45 | 46 | service.getFontFamilies = function() { 47 | return fontFamilies; 48 | }; 49 | 50 | service.getFontFamily = function(id) { 51 | return fontFamilies[id]; 52 | }; 53 | 54 | } 55 | 56 | })(); 57 | 58 | -------------------------------------------------------------------------------- /client/app/help/hello-world-controller.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | 3 | 'use strict'; 4 | 5 | angular.module('my-2d-diagram-editor', []). 6 | controller('HelloWorldController', HelloWorldController); 7 | 8 | HelloWorldController.$inject = ['$log']; 9 | 10 | function HelloWorldController($log) { 11 | 12 | $log.info('HelloWorldController'); 13 | 14 | var hello = this; 15 | 16 | hello.name = { first: "Rob", last: "Ferguson" }; 17 | } 18 | 19 | })(); 20 | -------------------------------------------------------------------------------- /client/app/help/main-module-config.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | 3 | 'use strict'; 4 | 5 | angular.module('app.main') 6 | .config(configModule); 7 | 8 | /* 9 | * Use $inject to manually identify your dependencies for Angular components. 10 | * This technique mirrors the technique used by ng-annotate, for automating the creation of minification safe 11 | * dependencies. If ng-annotate detects injection has already been made, it will not duplicate it. 12 | */ 13 | 14 | configModule.$inject = ['$provide', '$logProvider']; 15 | 16 | function configModule($provide, $logProvider) { 17 | 18 | } 19 | 20 | })(); 21 | 22 | -------------------------------------------------------------------------------- /client/app/help/resize-directive.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | 3 | 'use strict'; 4 | 5 | angular.module('my-2d-diagram-editor') 6 | .directive('resize', resize); 7 | 8 | /* 9 | * Use $inject to manually identify your dependencies for Angular components. 10 | * This technique mirrors the technique used by ng-annotate, for automating the creation of minification safe 11 | * dependencies. If ng-annotate detects injection has already been made, it will not duplicate it. 12 | */ 13 | 14 | resize.$inject = ['$log', '$window']; 15 | 16 | function resize($log, $window) { 17 | 18 | return function (scope, element) { 19 | 20 | $log.info('fabric - link()'); 21 | 22 | var w = angular.element($window); 23 | $log.info('w: ' + w); 24 | scope.getWindowDimensions = function () { 25 | return { 'h': w.height, 'w': w.width }; 26 | }; 27 | scope.$watch(scope.getWindowDimensions, function (newValue, oldValue) { 28 | scope.windowHeight = newValue.h; 29 | scope.windowWidth = newValue.w; 30 | 31 | scope.style = function () { 32 | return { 33 | 'height': (newValue.h - 101) + 'px', 34 | 'width': (newValue.w - 400) + 'px' 35 | }; 36 | }; 37 | 38 | }, true); 39 | 40 | w.bind('resize', function () { 41 | scope.$apply(); 42 | }); 43 | } 44 | 45 | } 46 | 47 | })(); 48 | 49 | // Note: "Best Practice: Directives should clean up after themselves. You can use element.on('$destroy', ...) or 50 | // scope.$on('$destroy', ...) to run a clean-up function when the directive is removed" .. 51 | -------------------------------------------------------------------------------- /client/app/help/shape-config-service.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | 3 | 'use strict'; 4 | 5 | /* 6 | * Use camelCase when naming services and factories. 7 | */ 8 | 9 | angular.module('app.main') 10 | .service('shapeConfig', shapeConfig); 11 | 12 | /* 13 | * Use $inject to manually identify your dependencies for Angular components. 14 | * This technique mirrors the technique used by ng-annotate, for automating the creation of minification safe 15 | * dependencies. If ng-annotate detects injection has already been made, it will not duplicate it. 16 | */ 17 | 18 | // shapesConfig.$inject = ['']; 19 | 20 | function shapeConfig() { 21 | 22 | var service = this; 23 | 24 | const NODE_ID = 0; 25 | const SQUARE_ID = 1; 26 | const RECTANGLE_ID = 2; 27 | 28 | var shapes = [ 29 | 30 | { 31 | "id" : NODE_ID, 32 | "name" : "NODE", 33 | "value" : "Node", 34 | "src" : "content/images/icons/32x32/light-gray.png", 35 | "backgroundColor" : "GRAY" 36 | } 37 | 38 | /* , 39 | { 40 | "id" : SQUARE_ID, 41 | "name" : "SQUARE", 42 | "value" : "Square", 43 | "src" : "content/images/icons/32x32/light-gray.png", 44 | "backgroundColor" : "GRAY" 45 | } 46 | */ 47 | 48 | /* , 49 | { 50 | "id" : RECTANGLE_ID, 51 | "name" : "RECTANGLE", 52 | "value" : "Rectangle", 53 | "src" : "content/images/icons/32x32/light-gray.png", 54 | "backgroundColor" : "LIGHTGRAY" 55 | } 56 | */ 57 | 58 | ]; 59 | 60 | service.getShapes = function() { 61 | return shapes; 62 | }; 63 | 64 | service.getShape = function(id) { 65 | return shapes[id]; 66 | }; 67 | 68 | const HELVETICA_ID = 0; 69 | const TAHOMA_ID = 1; 70 | const VERDANA_ID = 2; 71 | 72 | var fontFamilies = [ 73 | { 74 | "id" : HELVETICA_ID, 75 | "name" : "HELVETICA", 76 | "value" : "Helvetica" 77 | }, 78 | { 79 | "id" : TAHOMA_ID, 80 | "name" : "TAHOMA", 81 | "value" : "Tahoma" 82 | }, 83 | { 84 | "id" : VERDANA_ID, 85 | "name" : "VERDANA", 86 | "value" : "Verdana" 87 | } 88 | ]; 89 | 90 | service.getFontFamilies = function() { 91 | return fontFamilies; 92 | }; 93 | 94 | service.getFontFamily = function(id) { 95 | return fontFamilies[id]; 96 | }; 97 | 98 | const EIGHT_ID = 0; 99 | const TEN_ID = 1; 100 | const TWELVE_ID = 2; 101 | const FOURTEEN_ID = 3; 102 | const SIXTEEN_ID = 4; 103 | const EIGHTEEN_ID = 5; 104 | const TWENTY_ID = 6; 105 | 106 | var fontSizes = [ 107 | { 108 | "id" : EIGHT_ID, 109 | "name" : "EIGHT", 110 | "value" : "8" 111 | }, 112 | { 113 | "id" : TEN_ID, 114 | "name" : "TEN", 115 | "value" : "10" 116 | }, 117 | { 118 | "id" : TWELVE_ID, 119 | "name" : "TWELVE", 120 | "value" : "12" 121 | }, 122 | { 123 | "id" : FOURTEEN_ID, 124 | "name" : "FOURTEEN", 125 | "value" : "14" 126 | }, 127 | { 128 | "id" : SIXTEEN_ID, 129 | "name" : "SIXTEEN", 130 | "value" : "16" 131 | }, 132 | { 133 | "id" : EIGHTEEN_ID, 134 | "name" : "EIGHTEEN", 135 | "value" : "18" 136 | }, 137 | { 138 | "id" : TWENTY_ID, 139 | "name" : "TWENTY", 140 | "value" : "20" 141 | } 142 | 143 | ]; 144 | 145 | service.getFontSizes = function() { 146 | return fontSizes; 147 | }; 148 | 149 | service.getFontSize = function(id) { 150 | return fontSizes[id]; 151 | }; 152 | 153 | const COOLORS_ID = 0; 154 | 155 | var themes = [ 156 | { 157 | "id" : COOLORS_ID, 158 | "name" : "COOLORS", 159 | "value" : "Coolors (coolors.co)" // https://coolors.co 160 | } 161 | 162 | ]; 163 | 164 | service.getThemes = function() { 165 | return themes; 166 | }; 167 | 168 | service.getTheme = function(id) { 169 | return themes[id]; 170 | }; 171 | 172 | const A3_ID = 0; 173 | const A4_ID = 1; 174 | const A5_ID = 2; 175 | 176 | var paperSizes = [ 177 | { 178 | "id" : A3_ID, 179 | "name" : "A3", 180 | "value" : "A3 (297mm x 420mm)" 181 | }, 182 | { 183 | "id" : A4_ID, 184 | "name" : "A4", 185 | "value" : "A4 (210mm x 297mm)" 186 | }, 187 | { 188 | "id" : A5_ID, 189 | "name" : "A5", 190 | "value" : "A5 (148mm x 210mm)" 191 | } 192 | 193 | ]; 194 | 195 | service.getPaperSizes = function() { 196 | return paperSizes; 197 | }; 198 | 199 | service.getPaperSize = function(id) { 200 | return paperSizes[id]; 201 | }; 202 | 203 | } 204 | 205 | })(); 206 | 207 | /* 208 | 209 | // http://www.awwwards.com/trendy-web-color-palettes-and-material-design-color-schemes-tools.html 210 | // http://htmlcolorcodes.com/color-names/ 211 | "src" : "http://placehold.it/32x32/FFFF00", // YELLOW 212 | 213 | */ 214 | -------------------------------------------------------------------------------- /client/app/help/temp.js: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | (function() { 6 | 7 | 'use strict'; 8 | 9 | /* 10 | * Reference the App Module to attach a controller 11 | * 12 | * Dependency Injection Syntax and AngularJS 13 | * The notation that we have used is one of the two ways in which we can declare AngularJS controllers 14 | * (or services, directives, or filters). The style we have used, which is also the recommended way, 15 | * is the safe-style of Dependency Injection, or declaration. 16 | */ 17 | 18 | angular.module('my-2d-diagram-editor') 19 | .controller('MainController', ['$log', '$translate', '$scope', 'Fabric', 'FabricConstants', 'sidebarFactory', 20 | function($log, $translate, $scope, Fabric, FabricConstants, sidebarFactory) { 21 | 22 | $log.info('MainController'); 23 | 24 | $scope.shapes = sidebarFactory.getShapes(); 25 | $scope.containers = sidebarFactory.getContainers(); 26 | 27 | $scope.fabric = {}; 28 | // $scope.FabricConstants = FabricConstants; 29 | 30 | $scope.grid = { show: false }; 31 | $scope.verticalGridLinesGroup = {}; 32 | $scope.horizontalGridLinesGroup = {}; 33 | $scope.verticalGridLines = []; 34 | $scope.horizontalGridLines = []; 35 | 36 | $scope.init = function () { 37 | 38 | $scope.fabric = new Fabric({ 39 | JSONExportProperties: FabricConstants.JSONExportProperties, 40 | shapeDefaults: FabricConstants.shapeDefaults, 41 | rectDefaults: FabricConstants.rectDefaults, 42 | textDefaults: FabricConstants.textDefaults, 43 | json: {} 44 | }); 45 | 46 | $scope.toggleGrid(); 47 | 48 | }; 49 | 50 | $scope.$on('canvas:created', $scope.init); 51 | 52 | var containerTextDefaults = angular.copy(FabricConstants.textDefaults); 53 | containerTextDefaults.fontSize = 20; 54 | containerTextDefaults.fontWeight = 'bold'; 55 | var containerRectDefaults = angular.copy(FabricConstants.rectDefaults); 56 | 57 | var shapeTextDefaults = angular.copy(FabricConstants.textDefaults); 58 | shapeTextDefaults.fontSize = 14; 59 | var shapeRectDefaults = angular.copy(FabricConstants.rectDefaults); 60 | shapeRectDefaults.width = 100; 61 | shapeRectDefaults.height = 100; 62 | 63 | $scope.newShape = function(name, fill) { 64 | 65 | $log.info('MainController.newShape()'); 66 | 67 | fill = fill || '#cacaca'; 68 | shapeRectDefaults.fill = fill; 69 | 70 | // name = name || 'NODE' + ' 1'; 71 | name = 'NODE'; 72 | 73 | $translate(name) 74 | .then(function (translatedValue) { 75 | $scope.fabric.addRect(shapeRectDefaults); 76 | $scope.fabric.addText(translatedValue + ' 1', shapeTextDefaults); 77 | }); 78 | 79 | }; 80 | 81 | $scope.newContainer = function(name, fill) { 82 | 83 | $log.info('MainController.newContainer()'); 84 | 85 | fill = fill || '#cacaca'; 86 | containerRectDefaults.fill = fill; 87 | 88 | name = name || 'CONTROLLED_ZONE'; 89 | 90 | $translate(name) 91 | .then(function (translatedValue) { 92 | $scope.fabric.addRect(containerRectDefaults); 93 | $scope.fabric.addText(translatedValue, containerTextDefaults); 94 | }); 95 | }; 96 | 97 | $scope.fileNew = function() { 98 | $log.info('MainController.fileNew()'); 99 | }; 100 | 101 | $scope.editDelete = function() { 102 | $log.info('MainController.editDelete()'); 103 | $scope.fabric.deleteActiveObject(); 104 | }; 105 | 106 | $scope.toggleGrid = function() { 107 | 108 | $log.info('MainController.toggleGrid()'); 109 | 110 | $scope.grid.show = !$scope.grid.show; 111 | 112 | if ($scope.grid.show) { 113 | drawGrid(); 114 | } else { 115 | removeGrid(); 116 | } 117 | }; 118 | 119 | $scope.setPointerMode = function() { 120 | $log.info('MainController.setPointerMode()'); 121 | $scope.fabric.setDrawingMode(false); 122 | }; 123 | 124 | $scope.setConnectorMode = function() { 125 | $log.info('MainController.setConnectorMode()'); 126 | $scope.fabric.setDrawingMode(true); 127 | }; 128 | 129 | $scope.toggleSnapToGrid = function() { 130 | $log.info('MainController.toggleSnapToGrid()'); 131 | $scope.fabric.toggleSnapToGrid(); 132 | }; 133 | 134 | $scope.switchLanguage = function(key) { 135 | $translate.use(key); 136 | }; 137 | 138 | // 139 | // Private methods 140 | // 141 | 142 | var removeGrid = function() { 143 | 144 | $log.info('MainController.removeGrid()'); 145 | 146 | $scope.fabric.removeGroup($scope.verticalGridLinesGroup); 147 | $scope.fabric.removeGroup($scope.horizontalGridLinesGroup); 148 | }; 149 | 150 | var drawGrid = function() { 151 | 152 | $log.info('MainController.drawGrid()'); 153 | 154 | var grid = 50; 155 | var width = FabricConstants.canvasDefaults.width; 156 | var height = FabricConstants.canvasDefaults.height; 157 | 158 | // draw the Vertical lines 159 | var i = 0; 160 | for (var x = 0.5; x < width; x += grid) { 161 | $scope.verticalGridLines[i++] = $scope.fabric.drawGridLine([ x, 0.5, x, width], { stroke: '#ccc', selectable: false }); 162 | } 163 | 164 | // draw the Horizontal lines 165 | i = 0; 166 | for (var y = 0.5; y < height; y += grid) { 167 | $scope.horizontalGridLines[i++] = $scope.fabric.drawGridLine([ 0.5, y, height, y], { stroke: '#ccc', selectable: false }); 168 | } 169 | 170 | $scope.verticalGridLinesGroup = $scope.fabric.createGroup($scope.verticalGridLines, { selectable: false }); 171 | $scope.verticalGridLinesGroup.sendToBack(); 172 | $scope.horizontalGridLinesGroup = $scope.fabric.createGroup($scope.horizontalGridLines, { selectable: false }); 173 | $scope.horizontalGridLinesGroup.sendToBack(); 174 | 175 | // Why did we start x and y at 0.5? Why not 0? 176 | // See: http://diveintohtml5.info/canvas.html 177 | 178 | $scope.fabric.deselectActiveObject(); 179 | }; 180 | 181 | }]); 182 | })(); 183 | 184 | /* 185 | 186 | $scope.viewGrid = function() { 187 | $log.info('MainController.viewGrid()'); 188 | toggleGrid(); 189 | }; 190 | 191 | var grid = 100; 192 | var verticalY1= 1; 193 | var horizontalX1 = 1; 194 | 195 | for (var i = 0; i < (600 / grid); i++) { 196 | // draw the Vertical grid lines 197 | $scope.fabric.addLine([ i * grid, verticalY1, i * grid, 600], { stroke: '#ccc', selectable: false }); 198 | // draw the Horizontal grid lines 199 | $scope.fabric.addLine([ horizontalX1, i * grid, 600, i * grid], { stroke: '#ccc', selectable: false }); 200 | } 201 | 202 | // containerTextDefaults.left = 0; 203 | // containerTextDefaults.top = 0; 204 | // containerTextDefaults.fontFamily = 'Tahoma'; 205 | 206 | $scope.fabric.addText('Controlled Zone'); 207 | $scope.fabric.setFontFamily('Tahoma'); 208 | $scope.fabric.setFontSize(20); 209 | $scope.fabric.toggleBold(); 210 | 211 | $scope.fabric.addLine([ 50, 25, 50, 550], { stroke: '#ccc', selectable: false }); 212 | $scope.fabric.addLine([ 100, 25, 100, 550], { stroke: '#ccc', selectable: false }); 213 | $scope.fabric.addLine([ 150, 25, 150, 550], { stroke: '#ccc', selectable: false }); 214 | 215 | */ 216 | 217 | 218 | /* 219 | 220 | $scope.newContainer = function(label, fill) { 221 | 222 | $log.info('MainController.newContainer()'); 223 | 224 | label = label || 'New Container'; 225 | fill = fill || '#cacaca'; 226 | 227 | containerRectDefaults.fill = fill; 228 | 229 | $scope.fabric.addRect(containerRectDefaults); 230 | $scope.fabric.addText(label, containerTextDefaults); 231 | }; 232 | 233 | */ 234 | 235 | (function() { 236 | 237 | 'use strict'; 238 | 239 | /* 240 | * Reference the App Module to attach a controller 241 | * 242 | * Dependency Injection Syntax and AngularJS 243 | * The notation that we have used is one of the two ways in which we can declare AngularJS controllers 244 | * (or services, directives, or filters). The style we have used, which is also the recommended way, 245 | * is the safe-style of Dependency Injection, or declaration. 246 | * 247 | * $scope is the glue between the view and controller within an AngularJS application. With the 248 | * introduction of the controller-as syntax, the need to explicitly use $scope has been greatly reduced. 249 | * 250 | * However we still need it for Eventing :) 251 | * $broadcast: Sends events from a parent scope downward to its children. 252 | * $emit: Sends events from a child upward to its parent. 253 | * $on: Listens for an event and responds. 254 | * 255 | * We'll use the controller-as syntax by declaring the controller to be 'MainController as main', which 256 | * means that we’ll reference the MainController as main within our Views (e.g., layout.html). 257 | */ 258 | 259 | angular.module('my-2d-diagram-editor.main') 260 | .controller('MainController', ['$log', '$translate', '$scope', 'mainService', 'fabricService', 'fabricCanvas', 'fabricWindow', 261 | function($log, $translate, $scope, mainService, fabricService, fabricCanvas, fabricWindow) { 262 | 263 | $log.info('MainController as main'); 264 | 265 | /* 266 | * Per common convention, I like to store a reference to the top-level this object (this has a habit 267 | * of changing context based on function level scope). I also like to name the reference to this, the 268 | * same name that I declare the controller-as (e.g., MainController as main). 269 | * This makes it easier to read and connect the dots as you jump between the HTML and the JavaScript. 270 | */ 271 | 272 | var main = this; 273 | 274 | main.shapes = mainService.getShapes(); 275 | main.containers = mainService.getContainers(); 276 | 277 | main.init = function () { 278 | 279 | $log.info('MainController - init()'); 280 | 281 | var canvas = fabricCanvas.getCanvas(); 282 | 283 | var rectDefaults = angular.copy(fabricService.getRectDefaults()); 284 | 285 | // $log.info('rectDefaults: ' + JSON.stringify(['e', rectDefaults], null, '\t')); 286 | 287 | rectDefaults.left = 100; 288 | rectDefaults.top = 100; 289 | rectDefaults.width = 100; 290 | rectDefaults.height = 100; 291 | 292 | // $log.info('canvas: ' + JSON.stringify(['e', canvas], null, '\t')); 293 | 294 | var object = new fabricWindow.Rect(rectDefaults); 295 | 296 | canvas.add(object); 297 | 298 | rectDefaults.left = 200; 299 | rectDefaults.top = 200; 300 | 301 | var object = new fabricWindow.Rect(rectDefaults); 302 | 303 | canvas.add(object); 304 | 305 | canvas.setActiveObject(object); 306 | canvas.renderAll(); 307 | 308 | /* 309 | 310 | object.id = self.createId(); 311 | 312 | self.addObjectToCanvas(object); 313 | 314 | var points = [100, 200, 100, 200]; 315 | var options = { stroke: '#ccc' }; 316 | var object = new fabricWindow.Line(points, options); 317 | 318 | canvas.add(object); 319 | 320 | canvas.renderAll(); 321 | 322 | */ 323 | 324 | }; 325 | 326 | $scope.$on('canvas:created', main.init); 327 | 328 | main.newShape = function(name, fill) { 329 | $log.info('MainController.newShape()'); 330 | }; 331 | 332 | main.newContainer = function(name, fill) { 333 | $log.info('MainController.newContainer()'); 334 | }; 335 | 336 | main.fileNew = function() { 337 | $log.info('MainController.fileNew()'); 338 | }; 339 | 340 | main.editDelete = function() { 341 | $log.info('MainController.editDelete()'); 342 | }; 343 | 344 | main.toggleGrid = function() { 345 | $log.info('MainController.toggleGrid()'); 346 | }; 347 | 348 | main.setPointerMode = function() { 349 | $log.info('MainController.setPointerMode()'); 350 | }; 351 | 352 | main.setConnectorMode = function() { 353 | $log.info('MainController.setConnectorMode()'); 354 | }; 355 | 356 | main.toggleSnapToGrid = function() { 357 | $log.info('MainController.toggleSnapToGrid()'); 358 | }; 359 | 360 | main.switchLanguage = function(key) { 361 | $log.info('MainController.switchLanguage() - ' + key.toLocaleString()); 362 | $translate.use(key); 363 | }; 364 | 365 | // 366 | // Private methods 367 | // 368 | 369 | var removeGrid = function() { 370 | $log.info('MainController.removeGrid()'); 371 | }; 372 | 373 | var drawGrid = function() { 374 | $log.info('MainController.drawGrid()'); 375 | }; 376 | 377 | 378 | 379 | }]); 380 | 381 | })(); 382 | 383 | (function() { 384 | 385 | 'use strict'; 386 | 387 | angular.module('my-2d-diagram-editor.main') 388 | .directive('resize', resize); 389 | 390 | /* 391 | * Use $inject to manually identify your dependencies for Angular components. 392 | * This technique mirrors the technique used by ng-annotate, for automating the creation of minification safe 393 | * dependencies. If ng-annotate detects injection has already been made, it will not duplicate it. 394 | */ 395 | 396 | resize.$inject = ['$log', '$window']; 397 | 398 | function resize($log, $window) { 399 | return { 400 | 401 | restrict: 'A', 402 | scope: { 403 | options: '=' 404 | }, 405 | link: function link(scope, element) { 406 | 407 | $log.info('resize - link()'); 408 | 409 | const HEADER_HEIGHT = 101; 410 | 411 | var w = angular.element($window); 412 | 413 | scope.getWindowDimensions = function () { 414 | 415 | $log.info('width: ' + $window.innerWidth + ' height: ' + $window.innerHeight); 416 | 417 | return { 418 | 'width': $window.innerWidth, 419 | 'height': $window.innerHeight 420 | }; 421 | }; 422 | 423 | scope.$watch(scope.getWindowDimensions, function (newValue, oldValue) { 424 | 425 | // scope.windowHeight = newValue.h; 426 | // scope.windowWidth = newValue.w; 427 | 428 | scope.style = function () { 429 | 430 | $log.info('height: ' + (newValue.height - HEADER_HEIGHT) + 'px'); 431 | 432 | return { 433 | // 'width': (newValue.width - 100) + 'px', 434 | 'height': (newValue.height - HEADER_HEIGHT) + 'px' 435 | }; 436 | }; 437 | 438 | }, true); 439 | 440 | 441 | w.bind('resize', function () { 442 | scope.$apply(); 443 | }); 444 | 445 | } 446 | }; 447 | } 448 | 449 | })(); 450 | 451 | // Note: "Best Practice: Directives should clean up after themselves. You can use element.on('$destroy', ...) or 452 | // scope.$on('$destroy', ...) to run a clean-up function when the directive is removed" ... 453 | 454 | 455 | /* 456 | 457 | 458 | var objectCenter = service.selectedObject.getCenterPoint(); 459 | 460 | $log.info('mouse:up - service.selectedObject.__corner: ' + service.selectedObject.__corner); 461 | 462 | service.connectorLine.set({ x2: objectCenter.x, y2: objectCenter.y }); 463 | 464 | 465 | // add a reference to the line to each object 466 | service.fromObject.addChild = { 467 | // this retains the existing arrays (if there were any) 468 | from: (service.fromObject.addChild && service.fromObject.addChild.from), 469 | to: (service.fromObject.addChild && service.fromObject.addChild.to) 470 | }; 471 | 472 | // var pointer = service.canvas.getPointer(object.e); 473 | // var points = [ pointer.x, pointer.y, pointer.x, pointer.y ]; 474 | 475 | // $log.info('mouse:down - points: ' + points.toLocaleString()); 476 | 477 | // canvas.item(canvas._objects.length-1).set('active',true); 478 | 479 | // canvas.setActiveObject(canvas._objects[canvas._objects.length-1]); 480 | 481 | var object = element.target; 482 | 483 | object.set('hasRotatingPoint', true); 484 | object.setControlsVisibility({ 485 | tl: true, 486 | tr: true, 487 | br: true, 488 | bl: true 489 | }); 490 | 491 | // service.selectedObject.lockUniScaling = true; you only get the corners 492 | 493 | 494 | // var rectDefaults = angular.copy(fabricService.getRectDefaults()); 495 | // var objectControls = null; 496 | // const LINE_WIDTH = 1; 497 | 498 | service.objectControls = false; 499 | service.controlDefaults = null; 500 | service.controlsGroup = {}; 501 | service.controlLines = []; 502 | 503 | // $log.info('element: ' + JSON.stringify(['e', element], null, '\t')); 504 | 505 | // drawControls(element); 506 | 507 | // eraseControls(element); 508 | 509 | // 510 | // Controls 511 | // 512 | 513 | var drawControls = function(element) { 514 | drawObjectControls(element); 515 | }; 516 | 517 | var eraseControls = function(element) { 518 | eraseObjectControls(element); 519 | }; 520 | 521 | var drawObjectControls = function(element) { 522 | 523 | $log.info('fabric - drawObjectControls()'); 524 | 525 | $log.info('element: ' + JSON.stringify(['e', element], null, '\t')); 526 | 527 | if (service.objectControls === false) { 528 | 529 | $log.info('service.objectControls === false'); 530 | 531 | var topLeft = {x: element.target.left - 2, y: element.target.top - 2}; 532 | var topRight = {x: element.target.top + element.target.width, y: element.target.top - 2}; 533 | var bottomLeft = {x: element.target.left - 2, y: element.target.top + element.target.height}; 534 | var bottomRight = {x: element.target.top + element.target.width, y: element.target.top + element.target.height}; 535 | 536 | var i = 0; 537 | service.controlLines[i++] = fabricShape.line([ topLeft.x, topLeft.y, topRight.x, topRight.y], 538 | service.controlDefaults); 539 | service.controlLines[i++] = fabricShape.line([ topRight.x, topRight.y, bottomRight.x, bottomRight.y], 540 | service.controlDefaults); 541 | service.controlLines[i++] = fabricShape.line([ bottomRight.x, bottomRight.y, bottomLeft.x, bottomLeft.y], 542 | service.controlDefaults); 543 | service.controlLines[i++] = fabricShape.line([ bottomLeft.x, bottomLeft.y, topLeft.x, topLeft.y], 544 | service.controlDefaults); 545 | 546 | service.controlsGroup = service.createGroup(service.controlLines, { selectable: false }, false); 547 | 548 | service.objectControls = true; 549 | 550 | // top-left 551 | // top-right 552 | // bottom-left 553 | // bottom-right 554 | 555 | } 556 | 557 | }; 558 | 559 | var eraseObjectControls = function(element) { 560 | 561 | $log.info('fabric - eraseObjectControls()'); 562 | 563 | if (service.objectControls === true) { 564 | 565 | $log.info('service.objectControls === true'); 566 | 567 | service.removeGroup(service.controlsGroup, true) 568 | 569 | service.objectControls = false; 570 | } 571 | }; 572 | 573 | // element.target.setFill('red'); 574 | // service.canvas.renderAll(); 575 | 576 | 577 | // element.target.setFill('green'); 578 | // service.canvas.renderAll(); 579 | 580 | rectDefaults.strokeWidth = 5; 581 | 582 | rectDefaults.left = element.target.left - (rectDefaults.strokeWidth + 1); 583 | rectDefaults.top = element.target.top - (rectDefaults.strokeWidth + 1); 584 | rectDefaults.width = element.target.width + (2 * rectDefaults.strokeWidth); 585 | rectDefaults.height = element.target.height + (2 * rectDefaults.strokeWidth); 586 | rectDefaults.fill = 'none'; 587 | rectDefaults.stroke = 'rgba(100,200,200,0.5)'; 588 | rectDefaults.opacity = 0.5; 589 | 590 | // $log.info('rectDefaults: ' + JSON.stringify(['e', rectDefaults], null, '\t')); 591 | 592 | objectControls = service.addRect(rectDefaults, false); 593 | 594 | if (object.left === canvasDefaults.grid.size || object.top === canvasDefaults.grid.size) { 595 | $log.info('fabric - addObjectToCanvas() - centerObject()'); 596 | fabricWindow.centerObject(); 597 | } 598 | 599 | // $log.info('mouse:over - element.target: ' + JSON.stringify(['e', element.target], null, '\t')); 600 | 601 | rectDefaults.left = 50 - (rectDefaults.strokeWidth + 1); 602 | rectDefaults.top = 50 - (rectDefaults.strokeWidth + 1); 603 | rectDefaults.width = 300 + (2 * rectDefaults.strokeWidth); 604 | rectDefaults.height = 300 + (2 * rectDefaults.strokeWidth); 605 | 606 | var activeGroup = this.getActiveGroup(); 607 | 608 | if (activeGroup) { 609 | drawGroupControls(); 610 | } else { 611 | drawObjectControls(); 612 | } 613 | 614 | */ 615 | -------------------------------------------------------------------------------- /client/app/locales/de.json: -------------------------------------------------------------------------------- 1 | { 2 | "BRAND_NAME": "Rob's Awesome 2D Diagrammeditor", 3 | 4 | "TOGGLE_NAVIGATION": "Toggle -Navigation", 5 | "SIGN_IN": "Anmelden", 6 | 7 | "ENGLISH": "Englisch", 8 | "POLISH": "Polieren", 9 | "GERMAN": "Deutsch", 10 | 11 | "FILE": "Datei", 12 | "FILE_NEW": "Neu...", 13 | "CLOSE": "Nah dran", 14 | 15 | "EDIT": "Bearbeiten", 16 | "UNDO": "Rückgängig machen", 17 | "REDO": "Wiederherstellen", 18 | "CUT": "Cut", 19 | "COPY": "Copy", 20 | "PASTE": "Paste", 21 | "DELETE": "Löschen", 22 | 23 | "VIEW": "Aussicht", 24 | "GRID": "Gitter", 25 | "SNAP_TO_GRID": "Am Raster ausrichten", 26 | 27 | "ARRANGE": "Arrangieren", 28 | "BRING_FORWARD": "Bring Forward", 29 | "BRING_TO_FRONT": "Voran bringen", 30 | "SEND_BACKWARD": "Nach hinten", 31 | "SEND_TO_BACK": "In den Hintergrund", 32 | 33 | "OPTIONS": "Optionen", 34 | "LANGUAGE": "Sprache", 35 | "HELP": "Hilfe", 36 | 37 | "ZOOM_IN": "Hineinzoomen", 38 | "ZOOM_OUT": "Rauszoomen", 39 | 40 | "POINTER": "Set Pointer - Modus", 41 | "CONNECTOR": "Set Anschluss - Modus", 42 | "LOCK": "Sperren", 43 | "COMMENT": "Kommentar", 44 | 45 | "SHAPES": "Formen", 46 | "SQUARE": "Platz", 47 | "RECTANGLE": "Rechteck", 48 | 49 | "NODE": "Knoten", 50 | 51 | "CONTAINERS": "Behälter", 52 | "CONTROLLED_ZONE": "Kontrollierten Zone", 53 | "RESTRICTED_ZONE": "Sperrzone", 54 | "SECURED_ZONE": "Gesicherten Zone", 55 | "PARTNER_ZONE": "Partnerbereich", 56 | "MANAGEMENT_ZONE": "Verwaltungszone", 57 | 58 | "FORMAT_DIAGRAM": "Formatdiagramm", 59 | "PAPER_SIZE": "Papier größe", 60 | "PORTRAIT": "Porträt", 61 | "LANDSCAPE": "Landschaft", 62 | 63 | "FORMAT_SHAPE": "Shape formatieren", 64 | "TEXT": "Text", 65 | "NAME": "Name", 66 | "FONT": "Schriftart", 67 | "FONT_SIZE": "Schriftgröße", 68 | "FONT_STYLE": "Schriftstil", 69 | "BOLD": "Fett gedruckt", 70 | "ITALIC": "Kursiv", 71 | "ALIGNMENT": "Ausrichtung", 72 | "ALIGN_LEFT": "Align Left", 73 | "ALIGN_CENTER": "Linksbündig", 74 | "ALIGN_RIGHT": "Rechts ausrichten", 75 | "ALIGN_TOP": "oben ausrichten", 76 | "ALIGN_MIDDLE": "Vertikal zentrieren", 77 | "ALIGN_BOTTOM": "unten ausrichten", 78 | 79 | "STYLE": "Stil", 80 | "STYLES": "Styles", 81 | "SHAPE_STYLES": "Formenarten", 82 | "THEME": "Thema", 83 | "THEME_STYLES": "Stilarten", 84 | "FILL": "Füllen", 85 | "LINE": "Linie", 86 | "EFFECTS": "Auswirkungen", 87 | 88 | "ARRANGE": "Arrangieren", 89 | "ALIGN": "Ausrichten", 90 | "POSITION": "Position", 91 | "GROUP": "Gruppe", 92 | 93 | 94 | "COMING_SOON": "Demnächst :)" 95 | } 96 | -------------------------------------------------------------------------------- /client/app/locales/en.json: -------------------------------------------------------------------------------- 1 | { 2 | "BRAND_NAME": "Rob's Awesome 2D Diagram Editor", 3 | 4 | "TOGGLE_NAVIGATION": "Toggle navigation", 5 | "SIGN_IN": "Sign In", 6 | 7 | "ENGLISH": "English", 8 | "POLISH": "Polish", 9 | "GERMAN": "German", 10 | 11 | "FILE": "File", 12 | "FILE_NEW": "New...", 13 | "CLOSE": "Close", 14 | 15 | "EDIT": "Edit", 16 | "UNDO": "Undo", 17 | "REDO": "Redo", 18 | "CUT": "Cut", 19 | "COPY": "Copy", 20 | "PASTE": "Paste", 21 | "DELETE": "Delete", 22 | 23 | "VIEW": "View", 24 | "GRID": "Grid", 25 | "SNAP_TO_GRID": "Snap to Grid", 26 | 27 | "ARRANGE": "Arrange", 28 | "BRING_FORWARD": "Bring Forward", 29 | "BRING_TO_FRONT": "Bring to Front", 30 | "SEND_BACKWARD": "Send Backward", 31 | "SEND_TO_BACK": "Send to Back", 32 | 33 | "OPTIONS": "Options", 34 | "LANGUAGE": "Language", 35 | "HELP": "Help", 36 | 37 | "ZOOM_IN": "Zoom In", 38 | "ZOOM_OUT": "Zoom Out", 39 | 40 | "POINTER": "Set Pointer Mode", 41 | "CONNECTOR": "Set Connector Mode", 42 | "LOCK": "Lock", 43 | "COMMENT": "Comment", 44 | 45 | "SHAPES": "Shapes", 46 | "SQUARE": "Square", 47 | "RECTANGLE": "Rectangle", 48 | 49 | "NODE": "Node", 50 | 51 | "CONTAINERS": "Containers", 52 | "CONTROLLED_ZONE": "Controlled Zone", 53 | "RESTRICTED_ZONE": "Restricted Zone", 54 | "SECURED_ZONE": "Secured Zone", 55 | "PARTNER_ZONE": "Partner Zone", 56 | "MANAGEMENT_ZONE": "Management Zone", 57 | 58 | "FORMAT_DIAGRAM": "Format Diagram", 59 | "PAPER_SIZE": "Paper Size", 60 | "PORTRAIT": "Portrait", 61 | "LANDSCAPE": "Landscape", 62 | 63 | "FORMAT_SHAPE": "Format Shape", 64 | "TEXT": "Text", 65 | "NAME": "Name", 66 | "FONT": "Font", 67 | "FONT_SIZE": "Font Size", 68 | "FONT_STYLE": "Font Style", 69 | "BOLD": "Bold", 70 | "ITALIC": "Italic", 71 | "ALIGNMENT": "Alignment", 72 | "ALIGN_LEFT": "Align Left", 73 | "ALIGN_CENTER": "Align Center", 74 | "ALIGN_RIGHT": "Align Right", 75 | "ALIGN_TOP": "Align Top", 76 | "ALIGN_MIDDLE": "Align Middle", 77 | "ALIGN_BOTTOM": "Align Bottom", 78 | 79 | "STYLE": "Style", 80 | "STYLES": "Styles", 81 | "SHAPE_STYLES": "Shape Styles", 82 | "THEME": "Theme", 83 | "THEME_STYLES": "Theme Styles", 84 | "FILL": "Fill", 85 | "LINE": "Line", 86 | "EFFECTS": "Effects", 87 | 88 | "ARRANGE": "Arrange", 89 | "ALIGN": "Align", 90 | "POSITION": "Position", 91 | "GROUP": "Group", 92 | 93 | 94 | "COMING_SOON": "Coming Soon :)" 95 | } 96 | -------------------------------------------------------------------------------- /client/app/locales/pl.json: -------------------------------------------------------------------------------- 1 | { 2 | "BRAND_NAME": "Rob's Awesome 2D Diagram Editor", 3 | 4 | "TOGGLE_NAVIGATION": "TNawigacja", 5 | "SIGN_IN": "Logowanie", 6 | 7 | "ENGLISH": "Angielski", 8 | "POLISH": "Polskie", 9 | "GERMAN": "Niemiecki", 10 | 11 | "FILE": "Plik", 12 | "FILE_NEW": "Nowy...", 13 | "CLOSE": "Zamknij", 14 | 15 | "EDIT": "Edycja", 16 | "UNDO": "Cofnij", 17 | "REDO": "Powtorz", 18 | "CUT": "Cut", 19 | "COPY": "Copy", 20 | "PASTE": "Paste", 21 | "DELETE": "Usun", 22 | 23 | "VIEW": "Pokaz", 24 | "GRID": "Siec", 25 | "SNAP_TO_GRID": "Snap to Grid", 26 | 27 | "ARRANGE": "Arrange", 28 | "BRING_FORWARD": "Bring Forward", 29 | "BRING_TO_FRONT": "Bring to Front", 30 | "SEND_BACKWARD": "Send Backward", 31 | "SEND_TO_BACK": "Send to Back", 32 | 33 | "OPTIONS": "Opcje", 34 | "LANGUAGE": "Jezyk", 35 | "HELP": "Pomoc", 36 | 37 | "ZOOM_IN": "Zoom In", 38 | "ZOOM_OUT": "Zoom Out", 39 | 40 | "POINTER": "Set Pointer Mode", 41 | "CONNECTOR": "Set Connector Mode", 42 | "LOCK": "Zablokuj", 43 | "COMMENT": "Komentarz", 44 | 45 | "SHAPES": "Ksztalty", 46 | "SQUARE": "Kwadraty", 47 | "RECTANGLE": "Prostokąt", 48 | 49 | "NODE": "Node", 50 | 51 | "CONTAINERS": "Kontenery", 52 | "CONTROLLED_ZONE": "Strefa kontrolowana", 53 | "RESTRICTED_ZONE": "Strefa ograniczona", 54 | "SECURED_ZONE": "Strefa zabezpieczona", 55 | "PARTNER_ZONE": "Strefa partnerska", 56 | "MANAGEMENT_ZONE": "Strefa zarzadzania", 57 | 58 | "FORMAT_DIAGRAM": "Format Diagram", 59 | 60 | "FORMAT_SHAPE": "Format Shape", 61 | 62 | "TEXT": "Text", 63 | "NAME": "Name", 64 | "FONT": "Font", 65 | "FONT_SIZE": "Font Size", 66 | "FONT_STYLE": "Font Style", 67 | "BOLD": "Bold", 68 | "ITALIC": "Italic", 69 | "ALIGNMENT": "Alignment", 70 | "ALIGN_LEFT": "Align Left", 71 | "ALIGN_CENTER": "Align Center", 72 | "ALIGN_RIGHT": "Align Right", 73 | "ALIGN_TOP": "Align Top", 74 | "ALIGN_MIDDLE": "Align Middle", 75 | "ALIGN_BOTTOM": "Align Bottom", 76 | 77 | "STYLE": "Style", 78 | 79 | "ARRANGE": "Arrange", 80 | 81 | 82 | "COMING_SOON": "Wiecej w przyszlosci :)" 83 | } 84 | 85 | -------------------------------------------------------------------------------- /client/app/main/content-resize-directive.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | 3 | 'use strict'; 4 | 5 | angular.module('app.main') 6 | .directive('resize', resize); 7 | 8 | /* 9 | * Use $inject to manually identify your dependencies for Angular components. 10 | * This technique mirrors the technique used by ng-annotate, for automating the creation of minification safe 11 | * dependencies. If ng-annotate detects injection has already been made, it will not duplicate it. 12 | */ 13 | 14 | resize.$inject = ['$log', '$window']; 15 | 16 | function resize($log, $window) { 17 | return function(scope, element) { 18 | 19 | $log.debug('resize - link()'); 20 | 21 | const HEADER_HEIGHT = 101; 22 | 23 | var window = angular.element($window); 24 | 25 | scope.getWindowDimensions = function () { 26 | return { 27 | 'width': $window.innerWidth, 28 | 'height': $window.innerHeight 29 | }; 30 | }; 31 | 32 | scope.$watch(scope.getWindowDimensions, function (newValue) { 33 | 34 | scope.style = function () { 35 | 36 | var sidebarWidth = document.getElementById('sidebar-left-container').clientWidth; 37 | 38 | return { 39 | // 'width': (newValue.width - sidebarWidth) + 'px', 40 | 'width': (newValue.width - (sidebarWidth * 2)) + 'px', 41 | 'height': (newValue.height - HEADER_HEIGHT) + 'px' 42 | }; 43 | }; 44 | 45 | }, true); 46 | 47 | 48 | window.bind('resize', function () { 49 | scope.$apply(); 50 | }); 51 | 52 | } 53 | } 54 | 55 | })(); 56 | 57 | // Note: "Best Practice: Directives should clean up after themselves. You can use element.on('$destroy', ...) or 58 | // scope.$on('$destroy', ...) to run a clean-up function when the directive is removed" ... 59 | 60 | // $log.debug('width: ' + $window.innerWidth + ' height: ' + $window.innerHeight); 61 | 62 | // $log.debug('sidebarWidth: ' + (sidebarWidth) + 'px'); 63 | // $log.debug('width: ' + (newValue.width) + 'px'); 64 | // $log.debug('height: ' + (newValue.height - HEADER_HEIGHT) + 'px'); 65 | 66 | // 'width': (newValue.width - sidebarWidth - 10) + 'px', 67 | // 'width': (newValue.width - (sidebarWidth * 2) - 10) + 'px', 68 | -------------------------------------------------------------------------------- /client/app/main/main-controller.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | 3 | 'use strict'; 4 | 5 | /* 6 | * Reference the App Module to attach a controller 7 | * 8 | * controllerAs Controller Syntax 9 | * Helps avoid the temptation of using $scope methods inside a controller when it may otherwise be better to 10 | * avoid them or move the method to a factory, and reference them from the controller. 11 | * 12 | * We'll use the controllerAs syntax by declaring the controller to be 'MainController as main', which 13 | * means that we’ll reference the MainController as main within our Views (e.g., layout.html). 14 | * 15 | * Consider using $scope in a controller only when needed. For example when publishing or subscribing to events. 16 | * $broadcast: Sends events from a parent scope downward to its children. 17 | * $emit: Sends events from a child upward to its parent. 18 | * $on: Listens for an event and responds. 19 | */ 20 | 21 | /* 22 | * Use UpperCamelCase when naming controllers, as they are constructors. 23 | */ 24 | 25 | angular.module('app.main') 26 | .controller('MainController', MainController); 27 | 28 | /* 29 | * Use $inject to manually identify your dependencies for Angular components. 30 | * This technique mirrors the technique used by ng-annotate, for automating the creation of minification safe 31 | * dependencies. If ng-annotate detects injection has already been made, it will not duplicate it. 32 | */ 33 | 34 | MainController.$inject = ['$log', '$translate', '$scope', 'containersModel', 'shapesModel', 35 | 'paperSizesModel', 'fontFamiliesModel', 'fontSizesModel', 'themesModel', 'fabric', 'fabricConfig']; 36 | 37 | function MainController($log, $translate, $scope, containersModel, shapesModel, 38 | paperSizesModel, fontFamiliesModel, fontSizesModel, themesModel, fabric, fabricConfig) { 39 | 40 | $log.debug('MainController'); 41 | 42 | /* 43 | * Per common convention, I like to store a reference to the top-level this object (this has a habit 44 | * of changing context based on function level scope). I also like to name the reference to this, the 45 | * same name that I declare the controllerAs (e.g., MainController as main). 46 | * This makes it easier to read and connect the dots as you jump between the HTML and the JavaScript. 47 | */ 48 | 49 | var main = this; 50 | 51 | // 52 | // Shapes and Containers 53 | // 54 | 55 | main.shapes = null; 56 | main.containers = null; 57 | 58 | main.containerDefaults = angular.copy(fabricConfig.getRectWithTextDefaults()); 59 | 60 | // 61 | // Format Diagram 62 | // 63 | 64 | const A4_ARRAY_INDEX = 1; 65 | 66 | main.diagram = {}; 67 | // main.diagram.paperSize = main.paperSizes[A4_ARRAY_INDEX].value; 68 | 69 | main.paperSizes = null; 70 | main.pageView = {}; 71 | main.pageView.portrait = true; 72 | main.pageView.landscape = false; 73 | 74 | // 75 | // Format Shape 76 | // 77 | 78 | main.formatShape = false; 79 | main.shape = {}; 80 | 81 | main.fontFamilies = null; 82 | main.fontSizes = null; 83 | main.themes = null; 84 | 85 | main.nodeId = 1; 86 | 87 | main.nodeDefaults = angular.copy(fabricConfig.getRectWithTextDefaults()); 88 | 89 | // 90 | // Canvas 91 | // 92 | 93 | main.canvas = null; 94 | main.grid = { show: true, snapTo: false}; 95 | 96 | main.getShapes = function () { 97 | shapesModel.find() 98 | .then(function (response) { 99 | main.shapes = (response !== 'null') ? response.data : []; 100 | }, function (response) { 101 | $log.error('MainController - could not load shapes'); 102 | }); 103 | }; 104 | 105 | main.getContainers = function () { 106 | containersModel.find() 107 | .then(function (response) { 108 | main.containers = (response !== 'null') ? response.data : []; 109 | }, function (response) { 110 | $log.error('MainController - could not load containers'); 111 | }); 112 | }; 113 | 114 | main.getPaperSizes = function () { 115 | paperSizesModel.find() 116 | .then(function (response) { 117 | main.paperSizes = (response !== 'null') ? response.data : []; 118 | main.diagram.paperSize = main.paperSizes[A4_ARRAY_INDEX].value; 119 | }, function (response) { 120 | $log.error('MainController - could not load paper sizes'); 121 | }); 122 | }; 123 | 124 | main.getFontFamilies = function () { 125 | fontFamiliesModel.find() 126 | .then(function (response) { 127 | main.fontFamilies = (response !== 'null') ? response.data : []; 128 | }, function (response) { 129 | $log.error('MainController - could not load font families'); 130 | }); 131 | }; 132 | 133 | main.getFontSizes = function () { 134 | fontSizesModel.find() 135 | .then(function (response) { 136 | main.fontSizes = (response !== 'null') ? response.data : []; 137 | }, function (response) { 138 | $log.error('MainController - could not load font sizes'); 139 | }); 140 | }; 141 | 142 | main.getThemes = function () { 143 | themesModel.find() 144 | .then(function (response) { 145 | main.themes = (response !== 'null') ? response.data : []; 146 | }, function (response) { 147 | $log.error('MainController - could not load themes'); 148 | }); 149 | }; 150 | 151 | main.getShapes(); 152 | main.getContainers(); 153 | main.getPaperSizes(); 154 | main.getFontFamilies(); 155 | main.getFontSizes(); 156 | main.getThemes(); 157 | 158 | main.init = function () { 159 | 160 | $log.debug('MainController - init()'); 161 | 162 | main.canvas = fabric.getCanvas(); 163 | 164 | main.toggleGrid(); 165 | 166 | /* 167 | * Listen for Fabric 'object:selected' event 168 | */ 169 | 170 | main.canvas.on('object:selected', function(element) { 171 | 172 | $log.debug('MainController - object:selected'); 173 | 174 | fabric.objectSelectedListener(element); 175 | 176 | main.shape = fabric.getActiveObject(); 177 | main.formatShape = true; 178 | 179 | document.getElementById("format-diagram-container").style.display = "none"; 180 | document.getElementById("format-shape-container").style.display = "block"; 181 | }); 182 | 183 | /* 184 | * Listen for Fabric 'selection:cleared' event 185 | */ 186 | 187 | main.canvas.on('selection:cleared', function(element) { 188 | 189 | $log.debug('MainController - selection:cleared'); 190 | 191 | fabric.selectionClearedListener(element); 192 | 193 | main.shape = null; 194 | main.formatShape = false; 195 | 196 | document.getElementById("format-shape-container").style.display = "none"; 197 | document.getElementById("format-diagram-container").style.display = "block"; 198 | }); 199 | 200 | }; 201 | 202 | /* 203 | * Listen for 'canvas:created' event $broadcast by fabricCanvas 204 | */ 205 | 206 | $scope.$on('canvas:created', main.init); 207 | 208 | main.newShape = function(name, fill) { 209 | 210 | $log.debug('MainController.newShape()'); 211 | 212 | main.newNode(name, fill); 213 | }; 214 | 215 | // const GRID_SIZE = 50; 216 | 217 | main.newNode = function(name, fill) { 218 | 219 | $log.debug('MainController.newNode()'); 220 | 221 | fabric.setConnectorMode(false); 222 | 223 | name = name || 'NODE'; 224 | fill = fill || 'GRAY'; // http://htmlcolorcodes.com/color-names/ 225 | main.nodeDefaults.fill = fill; 226 | 227 | $translate(name) 228 | .then(function (translatedValue) { 229 | 230 | var id = main.nodeId++; 231 | var text = translatedValue + ' ' + id; 232 | 233 | // main.nodeDefaults.left = (main.nodeDefaults.width * id) + (GRID_SIZE * id); 234 | 235 | var object = fabric.addRectWithText(text, main.nodeDefaults); 236 | object.set('type', 'node'); 237 | 238 | // object(fromPort) <-- toArrow -- connector(fromLine or toLine) -- fromArrow --> (toPort)otherObject 239 | 240 | // object.connectors = { fromPort: [], fromLine: [], fromArrow: [], toPort: [], toLine: [], toArrow: [], otherObject: [] }; 241 | object.connectors = { fromPort: [], toArrow: [], fromLine: [], toLine: [], fromArrow: [], toPort: [], otherObject: [] }; 242 | 243 | fabric.setActiveObject(object); 244 | }); 245 | }; 246 | 247 | const RECT_WIDTH = 300; 248 | const RECT_HEIGHT = 300; 249 | const FONT_SIZE = '20'; 250 | const FONT_WEIGHT = 'bold'; 251 | 252 | main.newContainer = function(name, fill) { 253 | 254 | $log.debug('MainController.newContainer()'); 255 | 256 | fabric.setConnectorMode(false); 257 | 258 | name = name || 'CONTROLLED_ZONE'; 259 | fill = fill || 'GRAY'; 260 | main.containerDefaults.fill = fill; 261 | main.containerDefaults.fontSize = FONT_SIZE; 262 | main.containerDefaults.fontWeight = FONT_WEIGHT; 263 | main.containerDefaults.width = RECT_WIDTH; 264 | main.containerDefaults.height = RECT_HEIGHT; 265 | main.containerDefaults.textYAlign = 'top'; 266 | 267 | $translate(name) 268 | .then(function (translatedValue) { 269 | var object = fabric.addRectWithText(translatedValue, main.containerDefaults); 270 | object.set('type', 'container'); 271 | 272 | fabric.setActiveObject(object); 273 | }); 274 | }; 275 | 276 | main.fileNew = function() { 277 | $log.debug('MainController.fileNew()'); 278 | }; 279 | 280 | main.editDelete = function() { 281 | $log.debug('MainController.editDelete()'); 282 | fabric.removeActiveObjectFromCanvas(); 283 | }; 284 | 285 | main.togglePageViewOrientation = function() { 286 | $log.debug('MainController.togglePageViewOrientation()'); 287 | main.pageView.portrait = !main.pageView.portrait; 288 | main.pageView.landscape = !main.pageView.portrait; 289 | }; 290 | 291 | main.toggleGrid = function() { 292 | $log.debug('MainController.toggleGrid()'); 293 | main.grid.show = !main.grid.show; 294 | fabric.showGrid(main.grid.show); 295 | }; 296 | 297 | main.showGrid = function(flag) { 298 | $log.debug('MainController.showGrid()'); 299 | main.grid.show = flag; 300 | fabric.showGrid(main.grid.show); 301 | }; 302 | 303 | main.toggleSnapToGrid = function() { 304 | $log.debug('MainController.toggleSnapToGrid()'); 305 | main.grid.snapTo = !main.grid.snapTo; 306 | fabric.snapToGrid(main.grid.snapTo); 307 | }; 308 | 309 | main.snapToGrid = function(flag) { 310 | $log.debug('MainController.snapToGrid()'); 311 | main.grid.snapTo = flag; 312 | fabric.snapToGrid(main.grid.snapTo); 313 | }; 314 | 315 | main.setPointerMode = function() { 316 | $log.debug('MainController.setPointerMode()'); 317 | fabric.setConnectorMode(false); 318 | }; 319 | 320 | main.setConnectorMode = function() { 321 | $log.debug('MainController.setConnectorMode()'); 322 | fabric.setConnectorMode(true); 323 | main.grid.snapTo = false; 324 | fabric.snapToGrid(main.grid.snapTo); 325 | }; 326 | 327 | // Arrange Menu Items 328 | 329 | main.bringForward = function() { 330 | fabric.bringForward(); 331 | }; 332 | 333 | main.bringToFront = function() { 334 | fabric.bringToFront(); 335 | }; 336 | 337 | main.sendBackward = function() { 338 | fabric.sendBackward(); 339 | }; 340 | 341 | main.sendToBack = function() { 342 | fabric.sendToBack(); 343 | }; 344 | 345 | // 346 | // Language Menu Items 347 | // 348 | 349 | main.switchLanguage = function(key) { 350 | $log.debug('MainController.switchLanguage() - ' + key.toLocaleString()); 351 | $translate.use(key); 352 | }; 353 | 354 | // Format Shape 355 | 356 | // HTML5 Canvas 357 | // font-style: normal, italic and oblique 358 | // font-weight: normal, bold, bolder, lighter, 100-900 359 | 360 | main.toggleBold = function() { 361 | 362 | $log.debug('MainController.toggleBold()'); 363 | 364 | if (main.shape.fontWeight.indexOf('bold') !== -1) { 365 | if (main.shape.fontWeight.indexOf('italic') !== -1) { 366 | main.shape.fontWeight = 'italic'; 367 | } else { 368 | main.shape.fontWeight = ''; 369 | } 370 | } else { 371 | if (main.shape.fontWeight.indexOf('italic') !== -1) { 372 | main.shape.fontWeight = 'bold italic'; 373 | } else { 374 | main.shape.fontWeight = 'bold'; 375 | } 376 | } 377 | 378 | $log.debug('MainController.toggleBold() - fontWeight: ' + main.shape.fontWeight); 379 | }; 380 | 381 | main.toggleItalic = function() { 382 | 383 | $log.debug('MainController.toggleItalic()'); 384 | 385 | if (main.shape.fontWeight.indexOf('italic') !== -1) { 386 | if (main.shape.fontWeight.indexOf('bold') !== -1) { 387 | main.shape.fontWeight = 'bold'; 388 | } else { 389 | main.shape.fontWeight = ''; 390 | } 391 | } else { 392 | if (main.shape.fontWeight.indexOf('bold') !== -1) { 393 | main.shape.fontWeight = 'bold italic'; 394 | } else { 395 | main.shape.fontWeight = 'italic'; 396 | } 397 | } 398 | 399 | $log.debug('MainController.toggleBold() - fontWeight: ' + main.shape.fontWeight); 400 | }; 401 | 402 | // https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/textAlign 403 | // left, right, center, start, end 404 | 405 | main.textXAlign = function(align) { 406 | 407 | $log.debug('MainController.textXAlign()'); 408 | 409 | main.shape.textXAlign = align; 410 | 411 | $log.debug('MainController.textXAlign() - align: ' + main.shape.textXAlign); 412 | }; 413 | 414 | // top, bottom, middle 415 | 416 | main.textYAlign = function(align) { 417 | 418 | $log.debug('MainController.textYAlign()'); 419 | 420 | main.shape.textYAlign = align; 421 | 422 | $log.debug('MainController.textXAlign() - align: ' + main.shape.textYAlign); 423 | }; 424 | 425 | } 426 | 427 | })(); 428 | 429 | /* 430 | 431 | // https://coolors.co 432 | $log.debug('MainController - main.shape.text: ' + main.shape.text); 433 | $log.debug('MainController - main.shape.fontFamily: ' + main.shape.fontFamily); 434 | $log.debug('MainController - main.shape.fontSize: ' + main.shape.fontSize); 435 | 436 | 437 | main.setShapeName = function(name) { 438 | $log.debug('MainController.setShapeName()'); 439 | // fabric.setActiveObject(main.shape); 440 | }; 441 | 442 | */ 443 | -------------------------------------------------------------------------------- /client/app/main/main-module.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | 3 | /* 4 | * Wrap Angular components in an Immediately Invoked Function Expression (IIFE). 5 | * An IIFE removes variables from the global scope. This helps prevent variables and function declarations 6 | * from living longer than expected in the global scope, which also helps avoid variable collisions. 7 | */ 8 | 9 | 'use strict'; 10 | 11 | /* 12 | * Declare a new module called 'app.main', and list its dependencies. 13 | * Modules serve as containers to help you organise code within your AngularJS application. 14 | * Modules can contain sub-modules, making it easy to compose functionality as needed. 15 | */ 16 | 17 | angular.module('app.main', [ 18 | 19 | /* 20 | * Angular modules 21 | */ 22 | 23 | 'ngAnimate', 24 | 'ui.bootstrap', 25 | 'ui.router', 26 | 27 | /* 28 | * Our reusable cross app code modules 29 | */ 30 | 31 | 'blocks.exception', 32 | 'blocks.endpoint', 33 | 34 | /* 35 | * 3rd Party modules 36 | */ 37 | 38 | 'pascalprecht.translate', 39 | 'ui.fabric' 40 | 41 | ]); 42 | 43 | })(); 44 | -------------------------------------------------------------------------------- /client/app/main/models/containers-model.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | 3 | 'use strict'; 4 | 5 | /* 6 | * Use camelCase when naming services and factories. 7 | */ 8 | 9 | angular.module('app.main') 10 | .service('containersModel', containersModel); 11 | 12 | /* 13 | * Use $inject to manually identify your dependencies for Angular components. 14 | * This technique mirrors the technique used by ng-annotate, for automating the creation of minification safe 15 | * dependencies. If ng-annotate detects injection has already been made, it will not duplicate it. 16 | */ 17 | 18 | containersModel.$inject = ['$log', '$http', 'EndpointConfigService']; 19 | 20 | function containersModel($log, $http, EndpointConfigService) { 21 | 22 | var service = this; 23 | var MODEL = 'containers'; 24 | 25 | service.find = function () { 26 | return $http.get(EndpointConfigService.getUrl(MODEL)) 27 | .then(function(response) { 28 | $log.debug('Loaded model: ' + MODEL); 29 | return response; 30 | }, function(response) { 31 | $log.error('Could not load model: ' + MODEL); 32 | }); 33 | }; 34 | } 35 | 36 | })(); 37 | 38 | -------------------------------------------------------------------------------- /client/app/main/models/font-families-model.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | 3 | 'use strict'; 4 | 5 | /* 6 | * Use camelCase when naming services and factories. 7 | */ 8 | 9 | angular.module('app.main') 10 | .service('fontFamiliesModel', fontFamiliesModel); 11 | 12 | /* 13 | * Use $inject to manually identify your dependencies for Angular components. 14 | * This technique mirrors the technique used by ng-annotate, for automating the creation of minification safe 15 | * dependencies. If ng-annotate detects injection has already been made, it will not duplicate it. 16 | */ 17 | 18 | fontFamiliesModel.$inject = ['$log', '$http', 'EndpointConfigService']; 19 | 20 | function fontFamiliesModel($log, $http, EndpointConfigService) { 21 | 22 | var service = this; 23 | var MODEL = 'font-families'; 24 | 25 | service.find = function () { 26 | return $http.get(EndpointConfigService.getUrl(MODEL)) 27 | .then(function(response) { 28 | $log.debug('Loaded model: ' + MODEL); 29 | return response; 30 | }, function(response) { 31 | $log.error('Could not load model: ' + MODEL); 32 | }); 33 | }; 34 | } 35 | 36 | })(); 37 | -------------------------------------------------------------------------------- /client/app/main/models/font-sizes-model.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | 3 | 'use strict'; 4 | 5 | /* 6 | * Use camelCase when naming services and factories. 7 | */ 8 | 9 | angular.module('app.main') 10 | .service('fontSizesModel', fontSizesModel); 11 | 12 | /* 13 | * Use $inject to manually identify your dependencies for Angular components. 14 | * This technique mirrors the technique used by ng-annotate, for automating the creation of minification safe 15 | * dependencies. If ng-annotate detects injection has already been made, it will not duplicate it. 16 | */ 17 | 18 | fontSizesModel.$inject = ['$log', '$http', 'EndpointConfigService']; 19 | 20 | function fontSizesModel($log, $http, EndpointConfigService) { 21 | 22 | var service = this; 23 | var MODEL = 'font-sizes'; 24 | 25 | service.find = function () { 26 | return $http.get(EndpointConfigService.getUrl(MODEL)) 27 | .then(function(response) { 28 | $log.debug('Loaded model: ' + MODEL); 29 | return response; 30 | }, function(response) { 31 | $log.error('Could not load model: ' + MODEL); 32 | }); 33 | }; 34 | } 35 | 36 | })(); 37 | -------------------------------------------------------------------------------- /client/app/main/models/paper-sizes-model.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | 3 | 'use strict'; 4 | 5 | /* 6 | * Use camelCase when naming services and factories. 7 | */ 8 | 9 | angular.module('app.main') 10 | .service('paperSizesModel', paperSizesModel); 11 | 12 | /* 13 | * Use $inject to manually identify your dependencies for Angular components. 14 | * This technique mirrors the technique used by ng-annotate, for automating the creation of minification safe 15 | * dependencies. If ng-annotate detects injection has already been made, it will not duplicate it. 16 | */ 17 | 18 | paperSizesModel.$inject = ['$log', '$http', 'EndpointConfigService']; 19 | 20 | function paperSizesModel($log, $http, EndpointConfigService) { 21 | 22 | var service = this; 23 | var MODEL = 'paper-sizes'; 24 | 25 | service.find = function () { 26 | return $http.get(EndpointConfigService.getUrl(MODEL)) 27 | .then(function(response) { 28 | $log.debug('Loaded model: ' + MODEL); 29 | return response; 30 | }, function(response) { 31 | $log.error('Could not load model: ' + MODEL); 32 | }); 33 | }; 34 | } 35 | 36 | })(); 37 | -------------------------------------------------------------------------------- /client/app/main/models/shapes-model.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | 3 | 'use strict'; 4 | 5 | /* 6 | * Use camelCase when naming services and factories. 7 | */ 8 | 9 | angular.module('app.main') 10 | .service('shapesModel', shapesModel); 11 | 12 | /* 13 | * Use $inject to manually identify your dependencies for Angular components. 14 | * This technique mirrors the technique used by ng-annotate, for automating the creation of minification safe 15 | * dependencies. If ng-annotate detects injection has already been made, it will not duplicate it. 16 | */ 17 | 18 | shapesModel.$inject = ['$log', '$http', 'EndpointConfigService']; 19 | 20 | function shapesModel($log, $http, EndpointConfigService) { 21 | 22 | var service = this; 23 | var MODEL = 'shapes'; 24 | 25 | service.find = function () { 26 | return $http.get(EndpointConfigService.getUrl(MODEL)) 27 | .then(function(response) { 28 | $log.debug('Loaded model: ' + MODEL); 29 | return response; 30 | }, function(response) { 31 | $log.error('Could not load model: ' + MODEL); 32 | }); 33 | }; 34 | } 35 | 36 | })(); 37 | 38 | -------------------------------------------------------------------------------- /client/app/main/models/themes-model.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | 3 | 'use strict'; 4 | 5 | /* 6 | * Use camelCase when naming services and factories. 7 | */ 8 | 9 | angular.module('app.main') 10 | .service('themesModel', themesModel); 11 | 12 | /* 13 | * Use $inject to manually identify your dependencies for Angular components. 14 | * This technique mirrors the technique used by ng-annotate, for automating the creation of minification safe 15 | * dependencies. If ng-annotate detects injection has already been made, it will not duplicate it. 16 | */ 17 | 18 | themesModel.$inject = ['$log', '$http', 'EndpointConfigService']; 19 | 20 | function themesModel($log, $http, EndpointConfigService) { 21 | 22 | var service = this; 23 | var MODEL = 'themes'; 24 | 25 | service.find = function () { 26 | return $http.get(EndpointConfigService.getUrl(MODEL)) 27 | .then(function(response) { 28 | $log.debug('Loaded model: ' + MODEL); 29 | return response; 30 | }, function(response) { 31 | $log.error('Could not load model: ' + MODEL); 32 | }); 33 | }; 34 | } 35 | 36 | })(); 37 | -------------------------------------------------------------------------------- /client/app/main/templates/content.html: -------------------------------------------------------------------------------- 1 | 7 | 8 |
9 | 10 |
11 | 12 | 13 | -------------------------------------------------------------------------------- /client/app/main/templates/format-diagram.html: -------------------------------------------------------------------------------- 1 | 5 | 6 | 7 | 8 | 9 | 10 | {{ 'FORMAT_DIAGRAM' | translate }} 11 | 13 | 14 | 15 | 16 |
17 |
18 | 19 |
20 | 21 | 24 | 25 | 29 | 33 |
34 | 35 |
36 | 37 | 38 |
39 | 40 | 44 |
45 | 46 |
47 | 48 | 49 |
50 | 51 | 55 |
56 | 57 | 58 | 59 |
60 |
61 | 62 |
63 |
64 | 65 | 86 | -------------------------------------------------------------------------------- /client/app/main/templates/format-shape.html: -------------------------------------------------------------------------------- 1 | 5 | 6 | 7 | 8 | 9 | 10 | {{ 'FORMAT_SHAPE' | translate }} 11 | 13 | 14 | 15 | 16 | 17 | 18 | 21 | 22 | 23 |
24 |
25 | 26 |
27 | 28 | 29 | 30 |
31 | 32 |
33 | 34 | 37 |
38 | 39 |
40 | 41 | 44 |
45 | 46 | 47 |
48 | 52 | 56 |
57 | 58 | 59 | 60 | 61 |
62 | 66 | 70 | 74 | 78 | 82 | 86 |
87 | 88 |
89 |
90 |
91 | 92 | 95 | 96 | 97 |
98 |
99 | 100 |
101 | 102 | 105 |
106 | 107 |
108 | 109 | 110 |
111 |
112 | 113 | 114 | 115 |
116 | 117 |
118 | 119 | 120 | 121 |
122 | 123 |
124 | 125 | 126 | 127 |
128 | 129 |
130 | 131 | 132 | 133 |
134 | 135 |
136 | 137 | 138 | 139 |
140 |
141 |
142 | 143 |
144 | 145 |
146 | 147 |
148 | 149 |
150 | 151 |
152 | 153 |
154 | 155 |
156 | 157 |
158 |
159 |
160 | 161 | 164 | 165 | 166 |
167 |
168 | 169 |
170 | 171 |
172 | 173 |
174 | 175 |
176 | 177 |
178 | 179 |
180 | 181 |
182 |
183 |
184 | 185 |
186 | 187 |
188 |
189 | -------------------------------------------------------------------------------- /client/app/main/templates/header.html: -------------------------------------------------------------------------------- 1 | 5 | 6 |
7 | 8 |
9 | -------------------------------------------------------------------------------- /client/app/main/templates/layout.html: -------------------------------------------------------------------------------- 1 | 2 | 3 |
4 | 5 | 12 |
13 | 14 |
15 | 16 | 19 | 20 |
21 |
22 |
23 | 24 | 27 | 28 |
29 | 30 |
31 | 32 | 40 | 41 | 83 | -------------------------------------------------------------------------------- /client/app/main/templates/menubar.html: -------------------------------------------------------------------------------- 1 | 5 | 6 | 149 | 150 | -------------------------------------------------------------------------------- /client/app/main/templates/sidebar-left.html: -------------------------------------------------------------------------------- 1 | 9 | 10 |
11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | {{ 'SHAPES' | translate }} 20 | 22 | 23 | 24 | 25 |
26 |
27 | 28 | 29 | 30 | 37 |
38 |
39 | 40 | 41 |
42 | 43 | 44 | 45 | 46 | 47 | 48 | {{ 'CONTAINERS' | translate }} 49 | 51 | 52 | 53 | 54 |
55 | 67 |
68 | 69 |
70 | 71 |
72 | 73 |
74 | 75 | 76 | -------------------------------------------------------------------------------- /client/app/main/templates/sidebar-right.html: -------------------------------------------------------------------------------- 1 | 2 | 3 |
4 | 5 |
6 |
7 |
8 | 9 |
10 |
11 |
12 | 13 |
14 | 15 | 31 | -------------------------------------------------------------------------------- /client/app/main/templates/toolbar.html: -------------------------------------------------------------------------------- 1 | 98 | 99 | 100 | 121 | -------------------------------------------------------------------------------- /client/bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "my-2d-diagram-editor", 3 | "version": "1.0.0", 4 | "description": "A browser-based 2D diagram editor.", 5 | "main": "app-module.js", 6 | "authors": [ 7 | "Rob Ferguson" 8 | ], 9 | "license": "MIT", 10 | "moduleType": [], 11 | "homepage": "https://github.com/Robinyo", 12 | "private": true, 13 | "ignore": [ 14 | "**/.*", 15 | "node_modules", 16 | "bower_components", 17 | "test", 18 | "tests" 19 | ], 20 | "dependencies": { 21 | "angular": "~1.4.8", 22 | "angular-bootstrap": "~0.14.3", 23 | "bootstrap-css": "3.1.1", 24 | "angular-animate": "~1.4.8", 25 | "angular-ui-router": "~0.2.15", 26 | "fabric.js": "fabric#~1.5.0", 27 | "angular-translate": "~2.8.1", 28 | "angular-translate-loader-static-files": "~2.8.1", 29 | "font-awesome": "fontawesome#~4.5.0", 30 | "stacktrace-js": "~1.0.1" 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /client/content/css/styles.css: -------------------------------------------------------------------------------- 1 | /* .nav, .pagination, .carousel, .panel-title a { cursor: pointer; } */ 2 | 3 | /* See: http://angular-ui.github.io/bootstrap/#/getting_started */ 4 | 5 | .nav, .pagination, .carousel, .panel-title a { cursor: pointer; } 6 | 7 | body { 8 | font-family: 'Walter Turncoat', serif; 9 | font-size: 14px; 10 | overflow: hidden; /* hide the scrollbar */ 11 | } 12 | 13 | .sign-in { 14 | padding-right: 35px; 15 | } 16 | 17 | .toolbar { 18 | top: 51px; 19 | } 20 | 21 | .sidebar-left { 22 | top: 101px; /* menubar 50 + toolbar 51 */ 23 | left: 0; 24 | 25 | border-right: 1px solid #eee; 26 | bottom: 0; 27 | display: block; 28 | padding: 0px; /* padding: 5px; */ 29 | position: fixed; 30 | overflow-x: hidden; 31 | overflow-y: auto; 32 | 33 | /* z-index: 1000; */ 34 | } 35 | 36 | .content-container { 37 | top: 101px; /* menubar 50 + toolbar 51 */ 38 | 39 | display: block; 40 | padding: 0px; 41 | 42 | /* z-index: 1001; */ 43 | } 44 | 45 | .content { 46 | top: 101px; /* menubar 50 + toolbar 51 */ 47 | 48 | background-color: #f5f5f5; 49 | display: block; 50 | padding: 10px; 51 | position: fixed; 52 | overflow-x: auto; 53 | overflow-y: auto; 54 | 55 | width: 800px; 56 | height: 600px; 57 | } 58 | 59 | .sidebar-right { 60 | top: 101px; /* menubar 50 + toolbar 51 */ 61 | 62 | border-left: 1px solid #eee; 63 | bottom: 0; 64 | display: block; 65 | padding: 0px; /* padding: 5px; */ 66 | position: fixed; 67 | overflow-x: hidden; /* hide the scrollbar */ 68 | overflow-y: auto; 69 | 70 | /* z-index: 1002; */ 71 | } 72 | 73 | .accordion-panel .panel-body { 74 | padding-top: 0px; 75 | padding-left: 0px; 76 | padding-bottom: 0px; 77 | padding-right: 0px; 78 | } 79 | 80 | .panel-content { 81 | background-color: #f5f5f5; 82 | padding: 10px; 83 | } 84 | 85 | .tab-content { 86 | background-color: #f5f5f5; 87 | padding: 5px; 88 | } 89 | 90 | .radio-button-label { 91 | padding-top: 10px; 92 | } 93 | 94 | .nav-tabs.nav-justified > li.active > a, 95 | .nav-tabs.nav-justified > li.active > a:hover, 96 | .nav-tabs.nav-justified > li.active > a:focus{ 97 | background-color: #f5f5f5; !important; 98 | border-bottom-color: #f5f5f5; 99 | } 100 | 101 | .form-content { 102 | font-family: 'Tahoma', serif; 103 | font-size: 14px; 104 | } 105 | 106 | .thumbnail-column { 107 | padding-right: 5px; 108 | padding-left: 5px; 109 | } 110 | 111 | .bootstrap-select > .btn { 112 | height: 34px; 113 | } 114 | 115 | /* 116 | 117 | background-color: #f5f5f5; 118 | http://getbootstrap.com/css/#forms-control-sizes 119 | 120 | */ 121 | 122 | /* 123 | .nav-tabs{ 124 | background-color: #f5f5f5; 125 | } 126 | */ 127 | -------------------------------------------------------------------------------- /client/content/images/logical-security-zone-model-diagram.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Robinyo/my-2d-diagram-editor/bcdb1e6fabba0aea5d36994352a68a39002ea58a/client/content/images/logical-security-zone-model-diagram.png -------------------------------------------------------------------------------- /client/content/images/my-2d-diagram-editor-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Robinyo/my-2d-diagram-editor/bcdb1e6fabba0aea5d36994352a68a39002ea58a/client/content/images/my-2d-diagram-editor-1.png -------------------------------------------------------------------------------- /client/content/images/my-2d-diagram-editor-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Robinyo/my-2d-diagram-editor/bcdb1e6fabba0aea5d36994352a68a39002ea58a/client/content/images/my-2d-diagram-editor-2.png -------------------------------------------------------------------------------- /client/content/images/my-2d-diagram-editor-3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Robinyo/my-2d-diagram-editor/bcdb1e6fabba0aea5d36994352a68a39002ea58a/client/content/images/my-2d-diagram-editor-3.png -------------------------------------------------------------------------------- /client/content/images/my-2d-diagram-editor-4-english.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Robinyo/my-2d-diagram-editor/bcdb1e6fabba0aea5d36994352a68a39002ea58a/client/content/images/my-2d-diagram-editor-4-english.png -------------------------------------------------------------------------------- /client/content/images/my-2d-diagram-editor-4-german.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Robinyo/my-2d-diagram-editor/bcdb1e6fabba0aea5d36994352a68a39002ea58a/client/content/images/my-2d-diagram-editor-4-german.png -------------------------------------------------------------------------------- /client/content/images/my-2d-diagram-editor-4-polish.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Robinyo/my-2d-diagram-editor/bcdb1e6fabba0aea5d36994352a68a39002ea58a/client/content/images/my-2d-diagram-editor-4-polish.png -------------------------------------------------------------------------------- /client/content/images/my-2d-diagram-editor-5-english.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Robinyo/my-2d-diagram-editor/bcdb1e6fabba0aea5d36994352a68a39002ea58a/client/content/images/my-2d-diagram-editor-5-english.png -------------------------------------------------------------------------------- /client/content/images/my-2d-diagram-editor-6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Robinyo/my-2d-diagram-editor/bcdb1e6fabba0aea5d36994352a68a39002ea58a/client/content/images/my-2d-diagram-editor-6.png -------------------------------------------------------------------------------- /client/content/images/my-2d-diagram-editor-7.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Robinyo/my-2d-diagram-editor/bcdb1e6fabba0aea5d36994352a68a39002ea58a/client/content/images/my-2d-diagram-editor-7.png -------------------------------------------------------------------------------- /client/content/images/my-2d-diagram-editor-draw-connector-with-arrow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Robinyo/my-2d-diagram-editor/bcdb1e6fabba0aea5d36994352a68a39002ea58a/client/content/images/my-2d-diagram-editor-draw-connector-with-arrow.png -------------------------------------------------------------------------------- /client/content/images/my-2d-diagram-editor-formatting-shapes.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Robinyo/my-2d-diagram-editor/bcdb1e6fabba0aea5d36994352a68a39002ea58a/client/content/images/my-2d-diagram-editor-formatting-shapes.png -------------------------------------------------------------------------------- /client/content/images/my-2d-diagram-editor-interactivity.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Robinyo/my-2d-diagram-editor/bcdb1e6fabba0aea5d36994352a68a39002ea58a/client/content/images/my-2d-diagram-editor-interactivity.png -------------------------------------------------------------------------------- /client/content/images/my-2d-diagram-editor-with-connections-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Robinyo/my-2d-diagram-editor/bcdb1e6fabba0aea5d36994352a68a39002ea58a/client/content/images/my-2d-diagram-editor-with-connections-2.png -------------------------------------------------------------------------------- /client/content/images/my-2d-diagram-editor-with-connections.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Robinyo/my-2d-diagram-editor/bcdb1e6fabba0aea5d36994352a68a39002ea58a/client/content/images/my-2d-diagram-editor-with-connections.png -------------------------------------------------------------------------------- /client/content/images/my-2d-diagram-editor-with-ports-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Robinyo/my-2d-diagram-editor/bcdb1e6fabba0aea5d36994352a68a39002ea58a/client/content/images/my-2d-diagram-editor-with-ports-2.png -------------------------------------------------------------------------------- /client/content/images/my-2d-diagram-editor-with-ports-3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Robinyo/my-2d-diagram-editor/bcdb1e6fabba0aea5d36994352a68a39002ea58a/client/content/images/my-2d-diagram-editor-with-ports-3.png -------------------------------------------------------------------------------- /client/content/images/my-2d-diagram-editor-with-ports-4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Robinyo/my-2d-diagram-editor/bcdb1e6fabba0aea5d36994352a68a39002ea58a/client/content/images/my-2d-diagram-editor-with-ports-4.png -------------------------------------------------------------------------------- /client/content/images/my-2d-diagram-editor-with-ports.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Robinyo/my-2d-diagram-editor/bcdb1e6fabba0aea5d36994352a68a39002ea58a/client/content/images/my-2d-diagram-editor-with-ports.png -------------------------------------------------------------------------------- /client/content/images/my-2d-diagram-editor-with-toobar.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Robinyo/my-2d-diagram-editor/bcdb1e6fabba0aea5d36994352a68a39002ea58a/client/content/images/my-2d-diagram-editor-with-toobar.png -------------------------------------------------------------------------------- /client/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Robinyo/my-2d-diagram-editor/bcdb1e6fabba0aea5d36994352a68a39002ea58a/client/favicon.ico -------------------------------------------------------------------------------- /client/gulp-config.json: -------------------------------------------------------------------------------- 1 | { 2 | "test": "./test/", 3 | "html": "./src/client/**/*.html", 4 | "html-templates": "./src/client/app/**/*.html", 5 | "vendor-js": [ 6 | "./bower_components/angular/angular.min.js" 7 | ], 8 | "vendor-css": [ 9 | "./bower_components/bootstrap/dist/css/bootstrap.min.css" 10 | ], 11 | "css": [ 12 | "./content/styles.css" 13 | ], 14 | "scss": [ 15 | "./content/scss/main.scss" 16 | ], 17 | "js": [ 18 | "./app/**/*module*.js", 19 | "./app/**/*.js", 20 | "!./app/**/hello-world-controller.js" 21 | ], 22 | "specs": [ 23 | "./test/specs/*.spec.js" 24 | ], 25 | "nodejs": [ 26 | "../server/**/*.js" 27 | ], 28 | "fonts": [ 29 | "./bower_components/font-awesome/fonts/**/*.*" 30 | ], 31 | "images": [ 32 | "./src/client/content/images/**/*" 33 | ], 34 | "report": "./report/", 35 | "build": "./build/" 36 | } 37 | -------------------------------------------------------------------------------- /client/gulpfile.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var config = require('./gulp-config.json'); 4 | 5 | var gulp = require('gulp'); 6 | var webserver = require('gulp-webserver'); 7 | 8 | 9 | gulp.task('hello', function() { 10 | console.log('Rob Ferguson'); 11 | }); 12 | 13 | gulp.task('webserver', function() { 14 | gulp.src( '.' ) 15 | .pipe(webserver({ 16 | host: 'localhost', 17 | port: '8001', 18 | livereload: false, 19 | directoryListing: false 20 | })); 21 | }); 22 | 23 | /* 24 | 25 | var browserSync = require('browser-sync').create(); 26 | 27 | // Static server 28 | gulp.task('browser-sync', function() { 29 | browserSync.init({ 30 | server: { 31 | baseDir: "./" 32 | } 33 | }); 34 | }); 35 | 36 | */ 37 | 38 | -------------------------------------------------------------------------------- /client/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 9 | my-2d-diagram-editor 10 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 |
27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 88 | -------------------------------------------------------------------------------- /client/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "my-2d-diagram-editor", 3 | "version": "1.0.0", 4 | "description": "A browser-based 2D diagram editor.", 5 | "main": "app.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "author": "Rob Ferguson", 10 | "license": "MIT", 11 | "devDependencies": { 12 | "browser-sync": "^2.11.0", 13 | "gulp": "^3.9.0", 14 | "gulp-webserver": "^0.9.1" 15 | } 16 | } 17 | --------------------------------------------------------------------------------