├── .editorconfig ├── .gitattributes ├── .gitignore ├── .jshintrc ├── .npmignore ├── .travis.yml ├── README.md ├── app ├── USAGE ├── index.js └── templates │ ├── _package.json │ ├── bowerrc │ ├── editorconfig │ ├── gitattributes │ ├── gitignore │ ├── gulpfile.js │ ├── index.html │ ├── jshintrc │ ├── main.css │ ├── partials │ ├── auth.html │ ├── pagination-edit.html │ ├── pagination-list.html │ └── tabular.html │ ├── scripts │ ├── app.js │ ├── controllers │ │ ├── AuthCtrl.js │ │ ├── MenuCtrl.js │ │ ├── PaginationCtrl.js │ │ └── TabularCtrl.js │ ├── directives │ │ ├── pagination.js │ │ ├── showIf.js │ │ └── tabItem.js │ ├── route.js │ └── services │ │ ├── PaginationService.js │ │ └── TabularService.js │ └── tests │ ├── e2e │ └── app_spec.js │ ├── protractor.conf.js │ └── unit │ └── AuthCtrl_test.js └── package.json /.editorconfig: -------------------------------------------------------------------------------- 1 | # 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 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | * text=auto 2 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | bower_components 3 | test/gulp-file 4 | test/sass 5 | test/slug 6 | temp/ 7 | npm-debug.log 8 | .DS_Store 9 | -------------------------------------------------------------------------------- /.jshintrc: -------------------------------------------------------------------------------- 1 | { 2 | "node": true, 3 | "esnext": true, 4 | "bitwise": false, 5 | "curly": false, 6 | "eqeqeq": true, 7 | "eqnull": true, 8 | "immed": true, 9 | "latedef": true, 10 | "newcap": true, 11 | "noarg": true, 12 | "undef": true, 13 | "strict": false 14 | } 15 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | .npmignore 2 | .editorconfig 3 | .travis.yml 4 | .jshintrc 5 | .gitattributes 6 | contributing.md 7 | test 8 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | node_js: 3 | - '0.10' 4 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Gulp + AngularJs + Semantic-UI 2 | ============================== 3 | 4 | > [Yeoman](http://yeoman.io) generator for beautiful and responsive webapp 5 | 6 | ## Demo 7 | 8 | [http://gustavohenrique.github.io/gulp-angular-semantic-ui](http://gustavohenrique.github.io/gulp-angular-semantic-ui/) 9 | 10 | ## Features 11 | 12 | * Built-in preview server with livereload 13 | * Automagically lint your scripts 14 | * Awesome image optimization 15 | * Token authentication 16 | * Login form 17 | * Table with pagination 18 | * E2E tests using Protractor 19 | * Unit tests using Mocha + Chai 20 | * CSS Autoprefixing 21 | 22 | ## Getting Started 23 | 24 | ### Creating 25 | 26 | ```shell 27 | npm install -g gulp bower yo generator-gulp-angular-semantic-ui 28 | mkdir mywebproject && cd mywebproject 29 | yo gulp-angular-semantic-ui 30 | bower install 31 | npm install 32 | ``` 33 | 34 | ### Watching 35 | 36 | * Run a localhost server listen on port 9000: 37 | `gulp serve` 38 | 39 | ### Building 40 | 41 | * Concat all html, js and css files and minify them to the *dist* directory: 42 | `gulp build`: 43 | 44 | ### Testing 45 | 46 | * Install the drivers: 47 | `node_modules/gulp-protractor/node_modules/protractor/bin/webdriver-manager update` 48 | * Run the server via terminal: 49 | `gulp serve` 50 | * Start a standalone webdriver instance (if you aren't using Chrome): 51 | `gulp webdriver` 52 | * Run the e2e tests: 53 | `gulp e2e` 54 | * For unit tests: 55 | `npm test` 56 | 57 | ## Changes 58 | 59 | #### v0.9.0 60 | * AngularJS 1.47 61 | * Semantic-UI 2.1.4 62 | * Removed gulp-postcss 63 | 64 | ## License 65 | 66 | [MIT license](http://opensource.org/licenses/MIT) 67 | -------------------------------------------------------------------------------- /app/USAGE: -------------------------------------------------------------------------------- 1 | Description: 2 | Creates a new basic front-end web application. 3 | 4 | Example: 5 | yo gulp-angular-semantic-ui 6 | 7 | This will create: 8 | gulpfile.js: Configuration for the task runner. 9 | bower.json: Front-end packages installed by bower. 10 | package.json: Development packages installed by npm. 11 | 12 | app/: Your application files. 13 | tests/: Unit tests for your application. 14 | -------------------------------------------------------------------------------- /app/index.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var fs = require('fs'); 4 | var path = require('path'); 5 | var yeoman = require('yeoman-generator'); 6 | var yosay = require('yosay'); 7 | var chalk = require('chalk'); 8 | var mkdirp = require('mkdirp'); 9 | var _s = require('underscore.string'); 10 | 11 | module.exports = yeoman.generators.Base.extend({ 12 | constructor: function() { 13 | yeoman.generators.Base.apply(this, arguments); 14 | 15 | this.option('skip-install', { 16 | desc: 'Skips the installation of dependencies', 17 | type: Boolean 18 | }); 19 | }, 20 | 21 | initializing: function() { 22 | this.pkg = require('../package.json'); 23 | }, 24 | 25 | writing: { 26 | gulpfile: function() { 27 | this.fs.copyTpl( 28 | this.templatePath('gulpfile.js'), 29 | this.destinationPath('gulpfile.js') 30 | ); 31 | }, 32 | 33 | packageJSON: function() { 34 | this.fs.copyTpl( 35 | this.templatePath('_package.json'), 36 | this.destinationPath('package.json') 37 | ); 38 | }, 39 | 40 | git: function() { 41 | this.copy('gitignore', '.gitignore'); 42 | this.copy('gitattributes', '.gitattributes'); 43 | }, 44 | 45 | bower: function() { 46 | var bower = { 47 | name: _s.slugify(this.appname), 48 | private: true, 49 | dependencies: { 50 | 'angular': '~1.4.7', 51 | 'angular-route': '~1.4.7', 52 | 'angular-loading-bar': '~0.8.0', 53 | 'semantic-ui': '~2.1.4' 54 | } 55 | }; 56 | 57 | this.fs.writeJSON('bower.json', bower); 58 | this.fs.copy( 59 | this.templatePath('bowerrc'), 60 | this.destinationPath('.bowerrc') 61 | ); 62 | }, 63 | 64 | jshint: function() { 65 | this.copy('jshintrc', '.jshintrc'); 66 | }, 67 | 68 | editorConfig: function() { 69 | this.copy('editorconfig', '.editorconfig'); 70 | }, 71 | 72 | mainStylesheet: function() { 73 | var css = 'main.css'; 74 | this.copy(css, 'app/styles/' + css); 75 | }, 76 | 77 | writeIndex: function() { 78 | var params = { 79 | appname: this.appname 80 | }; 81 | 82 | this.fs.copyTpl( 83 | this.templatePath('index.html'), 84 | this.destinationPath('app/index.html'), 85 | params 86 | ); 87 | }, 88 | 89 | app: function() { 90 | mkdirp('app'); 91 | mkdirp('app/styles'); 92 | mkdirp('app/images'); 93 | mkdirp('app/fonts'); 94 | this.directory('scripts', 'app/scripts'); 95 | this.directory('partials', 'app/partials'); 96 | }, 97 | 98 | tests: function () { 99 | this.directory('tests', 'tests'); 100 | } 101 | }, 102 | 103 | install: function() { 104 | var howToInstall = '\nNow you need to run: ' + chalk.yellow.bold('bower install && npm install'); 105 | this.log(howToInstall); 106 | // if (this.options['skip-install']) { 107 | // this.log(howToInstall); 108 | // return; 109 | // } 110 | 111 | // this.installDependencies({ 112 | // skipInstall: this.options['skip-install'] 113 | // }); 114 | 115 | } 116 | }); 117 | -------------------------------------------------------------------------------- /app/templates/_package.json: -------------------------------------------------------------------------------- 1 | { 2 | "private": true, 3 | "engines": { 4 | "node": ">=4.2.1" 5 | }, 6 | "scripts": { 7 | "test": "./node_modules/.bin/mocha tests/unit/*_test.js" 8 | }, 9 | "devDependencies": { 10 | "connect": "3.4.0", 11 | "connect-livereload": "0.5.3", 12 | "del": "2.0.2", 13 | "jshint-stylish": "2.0.1", 14 | "main-bower-files": "2.9.0", 15 | "opn": "3.0.2", 16 | "serve-index": "1.7.2", 17 | "serve-static": "1.10.0", 18 | "chai": "^3.4.0", 19 | "mocha": "^2.3.3", 20 | "gulp": "3.9.0", 21 | "gulp-cache": "0.3.0", 22 | "gulp-csso": "1.0.1", 23 | "gulp-filter": "3.0.1", 24 | "gulp-flatten": "0.2.0", 25 | "gulp-if": "2.0.0", 26 | "gulp-imagemin": "2.3.0", 27 | "gulp-jshint": "1.11.2", 28 | "gulp-livereload": "3.8.1", 29 | "gulp-load-plugins": "1.0.0", 30 | "gulp-minify-html": "1.0.4", 31 | "gulp-protractor": "1.0.0", 32 | "gulp-size": "2.0.0", 33 | "gulp-uglify": "1.4.2", 34 | "gulp-useref": "1.3.0" 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /app/templates/bowerrc: -------------------------------------------------------------------------------- 1 | { 2 | "directory": "bower_components" 3 | } 4 | -------------------------------------------------------------------------------- /app/templates/editorconfig: -------------------------------------------------------------------------------- 1 | # EditorConfig helps developers define and maintain consistent 2 | # coding styles between different editors and IDEs 3 | # editorconfig.org 4 | 5 | root = true 6 | 7 | 8 | [*] 9 | 10 | # change these settings to your own preference 11 | indent_style = space 12 | indent_size = 4 13 | 14 | # we recommend you to keep these unchanged 15 | end_of_line = lf 16 | charset = utf-8 17 | trim_trailing_whitespace = true 18 | insert_final_newline = true 19 | 20 | [*.md] 21 | trim_trailing_whitespace = false 22 | 23 | [{package,bower}.json] 24 | indent_style = space 25 | indent_size = 2 26 | -------------------------------------------------------------------------------- /app/templates/gitattributes: -------------------------------------------------------------------------------- 1 | * text=auto -------------------------------------------------------------------------------- /app/templates/gitignore: -------------------------------------------------------------------------------- 1 | .tmp 2 | .sass-cache 3 | .DS_Store 4 | *.log 5 | *~ 6 | node_modules 7 | dist 8 | bower_components 9 | test/bower_components 10 | -------------------------------------------------------------------------------- /app/templates/gulpfile.js: -------------------------------------------------------------------------------- 1 | /* jshint node:true */ 2 | /* global -$ */ 3 | 'use strict'; 4 | // generated on 2015-05-29 using generator-gulp-angular-semantic-ui 0.5.0 5 | var gulp = require('gulp'); 6 | var $ = require('gulp-load-plugins')(); 7 | 8 | gulp.task('styles', function () { 9 | return gulp.src('app/styles/main.css') 10 | .pipe(gulp.dest('.tmp/styles')); 11 | }); 12 | 13 | gulp.task('semantic', function () { 14 | return gulp.src('bower_components/semantic-ui/dist/themes/**/**/**') 15 | .pipe(gulp.dest('dist/styles/themes')); 16 | }); 17 | 18 | gulp.task('jshint', function () { 19 | return gulp.src('app/scripts/**/*.js') 20 | .pipe($.jshint()) 21 | .pipe($.jshint.reporter('jshint-stylish')) 22 | .pipe($.jshint.reporter('fail')); 23 | }); 24 | 25 | gulp.task('html', ['styles', 'semantic'], function () { 26 | var assets = $.useref.assets({searchPath: ['.tmp', 'app', '.']}); 27 | 28 | return gulp.src('app/**/*.html') 29 | .pipe(assets) 30 | .pipe($.if('*.js', $.uglify())) 31 | .pipe($.if('*.css', $.csso())) 32 | .pipe(assets.restore()) 33 | .pipe($.useref()) 34 | .pipe($.if('*.html', $.minifyHtml({conditionals: true, loose: true}))) 35 | .pipe(gulp.dest('dist')); 36 | }); 37 | 38 | gulp.task('images', function () { 39 | return gulp.src('app/images/**/*') 40 | .pipe($.cache($.imagemin({ 41 | progressive: true, 42 | interlaced: true 43 | }))) 44 | .pipe(gulp.dest('dist/images')); 45 | }); 46 | 47 | gulp.task('fonts', function () { 48 | return gulp.src(require('main-bower-files')().concat('app/fonts/**/*')) 49 | .pipe($.filter('**/*.{eot,svg,ttf,woff}')) 50 | .pipe($.flatten()) 51 | .pipe(gulp.dest('.tmp/fonts')) 52 | .pipe(gulp.dest('dist/fonts')); 53 | }); 54 | 55 | gulp.task('extras', function () { 56 | return gulp.src([ 57 | 'app/*.*', 58 | '!app/*.html' 59 | ], { 60 | dot: true 61 | }).pipe(gulp.dest('dist')); 62 | }); 63 | 64 | gulp.task('webdriver', $.protractor.webdriver_standalone); 65 | 66 | gulp.task('e2e', function () { 67 | gulp.src(['./tests/e2e/*.js']) 68 | .pipe($.protractor.protractor({ 69 | configFile: 'tests/protractor.conf.js', 70 | args: ['--baseUrl', 'http://127.0.0.1:8000'], 71 | debug: false 72 | })) 73 | .on('error', function(e) { throw e }) 74 | }); 75 | 76 | gulp.task('clean', require('del').bind(null, ['.tmp', 'dist'])); 77 | 78 | gulp.task('connect', ['styles', 'fonts'], function () { 79 | var serveStatic = require('serve-static'); 80 | var serveIndex = require('serve-index'); 81 | var app = require('connect')() 82 | .use(require('connect-livereload')({port: 35729})) 83 | .use(serveStatic('.tmp')) 84 | .use(serveStatic('app')) 85 | .use('/bower_components', serveStatic('bower_components')) 86 | .use(serveIndex('app')); 87 | 88 | require('http').createServer(app) 89 | .listen(9000) 90 | .on('listening', function () { 91 | console.log('Started connect web server on http://localhost:9000'); 92 | }); 93 | }); 94 | 95 | gulp.task('serve', ['connect', 'watch'], function () { 96 | require('opn')('http://localhost:9000'); 97 | }); 98 | 99 | gulp.task('watch', ['connect'], function () { 100 | $.livereload.listen(); 101 | gulp.watch([ 102 | 'app/**/*.html', 103 | '.tmp/styles/**/*.css', 104 | 'app/scripts/**/*.js', 105 | 'app/images/**/*' 106 | ]).on('change', $.livereload.changed); 107 | 108 | gulp.watch('app/styles/**/*.css', ['styles']); 109 | gulp.watch('bower.json', ['wiredep', 'fonts']); 110 | }); 111 | 112 | gulp.task('build', ['jshint', 'html', 'images', 'fonts', 'extras'], function () { 113 | return gulp.src('dist/**/*').pipe($.size({title: 'build', gzip: true})); 114 | }); 115 | 116 | gulp.task('default', ['clean'], function () { 117 | gulp.start('build'); 118 | }); 119 | -------------------------------------------------------------------------------- /app/templates/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | <%= appname %> by gulp-angular-semantic-ui 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 43 | 44 |
45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | -------------------------------------------------------------------------------- /app/templates/jshintrc: -------------------------------------------------------------------------------- 1 | { 2 | "multistr": true, 3 | "browser": true, 4 | "esnext": true, 5 | "bitwise": true, 6 | "camelcase": true, 7 | "curly": true, 8 | "eqeqeq": true, 9 | "immed": true, 10 | "indent": 4, 11 | "latedef": false, 12 | "newcap": true, 13 | "noarg": true, 14 | "quotmark": "single", 15 | "undef": false, 16 | "unused": false, 17 | "strict": true, 18 | "jquery": true 19 | } 20 | -------------------------------------------------------------------------------- /app/templates/main.css: -------------------------------------------------------------------------------- 1 | hr { 2 | border: 0; 3 | border-top: 1px solid silver; 4 | } 5 | 6 | label.login { 7 | width: 70px !important; 8 | text-align: left; 9 | } 10 | 11 | div.ui.auth, div.ui.top.attached.menu { 12 | margin-top: 40px; 13 | } 14 | 15 | .ui.main.container { 16 | width: 100%; 17 | } 18 | 19 | .hide { 20 | display: none !important; 21 | } 22 | 23 | div.title.item { 24 | position: inherit !important; 25 | } -------------------------------------------------------------------------------- /app/templates/partials/auth.html: -------------------------------------------------------------------------------- 1 |
2 |
3 |

Login

4 |
5 |
6 |
Authentication failed
7 |

Invalid username or password.

8 |
9 |
10 | 11 | 12 |
13 |
14 | 15 | 16 |
17 |
18 | Enter 19 |
20 |
21 |
22 |
-------------------------------------------------------------------------------- /app/templates/partials/pagination-edit.html: -------------------------------------------------------------------------------- 1 |

2 |
3 |
4 |
5 |

Edit ID: {{ vm.selectedItem.id }}

6 |
7 |
8 | 9 | 10 |
11 |
12 | 13 | 14 |
15 |
16 | Save 17 | Cancel 18 |
19 |
20 |
21 |
22 |
-------------------------------------------------------------------------------- /app/templates/partials/pagination-list.html: -------------------------------------------------------------------------------- 1 |
2 |
3 |
4 |
5 |
Loading
6 |
7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 28 | 29 | 30 | 31 | 34 | 35 |
Github Repositories
{{ item.created_at | date : 'dd/MM/yyyy' }}{{ item.name | limitTo : 30 }}{{ item.description | limitTo : 50 }}...{{ item.language }} 21 | 22 | Edit 23 | 24 |
25 | 26 |
27 |
32 | 33 |
36 |
37 | 38 | -------------------------------------------------------------------------------- /app/templates/partials/tabular.html: -------------------------------------------------------------------------------- 1 |
2 | 6 | 7 |
8 |

This is the tab 1 content

9 |
10 | 11 |
12 |

And this is the tab 2 content

13 |
14 |
-------------------------------------------------------------------------------- /app/templates/scripts/app.js: -------------------------------------------------------------------------------- 1 | ;(function (angular) { 2 | 'use strict'; 3 | 4 | var app = angular.module('MainApp', [ 5 | 'MainRouter', 6 | 'angular-loading-bar', 7 | 8 | 'controllers.Auth', 9 | 'controllers.Menu', 10 | 'controllers.Pagination', 11 | 'controllers.Tabular', 12 | 13 | 'services.Pagination', 14 | 'services.Tabular', 15 | 16 | 'directives.Pagination', 17 | 'directives.Tabular', 18 | 'directives.showIf' 19 | ]); 20 | 21 | app.constant('Constants', { 22 | baseUrl: 'https://api.github.com' 23 | }); 24 | 25 | app.config(['cfpLoadingBarProvider', function(cfpLoadingBarProvider) { 26 | cfpLoadingBarProvider.includeSpinner = false; 27 | }]); 28 | /* 29 | app.config(['$httpProvider', function ($httpProvider) { 30 | // CORS 31 | $httpProvider.interceptors.push('AuthInterceptor'); 32 | $httpProvider.defaults.headers.common = {}; 33 | $httpProvider.defaults.headers.post = {}; 34 | $httpProvider.defaults.headers.put = {}; 35 | $httpProvider.defaults.headers.patch = {}; 36 | }]); 37 | 38 | app.factory('AuthInterceptor', [function () { 39 | return { 40 | request: function (config) { 41 | var token = ''; 42 | config.headers = config.headers || {}; 43 | config.headers.Authorization = 'Bearer ' + token; 44 | return config; 45 | } 46 | }; 47 | }]); 48 | */ 49 | 50 | })(angular); 51 | -------------------------------------------------------------------------------- /app/templates/scripts/controllers/AuthCtrl.js: -------------------------------------------------------------------------------- 1 | ;(function (angular) { 2 | 'use strict'; 3 | 4 | angular 5 | .module('controllers.Auth', []) 6 | .controller('AuthCtrl', AuthCtrl); 7 | 8 | function AuthCtrl () { 9 | var vm = this; 10 | vm.user = { 11 | username: 'wrong-username', 12 | password: 'wrong-password' 13 | }; 14 | vm.enter = enter; 15 | 16 | function enter () { 17 | vm.isError = true; 18 | } 19 | } 20 | 21 | })(angular); 22 | -------------------------------------------------------------------------------- /app/templates/scripts/controllers/MenuCtrl.js: -------------------------------------------------------------------------------- 1 | ;(function (angular) { 2 | 'use strict'; 3 | 4 | angular 5 | .module('controllers.Menu', []) 6 | .controller('MenuCtrl', MenuCtrl); 7 | 8 | MenuCtrl.$inject = ['$location']; 9 | 10 | function MenuCtrl ($location) { 11 | var vm = this; 12 | vm.showBox = function (box) { 13 | $location.path(box); 14 | }; 15 | 16 | } 17 | 18 | })(angular); 19 | -------------------------------------------------------------------------------- /app/templates/scripts/controllers/PaginationCtrl.js: -------------------------------------------------------------------------------- 1 | ;(function (angular) { 2 | 'use strict'; 3 | 4 | angular 5 | .module('controllers.Pagination', []) 6 | .controller('PaginationCtrl', PaginationCtrl); 7 | 8 | PaginationCtrl.$inject = [ 9 | '$location', '$routeParams', 10 | '$timeout', 'paginationService' 11 | ]; 12 | 13 | function PaginationCtrl ($location, $routeParams, $timeout, paginationService) { 14 | var vm = this; 15 | vm.paginationData = { 16 | perPage: 5, 17 | currentPage: 1 18 | }; 19 | vm.isLoading = false; 20 | vm.remove = remove; 21 | vm.save = save; 22 | vm.paginate = paginate; // called by directives 23 | 24 | if ($routeParams.name) { 25 | edit($routeParams.name); 26 | } 27 | else { 28 | paginate(vm.paginationData.currentPage); 29 | } 30 | 31 | function remove (item, index) { 32 | if (vm.paginationData.items && vm.paginationData.items.length > 0) { 33 | paginationService.remove(item) 34 | .then(function (res) { 35 | vm.paginationData.items.splice(index, 1); 36 | }); 37 | } 38 | } 39 | 40 | function save () { 41 | // $timeout is used just for simulate a "loading" 42 | vm.isLoading = true; 43 | $timeout(function () { 44 | paginationService.save(vm.selectedItem) 45 | .then(function (res) { 46 | var item = vm.selectedItem; 47 | //vm.items[item.index] = angular.copy(item.obj); 48 | vm.isLoading = false; 49 | }); 50 | }, 51 | 1000); 52 | } 53 | 54 | function calculateTotalPages () { 55 | paginationService.findAll(0, 0) 56 | .success(function (res) { 57 | var paginationData = vm.paginationData || {}; 58 | paginationData.total = res.length; 59 | paginationData.totalPages = Math.ceil(paginationData.total / paginationData.perPage); 60 | }) 61 | .error(function (res) { 62 | console.log('Error trying to get the total of repositories', res); 63 | }); 64 | } 65 | calculateTotalPages(); 66 | 67 | function paginate (pageNumber, perPage) { 68 | vm.isLoading = true; 69 | var paginationData = vm.paginationData || {}; 70 | if (! perPage) { 71 | perPage = paginationData.perPage; 72 | } 73 | paginationService.findAll(perPage, pageNumber) 74 | .success(function (res) { 75 | paginationData.items = res; 76 | vm.isLoading = false; 77 | }) 78 | .error(function (res) { 79 | console.log('Error getting the repositories list', res); 80 | }); 81 | } 82 | 83 | function edit (name) { 84 | paginationService.edit(name) 85 | .success(function (res) { 86 | vm.selectedItem = res; 87 | }) 88 | .error(function (res) { 89 | console.log('Error getting the repository by name ' + name, res); 90 | }); 91 | } 92 | 93 | } 94 | 95 | })(angular); 96 | -------------------------------------------------------------------------------- /app/templates/scripts/controllers/TabularCtrl.js: -------------------------------------------------------------------------------- 1 | ;(function (angular) { 2 | 'use strict'; 3 | 4 | angular 5 | .module('controllers.Tabular', []) 6 | .controller('TabularCtrl', TabularCtrl); 7 | 8 | TabularCtrl.$inject = []; 9 | 10 | function TabularCtrl () {} 11 | 12 | })(angular); -------------------------------------------------------------------------------- /app/templates/scripts/directives/pagination.js: -------------------------------------------------------------------------------- 1 | ;(function (angular) { 2 | 'use strict'; 3 | 4 | var app = angular.module('directives.Pagination', []); 5 | 6 | app.directive('pagination', [function () { 7 | return { 8 | restrict: 'E', 9 | template: '', 14 | scope: '=', 15 | link: function (scope, element, attrs) { 16 | var vm = scope.vm; 17 | vm.paginationData.currentPage = 1; 18 | vm.next = function () { 19 | vm.paginationData.currentPage++; 20 | if (vm.paginationData.currentPage > vm.paginationData.totalPages) { 21 | vm.paginationData.currentPage = vm.paginationData.totalPages; 22 | } 23 | vm.paginate(vm.paginationData.currentPage); 24 | }; 25 | 26 | vm.previous = function () { 27 | vm.paginationData.currentPage--; 28 | if (vm.paginationData.currentPage < 1) { 29 | vm.paginationData.currentPage = 1; 30 | } 31 | vm.paginate(vm.paginationData.currentPage); 32 | }; 33 | } 34 | }; 35 | }]); 36 | 37 | })(angular); 38 | -------------------------------------------------------------------------------- /app/templates/scripts/directives/showIf.js: -------------------------------------------------------------------------------- 1 | ;(function (angular) { 2 | 'use strict'; 3 | 4 | var app = angular.module('directives.showIf', []); 5 | 6 | app.directive('showIf', function () { 7 | return { 8 | restrict: 'A', 9 | scope: '&', 10 | link: function (scope, element, attrs) { 11 | attrs.$observe('showIf', function(value) { 12 | if (value === true || value === 'true') { 13 | element.removeClass('hide'); 14 | } 15 | else { 16 | element.addClass('hide'); 17 | } 18 | }); 19 | } 20 | }; 21 | }); 22 | 23 | })(angular); 24 | -------------------------------------------------------------------------------- /app/templates/scripts/directives/tabItem.js: -------------------------------------------------------------------------------- 1 | ;(function (angular) { 2 | 'use strict'; 3 | 4 | var app = angular.module('directives.Tabular', []); 5 | 6 | app.directive('tabItem', function () { 7 | return { 8 | restrict: 'A', 9 | link: function (scope, element, attrs) { 10 | var ACTIVE_CLASS = 'active'; 11 | var id = attrs.id; 12 | 13 | element.on('click', changeTab); 14 | 15 | function removeClass (el) { 16 | el.classList.remove(ACTIVE_CLASS); 17 | } 18 | 19 | function changeTab () { 20 | // Remove the active class from all tab items and tab contents 21 | Array.prototype.slice.call(document.querySelectorAll('.tab.active')).map(removeClass); 22 | 23 | // Add the active class to current tab and it content 24 | element.addClass(ACTIVE_CLASS); 25 | document.querySelector('.tab.segment.' + id).classList.add(ACTIVE_CLASS); 26 | } 27 | } 28 | }; 29 | }); 30 | 31 | })(angular); -------------------------------------------------------------------------------- /app/templates/scripts/route.js: -------------------------------------------------------------------------------- 1 | ;(function (angular) { 2 | 'use strict'; 3 | 4 | angular 5 | .module('MainRouter', ['ngRoute']) 6 | .config(['$routeProvider', function ($routeProvider) { 7 | $routeProvider. 8 | when('/pagination', { 9 | templateUrl: 'partials/pagination-list.html', 10 | controller: 'PaginationCtrl', 11 | controllerAs: 'vm' 12 | }). 13 | when('/pagination/edit/:name', { 14 | templateUrl: 'partials/pagination-edit.html', 15 | controller: 'PaginationCtrl', 16 | controllerAs: 'vm' 17 | }). 18 | when('/login', { 19 | templateUrl: 'partials/auth.html', 20 | controller: 'AuthCtrl', 21 | controllerAs: 'vm' 22 | }). 23 | when('/tabs', { 24 | templateUrl: 'partials/tabular.html', 25 | controller: 'TabularCtrl', 26 | controllerAs: 'vm' 27 | }). 28 | otherwise({ 29 | redirectTo: '/' 30 | }); 31 | } 32 | ]); 33 | })(angular); 34 | -------------------------------------------------------------------------------- /app/templates/scripts/services/PaginationService.js: -------------------------------------------------------------------------------- 1 | ;(function (angular) { 2 | 'use strict'; 3 | 4 | angular 5 | .module('services.Pagination', []) 6 | .service('paginationService', PaginationService); 7 | 8 | PaginationService.$inject = ['$http', '$q', 'Constants']; 9 | 10 | function PaginationService ($http, $q, Constants) { 11 | 12 | this.findAll = function (perPage, page) { 13 | var url = Constants.baseUrl + '/users/gustavohenrique/repos?sort=updated&direction=desc'; 14 | if (page > 0) { 15 | url += '&page=' + page; 16 | } 17 | if (perPage > 0) { 18 | url += '&per_page=' + perPage; 19 | } 20 | return $http.get(url); 21 | }; 22 | 23 | this.edit = function (name) { 24 | var url = Constants.baseUrl + '/repos/gustavohenrique/' + name; 25 | return $http.get(url); 26 | }; 27 | 28 | this.remove = function (item) { 29 | var id = item.id; 30 | //$http.delete('http://some-url/?id=' + id).success(success).error(error); 31 | var deferred = $q.defer(); 32 | deferred.resolve(); 33 | return deferred.promise; 34 | }; 35 | 36 | this.save = function (item) { 37 | if (item.hasOwnProperty('id') && item.id > 0) { 38 | // make a PUT to update url 39 | } 40 | else { 41 | // make a POST to insert url 42 | } 43 | var deferred = $q.defer(); 44 | deferred.resolve(); 45 | return deferred.promise; 46 | }; 47 | } 48 | 49 | })(angular); 50 | -------------------------------------------------------------------------------- /app/templates/scripts/services/TabularService.js: -------------------------------------------------------------------------------- 1 | ;(function (angular) { 2 | 'use strict'; 3 | 4 | angular 5 | .module('services.Tabular', []) 6 | .service('tabularService', TabularService); 7 | 8 | TabularService.$inject = ['$http']; 9 | 10 | function TabularService ($http) { 11 | this.findAll = function () { 12 | //return $http.get('url-here'); 13 | 14 | }; 15 | } 16 | 17 | })(angular); 18 | -------------------------------------------------------------------------------- /app/templates/tests/e2e/app_spec.js: -------------------------------------------------------------------------------- 1 | describe('Demo test', function() { 2 | 3 | beforeEach(function() { 4 | browser.ignoreSynchronization = true; 5 | nav.get(URL); 6 | //nav.sleep(500); 7 | }); 8 | 9 | it('should there is one contact added', function() { 10 | var list = element.all(by.repeater('person in contacts')); 11 | expect(list.count()).toEqual(1); 12 | 13 | var firstRow = by.repeater('person in contacts track by person.name').row(0); 14 | expect(element(firstRow.column('person.name')).getText()).toEqual('Gustavo Henrique'); 15 | expect(element(firstRow.column('person.site')).getText()).toEqual('about.me/gustavohenrique'); 16 | }); 17 | 18 | it('should add a person in contacts list', function() { 19 | element(by.model('name')).sendKeys('Uncle Bob Martin'); 20 | element(by.model('site')).sendKeys('cleancoder.com'); 21 | $('.primary').click(); 22 | 23 | var list = element.all(by.repeater('person in contacts')); 24 | expect(list.count()).toEqual(2); 25 | 26 | var secondRow = by.repeater('person in contacts track by person.name').row(1); 27 | expect(element(secondRow.column('person.name')).getText()).toEqual('Uncle Bob Martin'); 28 | expect(element(secondRow.column('person.site')).getText()).toEqual('cleancoder.com'); 29 | }); 30 | 31 | }); 32 | -------------------------------------------------------------------------------- /app/templates/tests/protractor.conf.js: -------------------------------------------------------------------------------- 1 | exports.config = { 2 | seleniumAddress: 'http://localhost:4444/wd/hub', 3 | 4 | capabilities: { 5 | browserName: 'firefox' 6 | }, 7 | /* 8 | chromeOnly: true, 9 | capabilities: { 10 | browserName: 'chrome', 11 | chromeOptions: { 12 | args: [ 13 | '--allow-file-access-from-files', 14 | '--disable-cache', 15 | '--disable-application-cache', 16 | '--disable-offline-load-stale-cache', 17 | '--disk-cache-size=0', 18 | '--v8-cache-options=off' 19 | ] 20 | } 21 | }, 22 | */ 23 | 24 | jasmineNodeOpts: { 25 | showColors: true, // Use colors in the command line report. 26 | }, 27 | 28 | onPrepare: function() { 29 | global.nav = browser.driver; 30 | global.URL = 'http://localhost:9000/' // lembrar de levantar o servidor antes com o http-server 31 | //global.URL = 'file:///C:/Users/gustavo.WDEV/Documents/design/camposAnexos.html' 32 | } 33 | 34 | } -------------------------------------------------------------------------------- /app/templates/tests/unit/AuthCtrl_test.js: -------------------------------------------------------------------------------- 1 | angular = { 2 | module: function () { return this; }, 3 | controller: function (name, func) { 4 | angular[name] = func; 5 | return this; 6 | } 7 | }; 8 | 9 | var expect = require('chai').expect; 10 | require ('../../app/scripts/controllers/AuthCtrl'); 11 | 12 | 13 | describe('AuthCtrl', function() { 14 | beforeEach( function () { 15 | angular.AuthCtrl(); 16 | }); 17 | 18 | it('should contains the default username and password', function() { 19 | var scope = angular; 20 | expect(scope.user.username).to.equal('wrong-username'); 21 | expect(scope.user.password).to.equal('wrong-password'); 22 | }); 23 | 24 | }); -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "generator-gulp-angular-semantic-ui", 3 | "version": "0.9.0", 4 | "description": "A yeoman generator for frontend webapp", 5 | "license": "MIT", 6 | "repository": "gustavohenrique/gulp-angular-semantic-ui", 7 | "author": "Gustavo Henrique", 8 | "main": "app/index.js", 9 | "engines": { 10 | "node": ">=4.2.1", 11 | "npm": ">=2.14.7" 12 | }, 13 | "files": [ 14 | "app" 15 | ], 16 | "keywords": [ 17 | "yeoman-generator", 18 | "webapp", 19 | "angular", 20 | "semantic-ui", 21 | "protractor", 22 | "gulp" 23 | ], 24 | "dependencies": { 25 | "chalk": "1.1.1", 26 | "cheerio": "0.19.0", 27 | "mkdirp": "^0.5.1", 28 | "underscore.string": "3.2.2", 29 | "yeoman-generator": "0.21.1", 30 | "yosay": "1.0.5", 31 | "yo": "1.4.8", 32 | "generator-mocha": "0.2.0", 33 | "gulp": "3.9.0" 34 | } 35 | } 36 | --------------------------------------------------------------------------------