├── .gitignore ├── Cakefile ├── LICENSE ├── README.md ├── build ├── client │ ├── .gitignore │ ├── app │ │ ├── application.coffee │ │ ├── assets │ │ │ ├── 404.html │ │ │ ├── asc.gif │ │ │ ├── bg.gif │ │ │ ├── crossdomain.xml │ │ │ ├── desc.gif │ │ │ ├── favicon.ico │ │ │ ├── fonts │ │ │ │ ├── fontawesome │ │ │ │ │ ├── FontAwesome.ttf │ │ │ │ │ ├── README.md │ │ │ │ │ ├── fontawesome-webfont.eot │ │ │ │ │ ├── fontawesome-webfont.svg │ │ │ │ │ ├── fontawesome-webfont.ttf │ │ │ │ │ └── fontawesome-webfont.woff │ │ │ │ ├── fontello.ttf │ │ │ │ ├── glyphicons-halflings-regular.eot │ │ │ │ ├── glyphicons-halflings-regular.svg │ │ │ │ ├── glyphicons-halflings-regular.ttf │ │ │ │ ├── glyphicons-halflings-regular.woff │ │ │ │ ├── maven-pro-light-100.otf │ │ │ │ ├── maven-pro-light-200.otf │ │ │ │ ├── maven-pro-light-300.otf │ │ │ │ ├── signika-bold.ttf │ │ │ │ ├── signika-light.ttf │ │ │ │ └── signika-regular.ttf │ │ │ ├── humans.txt │ │ │ ├── icons │ │ │ │ └── main_icon.png │ │ │ ├── images │ │ │ │ ├── .gitkeep │ │ │ │ ├── Melamine-wood-003.png │ │ │ │ ├── arrow.png │ │ │ │ └── arrow_vertical.png │ │ │ ├── index.html │ │ │ ├── javascripts │ │ │ │ └── modernizr-2.6.1.js │ │ │ ├── loader.gif │ │ │ ├── loader_big_blue.gif │ │ │ ├── loader_green.gif │ │ │ ├── loader_inverse.gif │ │ │ └── robots.txt │ │ ├── collections │ │ │ ├── .gitkeep │ │ │ ├── bank_accesses.coffee │ │ │ ├── bank_accounts.coffee │ │ │ ├── bank_alerts.coffee │ │ │ ├── bank_operations.coffee │ │ │ └── banks.coffee │ │ ├── initialize.coffee │ │ ├── lib │ │ │ ├── app_helpers.coffee │ │ │ ├── base_view.coffee │ │ │ └── view_collection.coffee │ │ ├── locales │ │ │ ├── en.coffee │ │ │ └── fr.coffee │ │ ├── models │ │ │ ├── .gitkeep │ │ │ ├── bank.coffee │ │ │ ├── bank_access.coffee │ │ │ ├── bank_account.coffee │ │ │ ├── bank_alert.coffee │ │ │ └── bank_operation.coffee │ │ ├── router.coffee │ │ └── views │ │ │ ├── accounts.coffee │ │ │ ├── accounts_alerts.coffee │ │ │ ├── accounts_alerts_alert.coffee │ │ │ ├── accounts_bank.coffee │ │ │ ├── accounts_bank_account.coffee │ │ │ ├── app.coffee │ │ │ ├── balance.coffee │ │ │ ├── balance_bank.coffee │ │ │ ├── balance_operation.coffee │ │ │ ├── balance_operations.coffee │ │ │ ├── bank_subtitle.coffee │ │ │ ├── bank_title.coffee │ │ │ ├── mockup.coffee │ │ │ ├── navbar.coffee │ │ │ ├── new_bank.coffee │ │ │ ├── search.coffee │ │ │ ├── search_bank.coffee │ │ │ ├── search_bank_subtitle.coffee │ │ │ ├── search_bank_title.coffee │ │ │ ├── search_operations.coffee │ │ │ ├── search_operations_table.coffee │ │ │ ├── styles │ │ │ ├── _base.styl │ │ │ ├── _colors.styl │ │ │ ├── _main.styl │ │ │ ├── _responsive.styl │ │ │ ├── _states.styl │ │ │ └── application.styl │ │ │ └── templates │ │ │ ├── .gitkeep │ │ │ ├── accounts.jade │ │ │ ├── accounts_alerts.jade │ │ │ ├── accounts_alerts_alert.jade │ │ │ ├── accounts_bank.jade │ │ │ ├── accounts_bank_account.jade │ │ │ ├── app.jade │ │ │ ├── balance_bank_subtitle.jade │ │ │ ├── balance_bank_title.jade │ │ │ ├── balance_banks_empty.jade │ │ │ ├── balance_operations_element.jade │ │ │ ├── balance_operations_empty.jade │ │ │ ├── balance_operations_header.jade │ │ │ ├── layout-2col.jade │ │ │ ├── mockup_balance.jade │ │ │ ├── modal_confirm.jade │ │ │ ├── navbar.jade │ │ │ ├── new_bank.jade │ │ │ ├── search_bank_subtitle.jade │ │ │ ├── search_bank_title.jade │ │ │ ├── search_operations.jade │ │ │ └── search_operations_table_header.jade │ ├── config.coffee │ ├── generators │ │ ├── collection │ │ │ ├── collection.coffee.hbs │ │ │ └── generator.json │ │ ├── collection_test │ │ │ ├── collection_test.coffee.hbs │ │ │ └── generator.json │ │ ├── generator │ │ │ ├── generated_file.coffee.hbs │ │ │ ├── generator.json │ │ │ └── generator.json.hbs │ │ ├── model │ │ │ ├── generator.json │ │ │ └── model.coffee.hbs │ │ ├── model_test │ │ │ ├── generator.json │ │ │ └── model_test.coffee.hbs │ │ ├── module │ │ │ ├── collection.coffee.hbs │ │ │ ├── generator.json │ │ │ ├── model.coffee.hbs │ │ │ ├── style.styl.hbs │ │ │ ├── template.jade.hbs │ │ │ ├── view.coffee.hbs │ │ │ └── view_collection.coffee.hbs │ │ ├── style │ │ │ ├── generator.json │ │ │ └── style.styl.hbs │ │ ├── template │ │ │ ├── generator.json │ │ │ └── template.hbs │ │ ├── view │ │ │ ├── generator.json │ │ │ └── view.coffee.hbs │ │ └── view_test │ │ │ ├── generator.json │ │ │ └── view_test.coffee.hbs │ ├── package.json │ ├── public │ │ ├── 404.html │ │ ├── asc.gif │ │ ├── bg.gif │ │ ├── crossdomain.xml │ │ ├── desc.gif │ │ ├── favicon.ico │ │ ├── fonts │ │ │ ├── fontawesome │ │ │ │ ├── FontAwesome.ttf │ │ │ │ ├── README.md │ │ │ │ ├── fontawesome-webfont.eot │ │ │ │ ├── fontawesome-webfont.svg │ │ │ │ ├── fontawesome-webfont.ttf │ │ │ │ └── fontawesome-webfont.woff │ │ │ ├── fontello.ttf │ │ │ ├── glyphicons-halflings-regular.eot │ │ │ ├── glyphicons-halflings-regular.svg │ │ │ ├── glyphicons-halflings-regular.ttf │ │ │ ├── glyphicons-halflings-regular.woff │ │ │ ├── maven-pro-light-100.otf │ │ │ ├── maven-pro-light-200.otf │ │ │ ├── maven-pro-light-300.otf │ │ │ ├── signika-bold.ttf │ │ │ ├── signika-light.ttf │ │ │ └── signika-regular.ttf │ │ ├── humans.txt │ │ ├── icons │ │ │ └── main_icon.png │ │ ├── images │ │ │ ├── Melamine-wood-003.png │ │ │ ├── arrow.png │ │ │ ├── arrow_vertical.png │ │ │ ├── glyphicons-halflings-white.png │ │ │ └── glyphicons-halflings.png │ │ ├── index.html │ │ ├── javascripts │ │ │ ├── app.js │ │ │ ├── app.js.map │ │ │ ├── jquery.min.map │ │ │ ├── modernizr-2.6.1.js │ │ │ ├── vendor.js │ │ │ └── vendor.js.map │ │ ├── loader.gif │ │ ├── loader_big_blue.gif │ │ ├── loader_green.gif │ │ ├── loader_inverse.gif │ │ ├── robots.txt │ │ └── stylesheets │ │ │ ├── app.css │ │ │ └── app.css.map │ └── vendor │ │ ├── scripts │ │ ├── async.js │ │ ├── backbone-1.0.0.js │ │ ├── backbone.mediator.js │ │ ├── bootstrap.js │ │ ├── jquery-1.10.2.js │ │ ├── jquery.nicescroll.js │ │ ├── moment.min.js │ │ ├── polyglot.js │ │ ├── underscore-1.4.4.js │ │ └── zoomico.png │ │ └── styles │ │ ├── bootstrap-theme.css │ │ ├── bootstrap.css │ │ ├── font-awesome.css │ │ ├── helpers.css │ │ ├── hint.css │ │ ├── normalize.css │ │ ├── sort.css │ │ └── tablesort_blue.css ├── package.json ├── server.js ├── server │ ├── config.js │ ├── controllers │ │ ├── bankaccesses.js │ │ ├── bankaccounts.js │ │ ├── bankalerts.js │ │ ├── bankoperations.js │ │ ├── banks.js │ │ └── routes.js │ ├── init.js │ ├── lib │ │ ├── accounts-poller.js │ │ ├── alert-manager.js │ │ ├── report-manager.js │ │ └── weboob-manager.js │ └── models │ │ ├── bank.js │ │ ├── bankaccess.js │ │ ├── bankaccount.js │ │ ├── bankalert.js │ │ ├── bankoperation.js │ │ ├── cozyinstance.js │ │ └── requests.js └── tests │ ├── controllers │ ├── bankaccesses.js │ ├── bankaccounts.js │ ├── bankalerts.js │ ├── bankoperations.js │ └── banks.js │ ├── fixtures │ ├── banks-all.json │ ├── banks-mesinfos.json │ └── weboob │ │ ├── accounts.js │ │ └── operations.js │ ├── helpers.js │ └── mock-weboob.js ├── client ├── .gitignore ├── app │ ├── application.coffee │ ├── assets │ │ ├── 404.html │ │ ├── asc.gif │ │ ├── bg.gif │ │ ├── crossdomain.xml │ │ ├── desc.gif │ │ ├── favicon.ico │ │ ├── fonts │ │ │ ├── fontawesome │ │ │ │ ├── FontAwesome.ttf │ │ │ │ ├── README.md │ │ │ │ ├── fontawesome-webfont.eot │ │ │ │ ├── fontawesome-webfont.svg │ │ │ │ ├── fontawesome-webfont.ttf │ │ │ │ └── fontawesome-webfont.woff │ │ │ ├── fontello.ttf │ │ │ ├── glyphicons-halflings-regular.eot │ │ │ ├── glyphicons-halflings-regular.svg │ │ │ ├── glyphicons-halflings-regular.ttf │ │ │ ├── glyphicons-halflings-regular.woff │ │ │ ├── maven-pro-light-100.otf │ │ │ ├── maven-pro-light-200.otf │ │ │ ├── maven-pro-light-300.otf │ │ │ ├── signika-bold.ttf │ │ │ ├── signika-light.ttf │ │ │ └── signika-regular.ttf │ │ ├── humans.txt │ │ ├── icons │ │ │ └── main_icon.png │ │ ├── images │ │ │ ├── .gitkeep │ │ │ ├── Melamine-wood-003.png │ │ │ ├── arrow.png │ │ │ └── arrow_vertical.png │ │ ├── index.html │ │ ├── javascripts │ │ │ └── modernizr-2.6.1.js │ │ ├── loader.gif │ │ ├── loader_big_blue.gif │ │ ├── loader_green.gif │ │ ├── loader_inverse.gif │ │ ├── pdf │ │ │ ├── factureSFR.pdf │ │ │ └── factureSNCF.pdf │ │ └── robots.txt │ ├── collections │ │ ├── .gitkeep │ │ ├── bank_accesses.coffee │ │ ├── bank_accounts.coffee │ │ ├── bank_alerts.coffee │ │ ├── bank_operations.coffee │ │ └── banks.coffee │ ├── initialize.coffee │ ├── lib │ │ ├── app_helpers.coffee │ │ ├── base_view.coffee │ │ └── view_collection.coffee │ ├── locales │ │ ├── en.coffee │ │ └── fr.coffee │ ├── models │ │ ├── .gitkeep │ │ ├── bank.coffee │ │ ├── bank_access.coffee │ │ ├── bank_account.coffee │ │ ├── bank_alert.coffee │ │ └── bank_operation.coffee │ ├── router.coffee │ └── views │ │ ├── accounts.coffee │ │ ├── accounts_alerts.coffee │ │ ├── accounts_alerts_alert.coffee │ │ ├── accounts_bank.coffee │ │ ├── accounts_bank_account.coffee │ │ ├── app.coffee │ │ ├── balance.coffee │ │ ├── balance_bank.coffee │ │ ├── balance_operation.coffee │ │ ├── balance_operations.coffee │ │ ├── bank_subtitle.coffee │ │ ├── bank_title.coffee │ │ ├── mockup.coffee │ │ ├── navbar.coffee │ │ ├── new_bank.coffee │ │ ├── search.coffee │ │ ├── search_bank.coffee │ │ ├── search_bank_subtitle.coffee │ │ ├── search_bank_title.coffee │ │ ├── search_operations.coffee │ │ ├── search_operations_table.coffee │ │ ├── styles │ │ ├── _base.styl │ │ ├── _colors.styl │ │ ├── _main.styl │ │ ├── _responsive.styl │ │ ├── _states.styl │ │ └── application.styl │ │ └── templates │ │ ├── .gitkeep │ │ ├── accounts.jade │ │ ├── accounts_alerts.jade │ │ ├── accounts_alerts_alert.jade │ │ ├── accounts_bank.jade │ │ ├── accounts_bank_account.jade │ │ ├── app.jade │ │ ├── balance_bank_subtitle.jade │ │ ├── balance_bank_title.jade │ │ ├── balance_banks_empty.jade │ │ ├── balance_operations_element.jade │ │ ├── balance_operations_empty.jade │ │ ├── balance_operations_header.jade │ │ ├── layout-2col.jade │ │ ├── mockup_balance.jade │ │ ├── modal_confirm.jade │ │ ├── navbar.jade │ │ ├── new_bank.jade │ │ ├── search_bank_subtitle.jade │ │ ├── search_bank_title.jade │ │ ├── search_operations.jade │ │ └── search_operations_table_header.jade ├── config.coffee ├── generators │ ├── collection │ │ ├── collection.coffee.hbs │ │ └── generator.json │ ├── collection_test │ │ ├── collection_test.coffee.hbs │ │ └── generator.json │ ├── generator │ │ ├── generated_file.coffee.hbs │ │ ├── generator.json │ │ └── generator.json.hbs │ ├── model │ │ ├── generator.json │ │ └── model.coffee.hbs │ ├── model_test │ │ ├── generator.json │ │ └── model_test.coffee.hbs │ ├── module │ │ ├── collection.coffee.hbs │ │ ├── generator.json │ │ ├── model.coffee.hbs │ │ ├── style.styl.hbs │ │ ├── template.jade.hbs │ │ ├── view.coffee.hbs │ │ └── view_collection.coffee.hbs │ ├── style │ │ ├── generator.json │ │ └── style.styl.hbs │ ├── template │ │ ├── generator.json │ │ └── template.hbs │ ├── view │ │ ├── generator.json │ │ └── view.coffee.hbs │ └── view_test │ │ ├── generator.json │ │ └── view_test.coffee.hbs ├── package.json ├── public │ ├── 404.html │ ├── asc.gif │ ├── bg.gif │ ├── crossdomain.xml │ ├── desc.gif │ ├── favicon.ico │ ├── fonts │ │ ├── fontawesome │ │ │ ├── FontAwesome.ttf │ │ │ ├── README.md │ │ │ ├── fontawesome-webfont.eot │ │ │ ├── fontawesome-webfont.svg │ │ │ ├── fontawesome-webfont.ttf │ │ │ └── fontawesome-webfont.woff │ │ ├── fontello.ttf │ │ ├── glyphicons-halflings-regular.eot │ │ ├── glyphicons-halflings-regular.svg │ │ ├── glyphicons-halflings-regular.ttf │ │ ├── glyphicons-halflings-regular.woff │ │ ├── maven-pro-light-100.otf │ │ ├── maven-pro-light-200.otf │ │ ├── maven-pro-light-300.otf │ │ ├── signika-bold.ttf │ │ ├── signika-light.ttf │ │ └── signika-regular.ttf │ ├── humans.txt │ ├── icons │ │ └── main_icon.png │ ├── images │ │ ├── Melamine-wood-003.png │ │ ├── arrow.png │ │ ├── arrow_vertical.png │ │ ├── glyphicons-halflings-white.png │ │ └── glyphicons-halflings.png │ ├── index.html │ ├── javascripts │ │ ├── app.js │ │ ├── app.js.map │ │ ├── jquery.min.map │ │ ├── modernizr-2.6.1.js │ │ ├── vendor.js │ │ └── vendor.js.map │ ├── loader.gif │ ├── loader_big_blue.gif │ ├── loader_green.gif │ ├── loader_inverse.gif │ ├── pdf │ │ ├── factureSFR.pdf │ │ └── factureSNCF.pdf │ ├── robots.txt │ └── stylesheets │ │ ├── app.css │ │ └── app.css.map └── vendor │ ├── scripts │ ├── async.js │ ├── backbone-1.0.0.js │ ├── backbone.mediator.js │ ├── bootstrap.js │ ├── jquery-1.10.2.js │ ├── jquery.nicescroll.js │ ├── moment.min.js │ ├── polyglot.js │ ├── underscore-1.4.4.js │ └── zoomico.png │ └── styles │ ├── bootstrap-theme.css │ ├── bootstrap.css │ ├── font-awesome.css │ ├── helpers.css │ ├── hint.css │ ├── normalize.css │ ├── sort.css │ └── tablesort_blue.css ├── coffeelint.json ├── log └── production.log ├── package.json ├── server.coffee ├── server ├── config.coffee ├── controllers │ ├── bankaccesses.coffee │ ├── bankaccounts.coffee │ ├── bankalerts.coffee │ ├── bankoperations.coffee │ ├── banks.coffee │ └── routes.coffee ├── init.coffee ├── lib │ ├── accounts-poller.coffee │ ├── alert-manager.coffee │ ├── report-manager.coffee │ └── weboob-manager.coffee ├── models │ ├── bank.coffee │ ├── bankaccess.coffee │ ├── bankaccount.coffee │ ├── bankalert.coffee │ ├── bankoperation.coffee │ ├── cozyinstance.coffee │ └── requests.coffee └── views │ └── mail-report.jade └── tests ├── controllers ├── bankaccesses.coffee ├── bankaccounts.coffee ├── bankalerts.coffee ├── bankoperations.coffee └── banks.coffee ├── fixtures ├── banks-all.json ├── banks-mesinfos.json └── weboob │ ├── accounts.coffee │ └── operations.coffee ├── helpers.coffee └── mock-weboob.coffee /.gitignore: -------------------------------------------------------------------------------- 1 | # Numerous always-ignored extensions 2 | *.diff 3 | *.err 4 | *.orig 5 | *.log 6 | *.rej 7 | *.swo 8 | *.swp 9 | *.vi 10 | *~ 11 | *.sass-cache 12 | 13 | # OS or Editor folders 14 | .DS_Store 15 | .cache 16 | .project 17 | .settings 18 | .tmproj 19 | nbproject 20 | Thumbs.db 21 | 22 | # Logs folder 23 | logs 24 | 25 | # NPM packages folder. 26 | node_modules/ 27 | 28 | -------------------------------------------------------------------------------- /build/client/.gitignore: -------------------------------------------------------------------------------- 1 | # Numerous always-ignore extensions 2 | *.diff 3 | *.err 4 | *.orig 5 | *.log 6 | *.rej 7 | *.swo 8 | *.swp 9 | *.vi 10 | *~ 11 | *.sass-cache 12 | 13 | # OS or Editor folders 14 | .DS_Store 15 | .cache 16 | .project 17 | .settings 18 | .tmproj 19 | nbproject 20 | Thumbs.db 21 | 22 | # NPM packages folder. 23 | node_modules/ 24 | 25 | # Brunch folder for temporary files. 26 | tmp/ 27 | -------------------------------------------------------------------------------- /build/client/app/application.coffee: -------------------------------------------------------------------------------- 1 | AppView = require 'views/app' 2 | 3 | BanksCollection = require 'collections/banks' 4 | BankOperationsCollection = require 'collections/bank_operations' 5 | 6 | module.exports = 7 | 8 | initialize: -> 9 | 10 | $.ajax('cozy-locale.json') 11 | .done( (data) => @locale = data.locale ) 12 | .fail( () => @locale = 'en' ) 13 | .always( () => @step2() ) 14 | 15 | step2: -> 16 | 17 | # internationalisation 18 | @polyglot = new Polyglot() 19 | window.polyglot = @polyglot 20 | try 21 | locales = require "locales/#{@locale}" 22 | catch e 23 | locales = require 'locales/en' 24 | 25 | @polyglot.extend locales 26 | window.t = @polyglot.t.bind @polyglot 27 | window.i18n = (key) -> window.polyglot.t key 28 | 29 | # collections, views 30 | window.collections = {} 31 | window.views = {} 32 | 33 | # banks, operations 34 | window.collections.allBanks = new BanksCollection() 35 | window.collections.banks = new BanksCollection() 36 | window.collections.operations = new BankOperationsCollection() 37 | 38 | ### 39 | views 40 | ### 41 | # this one is tricky - it lays down the structure, so it needs to be rendered 42 | # before any other view using that structure 43 | window.views.appView = new AppView() 44 | window.views.appView.render() 45 | 46 | window.activeObjects = {} 47 | _.extend(window.activeObjects, Backbone.Events); 48 | 49 | # Routing management 50 | Router = require 'router' 51 | @router = new Router() 52 | #Backbone.history.start() 53 | 54 | # Makes this object immuable. 55 | Object.freeze this if typeof Object.freeze is 'function' 56 | -------------------------------------------------------------------------------- /build/client/app/assets/asc.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/seeker89/cozy-pfm/3e17567625fe81eb879255a4cdbc7d83f374614f/build/client/app/assets/asc.gif -------------------------------------------------------------------------------- /build/client/app/assets/bg.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/seeker89/cozy-pfm/3e17567625fe81eb879255a4cdbc7d83f374614f/build/client/app/assets/bg.gif -------------------------------------------------------------------------------- /build/client/app/assets/crossdomain.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 15 | 16 | -------------------------------------------------------------------------------- /build/client/app/assets/desc.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/seeker89/cozy-pfm/3e17567625fe81eb879255a4cdbc7d83f374614f/build/client/app/assets/desc.gif -------------------------------------------------------------------------------- /build/client/app/assets/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/seeker89/cozy-pfm/3e17567625fe81eb879255a4cdbc7d83f374614f/build/client/app/assets/favicon.ico -------------------------------------------------------------------------------- /build/client/app/assets/fonts/fontawesome/FontAwesome.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/seeker89/cozy-pfm/3e17567625fe81eb879255a4cdbc7d83f374614f/build/client/app/assets/fonts/fontawesome/FontAwesome.ttf -------------------------------------------------------------------------------- /build/client/app/assets/fonts/fontawesome/README.md: -------------------------------------------------------------------------------- 1 | #Font Awesome 2.0 2 | ##the iconic font designed for use with Twitter Bootstrap 3 | 4 | The full suite of pictographic icons, examples, and documentation can be found at: 5 | http://fortawesome.github.com/Font-Awesome/ 6 | 7 | ##Contact 8 | - Email: dave@davegandy.com 9 | - Twitter: http://twitter.com/fortaweso_me 10 | - Work: Lead Product Designer @ http://kyru.us 11 | 12 | ##License 13 | Version 2.0 of the Font Awesome font, CSS, and LESS files are licensed under CC BY 3.0: 14 | http://creativecommons.org/licenses/by/3.0/ 15 | A mention of 'Font Awesome - http://fortawesome.github.com/Font-Awesome' 16 | in human-readable source code is considered acceptable attribution (most common on the 17 | web). If human readable source code is not available to the end user, a mention in an 'About' 18 | or 'Credits' screen is considered acceptable (most common in desktop or mobile software). 19 | -------------------------------------------------------------------------------- /build/client/app/assets/fonts/fontawesome/fontawesome-webfont.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/seeker89/cozy-pfm/3e17567625fe81eb879255a4cdbc7d83f374614f/build/client/app/assets/fonts/fontawesome/fontawesome-webfont.eot -------------------------------------------------------------------------------- /build/client/app/assets/fonts/fontawesome/fontawesome-webfont.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/seeker89/cozy-pfm/3e17567625fe81eb879255a4cdbc7d83f374614f/build/client/app/assets/fonts/fontawesome/fontawesome-webfont.ttf -------------------------------------------------------------------------------- /build/client/app/assets/fonts/fontawesome/fontawesome-webfont.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/seeker89/cozy-pfm/3e17567625fe81eb879255a4cdbc7d83f374614f/build/client/app/assets/fonts/fontawesome/fontawesome-webfont.woff -------------------------------------------------------------------------------- /build/client/app/assets/fonts/fontello.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/seeker89/cozy-pfm/3e17567625fe81eb879255a4cdbc7d83f374614f/build/client/app/assets/fonts/fontello.ttf -------------------------------------------------------------------------------- /build/client/app/assets/fonts/glyphicons-halflings-regular.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/seeker89/cozy-pfm/3e17567625fe81eb879255a4cdbc7d83f374614f/build/client/app/assets/fonts/glyphicons-halflings-regular.eot -------------------------------------------------------------------------------- /build/client/app/assets/fonts/glyphicons-halflings-regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/seeker89/cozy-pfm/3e17567625fe81eb879255a4cdbc7d83f374614f/build/client/app/assets/fonts/glyphicons-halflings-regular.ttf -------------------------------------------------------------------------------- /build/client/app/assets/fonts/glyphicons-halflings-regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/seeker89/cozy-pfm/3e17567625fe81eb879255a4cdbc7d83f374614f/build/client/app/assets/fonts/glyphicons-halflings-regular.woff -------------------------------------------------------------------------------- /build/client/app/assets/fonts/maven-pro-light-100.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/seeker89/cozy-pfm/3e17567625fe81eb879255a4cdbc7d83f374614f/build/client/app/assets/fonts/maven-pro-light-100.otf -------------------------------------------------------------------------------- /build/client/app/assets/fonts/maven-pro-light-200.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/seeker89/cozy-pfm/3e17567625fe81eb879255a4cdbc7d83f374614f/build/client/app/assets/fonts/maven-pro-light-200.otf -------------------------------------------------------------------------------- /build/client/app/assets/fonts/maven-pro-light-300.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/seeker89/cozy-pfm/3e17567625fe81eb879255a4cdbc7d83f374614f/build/client/app/assets/fonts/maven-pro-light-300.otf -------------------------------------------------------------------------------- /build/client/app/assets/fonts/signika-bold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/seeker89/cozy-pfm/3e17567625fe81eb879255a4cdbc7d83f374614f/build/client/app/assets/fonts/signika-bold.ttf -------------------------------------------------------------------------------- /build/client/app/assets/fonts/signika-light.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/seeker89/cozy-pfm/3e17567625fe81eb879255a4cdbc7d83f374614f/build/client/app/assets/fonts/signika-light.ttf -------------------------------------------------------------------------------- /build/client/app/assets/fonts/signika-regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/seeker89/cozy-pfm/3e17567625fe81eb879255a4cdbc7d83f374614f/build/client/app/assets/fonts/signika-regular.ttf -------------------------------------------------------------------------------- /build/client/app/assets/humans.txt: -------------------------------------------------------------------------------- 1 | # humanstxt.org/ 2 | # The humans responsible & technology colophon 3 | 4 | # TEAM 5 | 6 | -- -- 7 | 8 | # THANKS 9 | 10 | 11 | 12 | # TECHNOLOGY COLOPHON 13 | 14 | HTML5, CSS3 15 | jQuery, Modernizr, 16 | Lodash, Backbone, 17 | Handlebars, Coffeescript, 18 | Stylus, Brunch 19 | -------------------------------------------------------------------------------- /build/client/app/assets/icons/main_icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/seeker89/cozy-pfm/3e17567625fe81eb879255a4cdbc7d83f374614f/build/client/app/assets/icons/main_icon.png -------------------------------------------------------------------------------- /build/client/app/assets/images/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/seeker89/cozy-pfm/3e17567625fe81eb879255a4cdbc7d83f374614f/build/client/app/assets/images/.gitkeep -------------------------------------------------------------------------------- /build/client/app/assets/images/Melamine-wood-003.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/seeker89/cozy-pfm/3e17567625fe81eb879255a4cdbc7d83f374614f/build/client/app/assets/images/Melamine-wood-003.png -------------------------------------------------------------------------------- /build/client/app/assets/images/arrow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/seeker89/cozy-pfm/3e17567625fe81eb879255a4cdbc7d83f374614f/build/client/app/assets/images/arrow.png -------------------------------------------------------------------------------- /build/client/app/assets/images/arrow_vertical.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/seeker89/cozy-pfm/3e17567625fe81eb879255a4cdbc7d83f374614f/build/client/app/assets/images/arrow_vertical.png -------------------------------------------------------------------------------- /build/client/app/assets/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | Cozy PFM 10 | 11 | 12 | 17 | 18 | 19 | 20 | 21 | 22 | 25 | 26 | 27 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /build/client/app/assets/loader.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/seeker89/cozy-pfm/3e17567625fe81eb879255a4cdbc7d83f374614f/build/client/app/assets/loader.gif -------------------------------------------------------------------------------- /build/client/app/assets/loader_big_blue.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/seeker89/cozy-pfm/3e17567625fe81eb879255a4cdbc7d83f374614f/build/client/app/assets/loader_big_blue.gif -------------------------------------------------------------------------------- /build/client/app/assets/loader_green.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/seeker89/cozy-pfm/3e17567625fe81eb879255a4cdbc7d83f374614f/build/client/app/assets/loader_green.gif -------------------------------------------------------------------------------- /build/client/app/assets/loader_inverse.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/seeker89/cozy-pfm/3e17567625fe81eb879255a4cdbc7d83f374614f/build/client/app/assets/loader_inverse.gif -------------------------------------------------------------------------------- /build/client/app/assets/robots.txt: -------------------------------------------------------------------------------- 1 | # robotstxt.org/ 2 | 3 | User-agent: * 4 | -------------------------------------------------------------------------------- /build/client/app/collections/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/seeker89/cozy-pfm/3e17567625fe81eb879255a4cdbc7d83f374614f/build/client/app/collections/.gitkeep -------------------------------------------------------------------------------- /build/client/app/collections/bank_accesses.coffee: -------------------------------------------------------------------------------- 1 | BankAccess = require '../models/bank_access' 2 | 3 | module.exports = class BankAccesses extends Backbone.Collection 4 | 5 | model: BankAccess 6 | url: "bankaccesses" 7 | -------------------------------------------------------------------------------- /build/client/app/collections/bank_accounts.coffee: -------------------------------------------------------------------------------- 1 | BankAccount = require '../models/bank_account' 2 | 3 | module.exports = class BankAccounts extends Backbone.Collection 4 | 5 | model: BankAccount 6 | url: "bankaccounts" 7 | 8 | constructor: (@bank) -> 9 | @url = "banks/getAccounts/" + @bank.get("id") 10 | super() 11 | 12 | getSum: -> 13 | sum = 0 14 | for account in @models 15 | sum += Number(account.get("amount")) 16 | sum 17 | -------------------------------------------------------------------------------- /build/client/app/collections/bank_alerts.coffee: -------------------------------------------------------------------------------- 1 | BankAlert = require '../models/bank_alert' 2 | 3 | module.exports = class BankAlerts extends Backbone.Collection 4 | 5 | model: BankAlert 6 | url: "bankalerts" 7 | -------------------------------------------------------------------------------- /build/client/app/collections/bank_operations.coffee: -------------------------------------------------------------------------------- 1 | BankOperation = require '../models/bank_operation' 2 | 3 | module.exports = class BankOperations extends Backbone.Collection 4 | 5 | model: BankOperation 6 | url: "bankoperations" 7 | 8 | order: "asc" 9 | orderBy: "date" 10 | 11 | setAccount: (@account) -> 12 | @url = "bankaccounts/getOperations/" + @account.get("id") 13 | #console.log @url 14 | 15 | setComparator: (type) -> 16 | if type == "date" 17 | # sorting by date and then title 18 | @comparator = (o1, o2) => 19 | d1 = new Date(o1.get("date")).getTime() 20 | d2 = new Date(o2.get("date")).getTime() 21 | 22 | t1 = o1.get("title") 23 | t2 = o2.get("title") 24 | 25 | sort = if @order == "asc" then -1 else 1 26 | 27 | if d1 == d2 28 | if t1 > t2 then return sort 29 | if t1 < t2 then return -sort 30 | return 0 31 | else if d1 > d2 32 | return sort 33 | else 34 | return -sort 35 | 36 | else 37 | @orderBy = type 38 | @comparator = (o1, o2) -> 39 | 40 | t1 = o1.get @orderBy 41 | t2 = o2.get @orderBy 42 | 43 | sort = if @order == "asc" then -1 else 1 44 | 45 | if t1 == t2 46 | return 0 47 | else if t1 > t2 48 | return sort 49 | else 50 | return -sort 51 | 52 | toggleSort: (order) -> 53 | if @orderBy == order 54 | @order = if @order == "asc" then "desc" else "asc" 55 | else 56 | @orderBy = order 57 | 58 | -------------------------------------------------------------------------------- /build/client/app/collections/banks.coffee: -------------------------------------------------------------------------------- 1 | Bank = require '../models/bank' 2 | 3 | module.exports = class Banks extends Backbone.Collection 4 | 5 | model: Bank 6 | url: "banks" 7 | 8 | getSum: -> 9 | sum = 0 10 | for bank in @models 11 | sum += Number(bank.get("amount")) 12 | #console.log Number(bank.get("amount")) 13 | sum 14 | -------------------------------------------------------------------------------- /build/client/app/initialize.coffee: -------------------------------------------------------------------------------- 1 | app = require 'application' 2 | # The function called from index.html 3 | $ -> 4 | require 'lib/app_helpers' 5 | 6 | # init 7 | ### 8 | global variables 9 | ### 10 | # app, for nasty tricks 11 | window.app = app 12 | app.initialize() 13 | -------------------------------------------------------------------------------- /build/client/app/lib/app_helpers.coffee: -------------------------------------------------------------------------------- 1 | (() -> 2 | # IIFE to avoid collisions with other variables 3 | (-> 4 | # Make it safe to do console.log() always. 5 | console = window.console = window.console or {} 6 | method = undefined 7 | dummy = -> 8 | methods = ('assert,count,debug,dir,dirxml,error,exception, 9 | group,groupCollapsed,groupEnd,info,log,markTimeline, 10 | profile,profileEnd,time,timeEnd,trace,warn').split ',' 11 | 12 | console[method] = console[method] or dummy while method = methods.pop() 13 | )() 14 | )() 15 | 16 | Number::formatMoney = (decPlaces, thouSeparator, decSeparator) -> 17 | n = this 18 | decPlaces = (if isNaN(decPlaces = Math.abs(decPlaces)) then 2 else decPlaces) 19 | decSeparator = (if decSeparator is `undefined` then "." else decSeparator) 20 | thouSeparator = (if thouSeparator is `undefined` then "," else thouSeparator) 21 | sign = (if n < 0 then "-" else "") 22 | i = parseInt(n = Math.abs(+n or 0).toFixed(decPlaces)) + "" 23 | j = (if (j = i.length) > 3 then j % 3 else 0) 24 | sign + ((if j then i.substr(0, j) + thouSeparator else "")) + i.substr(j).replace(/(\d{3})(?=\d)/g, "$1" + thouSeparator) + ((if decPlaces then decSeparator + Math.abs(n - i).toFixed(decPlaces).slice(2) else "")) 25 | 26 | Number::money = -> 27 | @formatMoney(2, " ", ",") 28 | 29 | Date::dateString = -> 30 | addZeros = (num) -> 31 | if Number(num) < 10 32 | "0" + num 33 | else 34 | num 35 | myDate = @ 36 | addZeros(myDate.getDate() + 1) + "/" + addZeros(myDate.getMonth() + 1) + "/" + myDate.getFullYear() 37 | 38 | Date::timeString = -> 39 | addZeros = (num) -> 40 | if Number(num) < 10 41 | "0" + num 42 | else 43 | num 44 | myDate = @ 45 | addZeros(myDate.getHours()) + ":" + addZeros(myDate.getMinutes()) 46 | -------------------------------------------------------------------------------- /build/client/app/lib/base_view.coffee: -------------------------------------------------------------------------------- 1 | module.exports = class BaseView extends Backbone.View 2 | 3 | template: -> 4 | 5 | initialize: -> 6 | 7 | getRenderData: -> 8 | model: @model 9 | 10 | render: -> 11 | @beforeRender() 12 | @$el.html @template(@getRenderData()) 13 | @afterRender() 14 | @ 15 | 16 | beforeRender: -> 17 | 18 | afterRender: -> 19 | 20 | destroy: -> 21 | @undelegateEvents() 22 | @$el.removeData().unbind() 23 | @remove() 24 | Backbone.View::remove.call @ 25 | -------------------------------------------------------------------------------- /build/client/app/models/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/seeker89/cozy-pfm/3e17567625fe81eb879255a4cdbc7d83f374614f/build/client/app/models/.gitkeep -------------------------------------------------------------------------------- /build/client/app/models/bank.coffee: -------------------------------------------------------------------------------- 1 | BankAccountsCollection = require '../collections/bank_accounts' 2 | 3 | module.exports = class Bank extends Backbone.Model 4 | 5 | defaults: 6 | amount: 0 7 | 8 | checked: true 9 | 10 | initialize: -> 11 | @accounts = new BankAccountsCollection @ 12 | @listenTo @accounts, "add", @updateAmount 13 | @listenTo @accounts, "remove", @updateAmount 14 | @listenTo @accounts, "destroy", @updateAmount 15 | @listenTo @accounts, "change", @updateAmount 16 | 17 | updateAmount: -> 18 | @set("amount", @accounts.getSum()) 19 | console.log "updated balance bank " + @get("name") + " is now " + @get("amount") 20 | -------------------------------------------------------------------------------- /build/client/app/models/bank_access.coffee: -------------------------------------------------------------------------------- 1 | module.exports = class BankAccess extends Backbone.Model 2 | 3 | url: "bankaccesses" 4 | -------------------------------------------------------------------------------- /build/client/app/models/bank_account.coffee: -------------------------------------------------------------------------------- 1 | BankOperationsCollection = require '../collections/bank_operations' 2 | 3 | module.exports = class BankAccount extends Backbone.Model 4 | 5 | checked: true 6 | -------------------------------------------------------------------------------- /build/client/app/models/bank_alert.coffee: -------------------------------------------------------------------------------- 1 | module.exports = class BankAlert extends Backbone.Model 2 | 3 | url: "bankalerts" 4 | -------------------------------------------------------------------------------- /build/client/app/models/bank_operation.coffee: -------------------------------------------------------------------------------- 1 | module.exports = class BankOperation extends Backbone.Model 2 | -------------------------------------------------------------------------------- /build/client/app/router.coffee: -------------------------------------------------------------------------------- 1 | MockupView = require 'views/mockup' 2 | AppView = require 'views/app' 3 | BalanceView = require 'views/balance' 4 | 5 | module.exports = class Router extends Backbone.Router 6 | 7 | empty: -> 8 | window.views.balanceView?.empty() 9 | window.views.accountsView?.empty() 10 | window.views.searchView?.empty() 11 | 12 | routes: 13 | '': 'balance' 14 | 'accounts': 'accounts' 15 | 'search' : 'search' 16 | 17 | balance: -> 18 | @empty() 19 | window.views.balanceView?.render() 20 | $(".menu-position").removeClass("active") 21 | $(".menu-1").addClass("active") 22 | 23 | search: -> 24 | @empty() 25 | window.views.searchView?.render() 26 | $(".menu-position").removeClass("active") 27 | $(".menu-2").addClass("active") 28 | 29 | accounts: -> 30 | @empty() 31 | window.views.accountsView?.render() 32 | $(".menu-position").removeClass("active") 33 | $(".menu-3").addClass("active") 34 | -------------------------------------------------------------------------------- /build/client/app/views/accounts.coffee: -------------------------------------------------------------------------------- 1 | BaseView = require '../lib/base_view' 2 | AccountsBankView = require './accounts_bank' 3 | 4 | module.exports = class AccountsView extends BaseView 5 | 6 | template: require('./templates/accounts') 7 | 8 | el: 'div#content' 9 | elBanks: '.content-right-column' 10 | 11 | subViews: [] 12 | 13 | render: -> 14 | 15 | # load the template 16 | super() 17 | 18 | # prepare the banks list 19 | for bank in window.collections.banks.models 20 | view = new AccountsBankView bank 21 | @subViews.push view 22 | @$(@elBanks).append view.render().el 23 | 24 | # TODO - fix the compability issue with niceScroll 25 | #@$('#layout-2col-column-right').niceScroll() 26 | @ 27 | 28 | empty: -> 29 | for view in @subViews 30 | view.destroy() -------------------------------------------------------------------------------- /build/client/app/views/accounts_alerts_alert.coffee: -------------------------------------------------------------------------------- 1 | BaseView = require '../lib/base_view' 2 | BankAlert = require '../models/bank_alert' 3 | 4 | module.exports = class AccountsAlertsAlertView extends BaseView 5 | 6 | template: require "./templates/accounts_alerts_alert" 7 | 8 | events: 9 | "click .reports-save" : "save" 10 | "click .reports-cancel" : "destroy" 11 | "click .reports-delete" : "removeAlert" 12 | "click .reports-edit" : "edit" 13 | 14 | constructor: (@alert, @parent) -> 15 | super() 16 | 17 | initialize: -> 18 | 19 | save: -> 20 | view = @ 21 | 22 | # get the data 23 | if @alert.get("type") == "report" 24 | @alert.set "frequency", @$(".reports-frequency").val() 25 | else 26 | @alert.set "order", @$(".reports-order").val() 27 | valLimit = @$(".reports-limit").val() 28 | valLimit = valLimit.replace(" ", "").replace(",",".") # stripping all non digits 29 | @alert.set "limit", Number(valLimit) 30 | 31 | # save the report to the server 32 | @alert.save {}, 33 | success: -> 34 | console.log "Alert saved to server" 35 | view.render() 36 | error: -> 37 | console.log "error" 38 | 39 | removeAlert: -> 40 | 41 | view = @ 42 | 43 | @alert.url = "bankalerts/" + @alert.get("id") 44 | @alert.destroy 45 | success: -> 46 | console.log "Alert deleted from server" 47 | view.destroy() 48 | error: -> 49 | console.log "error" 50 | 51 | render: -> 52 | # lay down the template 53 | @$el.html @template 54 | model: @alert 55 | @ 56 | -------------------------------------------------------------------------------- /build/client/app/views/app.coffee: -------------------------------------------------------------------------------- 1 | BaseView = require '../lib/base_view' 2 | 3 | NavbarView = require 'views/navbar' 4 | NewBankView = require 'views/new_bank' 5 | 6 | AccountsView = require 'views/accounts' 7 | BalanceView = require 'views/balance' 8 | SearchView = require 'views/search' 9 | 10 | 11 | module.exports = class AppView extends BaseView 12 | 13 | template: require('./templates/app') 14 | 15 | el: 'body.application' 16 | 17 | afterRender: -> 18 | 19 | # init - get the necessary data 20 | window.collections.banks.fetch 21 | data: 22 | withAccountOnly: true 23 | success: -> 24 | 25 | window.collections.allBanks.fetch 26 | success: -> 27 | if not @navbarView 28 | @navbarView = new NavbarView() 29 | if not @newbankView 30 | @newbankView = new NewBankView() 31 | if not window.views.balanceView 32 | window.views.balanceView = new BalanceView() 33 | if not window.views.accountsView 34 | window.views.accountsView = new AccountsView() 35 | if not window.views.searchView 36 | window.views.searchView = new SearchView() 37 | 38 | @navbarView.render() 39 | @newbankView.render() 40 | 41 | # start routing 42 | Backbone.history.start() 43 | error: -> 44 | 45 | # could not get banks, or 0 banks available - fatal error 46 | console.log "Fatal error: could not get the banks list" 47 | alert window.i18n "fatal_error" 48 | 49 | -------------------------------------------------------------------------------- /build/client/app/views/balance_bank.coffee: -------------------------------------------------------------------------------- 1 | BaseView = require '../lib/base_view' 2 | BankTitleView = require './bank_title' 3 | BankSubTitleView = require './bank_subtitle' 4 | 5 | module.exports = class BalanceBankView extends BaseView 6 | 7 | className: 'bank' 8 | 9 | sum: 0 10 | 11 | subViews: [] 12 | 13 | constructor: (@bank) -> 14 | super() 15 | 16 | initialize: -> 17 | @listenTo @bank.accounts, "add", @addOne 18 | @listenTo @bank.accounts, "destroy", @render 19 | 20 | addOne: (account) -> 21 | # add the account 22 | viewAccount = new BankSubTitleView account 23 | @subViews.push viewAccount 24 | account.view = viewAccount 25 | @$el.append viewAccount.render().el 26 | 27 | render: -> 28 | 29 | # generate the title 30 | @viewTitle = new BankTitleView @bank 31 | @$el.html @viewTitle.render().el 32 | @viewTitle = null 33 | @sum = 0 34 | 35 | # add accounts 36 | for account in @bank.accounts.models 37 | @addOne account 38 | @ 39 | 40 | destroy: -> 41 | @viewTitle?.destroy() 42 | for view in @subViews 43 | view.destroy() 44 | super() -------------------------------------------------------------------------------- /build/client/app/views/balance_operation.coffee: -------------------------------------------------------------------------------- 1 | BaseView = require '../lib/base_view' 2 | 3 | module.exports = class BalanceOperationView extends BaseView 4 | 5 | template: require './templates/balance_operations_element' 6 | 7 | tagName: 'tr' 8 | 9 | constructor: (@model, @account, @showAccountNum = false) -> 10 | super() 11 | 12 | fakeFeatureLink: -> 13 | if @model.get('title') is "SNCF" and @model.get('amount') is -137.00 14 | return 'pdf/factureSNCF.pdf' 15 | else if @model.get('title') is "SFR Facture" 16 | return 'pdf/factureSFR.pdf' 17 | else return null 18 | 19 | render: -> 20 | if @model.get("amount") > 0 21 | @$el.addClass "success" 22 | @model.account = @account 23 | @model.formattedDate = moment(@model.get('date')).format "DD/MM/YYYY" 24 | formattedAmount = @fakeFeatureLink() 25 | @model.formattedAmount = formattedAmount unless formattedAmount is null 26 | 27 | if @showAccountNum 28 | hint = "#{@model.account.get('title')}, " + \ 29 | "n°#{@model.account.get('accountNumber')}" 30 | @model.hint = "#{@model.account.get('title')}, " + \ 31 | "n°#{@model.account.get('accountNumber')}" 32 | else 33 | @model.hint = "#{@model.get('raw')}" 34 | super() 35 | @ -------------------------------------------------------------------------------- /build/client/app/views/bank_subtitle.coffee: -------------------------------------------------------------------------------- 1 | BaseView = require '../lib/base_view' 2 | 3 | module.exports = class BankSubTitleView extends BaseView 4 | 5 | template: require('./templates/balance_bank_subtitle') 6 | 7 | constructor: (@model) -> 8 | super() 9 | 10 | events: 11 | "click .row" : "chooseAccount" 12 | 13 | initialize: -> 14 | @listenTo @model, 'change', @render 15 | @listenTo window.activeObjects, 'changeActiveAccount', @checkActive 16 | 17 | chooseAccount: (event) -> 18 | console.log "Account chosen: " + @model.get("title") 19 | window.activeObjects.trigger "changeActiveAccount", @model 20 | 21 | checkActive: (account) -> 22 | @$(".row").removeClass("active") 23 | if account == @model 24 | @$(".row").addClass("active") 25 | -------------------------------------------------------------------------------- /build/client/app/views/bank_title.coffee: -------------------------------------------------------------------------------- 1 | BaseView = require '../lib/base_view' 2 | 3 | module.exports = class BankTitleView extends BaseView 4 | 5 | template: require('./templates/balance_bank_title') 6 | 7 | constructor: (@model) -> 8 | super() 9 | 10 | initialize: -> 11 | @listenTo @model, 'change', @update 12 | @listenTo @model.accounts, "add", @update 13 | @listenTo @model.accounts, "destroy", @update 14 | @listenTo @model.accounts, "request", @displayLoading 15 | @listenTo @model.accounts, "change", @hideLoading 16 | 17 | displayLoading: -> 18 | @$(".bank-title-loading").show() 19 | 20 | hideLoading: -> 21 | @$(".bank-title-loading").hide() 22 | 23 | update: -> 24 | # update the sum 25 | @model.set("amount", @model.accounts.getSum()) 26 | @$(".bank-amount").html Number(@model.get('amount')).money() 27 | 28 | # display or hide the bank title 29 | if @model.accounts.length == 0 30 | @$(".bank-title").hide() 31 | @$(".bank-balance").hide() 32 | else 33 | @$(".bank-title").show() 34 | @$(".bank-balance").show() 35 | 36 | # hide loader 37 | @$(".bank-title-loading").hide() 38 | 39 | render: -> 40 | super() 41 | @update() 42 | @ -------------------------------------------------------------------------------- /build/client/app/views/mockup.coffee: -------------------------------------------------------------------------------- 1 | BaseView = require '../lib/base_view' 2 | 3 | 4 | module.exports = class AppView extends BaseView 5 | 6 | template: require('./templates/mockup_balance') 7 | 8 | el: 'body.application' 9 | 10 | afterRender: -> 11 | $('.content-right-column').niceScroll() 12 | -------------------------------------------------------------------------------- /build/client/app/views/navbar.coffee: -------------------------------------------------------------------------------- 1 | BaseView = require '../lib/base_view' 2 | 3 | 4 | module.exports = class NavbarView extends BaseView 5 | 6 | template: require('./templates/navbar') 7 | 8 | el: 'div#navbar' 9 | 10 | initialize: -> 11 | @listenTo window.collections.banks, "change", @refreshOverallBalance 12 | @listenTo window.collections.banks, 'destroy', @refreshOverallBalance 13 | @listenTo window.collections.banks, 'update', @refreshOverallBalance 14 | @listenTo window.collections.banks, 'reset', @refreshOverallBalance 15 | 16 | refreshOverallBalance: -> 17 | sum = window.collections.banks.getSum() 18 | console.log "recalculating the overall balance: " + sum 19 | $("span#total-amount").html sum.money() 20 | -------------------------------------------------------------------------------- /build/client/app/views/search_bank.coffee: -------------------------------------------------------------------------------- 1 | BaseView = require '../lib/base_view' 2 | SearchBankTitleView = require './search_bank_title' 3 | SearchBankSubTitleView = require './search_bank_subtitle' 4 | 5 | module.exports = class SearchBankView extends BaseView 6 | 7 | className: 'bank' 8 | 9 | events: 10 | "change .choice-bank" : "bankChange" 11 | 12 | viewsAccount: [] 13 | 14 | constructor: (@bank) -> 15 | super() 16 | 17 | initialize: -> 18 | @listenTo @bank.accounts, "add", @addOne 19 | @listenTo @bank.accounts, "destroy", @render 20 | 21 | bankChange: (event) -> 22 | 23 | enabled = @$(event.target).prop("checked") 24 | console.log "[Search] " + @bank.get("name") + ": " + enabled 25 | 26 | # check/uncheck all 27 | $.each @$("input[type=checkbox].choice-account"), (index, element) -> 28 | $(element).prop "checked", enabled 29 | for account in @bank.accounts.models 30 | account.checked = enabled 31 | 32 | # mark the entire bank as checked 33 | @bank.checked = enabled 34 | 35 | # and fire "update" on accounts 36 | window.collections.banks.trigger "search-update-accounts" 37 | 38 | addOne: (account) -> 39 | # add the account 40 | viewAccount = new SearchBankSubTitleView account 41 | @viewsAccount.push viewAccount 42 | account.view = viewAccount 43 | @$el.append viewAccount.render().el 44 | 45 | render: -> 46 | 47 | # generate the title 48 | @viewTitle = new SearchBankTitleView @bank 49 | @$el.html @viewTitle.render().el 50 | @viewTitle = null 51 | @sum = 0 52 | 53 | # add accounts 54 | for account in @bank.accounts.models 55 | @addOne account 56 | @ 57 | 58 | destroy: -> 59 | @viewTitle?.destroy() 60 | for viewAccount in @viewsAccount 61 | viewAccount.destroy() 62 | super() 63 | -------------------------------------------------------------------------------- /build/client/app/views/search_bank_subtitle.coffee: -------------------------------------------------------------------------------- 1 | BaseView = require '../lib/base_view' 2 | 3 | module.exports = class SearchBankSubTitleView extends BaseView 4 | 5 | template: require('./templates/search_bank_subtitle') 6 | 7 | constructor: (@model) -> 8 | super() 9 | 10 | events: 11 | "change .choice-account" : "accountChange" 12 | 13 | accountChange: (event) -> 14 | 15 | # get the value 16 | enabled = @$(event.target).prop("checked") 17 | console.log "[Search] " + @model.get("title") + ": " + enabled 18 | 19 | # mark the account as checked 20 | @model.checked = enabled 21 | 22 | # and fire "update" on accounts 23 | window.collections.banks.trigger "search-update-accounts" 24 | 25 | initialize: -> 26 | @listenTo @model, 'change', @render 27 | -------------------------------------------------------------------------------- /build/client/app/views/search_bank_title.coffee: -------------------------------------------------------------------------------- 1 | BaseView = require '../lib/base_view' 2 | 3 | module.exports = class SearchBankTitleView extends BaseView 4 | 5 | template: require('./templates/search_bank_title') 6 | 7 | constructor: (@model) -> 8 | super() 9 | 10 | initialize: -> 11 | @listenTo @model.accounts, "add", @update 12 | @listenTo @model.accounts, "destroy", @update 13 | @listenTo @model.accounts, "request", @displayLoading 14 | @listenTo @model.accounts, "change", @hideLoading 15 | 16 | displayLoading: -> 17 | @$(".bank-title-loading").show() 18 | 19 | hideLoading: -> 20 | @$(".bank-title-loading").hide() 21 | 22 | update: -> 23 | 24 | # display or hide the bank title 25 | if @model.accounts.length == 0 26 | @$(".bank-title").hide() 27 | @$(".bank-title-checkbox").hide() 28 | else 29 | @$(".bank-title").show() 30 | @$(".bank-title-checkbox").show() 31 | 32 | # hide loader 33 | @$(".bank-title-loading").hide() 34 | 35 | render: -> 36 | super() 37 | @update() 38 | @ -------------------------------------------------------------------------------- /build/client/app/views/styles/_base.styl: -------------------------------------------------------------------------------- 1 | // Base Styles 2 | 3 | * 4 | box-sizing: border-box 5 | 6 | html, 7 | body 8 | height 100% 9 | width 100% 10 | 11 | body 12 | text-rendering optimizeLegibility 13 | 14 | body, 15 | input 16 | color #444 17 | font 300 16px Geneva, Verdana, "Lucida Sans", "Lucida Grande", "Lucida Sans Unicode", sans-serif 18 | line-height 1.2 19 | 20 | a, 21 | a:visited 22 | color #0086cc 23 | text-decoration none 24 | 25 | &:hover 26 | text-decoration underline 27 | -------------------------------------------------------------------------------- /build/client/app/views/styles/_colors.styl: -------------------------------------------------------------------------------- 1 | basecolor = #34A6FF 2 | basecolor-alpha = rgba(49, 156, 256, 0.5) 3 | 4 | contrastcolor = #5C5 5 | contrastcolor-alpha = #5C5 6 | 7 | 8 | actioncolor = #fe8800 9 | actioncolor-alpha = rgba(254,128,0,0.5) -------------------------------------------------------------------------------- /build/client/app/views/styles/_responsive.styl: -------------------------------------------------------------------------------- 1 | @media screen and (max-width: 480px) 2 | // Landscape phones and down 3 | 4 | body 5 | text-rendering optimizeSpeed 6 | 7 | .content-left-column 8 | height 30% 9 | 10 | .content-right-column 11 | height 70% 12 | 13 | @media screen and (max-width: 767px) 14 | // Landscape phone to portrait tablet 15 | 16 | body 17 | text-rendering optimizeSpeed 18 | 19 | .content-left-column 20 | height 30% 21 | 22 | .content-right-column 23 | height 70% 24 | 25 | @media screen and (min-width: 768px) and (max-width: 1200px) 26 | // Portrait tablet to landscape and desktop 27 | 28 | .content-left-column 29 | height 30% 30 | 31 | .content-right-column 32 | height 70% 33 | 34 | @media screen and (min-width: 1200px) 35 | // Desktop 36 | 37 | .content-left-column, .content-right-column 38 | height 100% 39 | -------------------------------------------------------------------------------- /build/client/app/views/styles/_states.styl: -------------------------------------------------------------------------------- 1 | [data-state~="default"], 2 | [data-state~="enabled"] 3 | cursor inherit 4 | opacity 1 5 | transition opacity 0.2s linear 6 | 7 | [data-state~="disabled"], 8 | cursor not-allowed 9 | opacity 0.5 10 | transition opacity 0.2s linear 11 | 12 | [data-state~="hidden"] 13 | display none 14 | 15 | [data-state~="visible"] 16 | visibility visible 17 | 18 | [data-state~="invisible"] 19 | visibility hidden 20 | 21 | [data-state~="waiting"], 22 | [data-state~="loading"] 23 | cursor wait 24 | 25 | [data-state~="success"], 26 | [data-state~="valid"] 27 | border-color #82cf82 28 | color #82cf82 29 | transition color 0.2s linear, border-color 0.2s linear 30 | 31 | [data-state~="error"], 32 | [data-state~="invalid"] 33 | border-color #f0dddd 34 | color #f0dddd 35 | transition color 0.2s linear, border-color 0.2s linear 36 | -------------------------------------------------------------------------------- /build/client/app/views/styles/application.styl: -------------------------------------------------------------------------------- 1 | // nib is a powerful lib for stylus that provides cross-browser css3 mixins. 2 | @import 'nib' 3 | 4 | @import '_responsive' 5 | 6 | @import '_main' 7 | -------------------------------------------------------------------------------- /build/client/app/views/templates/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/seeker89/cozy-pfm/3e17567625fe81eb879255a4cdbc7d83f374614f/build/client/app/views/templates/.gitkeep -------------------------------------------------------------------------------- /build/client/app/views/templates/accounts.jade: -------------------------------------------------------------------------------- 1 | .row.content-background 2 | .col-lg-12.content-right-column -------------------------------------------------------------------------------- /build/client/app/views/templates/accounts_alerts.jade: -------------------------------------------------------------------------------- 1 | #reports-dialog.modal.fade 2 | .modal-dialog 3 | .modal-content 4 | .modal-header 5 | button.close(type='button', data-dismiss='modal', aria-hidden='true') x 6 | h4.modal-title 7 | | #{window.i18n("accounts_alerts_title")} 8 | .modal-body 9 | h3 10 | | #{window.i18n("accounts_alerts_title_periodic")} 11 | div#reports-body-periodic 12 | p 13 | a.btn.btn-small.btn-cozy.reports-add-periodic #{window.i18n("accounts_alerts_periodic_add")} 14 | 15 | 16 | h3 17 | | #{window.i18n("accounts_alerts_title_balance")} 18 | div#reports-body-amount 19 | p 20 | a.btn.btn-small.btn-cozy.reports-add-amount #{window.i18n("accounts_alerts_balance_add")} 21 | 22 | 23 | h3 24 | | #{window.i18n("accounts_alerts_title_transaction")} 25 | div#reports-body-transaction 26 | p 27 | a.btn.btn-small.btn-cozy.reports-add-transaction #{window.i18n("accounts_alerts_transaction_add")} 28 | 29 | -------------------------------------------------------------------------------- /build/client/app/views/templates/accounts_bank.jade: -------------------------------------------------------------------------------- 1 | h2 #{model.get("name")} 2 | a.btn.btn-cozy.pull-right.delete-bank 3 | | #{window.i18n("accounts_delete_bank")} 4 | table.table-accounts.table.table-striped.table-hover.table-bordered 5 | tbody#account-container 6 | -------------------------------------------------------------------------------- /build/client/app/views/templates/accounts_bank_account.jade: -------------------------------------------------------------------------------- 1 | td.account-title #{model.get("title")} 2 | td.account-title 3 | span.account-details n°#{model.get("accountNumber")} 4 | td 5 | span.text-right 6 | a.btn.btn-small.btn-cozy.pull-right.alert-management 7 | | manage reports and notifications 8 | td 9 | span.text-right 10 | a.btn.btn-small.btn-cozy.pull-right.delete-account 11 | | #{window.i18n("accounts_delete_account")} -------------------------------------------------------------------------------- /build/client/app/views/templates/app.jade: -------------------------------------------------------------------------------- 1 | // navigation bar 2 | #navbar.navbar.navbar-fixed-top.navbar-inverse 3 | 4 | // modal window to add a new bank 5 | #add-bank-window.modal.fade 6 | 7 | // content 8 | #content.container 9 | -------------------------------------------------------------------------------- /build/client/app/views/templates/balance_bank_subtitle.jade: -------------------------------------------------------------------------------- 1 | .row.accounts-sub 2 | .pull-left 3 | p.pull-left #{model.get('title')} 4 | br 5 | span.account-details n°#{model.get("accountNumber")} 6 | .pull-right 7 | p.pull-right #{Number(model.get('amount')).money()} 8 | span.euro-sign € 9 | -------------------------------------------------------------------------------- /build/client/app/views/templates/balance_bank_title.jade: -------------------------------------------------------------------------------- 1 | .row.accounts-top 2 | .col-lg-7 3 | p.pull-left 4 | span.bank-title-loading 5 | img(src="./loader.gif") 6 | span.bank-title #{model.get('name')} 7 | .col-lg-5 8 | p.pull-right.bank-balance 9 | span.bank-amount #{Number(model.get('amount')).money()} 10 | span.euro-sign € 11 | -------------------------------------------------------------------------------- /build/client/app/views/templates/balance_banks_empty.jade: -------------------------------------------------------------------------------- 1 | p.arrow.text-right 2 | img(src="images/arrow_vertical.png") 3 | p.loading 4 | | #{window.i18n("balance_banks_empty")} 5 | -------------------------------------------------------------------------------- /build/client/app/views/templates/balance_operations_element.jade: -------------------------------------------------------------------------------- 1 | td.operation-date #{model.formattedDate} 2 | td.operation-title 3 | .hint--top(data-hint="#{model.hint}") 4 | span.infobulle.glyphicon.glyphicon-info-sign 5 | | #{model.get('title')} 6 | td.operation-amount.text-right 7 | - if(model.formattedAmount == null) 8 | | #{Number(model.get('amount')).money()} 9 | - else 10 | a(href="#{model.formattedAmount}", target="_blank") 11 | | #{Number(model.get('amount')).money()} -------------------------------------------------------------------------------- /build/client/app/views/templates/balance_operations_empty.jade: -------------------------------------------------------------------------------- 1 | br 2 | br 3 | p.loading 4 | | #{window.i18n("balance_please_choose_account")} -------------------------------------------------------------------------------- /build/client/app/views/templates/balance_operations_header.jade: -------------------------------------------------------------------------------- 1 | h2 #{model.get("title")} 2 | p 3 | span.last-checked #{window.i18n("balance_last_checked")} #{moment(moment(model.get("lastChecked"))).fromNow()}. 4 | a.recheck-button.btn-link #{window.i18n("balance_recheck_now")} 5 | 6 | .text-center.loading.loader-operations 7 | img(src="./loader_big_blue.gif") 8 | 9 | table.table.tablesorter.table-striped.table-hover 10 | thead 11 | tr 12 | th.sort-date.text-left #{window.i18n("header_date")} 13 | th.sort-title.text-center #{window.i18n("header_title")} 14 | th.sort-amount.text-right #{window.i18n("header_amount")} 15 | tbody#table-operations 16 | -------------------------------------------------------------------------------- /build/client/app/views/templates/layout-2col.jade: -------------------------------------------------------------------------------- 1 | .row.content-background 2 | #layout-2col-column-left.col-lg-4.content-left-column 3 | 4 | #layout-2col-column-right.col-lg-8.content-right-column 5 | -------------------------------------------------------------------------------- /build/client/app/views/templates/modal_confirm.jade: -------------------------------------------------------------------------------- 1 | #confirmation-dialog.modal.fade 2 | .modal-dialog 3 | .modal-content 4 | .modal-header 5 | button.close(type='button', data-dismiss='modal', aria-hidden='true') x 6 | h4.modal-title 7 | | #{title} 8 | .modal-body 9 | p 10 | | #{body} 11 | .modal-footer 12 | a.btn.btn-link(data-dismiss='modal',href='#') #{window.i18n("cancel")} 13 | a#confirmation-dialog-confirm.btn.btn-cozy(href='#') #{confirm} 14 | 15 | -------------------------------------------------------------------------------- /build/client/app/views/templates/navbar.jade: -------------------------------------------------------------------------------- 1 | nav.navbar.navbar-inverse.navbar-fixed-top(role='navigation') 2 | .container 3 | // Brand and toggle get grouped for better mobile display 4 | .navbar-header 5 | button.navbar-toggle(type='button', data-toggle='collapse', data-target='.navbar-collapse') 6 | span.sr-only Toggle navigation 7 | span.icon-bar 8 | span.icon-bar 9 | span.icon-bar 10 | // Collect the nav links, forms, and other content for toggling 11 | .collapse.navbar-collapse 12 | ul.nav.navbar-nav 13 | li.menu-position.menu-1 14 | a#menu-pos-balance(href='#') #{window.i18n("menu_balance")} 15 | li.menu-position.menu-2 16 | a#menu-pos-accounts(href='#search') #{window.i18n("menu_search")} 17 | li.menu-position.menu-3 18 | a#menu-pos-accounts(href='#accounts') #{window.i18n("menu_accounts")} 19 | li 20 | a#menu-pos-new-bank(data-toggle='modal', href='#add-bank-window') #{window.i18n("menu_add_bank")} 21 | 22 | ul.nav.navbar-nav.navbar-right 23 | p.navbar-text 24 | | #{window.i18n("overall_balance")} 25 | span#total-amount 0,00 -------------------------------------------------------------------------------- /build/client/app/views/templates/new_bank.jade: -------------------------------------------------------------------------------- 1 | .modal-dialog 2 | .modal-content 3 | .modal-header 4 | button.close(type='button', data-dismiss='modal', aria-hidden='true') x 5 | h4.modal-title 6 | | #{window.i18n("menu_add_bank")} 7 | .modal-body 8 | .message-modal 9 | form 10 | fieldset 11 | legend 12 | | #{window.i18n("add_bank_bank")} 13 | .form-group 14 | select#inputBank.form-control 15 | each bank in banks 16 | option(value=bank.get("uuid")) 17 | =bank.get("name") 18 | 19 | #formInputWebsite.form-group.hide 20 | label(for='inputWebsite') 21 | | #{window.i18n("add_bank_website")} 22 | select#inputWebsite.form-control 23 | 24 | fieldset 25 | legend 26 | | #{window.i18n("add_bank_credentials")} 27 | .form-group 28 | label(for='inputLogin') 29 | | #{window.i18n("add_bank_login")} 30 | input#inputLogin.form-control(type='text', placeholder=window.i18n("add_bank_login_placeholder")) 31 | .form-group 32 | label(for='inputPass') 33 | | #{window.i18n("add_bank_password")} 34 | input#inputPass.form-control(type='password', placeholder=window.i18n("add_bank_password_placeholder")) 35 | h3.important-notice 36 | | #{window.i18n("add_bank_security_notice")} 37 | p 38 | | #{window.i18n("add_bank_security_notice_text")} 39 | .modal-footer 40 | a.btn.btn-link(data-dismiss='modal',href='#') #{window.i18n("add_bank_cancel")} 41 | a#btn-add-bank-save.btn.btn-success(href='#') #{window.i18n("add_bank_ok")} 42 | -------------------------------------------------------------------------------- /build/client/app/views/templates/search_bank_subtitle.jade: -------------------------------------------------------------------------------- 1 | .row.accounts-sub 2 | .col-lg-7 3 | p.pull-left #{model.get('title')} 4 | .col-lg-5 5 | p.pull-right 6 | if model.checked 7 | input(type="checkbox", checked).choice-account 8 | else 9 | input(type="checkbox").choice-account 10 | -------------------------------------------------------------------------------- /build/client/app/views/templates/search_bank_title.jade: -------------------------------------------------------------------------------- 1 | .row.accounts-top 2 | .col-lg-7 3 | p.pull-left 4 | span.bank-title-loading 5 | img(src="./loader.gif") 6 | span.bank-title 7 | | #{model.get('name')} 8 | .col-lg-5 9 | p.pull-right.bank-title-checkbox 10 | if model.checked 11 | input(type="checkbox", checked).choice-bank 12 | else 13 | input(type="checkbox").choice-bank -------------------------------------------------------------------------------- /build/client/app/views/templates/search_operations.jade: -------------------------------------------------------------------------------- 1 | form.form-search 2 | .row 3 | .col-lg-6 4 | .form-group 5 | label(for='search-date-from') 6 | | #{window.i18n("search_date_from")} 7 | input#search-date-from.form-control(type='date') 8 | .col-lg-6 9 | .form-group 10 | label(for='search-date-to') 11 | | #{window.i18n("search_date_to")} 12 | input#search-date-to.form-control(type='date') 13 | 14 | .row 15 | .col-lg-6 16 | .form-group 17 | label(for='search-amount-from') 18 | | #{window.i18n("search_amount_from")} 19 | input#search-amount-from.form-control(type='number') 20 | .col-lg-6 21 | .form-group 22 | label(for='search-amount-to') 23 | | #{window.i18n("search_amount_to")} 24 | input#search-amount-to.form-control(type='number') 25 | 26 | .row 27 | .col-lg-12 28 | label(for='search-text') 29 | | #{window.i18n("search_text")} 30 | input#search-text.form-control(type='text') 31 | 32 | .row 33 | .col-lg-12#search-operations-table 34 | -------------------------------------------------------------------------------- /build/client/app/views/templates/search_operations_table_header.jade: -------------------------------------------------------------------------------- 1 | br 2 | table#search-table.table.tablesorter.table-striped.table-hover 3 | thead 4 | tr 5 | th.sort-date.text-left #{window.i18n("header_date")} 6 | th.sort-title.text-center #{window.i18n("header_title")} 7 | th.sort-amount.text-right #{window.i18n("header_amount")} 8 | tbody#search-operations-table-body 9 | -------------------------------------------------------------------------------- /build/client/config.coffee: -------------------------------------------------------------------------------- 1 | exports.config = 2 | # See docs at http://brunch.readthedocs.org/en/latest/config.html. 3 | #coffeelint: 4 | #pattern: /^app\/.*\.coffee$/ 5 | #options: 6 | #indentation: 7 | #value: 4 8 | #level: "error" 9 | 10 | files: 11 | javascripts: 12 | joinTo: 13 | 'javascripts/app.js': /^app/ 14 | 'javascripts/vendor.js': /^vendor/ 15 | order: 16 | # Files in `vendor` directories are compiled before other files 17 | # even if they aren't specified in order. 18 | before: [ 19 | 'vendor/scripts/jquery-1.10.2.js' 20 | 'vendor/scripts/underscore-1.4.4.js' 21 | 'vendor/scripts/backbone-1.0.0.js' 22 | 'vendor/scripts/jquery.dataTables.js' 23 | ] 24 | 25 | stylesheets: 26 | joinTo: 'stylesheets/app.css' 27 | order: 28 | before: ['vendor/styles/normalize.css'] 29 | after: ['vendor/styles/helpers.css'] 30 | 31 | templates: 32 | defaultExtension: 'jade' 33 | joinTo: 'javascripts/app.js' 34 | -------------------------------------------------------------------------------- /build/client/generators/collection/collection.coffee.hbs: -------------------------------------------------------------------------------- 1 | module.exports = class {{#camelize}}{{pluralName}}{{/camelize}}Collection extends Backbone.Collection 2 | model: require '../models/{{name}}' 3 | url: '{{name}}s/' 4 | -------------------------------------------------------------------------------- /build/client/generators/collection/generator.json: -------------------------------------------------------------------------------- 1 | { 2 | "files": [{ 3 | "from": "collection.coffee.hbs", 4 | "to": "app/collections/{{pluralName}}.coffee" 5 | }], 6 | "dependencies": [{ 7 | "name": "collection_test", 8 | "params": "{{pluralName}}" 9 | }] 10 | } 11 | -------------------------------------------------------------------------------- /build/client/generators/collection_test/collection_test.coffee.hbs: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/seeker89/cozy-pfm/3e17567625fe81eb879255a4cdbc7d83f374614f/build/client/generators/collection_test/collection_test.coffee.hbs -------------------------------------------------------------------------------- /build/client/generators/collection_test/generator.json: -------------------------------------------------------------------------------- 1 | { 2 | "files": [{ 3 | "from": "collection_test.coffee.hbs", 4 | "to": "test/collections/{{pluralName}}_test.coffee" 5 | }], 6 | "dependencies": [] 7 | } 8 | -------------------------------------------------------------------------------- /build/client/generators/generator/generated_file.coffee.hbs: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/seeker89/cozy-pfm/3e17567625fe81eb879255a4cdbc7d83f374614f/build/client/generators/generator/generated_file.coffee.hbs -------------------------------------------------------------------------------- /build/client/generators/generator/generator.json: -------------------------------------------------------------------------------- 1 | { 2 | "files": [ 3 | { 4 | "from": "generator.json.hbs", 5 | "to": "generators/{{name}}/generator.json" 6 | }, 7 | { 8 | "from": "generated_file.coffee.hbs", 9 | "to": "generators/{{name}}/{{name}}.coffee.hbs" 10 | } 11 | ], 12 | "dependencies": [] 13 | } 14 | -------------------------------------------------------------------------------- /build/client/generators/generator/generator.json.hbs: -------------------------------------------------------------------------------- 1 | { 2 | "files": [{ 3 | "from": "{{name}}.coffee.hbs", 4 | "to": "app/file.coffee" 5 | }], 6 | "dependencies": [] 7 | } 8 | -------------------------------------------------------------------------------- /build/client/generators/model/generator.json: -------------------------------------------------------------------------------- 1 | { 2 | "files": [{ 3 | "from": "model.coffee.hbs", 4 | "to": "app/models/{{name}}.coffee" 5 | }], 6 | "dependencies": [{ 7 | "name": "model_test", 8 | "params": "{{name}}" 9 | }] 10 | } 11 | -------------------------------------------------------------------------------- /build/client/generators/model/model.coffee.hbs: -------------------------------------------------------------------------------- 1 | module.exports = class {{#camelize}}{{name}}{{/camelize}}Model extends Backbone.Model 2 | rootUrl: "{{name}}s/" -------------------------------------------------------------------------------- /build/client/generators/model_test/generator.json: -------------------------------------------------------------------------------- 1 | { 2 | "files": [{ 3 | "from": "model_test.coffee.hbs", 4 | "to": "test/models/{{name}}.coffee" 5 | }], 6 | "dependencies": [] 7 | } 8 | -------------------------------------------------------------------------------- /build/client/generators/model_test/model_test.coffee.hbs: -------------------------------------------------------------------------------- 1 | {{#camelize}}{{name}}{{/camelize}}Model = require 'models/{{name}}' 2 | 3 | describe '{{#camelize}}{{name}}{{/camelize}}Model', -> 4 | beforeEach -> 5 | @model = new {{#camelize}}{{name}}{{/camelize}}Model() 6 | -------------------------------------------------------------------------------- /build/client/generators/module/collection.coffee.hbs: -------------------------------------------------------------------------------- 1 | module.exports = class {{#camelize}}{{pluralName}}{{/camelize}}Collection extends Backbone.Collection 2 | model: require '../models/{{name}}' 3 | url: '{{name}}s/' 4 | -------------------------------------------------------------------------------- /build/client/generators/module/generator.json: -------------------------------------------------------------------------------- 1 | { 2 | "files": [ 3 | { 4 | "from": "model.coffee.hbs", 5 | "to": "app/models/{{name}}.coffee" 6 | }, 7 | { 8 | "from": "view.coffee.hbs", 9 | "to": "app/views/{{name}}.coffee" 10 | }, 11 | { 12 | "from": "collection.coffee.hbs", 13 | "to": "app/collections/{{name}}s.coffee" 14 | }, 15 | { 16 | "from": "template.jade.hbs", 17 | "to": "app/views/templates/{{name}}.jade" 18 | }, 19 | { 20 | "from": "style.styl.hbs", 21 | "to": "app/views/styles/_{{name}}.styl" 22 | }, 23 | { 24 | "from": "view_collection.coffee.hbs", 25 | "to": "app/views/{{name}}s.coffee" 26 | } 27 | ], 28 | "dependencies": [] 29 | } 30 | -------------------------------------------------------------------------------- /build/client/generators/module/model.coffee.hbs: -------------------------------------------------------------------------------- 1 | module.exports = class {{#camelize}}{{name}}{{/camelize}}Model extends Backbone.Model 2 | rootUrl: "{{name}}s/" -------------------------------------------------------------------------------- /build/client/generators/module/style.styl.hbs: -------------------------------------------------------------------------------- 1 | .{{name}} 2 | // {{#camelize}}{{name}}{{/camelize}} Module 3 | 4 | -------------------------------------------------------------------------------- /build/client/generators/module/template.jade.hbs: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /build/client/generators/module/view.coffee.hbs: -------------------------------------------------------------------------------- 1 | BaseView = require '../lib/base_view' 2 | 3 | module.exports = class {{#camelize}}{{name}}{{/camelize}}View extends BaseView 4 | template: require './templates/{{name}}' 5 | className: '{{name}}' 6 | -------------------------------------------------------------------------------- /build/client/generators/module/view_collection.coffee.hbs: -------------------------------------------------------------------------------- 1 | ViewCollection = require '../lib/view_collection' 2 | {{#camelize}}{{name}}{{/camelize}}sCollection = require '../collections/{{name}}s' 3 | {{#camelize}}{{name}}{{/camelize}}View = require './{{name}}' 4 | 5 | module.exports = class {{#camelize}}{{name}}{{/camelize}}sView extends ViewCollection 6 | el: '#{{name}}s' 7 | 8 | collection: new {{#camelize}}{{name}}{{/camelize}}sCollection() 9 | itemview: {{#camelize}}{{name}}{{/camelize}}View 10 | 11 | afterRender: -> 12 | @collection.on 'reset', => 13 | @renderAll() 14 | @collection.on 'add', (model) => 15 | @renderOne model 16 | -------------------------------------------------------------------------------- /build/client/generators/style/generator.json: -------------------------------------------------------------------------------- 1 | { 2 | "files": [{ 3 | "from": "style.styl.hbs", 4 | "to": "app/views/styles/_{{name}}.styl" 5 | }], 6 | "dependencies": [] 7 | } 8 | -------------------------------------------------------------------------------- /build/client/generators/style/style.styl.hbs: -------------------------------------------------------------------------------- 1 | .{{name}} 2 | // {{#camelize}}{{name}}{{/camelize}} Module 3 | -------------------------------------------------------------------------------- /build/client/generators/template/generator.json: -------------------------------------------------------------------------------- 1 | { 2 | "files": [{ 3 | "from": "template.hbs.hbs", 4 | "to": "app/views/templates/{{name}}.jade" 5 | }], 6 | "dependencies": [] 7 | } 8 | -------------------------------------------------------------------------------- /build/client/generators/template/template.hbs: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /build/client/generators/view/generator.json: -------------------------------------------------------------------------------- 1 | { 2 | "files": [{ 3 | "from": "view.coffee.hbs", 4 | "to": "app/views/{{name}}.coffee" 5 | }], 6 | "dependencies": [{ 7 | "name": "view_test", 8 | "params": "{{name}}" 9 | }] 10 | } 11 | -------------------------------------------------------------------------------- /build/client/generators/view/view.coffee.hbs: -------------------------------------------------------------------------------- 1 | BaseView = require '../lib/base_view' 2 | 3 | module.exports = class {{#camelize}}{{name}}{{/camelize}}View extends BaseView 4 | template: require './templates/{{name}}' 5 | className: '{{name}}' 6 | -------------------------------------------------------------------------------- /build/client/generators/view_test/generator.json: -------------------------------------------------------------------------------- 1 | { 2 | "files": [ 3 | { 4 | "from": "view_test.coffee.hbs", 5 | "to": "test/views/{{name}}.coffee" 6 | } 7 | ], 8 | "dependencies": [] 9 | } 10 | -------------------------------------------------------------------------------- /build/client/generators/view_test/view_test.coffee.hbs: -------------------------------------------------------------------------------- 1 | {{#camelize}}{{name}}{{/camelize}}View = require 'views/{{name}}' 2 | 3 | describe '{{#camelize}}{{name}}{{/camelize}}View', -> 4 | beforeEach -> 5 | @view = new {{#camelize}}{{name}}{{/camelize}}View() 6 | -------------------------------------------------------------------------------- /build/client/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "author": "Your Name", 3 | "name": "package-name", 4 | "description": "Package description", 5 | "version": "0.0.1", 6 | "homepage": "", 7 | "repository": { 8 | "type": "git", 9 | "url": "" 10 | }, 11 | "engines": { 12 | "node": "~0.6.10 || 0.8 || 0.9" 13 | }, 14 | "scripts": { 15 | "start": "brunch watch --server" 16 | }, 17 | "dependencies": { 18 | "javascript-brunch": "> 1.0 < 1.5", 19 | "coffee-script-brunch": "> 1.0 < 1.5", 20 | 21 | "css-brunch": "> 1.0 < 1.5", 22 | "stylus-brunch": "> 1.0 < 1.5", 23 | 24 | "jade-brunch": "> 1.0 < 1.5", 25 | 26 | "uglify-js-brunch": "> 1.0 < 1.5", 27 | "clean-css-brunch": "> 1.0 < 1.5", 28 | 29 | "auto-reload-brunch": "> 1.0 < 1.5", 30 | 31 | "async": ">= 0" 32 | }, 33 | "devDependencies": { 34 | "mocha": "0.14.0", 35 | "expect.js": "0.1.2", 36 | "ws": "0.4.21" 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /build/client/public/asc.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/seeker89/cozy-pfm/3e17567625fe81eb879255a4cdbc7d83f374614f/build/client/public/asc.gif -------------------------------------------------------------------------------- /build/client/public/bg.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/seeker89/cozy-pfm/3e17567625fe81eb879255a4cdbc7d83f374614f/build/client/public/bg.gif -------------------------------------------------------------------------------- /build/client/public/crossdomain.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 15 | 16 | -------------------------------------------------------------------------------- /build/client/public/desc.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/seeker89/cozy-pfm/3e17567625fe81eb879255a4cdbc7d83f374614f/build/client/public/desc.gif -------------------------------------------------------------------------------- /build/client/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/seeker89/cozy-pfm/3e17567625fe81eb879255a4cdbc7d83f374614f/build/client/public/favicon.ico -------------------------------------------------------------------------------- /build/client/public/fonts/fontawesome/FontAwesome.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/seeker89/cozy-pfm/3e17567625fe81eb879255a4cdbc7d83f374614f/build/client/public/fonts/fontawesome/FontAwesome.ttf -------------------------------------------------------------------------------- /build/client/public/fonts/fontawesome/README.md: -------------------------------------------------------------------------------- 1 | #Font Awesome 2.0 2 | ##the iconic font designed for use with Twitter Bootstrap 3 | 4 | The full suite of pictographic icons, examples, and documentation can be found at: 5 | http://fortawesome.github.com/Font-Awesome/ 6 | 7 | ##Contact 8 | - Email: dave@davegandy.com 9 | - Twitter: http://twitter.com/fortaweso_me 10 | - Work: Lead Product Designer @ http://kyru.us 11 | 12 | ##License 13 | Version 2.0 of the Font Awesome font, CSS, and LESS files are licensed under CC BY 3.0: 14 | http://creativecommons.org/licenses/by/3.0/ 15 | A mention of 'Font Awesome - http://fortawesome.github.com/Font-Awesome' 16 | in human-readable source code is considered acceptable attribution (most common on the 17 | web). If human readable source code is not available to the end user, a mention in an 'About' 18 | or 'Credits' screen is considered acceptable (most common in desktop or mobile software). 19 | -------------------------------------------------------------------------------- /build/client/public/fonts/fontawesome/fontawesome-webfont.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/seeker89/cozy-pfm/3e17567625fe81eb879255a4cdbc7d83f374614f/build/client/public/fonts/fontawesome/fontawesome-webfont.eot -------------------------------------------------------------------------------- /build/client/public/fonts/fontawesome/fontawesome-webfont.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/seeker89/cozy-pfm/3e17567625fe81eb879255a4cdbc7d83f374614f/build/client/public/fonts/fontawesome/fontawesome-webfont.ttf -------------------------------------------------------------------------------- /build/client/public/fonts/fontawesome/fontawesome-webfont.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/seeker89/cozy-pfm/3e17567625fe81eb879255a4cdbc7d83f374614f/build/client/public/fonts/fontawesome/fontawesome-webfont.woff -------------------------------------------------------------------------------- /build/client/public/fonts/fontello.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/seeker89/cozy-pfm/3e17567625fe81eb879255a4cdbc7d83f374614f/build/client/public/fonts/fontello.ttf -------------------------------------------------------------------------------- /build/client/public/fonts/glyphicons-halflings-regular.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/seeker89/cozy-pfm/3e17567625fe81eb879255a4cdbc7d83f374614f/build/client/public/fonts/glyphicons-halflings-regular.eot -------------------------------------------------------------------------------- /build/client/public/fonts/glyphicons-halflings-regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/seeker89/cozy-pfm/3e17567625fe81eb879255a4cdbc7d83f374614f/build/client/public/fonts/glyphicons-halflings-regular.ttf -------------------------------------------------------------------------------- /build/client/public/fonts/glyphicons-halflings-regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/seeker89/cozy-pfm/3e17567625fe81eb879255a4cdbc7d83f374614f/build/client/public/fonts/glyphicons-halflings-regular.woff -------------------------------------------------------------------------------- /build/client/public/fonts/maven-pro-light-100.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/seeker89/cozy-pfm/3e17567625fe81eb879255a4cdbc7d83f374614f/build/client/public/fonts/maven-pro-light-100.otf -------------------------------------------------------------------------------- /build/client/public/fonts/maven-pro-light-200.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/seeker89/cozy-pfm/3e17567625fe81eb879255a4cdbc7d83f374614f/build/client/public/fonts/maven-pro-light-200.otf -------------------------------------------------------------------------------- /build/client/public/fonts/maven-pro-light-300.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/seeker89/cozy-pfm/3e17567625fe81eb879255a4cdbc7d83f374614f/build/client/public/fonts/maven-pro-light-300.otf -------------------------------------------------------------------------------- /build/client/public/fonts/signika-bold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/seeker89/cozy-pfm/3e17567625fe81eb879255a4cdbc7d83f374614f/build/client/public/fonts/signika-bold.ttf -------------------------------------------------------------------------------- /build/client/public/fonts/signika-light.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/seeker89/cozy-pfm/3e17567625fe81eb879255a4cdbc7d83f374614f/build/client/public/fonts/signika-light.ttf -------------------------------------------------------------------------------- /build/client/public/fonts/signika-regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/seeker89/cozy-pfm/3e17567625fe81eb879255a4cdbc7d83f374614f/build/client/public/fonts/signika-regular.ttf -------------------------------------------------------------------------------- /build/client/public/humans.txt: -------------------------------------------------------------------------------- 1 | # humanstxt.org/ 2 | # The humans responsible & technology colophon 3 | 4 | # TEAM 5 | 6 | -- -- 7 | 8 | # THANKS 9 | 10 | 11 | 12 | # TECHNOLOGY COLOPHON 13 | 14 | HTML5, CSS3 15 | jQuery, Modernizr, 16 | Lodash, Backbone, 17 | Handlebars, Coffeescript, 18 | Stylus, Brunch 19 | -------------------------------------------------------------------------------- /build/client/public/icons/main_icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/seeker89/cozy-pfm/3e17567625fe81eb879255a4cdbc7d83f374614f/build/client/public/icons/main_icon.png -------------------------------------------------------------------------------- /build/client/public/images/Melamine-wood-003.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/seeker89/cozy-pfm/3e17567625fe81eb879255a4cdbc7d83f374614f/build/client/public/images/Melamine-wood-003.png -------------------------------------------------------------------------------- /build/client/public/images/arrow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/seeker89/cozy-pfm/3e17567625fe81eb879255a4cdbc7d83f374614f/build/client/public/images/arrow.png -------------------------------------------------------------------------------- /build/client/public/images/arrow_vertical.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/seeker89/cozy-pfm/3e17567625fe81eb879255a4cdbc7d83f374614f/build/client/public/images/arrow_vertical.png -------------------------------------------------------------------------------- /build/client/public/images/glyphicons-halflings-white.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/seeker89/cozy-pfm/3e17567625fe81eb879255a4cdbc7d83f374614f/build/client/public/images/glyphicons-halflings-white.png -------------------------------------------------------------------------------- /build/client/public/images/glyphicons-halflings.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/seeker89/cozy-pfm/3e17567625fe81eb879255a4cdbc7d83f374614f/build/client/public/images/glyphicons-halflings.png -------------------------------------------------------------------------------- /build/client/public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | Cozy PFM 10 | 11 | 12 | 17 | 18 | 19 | 20 | 21 | 22 | 25 | 26 | 27 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /build/client/public/loader.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/seeker89/cozy-pfm/3e17567625fe81eb879255a4cdbc7d83f374614f/build/client/public/loader.gif -------------------------------------------------------------------------------- /build/client/public/loader_big_blue.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/seeker89/cozy-pfm/3e17567625fe81eb879255a4cdbc7d83f374614f/build/client/public/loader_big_blue.gif -------------------------------------------------------------------------------- /build/client/public/loader_green.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/seeker89/cozy-pfm/3e17567625fe81eb879255a4cdbc7d83f374614f/build/client/public/loader_green.gif -------------------------------------------------------------------------------- /build/client/public/loader_inverse.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/seeker89/cozy-pfm/3e17567625fe81eb879255a4cdbc7d83f374614f/build/client/public/loader_inverse.gif -------------------------------------------------------------------------------- /build/client/public/robots.txt: -------------------------------------------------------------------------------- 1 | # robotstxt.org/ 2 | 3 | User-agent: * 4 | -------------------------------------------------------------------------------- /build/client/vendor/scripts/zoomico.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/seeker89/cozy-pfm/3e17567625fe81eb879255a4cdbc7d83f374614f/build/client/vendor/scripts/zoomico.png -------------------------------------------------------------------------------- /build/client/vendor/styles/helpers.css: -------------------------------------------------------------------------------- 1 | .chromeframe { margin: 0.2em 0; background: #ccc; color: #000; padding: 0.2em 0; } 2 | .ir { display: block; border: 0; text-indent: -999em; overflow: hidden; background-color: transparent; background-repeat: no-repeat; text-align: left; direction: ltr; *line-height: 0; } 3 | .ir br { display: none; } 4 | .hidden { display: none !important; visibility: hidden; } 5 | .visuallyhidden { border: 0; clip: rect(0 0 0 0); height: 1px; margin: -1px; overflow: hidden; padding: 0; position: absolute; width: 1px; } 6 | .visuallyhidden.focusable:active, .visuallyhidden.focusable:focus { clip: auto; height: auto; margin: 0; overflow: visible; position: static; width: auto; } 7 | .invisible { visibility: hidden; } 8 | .clearfix:before, .clearfix:after { content: ""; display: table; } 9 | .clearfix:after { clear: both; } 10 | .clearfix { *zoom: 1; } 11 | 12 | @media print { 13 | * { background: transparent !important; color: black !important; box-shadow:none !important; text-shadow: none !important; filter:none !important; -ms-filter: none !important; } 14 | a, a:visited { text-decoration: underline; } 15 | a[href]:after { content: " (" attr(href) ")"; } 16 | abbr[title]:after { content: " (" attr(title) ")"; } 17 | .ir a:after, a[href^="javascript:"]:after, a[href^="#"]:after { content: ""; } 18 | pre, blockquote { border: 1px solid #999; page-break-inside: avoid; } 19 | thead { display: table-header-group; } 20 | tr, img { page-break-inside: avoid; } 21 | img { max-width: 100% !important; } 22 | @page { margin: 0.5cm; } 23 | p, h2, h3 { orphans: 3; widows: 3; } 24 | h2, h3 { page-break-after: avoid; } 25 | } 26 | -------------------------------------------------------------------------------- /build/client/vendor/styles/sort.css: -------------------------------------------------------------------------------- 1 | /* table sorter */ 2 | table.tablesorter thead tr th { 3 | background-image: url(../bg.gif); 4 | background-repeat: no-repeat; 5 | background-position: center right; 6 | /* background-color: #F7F7F7; */ 7 | padding-right: 20px; 8 | cursor: pointer; 9 | } 10 | table.tablesorter thead tr .sorting_asc { 11 | background-image: url(../asc.gif); 12 | } 13 | table.tablesorter thead tr .sorting_desc { 14 | background-image: url(../desc.gif); 15 | } 16 | table.tablesorter thead tr .sorting_asc, table.tablesorter thead tr .sorting_desc { 17 | /* background-color: #dddddd; */ 18 | font-weight: bold; 19 | color: #34A6FF; 20 | } -------------------------------------------------------------------------------- /build/client/vendor/styles/tablesort_blue.css: -------------------------------------------------------------------------------- 1 | /* table sorter */ 2 | table.tablesorter thead tr .header { 3 | background-image: url(../bg.gif); 4 | background-repeat: no-repeat; 5 | background-position: center right; 6 | /* background-color: #F7F7F7; */ 7 | padding-right: 20px; 8 | cursor: pointer; 9 | } 10 | table.tablesorter thead tr .headerSortUp { 11 | background-image: url(../asc.gif); 12 | } 13 | table.tablesorter thead tr .headerSortDown { 14 | background-image: url(../desc.gif); 15 | } 16 | table.tablesorter thead tr .headerSortDown, table.tablesorter thead tr .headerSortUp { 17 | /* background-color: #dddddd; */ 18 | font-weight: bold; 19 | color: #34A6FF; 20 | } 21 | -------------------------------------------------------------------------------- /build/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "pfm", 3 | "version": "1.0.0", 4 | "engines": [ 5 | "node = 0.8.x" 6 | ], 7 | "description": "Personal Finance Manager you own and control", 8 | "license": "MIT", 9 | "repository": { 10 | "type": "git", 11 | "url": "https://github.com/mycozycloud/cozy-pfm.git" 12 | }, 13 | "main": "server.coffee", 14 | "dependencies": { 15 | "americano": "0.3.3", 16 | "americano-cozy": "0.2.2", 17 | "async": "0.2.10", 18 | "request-json": "0.4.8", 19 | "moment": "2.5.1", 20 | "cozy-notifications-helper": "1.0.2", 21 | "jade": "1.3.0", 22 | "nock": "0.27.2", 23 | "cozy-i18n-helper": "0.0.4", 24 | "printit": "0.1.3" 25 | }, 26 | "devDependencies": { 27 | "should": "3.1.4", 28 | "mocha": "1.18.2", 29 | "cozy-fixtures": "1.1.0", 30 | "coffeelint": "1.1.0" 31 | }, 32 | "scripts": { 33 | "test": "cake --use-js tests", 34 | "start": "node build/server.js" 35 | }, 36 | "cozy-displayName": "Mes Comptes", 37 | "cozy-permissions": { 38 | "Bank": { 39 | "description": "Les banques auxquelles vous pouvez accéder via l'application." 40 | }, 41 | "BankAccess": { 42 | "description": "Vos identifiants d'accès à votre banque sont stockés de façon sécurisée." 43 | }, 44 | "BankAccount": { 45 | "description": "Vos différents comptes bancaires." 46 | }, 47 | "BankOperation": { 48 | "description": "Une opération bancaire." 49 | }, 50 | "BankAlert": { 51 | "description": "Une alerte liée à vos comptes bancaires." 52 | }, 53 | "send mail to user": { 54 | "description": "A votre demande, des rapports journaliers, hebdomadaires ou mensuels peuvent vous être envoyés par email." 55 | }, 56 | "Notification": { 57 | "description": "Des notifications sont créées lorsque des alertes sont mises en place dans l'application." 58 | }, 59 | "CozyInstance": { 60 | "description": "Afin d'afficher le contenu dans votre langue, l'application doit accéder à vos préférences." 61 | } 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /build/server.js: -------------------------------------------------------------------------------- 1 | // Generated by CoffeeScript 1.8.0 2 | var application; 3 | 4 | application = module.exports = function(callback) { 5 | var americano, initialize, options; 6 | americano = require('americano'); 7 | initialize = require('./server/init'); 8 | require('./tests/mock-weboob'); 9 | options = { 10 | name: 'pfm', 11 | port: process.env.PORT || 9875, 12 | host: process.env.HOST || "127.0.0.1", 13 | root: __dirname 14 | }; 15 | return americano.start(options, function(app, server) { 16 | return initialize(app, server, callback); 17 | }); 18 | }; 19 | 20 | if (!module.parent) { 21 | application(); 22 | } 23 | -------------------------------------------------------------------------------- /build/server/config.js: -------------------------------------------------------------------------------- 1 | // Generated by CoffeeScript 1.8.0 2 | var americano, config; 3 | 4 | americano = require('americano'); 5 | 6 | config = { 7 | common: [ 8 | americano.bodyParser(), americano.methodOverride(), americano.errorHandler({ 9 | dumpExceptions: true, 10 | showStack: true 11 | }), americano["static"](__dirname + '/../client/public', { 12 | maxAge: 86400000 13 | }), require('cozy-i18n-helper').middleware 14 | ], 15 | development: [americano.logger('dev')], 16 | production: [americano.logger('short')], 17 | plugins: ['americano-cozy'] 18 | }; 19 | 20 | module.exports = config; 21 | -------------------------------------------------------------------------------- /build/server/init.js: -------------------------------------------------------------------------------- 1 | // Generated by CoffeeScript 1.8.0 2 | module.exports = function(app, server, callback) { 3 | var Bank, poller, reportManager; 4 | Bank = require('./models/bank'); 5 | Bank.all(function(err, banks) { 6 | var async, bankList, process; 7 | if (err || (banks != null ? banks.length : void 0) === 0) { 8 | async = require('async'); 9 | bankList = require("../tests/fixtures/banks-all.json"); 10 | process = function(bank, callback) { 11 | var newBank; 12 | newBank = { 13 | name: bank.name, 14 | uuid: bank.uuid, 15 | websites: bank.websites 16 | }; 17 | return Bank.create(newBank, function(err) { 18 | if (err != null) { 19 | return callback(err); 20 | } else { 21 | return callback(null); 22 | } 23 | }); 24 | }; 25 | return async.each(bankList, process, function(err) { 26 | var msg; 27 | if (err != null) { 28 | msg = "Couldn't add the bank to the database -- " + err; 29 | return console.log(msg); 30 | } else { 31 | msg = "Banks added to the database."; 32 | console.log(msg); 33 | if (callback != null) { 34 | return callback(app, server); 35 | } 36 | } 37 | }); 38 | } else { 39 | if (callback != null) { 40 | return callback(app, server); 41 | } 42 | } 43 | }); 44 | console.log("Start bank accounts polling..."); 45 | poller = require('./lib/accounts-poller'); 46 | poller.start(); 47 | console.log("Start alert watcher..."); 48 | reportManager = require('./lib/report-manager'); 49 | return reportManager.start(); 50 | }; 51 | -------------------------------------------------------------------------------- /build/server/lib/accounts-poller.js: -------------------------------------------------------------------------------- 1 | // Generated by CoffeeScript 1.8.0 2 | var AccountsPoller, BankAccess, async, moment; 3 | 4 | async = require("async"); 5 | 6 | moment = require("moment"); 7 | 8 | BankAccess = require("../models/bankaccess"); 9 | 10 | AccountsPoller = (function() { 11 | function AccountsPoller() {} 12 | 13 | AccountsPoller.prototype.start = function() { 14 | return this.prepareNextCheck(); 15 | }; 16 | 17 | AccountsPoller.prototype.prepareNextCheck = function() { 18 | var delta, format, msg, nextUpdate, now; 19 | delta = Math.floor(Math.random() * 120); 20 | now = moment(); 21 | nextUpdate = now.clone().add(1, 'days').hours(0).minutes(delta).seconds(0); 22 | format = "DD/MM/YYYY [at] HH:mm:ss"; 23 | msg = "> Next check of bank accounts on " + (nextUpdate.format(format)); 24 | console.log(msg); 25 | return this.timeout = setTimeout((function(_this) { 26 | return function() { 27 | return _this.checkAllAccesses(); 28 | }; 29 | })(this), nextUpdate.diff(now)); 30 | }; 31 | 32 | AccountsPoller.prototype.checkAllAccesses = function() { 33 | console.log("Checking new operations for all bank accesses..."); 34 | return BankAccess.retrieveOperationsForAllAccesses((function(_this) { 35 | return function(err) { 36 | if (err != null) { 37 | console.log("An error occurred during access check -- " + err); 38 | } 39 | console.log("Bank accesses checked."); 40 | return _this.prepareNextCheck(); 41 | }; 42 | })(this)); 43 | }; 44 | 45 | return AccountsPoller; 46 | 47 | })(); 48 | 49 | module.exports = new AccountsPoller; 50 | -------------------------------------------------------------------------------- /build/server/models/bankalert.js: -------------------------------------------------------------------------------- 1 | // Generated by CoffeeScript 1.8.0 2 | var BankAlert, americano; 3 | 4 | americano = require('americano'); 5 | 6 | module.exports = BankAlert = americano.getModel('bankalert', { 7 | bankAccount: String, 8 | type: String, 9 | frequency: String, 10 | limit: Number, 11 | order: String 12 | }); 13 | 14 | BankAlert.all = function(callback) { 15 | return BankAlert.request("all", callback); 16 | }; 17 | 18 | BankAlert.allFromBankAccount = function(account, callback) { 19 | var params; 20 | params = { 21 | key: account.id 22 | }; 23 | return BankAlert.request("allByBankAccount", params, callback); 24 | }; 25 | 26 | BankAlert.allByAccountAndType = function(accountID, type, callback) { 27 | var params; 28 | params = { 29 | key: [accountID, type] 30 | }; 31 | return BankAlert.request("allByBankAccountAndType", params, callback); 32 | }; 33 | 34 | BankAlert.allReportsByFrequency = function(frequency, callback) { 35 | var params; 36 | params = { 37 | key: ["report", frequency] 38 | }; 39 | return BankAlert.request("allReportsByFrequency", params, callback); 40 | }; 41 | 42 | BankAlert.destroyByAccount = function(id, callback) { 43 | return BankAlert.requestDestroy("allByBankAccount", { 44 | key: id 45 | }, callback); 46 | }; 47 | 48 | BankAlert.prototype.testTransaction = function(operation) { 49 | var alertLimit, amount; 50 | if (this.type !== "transaction") { 51 | return false; 52 | } else { 53 | alertLimit = Number(this.limit); 54 | amount = Math.abs(operation.amount); 55 | return (this.order === "lt" && amount <= alertLimit) || (this.order === "gt" && amount >= alertLimit); 56 | } 57 | }; 58 | 59 | BankAlert.prototype.testBalance = function(account) { 60 | var alertLimit, balance; 61 | if (this.type !== "balance") { 62 | return false; 63 | } else { 64 | alertLimit = Number(this.limit); 65 | balance = account.getBalance(); 66 | return (this.order === "lt" && balance <= alertLimit) || (this.order === "gt" && balance >= alertLimit); 67 | } 68 | }; 69 | -------------------------------------------------------------------------------- /build/server/models/bankoperation.js: -------------------------------------------------------------------------------- 1 | // Generated by CoffeeScript 1.8.0 2 | var BankOperation, americano; 3 | 4 | americano = require('americano'); 5 | 6 | module.exports = BankOperation = americano.getModel('bankoperation', { 7 | bankAccount: String, 8 | title: String, 9 | date: Date, 10 | amount: Number, 11 | raw: String, 12 | dateImport: Date 13 | }); 14 | 15 | BankOperation.all = function(callback) { 16 | return BankOperation.request("all", callback); 17 | }; 18 | 19 | BankOperation.allFromBankAccount = function(account, callback) { 20 | var params; 21 | params = { 22 | key: account.id 23 | }; 24 | return BankOperation.request("allByBankAccount", params, callback); 25 | }; 26 | 27 | BankOperation.allFromBankAccounts = function(accountNums, callback) { 28 | var params; 29 | params = { 30 | keys: accountNums 31 | }; 32 | return BankOperation.request("allByBankAccount", params, callback); 33 | }; 34 | 35 | BankOperation.allFromBankAccountDate = function(account, callback) { 36 | var params; 37 | params = { 38 | startkey: [account.accountNumber + "0"], 39 | endkey: [account.accountNumber], 40 | descending: true 41 | }; 42 | return BankOperation.request("allByBankAccountAndDate", params, callback); 43 | }; 44 | 45 | BankOperation.allLike = function(operation, callback) { 46 | var date, params; 47 | date = new Date(operation.date).toISOString(); 48 | params = { 49 | key: [operation.bankAccount, date, operation.amount, operation.raw] 50 | }; 51 | return BankOperation.request("allLike", params, callback); 52 | }; 53 | 54 | BankOperation.destroyByAccount = function(accountNum, callback) { 55 | return BankOperation.requestDestroy("allByBankAccount", { 56 | key: accountNum 57 | }, callback); 58 | }; 59 | -------------------------------------------------------------------------------- /build/server/models/cozyinstance.js: -------------------------------------------------------------------------------- 1 | // Generated by CoffeeScript 1.8.0 2 | var CozyInstance, americano; 3 | 4 | americano = require('americano'); 5 | 6 | module.exports = CozyInstance = americano.getModel('CozyInstance', { 7 | domain: String, 8 | helpUrl: String, 9 | locale: String 10 | }); 11 | 12 | CozyInstance.getInstance = function(callback) { 13 | return CozyInstance.request('all', function(err, instances) { 14 | if (err) { 15 | return callback(err, null); 16 | } else if (!((instances != null) && instances.length > 0)) { 17 | return callback(new Error('No instance parameters found', null)); 18 | } else { 19 | return callback(null, instances[0]); 20 | } 21 | }); 22 | }; 23 | -------------------------------------------------------------------------------- /build/tests/controllers/bankalerts.js: -------------------------------------------------------------------------------- 1 | // Generated by CoffeeScript 1.8.0 2 | var client, fixtures, helpers, path, should; 3 | 4 | should = require('should'); 5 | 6 | path = require('path'); 7 | 8 | fixtures = require('cozy-fixtures'); 9 | 10 | fixtures.setDefaultValues({ 11 | dirPath: path.resolve(__dirname, '../fixtures/'), 12 | silent: true, 13 | removeBeforeLoad: false 14 | }); 15 | 16 | helpers = require('../helpers'); 17 | 18 | client = helpers.getClient(); 19 | 20 | describe("Bank Alerts Controller", function() { 21 | before(helpers.cleanDBWithRequests); 22 | before(helpers.startApp); 23 | after(helpers.stopApp); 24 | after(helpers.cleanDBWithRequests); 25 | describe("When I add bank alerts", function() { 26 | describe("When I retrieve them", function() { 27 | it("The response should be a success"); 28 | return it("There should be x bank alerts"); 29 | }); 30 | describe("When I retrieve one of them", function() { 31 | it("The response should be a success"); 32 | return it("The alert should have the correct values"); 33 | }); 34 | describe("When I update one of them", function() { 35 | it("The response should be a success"); 36 | return it("The alert in the database should be updated"); 37 | }); 38 | describe("When I destroy one of them", function() { 39 | it("The response should be a success"); 40 | return it("The alert shouldn't be in the database anymore"); 41 | }); 42 | return describe("When I retrieve the alerts for a given bank account", function() { 43 | it("The response should be a success"); 44 | return it("There should be x bank alerts"); 45 | }); 46 | }); 47 | return describe("When I create a bank alert", function() { 48 | it("The response should be a success"); 49 | return it("It should be in the database"); 50 | }); 51 | }); 52 | -------------------------------------------------------------------------------- /build/tests/fixtures/banks-mesinfos.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "docType": "Bank", 4 | "name": "Société Générale", 5 | "uuid": "societegenerale" 6 | }, 7 | { 8 | "docType": "Bank", 9 | "name": "La Banque Postale", 10 | "uuid": "bp" 11 | }, 12 | { 13 | "docType": "Bank", 14 | "name": "Crédit Coopératif", 15 | "uuid": "creditcooperatif" 16 | } 17 | ] 18 | -------------------------------------------------------------------------------- /build/tests/fixtures/weboob/accounts.js: -------------------------------------------------------------------------------- 1 | // Generated by CoffeeScript 1.8.0 2 | var bank, banks, output, _i, _len; 3 | 4 | banks = require('../banks-all.json'); 5 | 6 | output = {}; 7 | 8 | for (_i = 0, _len = banks.length; _i < _len; _i++) { 9 | bank = banks[_i]; 10 | output[bank.uuid] = [ 11 | { 12 | "accountNumber": "1234567890", 13 | "label": "Compte bancaire", 14 | "balance": "150" 15 | }, { 16 | "accountNumber": "0987654321", 17 | "label": "Livret A", 18 | "balance": "500" 19 | } 20 | ]; 21 | } 22 | 23 | module.exports = output; 24 | -------------------------------------------------------------------------------- /build/tests/helpers.js: -------------------------------------------------------------------------------- 1 | // Generated by CoffeeScript 1.8.0 2 | var Client, client, fixtures, helpers, initializeApplication; 3 | 4 | fixtures = require('cozy-fixtures'); 5 | 6 | Client = require('request-json').JsonClient; 7 | 8 | module.exports = helpers = {}; 9 | 10 | helpers.options = {}; 11 | 12 | helpers.app = null; 13 | 14 | if (process.env.COVERAGE) { 15 | helpers.prefix = '../instrumented/'; 16 | } else if (process.env.USE_JS) { 17 | helpers.prefix = '../build/'; 18 | } else { 19 | helpers.prefix = '../'; 20 | } 21 | 22 | helpers.options = { 23 | serverHost: process.env.HOST || 'localhost', 24 | serverPort: process.env.PORT || 9875 25 | }; 26 | 27 | process.env.HOST = helpers.options.serverHost; 28 | 29 | process.env.PORT = helpers.options.serverPort; 30 | 31 | client = new Client("http://" + helpers.options.serverHost + ":" + helpers.options.serverPort + "/", { 32 | jar: true 33 | }); 34 | 35 | helpers.getClient = function() { 36 | return client; 37 | }; 38 | 39 | initializeApplication = require("" + helpers.prefix + "server"); 40 | 41 | helpers.startApp = function(done) { 42 | this.timeout(15000); 43 | return initializeApplication((function(_this) { 44 | return function(app, server) { 45 | _this.app = app; 46 | _this.app.server = server; 47 | return done(); 48 | }; 49 | })(this)); 50 | }; 51 | 52 | helpers.stopApp = function(done) { 53 | this.timeout(10000); 54 | return this.app.server.close(done); 55 | }; 56 | 57 | helpers.cleanDB = function(done) { 58 | this.timeout(10000); 59 | return fixtures.resetDatabase({ 60 | callback: done 61 | }); 62 | }; 63 | 64 | helpers.cleanDBWithRequests = function(done) { 65 | this.timeout(10000); 66 | return fixtures.resetDatabase({ 67 | removeAllRequests: true, 68 | callback: done 69 | }); 70 | }; 71 | -------------------------------------------------------------------------------- /build/tests/mock-weboob.js: -------------------------------------------------------------------------------- 1 | // Generated by CoffeeScript 1.8.0 2 | var accounts, nock, operations, options; 3 | 4 | if ((process.env.NODE_ENV == null) || process.env.NODE_ENV !== 'production') { 5 | nock = require('nock'); 6 | options = { 7 | allowUnmocked: true 8 | }; 9 | accounts = nock('http://localhost:9101', options).persist().log(console.log).defaultReplyHeaders({ 10 | 'content-type': 'application/json; charset=utf-8' 11 | }).filteringPath(/bank\/[a-z]+\//g, 'bank/societegenerale/').filteringRequestBody(function(path) { 12 | return { 13 | "login": "12345", 14 | "password": "54321" 15 | }; 16 | }).post('/connectors/bank/societegenerale/', { 17 | "login": "12345", 18 | "password": "54321" 19 | }).reply(200, require('./fixtures/weboob/accounts')); 20 | operations = nock('http://localhost:9101', options).persist().log(console.log).defaultReplyHeaders({ 21 | 'content-type': 'application/json; charset=utf-8' 22 | }).filteringPath(/bank\/[a-z]+\//g, 'bank/societegenerale/').filteringRequestBody(function(path) { 23 | return { 24 | "login": "12345", 25 | "password": "54321" 26 | }; 27 | }).post('/connectors/bank/societegenerale/history', { 28 | "login": "12345", 29 | "password": "54321" 30 | }).reply(200, require('./fixtures/weboob/operations')); 31 | } 32 | -------------------------------------------------------------------------------- /client/.gitignore: -------------------------------------------------------------------------------- 1 | # Numerous always-ignore extensions 2 | *.diff 3 | *.err 4 | *.orig 5 | *.log 6 | *.rej 7 | *.swo 8 | *.swp 9 | *.vi 10 | *~ 11 | *.sass-cache 12 | 13 | # OS or Editor folders 14 | .DS_Store 15 | .cache 16 | .project 17 | .settings 18 | .tmproj 19 | nbproject 20 | Thumbs.db 21 | 22 | # NPM packages folder. 23 | node_modules/ 24 | 25 | # Brunch folder for temporary files. 26 | tmp/ 27 | -------------------------------------------------------------------------------- /client/app/application.coffee: -------------------------------------------------------------------------------- 1 | AppView = require 'views/app' 2 | 3 | BanksCollection = require 'collections/banks' 4 | BankOperationsCollection = require 'collections/bank_operations' 5 | 6 | module.exports = 7 | 8 | initialize: -> 9 | 10 | $.ajax('cozy-locale.json') 11 | .done( (data) => @locale = data.locale ) 12 | .fail( () => @locale = 'en' ) 13 | .always( () => @step2() ) 14 | 15 | step2: -> 16 | 17 | # internationalisation 18 | @polyglot = new Polyglot() 19 | window.polyglot = @polyglot 20 | try 21 | locales = require "locales/#{@locale}" 22 | catch e 23 | locales = require 'locales/en' 24 | 25 | @polyglot.extend locales 26 | window.t = @polyglot.t.bind @polyglot 27 | window.i18n = (key) -> window.polyglot.t key 28 | 29 | # collections, views 30 | window.collections = {} 31 | window.views = {} 32 | 33 | # banks, operations 34 | window.collections.allBanks = new BanksCollection() 35 | window.collections.banks = new BanksCollection() 36 | window.collections.operations = new BankOperationsCollection() 37 | 38 | ### 39 | views 40 | ### 41 | # this one is tricky - it lays down the structure, so it needs to be rendered 42 | # before any other view using that structure 43 | window.views.appView = new AppView() 44 | window.views.appView.render() 45 | 46 | window.activeObjects = {} 47 | _.extend(window.activeObjects, Backbone.Events); 48 | 49 | # Routing management 50 | Router = require 'router' 51 | @router = new Router() 52 | #Backbone.history.start() 53 | 54 | # Makes this object immuable. 55 | Object.freeze this if typeof Object.freeze is 'function' 56 | -------------------------------------------------------------------------------- /client/app/assets/asc.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/seeker89/cozy-pfm/3e17567625fe81eb879255a4cdbc7d83f374614f/client/app/assets/asc.gif -------------------------------------------------------------------------------- /client/app/assets/bg.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/seeker89/cozy-pfm/3e17567625fe81eb879255a4cdbc7d83f374614f/client/app/assets/bg.gif -------------------------------------------------------------------------------- /client/app/assets/crossdomain.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 15 | 16 | -------------------------------------------------------------------------------- /client/app/assets/desc.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/seeker89/cozy-pfm/3e17567625fe81eb879255a4cdbc7d83f374614f/client/app/assets/desc.gif -------------------------------------------------------------------------------- /client/app/assets/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/seeker89/cozy-pfm/3e17567625fe81eb879255a4cdbc7d83f374614f/client/app/assets/favicon.ico -------------------------------------------------------------------------------- /client/app/assets/fonts/fontawesome/FontAwesome.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/seeker89/cozy-pfm/3e17567625fe81eb879255a4cdbc7d83f374614f/client/app/assets/fonts/fontawesome/FontAwesome.ttf -------------------------------------------------------------------------------- /client/app/assets/fonts/fontawesome/README.md: -------------------------------------------------------------------------------- 1 | #Font Awesome 2.0 2 | ##the iconic font designed for use with Twitter Bootstrap 3 | 4 | The full suite of pictographic icons, examples, and documentation can be found at: 5 | http://fortawesome.github.com/Font-Awesome/ 6 | 7 | ##Contact 8 | - Email: dave@davegandy.com 9 | - Twitter: http://twitter.com/fortaweso_me 10 | - Work: Lead Product Designer @ http://kyru.us 11 | 12 | ##License 13 | Version 2.0 of the Font Awesome font, CSS, and LESS files are licensed under CC BY 3.0: 14 | http://creativecommons.org/licenses/by/3.0/ 15 | A mention of 'Font Awesome - http://fortawesome.github.com/Font-Awesome' 16 | in human-readable source code is considered acceptable attribution (most common on the 17 | web). If human readable source code is not available to the end user, a mention in an 'About' 18 | or 'Credits' screen is considered acceptable (most common in desktop or mobile software). 19 | -------------------------------------------------------------------------------- /client/app/assets/fonts/fontawesome/fontawesome-webfont.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/seeker89/cozy-pfm/3e17567625fe81eb879255a4cdbc7d83f374614f/client/app/assets/fonts/fontawesome/fontawesome-webfont.eot -------------------------------------------------------------------------------- /client/app/assets/fonts/fontawesome/fontawesome-webfont.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/seeker89/cozy-pfm/3e17567625fe81eb879255a4cdbc7d83f374614f/client/app/assets/fonts/fontawesome/fontawesome-webfont.ttf -------------------------------------------------------------------------------- /client/app/assets/fonts/fontawesome/fontawesome-webfont.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/seeker89/cozy-pfm/3e17567625fe81eb879255a4cdbc7d83f374614f/client/app/assets/fonts/fontawesome/fontawesome-webfont.woff -------------------------------------------------------------------------------- /client/app/assets/fonts/fontello.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/seeker89/cozy-pfm/3e17567625fe81eb879255a4cdbc7d83f374614f/client/app/assets/fonts/fontello.ttf -------------------------------------------------------------------------------- /client/app/assets/fonts/glyphicons-halflings-regular.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/seeker89/cozy-pfm/3e17567625fe81eb879255a4cdbc7d83f374614f/client/app/assets/fonts/glyphicons-halflings-regular.eot -------------------------------------------------------------------------------- /client/app/assets/fonts/glyphicons-halflings-regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/seeker89/cozy-pfm/3e17567625fe81eb879255a4cdbc7d83f374614f/client/app/assets/fonts/glyphicons-halflings-regular.ttf -------------------------------------------------------------------------------- /client/app/assets/fonts/glyphicons-halflings-regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/seeker89/cozy-pfm/3e17567625fe81eb879255a4cdbc7d83f374614f/client/app/assets/fonts/glyphicons-halflings-regular.woff -------------------------------------------------------------------------------- /client/app/assets/fonts/maven-pro-light-100.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/seeker89/cozy-pfm/3e17567625fe81eb879255a4cdbc7d83f374614f/client/app/assets/fonts/maven-pro-light-100.otf -------------------------------------------------------------------------------- /client/app/assets/fonts/maven-pro-light-200.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/seeker89/cozy-pfm/3e17567625fe81eb879255a4cdbc7d83f374614f/client/app/assets/fonts/maven-pro-light-200.otf -------------------------------------------------------------------------------- /client/app/assets/fonts/maven-pro-light-300.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/seeker89/cozy-pfm/3e17567625fe81eb879255a4cdbc7d83f374614f/client/app/assets/fonts/maven-pro-light-300.otf -------------------------------------------------------------------------------- /client/app/assets/fonts/signika-bold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/seeker89/cozy-pfm/3e17567625fe81eb879255a4cdbc7d83f374614f/client/app/assets/fonts/signika-bold.ttf -------------------------------------------------------------------------------- /client/app/assets/fonts/signika-light.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/seeker89/cozy-pfm/3e17567625fe81eb879255a4cdbc7d83f374614f/client/app/assets/fonts/signika-light.ttf -------------------------------------------------------------------------------- /client/app/assets/fonts/signika-regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/seeker89/cozy-pfm/3e17567625fe81eb879255a4cdbc7d83f374614f/client/app/assets/fonts/signika-regular.ttf -------------------------------------------------------------------------------- /client/app/assets/humans.txt: -------------------------------------------------------------------------------- 1 | # humanstxt.org/ 2 | # The humans responsible & technology colophon 3 | 4 | # TEAM 5 | 6 | -- -- 7 | 8 | # THANKS 9 | 10 | 11 | 12 | # TECHNOLOGY COLOPHON 13 | 14 | HTML5, CSS3 15 | jQuery, Modernizr, 16 | Lodash, Backbone, 17 | Handlebars, Coffeescript, 18 | Stylus, Brunch 19 | -------------------------------------------------------------------------------- /client/app/assets/icons/main_icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/seeker89/cozy-pfm/3e17567625fe81eb879255a4cdbc7d83f374614f/client/app/assets/icons/main_icon.png -------------------------------------------------------------------------------- /client/app/assets/images/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/seeker89/cozy-pfm/3e17567625fe81eb879255a4cdbc7d83f374614f/client/app/assets/images/.gitkeep -------------------------------------------------------------------------------- /client/app/assets/images/Melamine-wood-003.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/seeker89/cozy-pfm/3e17567625fe81eb879255a4cdbc7d83f374614f/client/app/assets/images/Melamine-wood-003.png -------------------------------------------------------------------------------- /client/app/assets/images/arrow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/seeker89/cozy-pfm/3e17567625fe81eb879255a4cdbc7d83f374614f/client/app/assets/images/arrow.png -------------------------------------------------------------------------------- /client/app/assets/images/arrow_vertical.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/seeker89/cozy-pfm/3e17567625fe81eb879255a4cdbc7d83f374614f/client/app/assets/images/arrow_vertical.png -------------------------------------------------------------------------------- /client/app/assets/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | Cozy PFM 10 | 11 | 12 | 17 | 18 | 19 | 20 | 21 | 22 | 25 | 26 | 27 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /client/app/assets/loader.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/seeker89/cozy-pfm/3e17567625fe81eb879255a4cdbc7d83f374614f/client/app/assets/loader.gif -------------------------------------------------------------------------------- /client/app/assets/loader_big_blue.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/seeker89/cozy-pfm/3e17567625fe81eb879255a4cdbc7d83f374614f/client/app/assets/loader_big_blue.gif -------------------------------------------------------------------------------- /client/app/assets/loader_green.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/seeker89/cozy-pfm/3e17567625fe81eb879255a4cdbc7d83f374614f/client/app/assets/loader_green.gif -------------------------------------------------------------------------------- /client/app/assets/loader_inverse.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/seeker89/cozy-pfm/3e17567625fe81eb879255a4cdbc7d83f374614f/client/app/assets/loader_inverse.gif -------------------------------------------------------------------------------- /client/app/assets/pdf/factureSFR.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/seeker89/cozy-pfm/3e17567625fe81eb879255a4cdbc7d83f374614f/client/app/assets/pdf/factureSFR.pdf -------------------------------------------------------------------------------- /client/app/assets/pdf/factureSNCF.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/seeker89/cozy-pfm/3e17567625fe81eb879255a4cdbc7d83f374614f/client/app/assets/pdf/factureSNCF.pdf -------------------------------------------------------------------------------- /client/app/assets/robots.txt: -------------------------------------------------------------------------------- 1 | # robotstxt.org/ 2 | 3 | User-agent: * 4 | -------------------------------------------------------------------------------- /client/app/collections/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/seeker89/cozy-pfm/3e17567625fe81eb879255a4cdbc7d83f374614f/client/app/collections/.gitkeep -------------------------------------------------------------------------------- /client/app/collections/bank_accesses.coffee: -------------------------------------------------------------------------------- 1 | BankAccess = require '../models/bank_access' 2 | 3 | module.exports = class BankAccesses extends Backbone.Collection 4 | 5 | model: BankAccess 6 | url: "bankaccesses" 7 | -------------------------------------------------------------------------------- /client/app/collections/bank_accounts.coffee: -------------------------------------------------------------------------------- 1 | BankAccount = require '../models/bank_account' 2 | 3 | module.exports = class BankAccounts extends Backbone.Collection 4 | 5 | model: BankAccount 6 | url: "bankaccounts" 7 | 8 | constructor: (@bank) -> 9 | @url = "banks/getAccounts/" + @bank.get("id") 10 | super() 11 | 12 | getSum: -> 13 | sum = 0 14 | for account in @models 15 | sum += Number(account.get("amount")) 16 | sum 17 | -------------------------------------------------------------------------------- /client/app/collections/bank_alerts.coffee: -------------------------------------------------------------------------------- 1 | BankAlert = require '../models/bank_alert' 2 | 3 | module.exports = class BankAlerts extends Backbone.Collection 4 | 5 | model: BankAlert 6 | url: "bankalerts" 7 | -------------------------------------------------------------------------------- /client/app/collections/bank_operations.coffee: -------------------------------------------------------------------------------- 1 | BankOperation = require '../models/bank_operation' 2 | 3 | module.exports = class BankOperations extends Backbone.Collection 4 | 5 | model: BankOperation 6 | url: "bankoperations" 7 | 8 | order: "asc" 9 | orderBy: "date" 10 | 11 | setAccount: (@account) -> 12 | @url = "bankaccounts/getOperations/" + @account.get("id") 13 | #console.log @url 14 | 15 | setComparator: (type) -> 16 | if type == "date" 17 | # sorting by date and then title 18 | @comparator = (o1, o2) => 19 | d1 = new Date(o1.get("date")).getTime() 20 | d2 = new Date(o2.get("date")).getTime() 21 | 22 | t1 = o1.get("title") 23 | t2 = o2.get("title") 24 | 25 | sort = if @order == "asc" then -1 else 1 26 | 27 | if d1 == d2 28 | if t1 > t2 then return sort 29 | if t1 < t2 then return -sort 30 | return 0 31 | else if d1 > d2 32 | return sort 33 | else 34 | return -sort 35 | 36 | else 37 | @orderBy = type 38 | @comparator = (o1, o2) -> 39 | 40 | t1 = o1.get @orderBy 41 | t2 = o2.get @orderBy 42 | 43 | sort = if @order == "asc" then -1 else 1 44 | 45 | if t1 == t2 46 | return 0 47 | else if t1 > t2 48 | return sort 49 | else 50 | return -sort 51 | 52 | toggleSort: (order) -> 53 | if @orderBy == order 54 | @order = if @order == "asc" then "desc" else "asc" 55 | else 56 | @orderBy = order 57 | 58 | -------------------------------------------------------------------------------- /client/app/collections/banks.coffee: -------------------------------------------------------------------------------- 1 | Bank = require '../models/bank' 2 | 3 | module.exports = class Banks extends Backbone.Collection 4 | 5 | model: Bank 6 | url: "banks" 7 | 8 | getSum: -> 9 | sum = 0 10 | for bank in @models 11 | sum += Number(bank.get("amount")) 12 | #console.log Number(bank.get("amount")) 13 | sum 14 | -------------------------------------------------------------------------------- /client/app/initialize.coffee: -------------------------------------------------------------------------------- 1 | app = require 'application' 2 | # The function called from index.html 3 | $ -> 4 | require 'lib/app_helpers' 5 | 6 | # init 7 | ### 8 | global variables 9 | ### 10 | # app, for nasty tricks 11 | window.app = app 12 | app.initialize() 13 | -------------------------------------------------------------------------------- /client/app/lib/app_helpers.coffee: -------------------------------------------------------------------------------- 1 | (() -> 2 | # IIFE to avoid collisions with other variables 3 | (-> 4 | # Make it safe to do console.log() always. 5 | console = window.console = window.console or {} 6 | method = undefined 7 | dummy = -> 8 | methods = ('assert,count,debug,dir,dirxml,error,exception, 9 | group,groupCollapsed,groupEnd,info,log,markTimeline, 10 | profile,profileEnd,time,timeEnd,trace,warn').split ',' 11 | 12 | console[method] = console[method] or dummy while method = methods.pop() 13 | )() 14 | )() 15 | 16 | Number::formatMoney = (decPlaces, thouSeparator, decSeparator) -> 17 | n = this 18 | decPlaces = (if isNaN(decPlaces = Math.abs(decPlaces)) then 2 else decPlaces) 19 | decSeparator = (if decSeparator is `undefined` then "." else decSeparator) 20 | thouSeparator = (if thouSeparator is `undefined` then "," else thouSeparator) 21 | sign = (if n < 0 then "-" else "") 22 | i = parseInt(n = Math.abs(+n or 0).toFixed(decPlaces)) + "" 23 | j = (if (j = i.length) > 3 then j % 3 else 0) 24 | sign + ((if j then i.substr(0, j) + thouSeparator else "")) + i.substr(j).replace(/(\d{3})(?=\d)/g, "$1" + thouSeparator) + ((if decPlaces then decSeparator + Math.abs(n - i).toFixed(decPlaces).slice(2) else "")) 25 | 26 | Number::money = -> 27 | @formatMoney(2, " ", ",") 28 | 29 | Date::dateString = -> 30 | addZeros = (num) -> 31 | if Number(num) < 10 32 | "0" + num 33 | else 34 | num 35 | myDate = @ 36 | addZeros(myDate.getDate() + 1) + "/" + addZeros(myDate.getMonth() + 1) + "/" + myDate.getFullYear() 37 | 38 | Date::timeString = -> 39 | addZeros = (num) -> 40 | if Number(num) < 10 41 | "0" + num 42 | else 43 | num 44 | myDate = @ 45 | addZeros(myDate.getHours()) + ":" + addZeros(myDate.getMinutes()) 46 | -------------------------------------------------------------------------------- /client/app/lib/base_view.coffee: -------------------------------------------------------------------------------- 1 | module.exports = class BaseView extends Backbone.View 2 | 3 | template: -> 4 | 5 | initialize: -> 6 | 7 | getRenderData: -> 8 | model: @model 9 | 10 | render: -> 11 | @beforeRender() 12 | @$el.html @template(@getRenderData()) 13 | @afterRender() 14 | @ 15 | 16 | beforeRender: -> 17 | 18 | afterRender: -> 19 | 20 | destroy: -> 21 | @undelegateEvents() 22 | @$el.removeData().unbind() 23 | @remove() 24 | Backbone.View::remove.call @ 25 | -------------------------------------------------------------------------------- /client/app/models/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/seeker89/cozy-pfm/3e17567625fe81eb879255a4cdbc7d83f374614f/client/app/models/.gitkeep -------------------------------------------------------------------------------- /client/app/models/bank.coffee: -------------------------------------------------------------------------------- 1 | BankAccountsCollection = require '../collections/bank_accounts' 2 | 3 | module.exports = class Bank extends Backbone.Model 4 | 5 | defaults: 6 | amount: 0 7 | 8 | checked: true 9 | 10 | initialize: -> 11 | @accounts = new BankAccountsCollection @ 12 | @listenTo @accounts, "add", @updateAmount 13 | @listenTo @accounts, "remove", @updateAmount 14 | @listenTo @accounts, "destroy", @updateAmount 15 | @listenTo @accounts, "change", @updateAmount 16 | 17 | updateAmount: -> 18 | @set("amount", @accounts.getSum()) 19 | console.log "updated balance bank " + @get("name") + " is now " + @get("amount") 20 | -------------------------------------------------------------------------------- /client/app/models/bank_access.coffee: -------------------------------------------------------------------------------- 1 | module.exports = class BankAccess extends Backbone.Model 2 | 3 | url: "bankaccesses" 4 | -------------------------------------------------------------------------------- /client/app/models/bank_account.coffee: -------------------------------------------------------------------------------- 1 | BankOperationsCollection = require '../collections/bank_operations' 2 | 3 | module.exports = class BankAccount extends Backbone.Model 4 | 5 | checked: true 6 | -------------------------------------------------------------------------------- /client/app/models/bank_alert.coffee: -------------------------------------------------------------------------------- 1 | module.exports = class BankAlert extends Backbone.Model 2 | 3 | url: "bankalerts" 4 | -------------------------------------------------------------------------------- /client/app/models/bank_operation.coffee: -------------------------------------------------------------------------------- 1 | module.exports = class BankOperation extends Backbone.Model 2 | -------------------------------------------------------------------------------- /client/app/router.coffee: -------------------------------------------------------------------------------- 1 | MockupView = require 'views/mockup' 2 | AppView = require 'views/app' 3 | BalanceView = require 'views/balance' 4 | 5 | module.exports = class Router extends Backbone.Router 6 | 7 | empty: -> 8 | window.views.balanceView?.empty() 9 | window.views.accountsView?.empty() 10 | window.views.searchView?.empty() 11 | 12 | routes: 13 | '': 'balance' 14 | 'accounts': 'accounts' 15 | 'search' : 'search' 16 | 17 | balance: -> 18 | @empty() 19 | window.views.balanceView?.render() 20 | $(".menu-position").removeClass("active") 21 | $(".menu-1").addClass("active") 22 | 23 | search: -> 24 | @empty() 25 | window.views.searchView?.render() 26 | $(".menu-position").removeClass("active") 27 | $(".menu-2").addClass("active") 28 | 29 | accounts: -> 30 | @empty() 31 | window.views.accountsView?.render() 32 | $(".menu-position").removeClass("active") 33 | $(".menu-3").addClass("active") 34 | -------------------------------------------------------------------------------- /client/app/views/accounts.coffee: -------------------------------------------------------------------------------- 1 | BaseView = require '../lib/base_view' 2 | AccountsBankView = require './accounts_bank' 3 | 4 | module.exports = class AccountsView extends BaseView 5 | 6 | template: require('./templates/accounts') 7 | 8 | el: 'div#content' 9 | elBanks: '.content-right-column' 10 | 11 | subViews: [] 12 | 13 | render: -> 14 | 15 | # load the template 16 | super() 17 | 18 | # prepare the banks list 19 | for bank in window.collections.banks.models 20 | view = new AccountsBankView bank 21 | @subViews.push view 22 | @$(@elBanks).append view.render().el 23 | 24 | # TODO - fix the compability issue with niceScroll 25 | #@$('#layout-2col-column-right').niceScroll() 26 | @ 27 | 28 | empty: -> 29 | for view in @subViews 30 | view.destroy() -------------------------------------------------------------------------------- /client/app/views/accounts_alerts_alert.coffee: -------------------------------------------------------------------------------- 1 | BaseView = require '../lib/base_view' 2 | BankAlert = require '../models/bank_alert' 3 | 4 | module.exports = class AccountsAlertsAlertView extends BaseView 5 | 6 | template: require "./templates/accounts_alerts_alert" 7 | 8 | events: 9 | "click .reports-save" : "save" 10 | "click .reports-cancel" : "destroy" 11 | "click .reports-delete" : "removeAlert" 12 | "click .reports-edit" : "edit" 13 | 14 | constructor: (@alert, @parent) -> 15 | super() 16 | 17 | initialize: -> 18 | 19 | save: -> 20 | view = @ 21 | 22 | # get the data 23 | if @alert.get("type") == "report" 24 | @alert.set "frequency", @$(".reports-frequency").val() 25 | else 26 | @alert.set "order", @$(".reports-order").val() 27 | valLimit = @$(".reports-limit").val() 28 | valLimit = valLimit.replace(" ", "").replace(",",".") # stripping all non digits 29 | @alert.set "limit", Number(valLimit) 30 | 31 | # save the report to the server 32 | @alert.save {}, 33 | success: -> 34 | console.log "Alert saved to server" 35 | view.render() 36 | error: -> 37 | console.log "error" 38 | 39 | removeAlert: -> 40 | 41 | view = @ 42 | 43 | @alert.url = "bankalerts/" + @alert.get("id") 44 | @alert.destroy 45 | success: -> 46 | console.log "Alert deleted from server" 47 | view.destroy() 48 | error: -> 49 | console.log "error" 50 | 51 | render: -> 52 | # lay down the template 53 | @$el.html @template 54 | model: @alert 55 | @ 56 | -------------------------------------------------------------------------------- /client/app/views/app.coffee: -------------------------------------------------------------------------------- 1 | BaseView = require '../lib/base_view' 2 | 3 | NavbarView = require 'views/navbar' 4 | NewBankView = require 'views/new_bank' 5 | 6 | AccountsView = require 'views/accounts' 7 | BalanceView = require 'views/balance' 8 | SearchView = require 'views/search' 9 | 10 | 11 | module.exports = class AppView extends BaseView 12 | 13 | template: require('./templates/app') 14 | 15 | el: 'body.application' 16 | 17 | afterRender: -> 18 | 19 | # init - get the necessary data 20 | window.collections.banks.fetch 21 | data: 22 | withAccountOnly: true 23 | success: -> 24 | 25 | window.collections.allBanks.fetch 26 | success: -> 27 | if not @navbarView 28 | @navbarView = new NavbarView() 29 | if not @newbankView 30 | @newbankView = new NewBankView() 31 | if not window.views.balanceView 32 | window.views.balanceView = new BalanceView() 33 | if not window.views.accountsView 34 | window.views.accountsView = new AccountsView() 35 | if not window.views.searchView 36 | window.views.searchView = new SearchView() 37 | 38 | @navbarView.render() 39 | @newbankView.render() 40 | 41 | # start routing 42 | Backbone.history.start() 43 | error: -> 44 | 45 | # could not get banks, or 0 banks available - fatal error 46 | console.log "Fatal error: could not get the banks list" 47 | alert window.i18n "fatal_error" 48 | 49 | -------------------------------------------------------------------------------- /client/app/views/balance_bank.coffee: -------------------------------------------------------------------------------- 1 | BaseView = require '../lib/base_view' 2 | BankTitleView = require './bank_title' 3 | BankSubTitleView = require './bank_subtitle' 4 | 5 | module.exports = class BalanceBankView extends BaseView 6 | 7 | className: 'bank' 8 | 9 | sum: 0 10 | 11 | subViews: [] 12 | 13 | constructor: (@bank) -> 14 | super() 15 | 16 | initialize: -> 17 | @listenTo @bank.accounts, "add", @addOne 18 | @listenTo @bank.accounts, "destroy", @render 19 | 20 | addOne: (account) -> 21 | # add the account 22 | viewAccount = new BankSubTitleView account 23 | @subViews.push viewAccount 24 | account.view = viewAccount 25 | @$el.append viewAccount.render().el 26 | 27 | render: -> 28 | 29 | # generate the title 30 | @viewTitle = new BankTitleView @bank 31 | @$el.html @viewTitle.render().el 32 | @viewTitle = null 33 | @sum = 0 34 | 35 | # add accounts 36 | for account in @bank.accounts.models 37 | @addOne account 38 | @ 39 | 40 | destroy: -> 41 | @viewTitle?.destroy() 42 | for view in @subViews 43 | view.destroy() 44 | super() -------------------------------------------------------------------------------- /client/app/views/balance_operation.coffee: -------------------------------------------------------------------------------- 1 | BaseView = require '../lib/base_view' 2 | 3 | module.exports = class BalanceOperationView extends BaseView 4 | 5 | template: require './templates/balance_operations_element' 6 | 7 | tagName: 'tr' 8 | 9 | constructor: (@model, @account, @showAccountNum = false) -> 10 | super() 11 | 12 | fakeFeatureLink: -> 13 | if @model.get('title') is "SNCF" and @model.get('amount') is -137.00 14 | return 'pdf/factureSNCF.pdf' 15 | else if @model.get('title') is "SFR Facture" 16 | return 'pdf/factureSFR.pdf' 17 | else return null 18 | 19 | render: -> 20 | if @model.get("amount") > 0 21 | @$el.addClass "success" 22 | @model.account = @account 23 | @model.formattedDate = moment(@model.get('date')).format "DD/MM/YYYY" 24 | formattedAmount = @fakeFeatureLink() 25 | @model.formattedAmount = formattedAmount unless formattedAmount is null 26 | 27 | if @showAccountNum 28 | hint = "#{@model.account.get('title')}, " + \ 29 | "n°#{@model.account.get('accountNumber')}" 30 | @model.hint = "#{@model.account.get('title')}, " + \ 31 | "n°#{@model.account.get('accountNumber')}" 32 | else 33 | @model.hint = "#{@model.get('raw')}" 34 | super() 35 | @ -------------------------------------------------------------------------------- /client/app/views/bank_subtitle.coffee: -------------------------------------------------------------------------------- 1 | BaseView = require '../lib/base_view' 2 | 3 | module.exports = class BankSubTitleView extends BaseView 4 | 5 | template: require('./templates/balance_bank_subtitle') 6 | 7 | constructor: (@model) -> 8 | super() 9 | 10 | events: 11 | "click .row" : "chooseAccount" 12 | 13 | initialize: -> 14 | @listenTo @model, 'change', @render 15 | @listenTo window.activeObjects, 'changeActiveAccount', @checkActive 16 | 17 | chooseAccount: (event) -> 18 | console.log "Account chosen: " + @model.get("title") 19 | window.activeObjects.trigger "changeActiveAccount", @model 20 | 21 | checkActive: (account) -> 22 | @$(".row").removeClass("active") 23 | if account == @model 24 | @$(".row").addClass("active") 25 | -------------------------------------------------------------------------------- /client/app/views/bank_title.coffee: -------------------------------------------------------------------------------- 1 | BaseView = require '../lib/base_view' 2 | 3 | module.exports = class BankTitleView extends BaseView 4 | 5 | template: require('./templates/balance_bank_title') 6 | 7 | constructor: (@model) -> 8 | super() 9 | 10 | initialize: -> 11 | @listenTo @model, 'change', @update 12 | @listenTo @model.accounts, "add", @update 13 | @listenTo @model.accounts, "destroy", @update 14 | @listenTo @model.accounts, "request", @displayLoading 15 | @listenTo @model.accounts, "change", @hideLoading 16 | 17 | displayLoading: -> 18 | @$(".bank-title-loading").show() 19 | 20 | hideLoading: -> 21 | @$(".bank-title-loading").hide() 22 | 23 | update: -> 24 | # update the sum 25 | @model.set("amount", @model.accounts.getSum()) 26 | @$(".bank-amount").html Number(@model.get('amount')).money() 27 | 28 | # display or hide the bank title 29 | if @model.accounts.length == 0 30 | @$(".bank-title").hide() 31 | @$(".bank-balance").hide() 32 | else 33 | @$(".bank-title").show() 34 | @$(".bank-balance").show() 35 | 36 | # hide loader 37 | @$(".bank-title-loading").hide() 38 | 39 | render: -> 40 | super() 41 | @update() 42 | @ -------------------------------------------------------------------------------- /client/app/views/mockup.coffee: -------------------------------------------------------------------------------- 1 | BaseView = require '../lib/base_view' 2 | 3 | 4 | module.exports = class AppView extends BaseView 5 | 6 | template: require('./templates/mockup_balance') 7 | 8 | el: 'body.application' 9 | 10 | afterRender: -> 11 | $('.content-right-column').niceScroll() 12 | -------------------------------------------------------------------------------- /client/app/views/navbar.coffee: -------------------------------------------------------------------------------- 1 | BaseView = require '../lib/base_view' 2 | 3 | 4 | module.exports = class NavbarView extends BaseView 5 | 6 | template: require('./templates/navbar') 7 | 8 | el: 'div#navbar' 9 | 10 | initialize: -> 11 | @listenTo window.collections.banks, "change", @refreshOverallBalance 12 | @listenTo window.collections.banks, 'destroy', @refreshOverallBalance 13 | @listenTo window.collections.banks, 'update', @refreshOverallBalance 14 | @listenTo window.collections.banks, 'reset', @refreshOverallBalance 15 | 16 | refreshOverallBalance: -> 17 | sum = window.collections.banks.getSum() 18 | console.log "recalculating the overall balance: " + sum 19 | $("span#total-amount").html sum.money() 20 | -------------------------------------------------------------------------------- /client/app/views/search_bank.coffee: -------------------------------------------------------------------------------- 1 | BaseView = require '../lib/base_view' 2 | SearchBankTitleView = require './search_bank_title' 3 | SearchBankSubTitleView = require './search_bank_subtitle' 4 | 5 | module.exports = class SearchBankView extends BaseView 6 | 7 | className: 'bank' 8 | 9 | events: 10 | "change .choice-bank" : "bankChange" 11 | 12 | viewsAccount: [] 13 | 14 | constructor: (@bank) -> 15 | super() 16 | 17 | initialize: -> 18 | @listenTo @bank.accounts, "add", @addOne 19 | @listenTo @bank.accounts, "destroy", @render 20 | 21 | bankChange: (event) -> 22 | 23 | enabled = @$(event.target).prop("checked") 24 | console.log "[Search] " + @bank.get("name") + ": " + enabled 25 | 26 | # check/uncheck all 27 | $.each @$("input[type=checkbox].choice-account"), (index, element) -> 28 | $(element).prop "checked", enabled 29 | for account in @bank.accounts.models 30 | account.checked = enabled 31 | 32 | # mark the entire bank as checked 33 | @bank.checked = enabled 34 | 35 | # and fire "update" on accounts 36 | window.collections.banks.trigger "search-update-accounts" 37 | 38 | addOne: (account) -> 39 | # add the account 40 | viewAccount = new SearchBankSubTitleView account 41 | @viewsAccount.push viewAccount 42 | account.view = viewAccount 43 | @$el.append viewAccount.render().el 44 | 45 | render: -> 46 | 47 | # generate the title 48 | @viewTitle = new SearchBankTitleView @bank 49 | @$el.html @viewTitle.render().el 50 | @viewTitle = null 51 | @sum = 0 52 | 53 | # add accounts 54 | for account in @bank.accounts.models 55 | @addOne account 56 | @ 57 | 58 | destroy: -> 59 | @viewTitle?.destroy() 60 | for viewAccount in @viewsAccount 61 | viewAccount.destroy() 62 | super() 63 | -------------------------------------------------------------------------------- /client/app/views/search_bank_subtitle.coffee: -------------------------------------------------------------------------------- 1 | BaseView = require '../lib/base_view' 2 | 3 | module.exports = class SearchBankSubTitleView extends BaseView 4 | 5 | template: require('./templates/search_bank_subtitle') 6 | 7 | constructor: (@model) -> 8 | super() 9 | 10 | events: 11 | "change .choice-account" : "accountChange" 12 | 13 | accountChange: (event) -> 14 | 15 | # get the value 16 | enabled = @$(event.target).prop("checked") 17 | console.log "[Search] " + @model.get("title") + ": " + enabled 18 | 19 | # mark the account as checked 20 | @model.checked = enabled 21 | 22 | # and fire "update" on accounts 23 | window.collections.banks.trigger "search-update-accounts" 24 | 25 | initialize: -> 26 | @listenTo @model, 'change', @render 27 | -------------------------------------------------------------------------------- /client/app/views/search_bank_title.coffee: -------------------------------------------------------------------------------- 1 | BaseView = require '../lib/base_view' 2 | 3 | module.exports = class SearchBankTitleView extends BaseView 4 | 5 | template: require('./templates/search_bank_title') 6 | 7 | constructor: (@model) -> 8 | super() 9 | 10 | initialize: -> 11 | @listenTo @model.accounts, "add", @update 12 | @listenTo @model.accounts, "destroy", @update 13 | @listenTo @model.accounts, "request", @displayLoading 14 | @listenTo @model.accounts, "change", @hideLoading 15 | 16 | displayLoading: -> 17 | @$(".bank-title-loading").show() 18 | 19 | hideLoading: -> 20 | @$(".bank-title-loading").hide() 21 | 22 | update: -> 23 | 24 | # display or hide the bank title 25 | if @model.accounts.length == 0 26 | @$(".bank-title").hide() 27 | @$(".bank-title-checkbox").hide() 28 | else 29 | @$(".bank-title").show() 30 | @$(".bank-title-checkbox").show() 31 | 32 | # hide loader 33 | @$(".bank-title-loading").hide() 34 | 35 | render: -> 36 | super() 37 | @update() 38 | @ -------------------------------------------------------------------------------- /client/app/views/styles/_base.styl: -------------------------------------------------------------------------------- 1 | // Base Styles 2 | 3 | * 4 | box-sizing: border-box 5 | 6 | html, 7 | body 8 | height 100% 9 | width 100% 10 | 11 | body 12 | text-rendering optimizeLegibility 13 | 14 | body, 15 | input 16 | color #444 17 | font 300 16px Geneva, Verdana, "Lucida Sans", "Lucida Grande", "Lucida Sans Unicode", sans-serif 18 | line-height 1.2 19 | 20 | a, 21 | a:visited 22 | color #0086cc 23 | text-decoration none 24 | 25 | &:hover 26 | text-decoration underline 27 | -------------------------------------------------------------------------------- /client/app/views/styles/_colors.styl: -------------------------------------------------------------------------------- 1 | basecolor = #34A6FF 2 | basecolor-alpha = rgba(49, 156, 256, 0.5) 3 | 4 | contrastcolor = #5C5 5 | contrastcolor-alpha = #5C5 6 | 7 | 8 | actioncolor = #fe8800 9 | actioncolor-alpha = rgba(254,128,0,0.5) -------------------------------------------------------------------------------- /client/app/views/styles/_responsive.styl: -------------------------------------------------------------------------------- 1 | @media screen and (max-width: 480px) 2 | // Landscape phones and down 3 | 4 | body 5 | text-rendering optimizeSpeed 6 | 7 | .content-left-column 8 | height 30% 9 | 10 | .content-right-column 11 | height 70% 12 | 13 | @media screen and (max-width: 767px) 14 | // Landscape phone to portrait tablet 15 | 16 | body 17 | text-rendering optimizeSpeed 18 | 19 | .content-left-column 20 | height 30% 21 | 22 | .content-right-column 23 | height 70% 24 | 25 | @media screen and (min-width: 768px) and (max-width: 1200px) 26 | // Portrait tablet to landscape and desktop 27 | 28 | .content-left-column 29 | height 30% 30 | 31 | .content-right-column 32 | height 70% 33 | 34 | @media screen and (min-width: 1200px) 35 | // Desktop 36 | 37 | .content-left-column, .content-right-column 38 | height 100% 39 | -------------------------------------------------------------------------------- /client/app/views/styles/_states.styl: -------------------------------------------------------------------------------- 1 | [data-state~="default"], 2 | [data-state~="enabled"] 3 | cursor inherit 4 | opacity 1 5 | transition opacity 0.2s linear 6 | 7 | [data-state~="disabled"], 8 | cursor not-allowed 9 | opacity 0.5 10 | transition opacity 0.2s linear 11 | 12 | [data-state~="hidden"] 13 | display none 14 | 15 | [data-state~="visible"] 16 | visibility visible 17 | 18 | [data-state~="invisible"] 19 | visibility hidden 20 | 21 | [data-state~="waiting"], 22 | [data-state~="loading"] 23 | cursor wait 24 | 25 | [data-state~="success"], 26 | [data-state~="valid"] 27 | border-color #82cf82 28 | color #82cf82 29 | transition color 0.2s linear, border-color 0.2s linear 30 | 31 | [data-state~="error"], 32 | [data-state~="invalid"] 33 | border-color #f0dddd 34 | color #f0dddd 35 | transition color 0.2s linear, border-color 0.2s linear 36 | -------------------------------------------------------------------------------- /client/app/views/styles/application.styl: -------------------------------------------------------------------------------- 1 | // nib is a powerful lib for stylus that provides cross-browser css3 mixins. 2 | @import 'nib' 3 | 4 | @import '_responsive' 5 | 6 | @import '_main' 7 | -------------------------------------------------------------------------------- /client/app/views/templates/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/seeker89/cozy-pfm/3e17567625fe81eb879255a4cdbc7d83f374614f/client/app/views/templates/.gitkeep -------------------------------------------------------------------------------- /client/app/views/templates/accounts.jade: -------------------------------------------------------------------------------- 1 | .row.content-background 2 | .col-lg-12.content-right-column -------------------------------------------------------------------------------- /client/app/views/templates/accounts_alerts.jade: -------------------------------------------------------------------------------- 1 | #reports-dialog.modal.fade 2 | .modal-dialog 3 | .modal-content 4 | .modal-header 5 | button.close(type='button', data-dismiss='modal', aria-hidden='true') x 6 | h4.modal-title 7 | | #{window.i18n("accounts_alerts_title")} 8 | .modal-body 9 | h3 10 | | #{window.i18n("accounts_alerts_title_periodic")} 11 | div#reports-body-periodic 12 | p 13 | a.btn.btn-small.btn-cozy.reports-add-periodic #{window.i18n("accounts_alerts_periodic_add")} 14 | 15 | 16 | h3 17 | | #{window.i18n("accounts_alerts_title_balance")} 18 | div#reports-body-amount 19 | p 20 | a.btn.btn-small.btn-cozy.reports-add-amount #{window.i18n("accounts_alerts_balance_add")} 21 | 22 | 23 | h3 24 | | #{window.i18n("accounts_alerts_title_transaction")} 25 | div#reports-body-transaction 26 | p 27 | a.btn.btn-small.btn-cozy.reports-add-transaction #{window.i18n("accounts_alerts_transaction_add")} 28 | 29 | -------------------------------------------------------------------------------- /client/app/views/templates/accounts_bank.jade: -------------------------------------------------------------------------------- 1 | h2 #{model.get("name")} 2 | a.btn.btn-cozy.pull-right.delete-bank 3 | | #{window.i18n("accounts_delete_bank")} 4 | table.table-accounts.table.table-striped.table-hover.table-bordered 5 | tbody#account-container 6 | -------------------------------------------------------------------------------- /client/app/views/templates/accounts_bank_account.jade: -------------------------------------------------------------------------------- 1 | td.account-title #{model.get("title")} 2 | td.account-title 3 | span.account-details n°#{model.get("accountNumber")} 4 | td 5 | span.text-right 6 | a.btn.btn-small.btn-cozy.pull-right.alert-management 7 | | manage reports and notifications 8 | td 9 | span.text-right 10 | a.btn.btn-small.btn-cozy.pull-right.delete-account 11 | | #{window.i18n("accounts_delete_account")} -------------------------------------------------------------------------------- /client/app/views/templates/app.jade: -------------------------------------------------------------------------------- 1 | // navigation bar 2 | #navbar.navbar.navbar-fixed-top.navbar-inverse 3 | 4 | // modal window to add a new bank 5 | #add-bank-window.modal.fade 6 | 7 | // content 8 | #content.container 9 | -------------------------------------------------------------------------------- /client/app/views/templates/balance_bank_subtitle.jade: -------------------------------------------------------------------------------- 1 | .row.accounts-sub 2 | .pull-left 3 | p.pull-left #{model.get('title')} 4 | br 5 | span.account-details n°#{model.get("accountNumber")} 6 | .pull-right 7 | p.pull-right #{Number(model.get('amount')).money()} 8 | span.euro-sign € 9 | -------------------------------------------------------------------------------- /client/app/views/templates/balance_bank_title.jade: -------------------------------------------------------------------------------- 1 | .row.accounts-top 2 | .col-lg-7 3 | p.pull-left 4 | span.bank-title-loading 5 | img(src="./loader.gif") 6 | span.bank-title #{model.get('name')} 7 | .col-lg-5 8 | p.pull-right.bank-balance 9 | span.bank-amount #{Number(model.get('amount')).money()} 10 | span.euro-sign € 11 | -------------------------------------------------------------------------------- /client/app/views/templates/balance_banks_empty.jade: -------------------------------------------------------------------------------- 1 | p.arrow.text-right 2 | img(src="images/arrow_vertical.png") 3 | p.loading 4 | | #{window.i18n("balance_banks_empty")} 5 | -------------------------------------------------------------------------------- /client/app/views/templates/balance_operations_element.jade: -------------------------------------------------------------------------------- 1 | td.operation-date #{model.formattedDate} 2 | td.operation-title 3 | .hint--top(data-hint="#{model.hint}") 4 | span.infobulle.glyphicon.glyphicon-info-sign 5 | | #{model.get('title')} 6 | td.operation-amount.text-right 7 | - if(model.formattedAmount == null) 8 | | #{Number(model.get('amount')).money()} 9 | - else 10 | a(href="#{model.formattedAmount}", target="_blank") 11 | | #{Number(model.get('amount')).money()} -------------------------------------------------------------------------------- /client/app/views/templates/balance_operations_empty.jade: -------------------------------------------------------------------------------- 1 | br 2 | br 3 | p.loading 4 | | #{window.i18n("balance_please_choose_account")} -------------------------------------------------------------------------------- /client/app/views/templates/balance_operations_header.jade: -------------------------------------------------------------------------------- 1 | h2 #{model.get("title")} 2 | p 3 | span.last-checked #{window.i18n("balance_last_checked")} #{moment(moment(model.get("lastChecked"))).fromNow()}. 4 | a.recheck-button.btn-link #{window.i18n("balance_recheck_now")} 5 | 6 | .text-center.loading.loader-operations 7 | img(src="./loader_big_blue.gif") 8 | 9 | table.table.tablesorter.table-striped.table-hover 10 | thead 11 | tr 12 | th.sort-date.text-left #{window.i18n("header_date")} 13 | th.sort-title.text-center #{window.i18n("header_title")} 14 | th.sort-amount.text-right #{window.i18n("header_amount")} 15 | tbody#table-operations 16 | -------------------------------------------------------------------------------- /client/app/views/templates/layout-2col.jade: -------------------------------------------------------------------------------- 1 | .row.content-background 2 | #layout-2col-column-left.col-lg-4.content-left-column 3 | 4 | #layout-2col-column-right.col-lg-8.content-right-column 5 | -------------------------------------------------------------------------------- /client/app/views/templates/modal_confirm.jade: -------------------------------------------------------------------------------- 1 | #confirmation-dialog.modal.fade 2 | .modal-dialog 3 | .modal-content 4 | .modal-header 5 | button.close(type='button', data-dismiss='modal', aria-hidden='true') x 6 | h4.modal-title 7 | | #{title} 8 | .modal-body 9 | p 10 | | #{body} 11 | .modal-footer 12 | a.btn.btn-link(data-dismiss='modal',href='#') #{window.i18n("cancel")} 13 | a#confirmation-dialog-confirm.btn.btn-cozy(href='#') #{confirm} 14 | 15 | -------------------------------------------------------------------------------- /client/app/views/templates/navbar.jade: -------------------------------------------------------------------------------- 1 | nav.navbar.navbar-inverse.navbar-fixed-top(role='navigation') 2 | .container 3 | // Brand and toggle get grouped for better mobile display 4 | .navbar-header 5 | button.navbar-toggle(type='button', data-toggle='collapse', data-target='.navbar-collapse') 6 | span.sr-only Toggle navigation 7 | span.icon-bar 8 | span.icon-bar 9 | span.icon-bar 10 | // Collect the nav links, forms, and other content for toggling 11 | .collapse.navbar-collapse 12 | ul.nav.navbar-nav 13 | li.menu-position.menu-1 14 | a#menu-pos-balance(href='#') #{window.i18n("menu_balance")} 15 | li.menu-position.menu-2 16 | a#menu-pos-accounts(href='#search') #{window.i18n("menu_search")} 17 | li.menu-position.menu-3 18 | a#menu-pos-accounts(href='#accounts') #{window.i18n("menu_accounts")} 19 | li 20 | a#menu-pos-new-bank(data-toggle='modal', href='#add-bank-window') #{window.i18n("menu_add_bank")} 21 | 22 | ul.nav.navbar-nav.navbar-right 23 | p.navbar-text 24 | | #{window.i18n("overall_balance")} 25 | span#total-amount 0,00 -------------------------------------------------------------------------------- /client/app/views/templates/new_bank.jade: -------------------------------------------------------------------------------- 1 | .modal-dialog 2 | .modal-content 3 | .modal-header 4 | button.close(type='button', data-dismiss='modal', aria-hidden='true') x 5 | h4.modal-title 6 | | #{window.i18n("menu_add_bank")} 7 | .modal-body 8 | .message-modal 9 | form 10 | fieldset 11 | legend 12 | | #{window.i18n("add_bank_bank")} 13 | .form-group 14 | select#inputBank.form-control 15 | each bank in banks 16 | option(value=bank.get("uuid")) 17 | =bank.get("name") 18 | 19 | #formInputWebsite.form-group.hide 20 | label(for='inputWebsite') 21 | | #{window.i18n("add_bank_website")} 22 | select#inputWebsite.form-control 23 | 24 | fieldset 25 | legend 26 | | #{window.i18n("add_bank_credentials")} 27 | .form-group 28 | label(for='inputLogin') 29 | | #{window.i18n("add_bank_login")} 30 | input#inputLogin.form-control(type='text', placeholder=window.i18n("add_bank_login_placeholder")) 31 | .form-group 32 | label(for='inputPass') 33 | | #{window.i18n("add_bank_password")} 34 | input#inputPass.form-control(type='password', placeholder=window.i18n("add_bank_password_placeholder")) 35 | h3.important-notice 36 | | #{window.i18n("add_bank_security_notice")} 37 | p 38 | | #{window.i18n("add_bank_security_notice_text")} 39 | .modal-footer 40 | a.btn.btn-link(data-dismiss='modal',href='#') #{window.i18n("add_bank_cancel")} 41 | a#btn-add-bank-save.btn.btn-success(href='#') #{window.i18n("add_bank_ok")} 42 | -------------------------------------------------------------------------------- /client/app/views/templates/search_bank_subtitle.jade: -------------------------------------------------------------------------------- 1 | .row.accounts-sub 2 | .col-lg-7 3 | p.pull-left #{model.get('title')} 4 | .col-lg-5 5 | p.pull-right 6 | if model.checked 7 | input(type="checkbox", checked).choice-account 8 | else 9 | input(type="checkbox").choice-account 10 | -------------------------------------------------------------------------------- /client/app/views/templates/search_bank_title.jade: -------------------------------------------------------------------------------- 1 | .row.accounts-top 2 | .col-lg-7 3 | p.pull-left 4 | span.bank-title-loading 5 | img(src="./loader.gif") 6 | span.bank-title 7 | | #{model.get('name')} 8 | .col-lg-5 9 | p.pull-right.bank-title-checkbox 10 | if model.checked 11 | input(type="checkbox", checked).choice-bank 12 | else 13 | input(type="checkbox").choice-bank -------------------------------------------------------------------------------- /client/app/views/templates/search_operations.jade: -------------------------------------------------------------------------------- 1 | form.form-search 2 | .row 3 | .col-lg-6 4 | .form-group 5 | label(for='search-date-from') 6 | | #{window.i18n("search_date_from")} 7 | input#search-date-from.form-control(type='date') 8 | .col-lg-6 9 | .form-group 10 | label(for='search-date-to') 11 | | #{window.i18n("search_date_to")} 12 | input#search-date-to.form-control(type='date') 13 | 14 | .row 15 | .col-lg-6 16 | .form-group 17 | label(for='search-amount-from') 18 | | #{window.i18n("search_amount_from")} 19 | input#search-amount-from.form-control(type='number') 20 | .col-lg-6 21 | .form-group 22 | label(for='search-amount-to') 23 | | #{window.i18n("search_amount_to")} 24 | input#search-amount-to.form-control(type='number') 25 | 26 | .row 27 | .col-lg-12 28 | label(for='search-text') 29 | | #{window.i18n("search_text")} 30 | input#search-text.form-control(type='text') 31 | 32 | .row 33 | .col-lg-12#search-operations-table 34 | -------------------------------------------------------------------------------- /client/app/views/templates/search_operations_table_header.jade: -------------------------------------------------------------------------------- 1 | br 2 | table#search-table.table.tablesorter.table-striped.table-hover 3 | thead 4 | tr 5 | th.sort-date.text-left #{window.i18n("header_date")} 6 | th.sort-title.text-center #{window.i18n("header_title")} 7 | th.sort-amount.text-right #{window.i18n("header_amount")} 8 | tbody#search-operations-table-body 9 | -------------------------------------------------------------------------------- /client/config.coffee: -------------------------------------------------------------------------------- 1 | exports.config = 2 | # See docs at http://brunch.readthedocs.org/en/latest/config.html. 3 | #coffeelint: 4 | #pattern: /^app\/.*\.coffee$/ 5 | #options: 6 | #indentation: 7 | #value: 4 8 | #level: "error" 9 | 10 | files: 11 | javascripts: 12 | joinTo: 13 | 'javascripts/app.js': /^app/ 14 | 'javascripts/vendor.js': /^vendor/ 15 | order: 16 | # Files in `vendor` directories are compiled before other files 17 | # even if they aren't specified in order. 18 | before: [ 19 | 'vendor/scripts/jquery-1.10.2.js' 20 | 'vendor/scripts/underscore-1.4.4.js' 21 | 'vendor/scripts/backbone-1.0.0.js' 22 | 'vendor/scripts/jquery.dataTables.js' 23 | ] 24 | 25 | stylesheets: 26 | joinTo: 'stylesheets/app.css' 27 | order: 28 | before: ['vendor/styles/normalize.css'] 29 | after: ['vendor/styles/helpers.css'] 30 | 31 | templates: 32 | defaultExtension: 'jade' 33 | joinTo: 'javascripts/app.js' 34 | -------------------------------------------------------------------------------- /client/generators/collection/collection.coffee.hbs: -------------------------------------------------------------------------------- 1 | module.exports = class {{#camelize}}{{pluralName}}{{/camelize}}Collection extends Backbone.Collection 2 | model: require '../models/{{name}}' 3 | url: '{{name}}s/' 4 | -------------------------------------------------------------------------------- /client/generators/collection/generator.json: -------------------------------------------------------------------------------- 1 | { 2 | "files": [{ 3 | "from": "collection.coffee.hbs", 4 | "to": "app/collections/{{pluralName}}.coffee" 5 | }], 6 | "dependencies": [{ 7 | "name": "collection_test", 8 | "params": "{{pluralName}}" 9 | }] 10 | } 11 | -------------------------------------------------------------------------------- /client/generators/collection_test/collection_test.coffee.hbs: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/seeker89/cozy-pfm/3e17567625fe81eb879255a4cdbc7d83f374614f/client/generators/collection_test/collection_test.coffee.hbs -------------------------------------------------------------------------------- /client/generators/collection_test/generator.json: -------------------------------------------------------------------------------- 1 | { 2 | "files": [{ 3 | "from": "collection_test.coffee.hbs", 4 | "to": "test/collections/{{pluralName}}_test.coffee" 5 | }], 6 | "dependencies": [] 7 | } 8 | -------------------------------------------------------------------------------- /client/generators/generator/generated_file.coffee.hbs: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/seeker89/cozy-pfm/3e17567625fe81eb879255a4cdbc7d83f374614f/client/generators/generator/generated_file.coffee.hbs -------------------------------------------------------------------------------- /client/generators/generator/generator.json: -------------------------------------------------------------------------------- 1 | { 2 | "files": [ 3 | { 4 | "from": "generator.json.hbs", 5 | "to": "generators/{{name}}/generator.json" 6 | }, 7 | { 8 | "from": "generated_file.coffee.hbs", 9 | "to": "generators/{{name}}/{{name}}.coffee.hbs" 10 | } 11 | ], 12 | "dependencies": [] 13 | } 14 | -------------------------------------------------------------------------------- /client/generators/generator/generator.json.hbs: -------------------------------------------------------------------------------- 1 | { 2 | "files": [{ 3 | "from": "{{name}}.coffee.hbs", 4 | "to": "app/file.coffee" 5 | }], 6 | "dependencies": [] 7 | } 8 | -------------------------------------------------------------------------------- /client/generators/model/generator.json: -------------------------------------------------------------------------------- 1 | { 2 | "files": [{ 3 | "from": "model.coffee.hbs", 4 | "to": "app/models/{{name}}.coffee" 5 | }], 6 | "dependencies": [{ 7 | "name": "model_test", 8 | "params": "{{name}}" 9 | }] 10 | } 11 | -------------------------------------------------------------------------------- /client/generators/model/model.coffee.hbs: -------------------------------------------------------------------------------- 1 | module.exports = class {{#camelize}}{{name}}{{/camelize}}Model extends Backbone.Model 2 | rootUrl: "{{name}}s/" -------------------------------------------------------------------------------- /client/generators/model_test/generator.json: -------------------------------------------------------------------------------- 1 | { 2 | "files": [{ 3 | "from": "model_test.coffee.hbs", 4 | "to": "test/models/{{name}}.coffee" 5 | }], 6 | "dependencies": [] 7 | } 8 | -------------------------------------------------------------------------------- /client/generators/model_test/model_test.coffee.hbs: -------------------------------------------------------------------------------- 1 | {{#camelize}}{{name}}{{/camelize}}Model = require 'models/{{name}}' 2 | 3 | describe '{{#camelize}}{{name}}{{/camelize}}Model', -> 4 | beforeEach -> 5 | @model = new {{#camelize}}{{name}}{{/camelize}}Model() 6 | -------------------------------------------------------------------------------- /client/generators/module/collection.coffee.hbs: -------------------------------------------------------------------------------- 1 | module.exports = class {{#camelize}}{{pluralName}}{{/camelize}}Collection extends Backbone.Collection 2 | model: require '../models/{{name}}' 3 | url: '{{name}}s/' 4 | -------------------------------------------------------------------------------- /client/generators/module/generator.json: -------------------------------------------------------------------------------- 1 | { 2 | "files": [ 3 | { 4 | "from": "model.coffee.hbs", 5 | "to": "app/models/{{name}}.coffee" 6 | }, 7 | { 8 | "from": "view.coffee.hbs", 9 | "to": "app/views/{{name}}.coffee" 10 | }, 11 | { 12 | "from": "collection.coffee.hbs", 13 | "to": "app/collections/{{name}}s.coffee" 14 | }, 15 | { 16 | "from": "template.jade.hbs", 17 | "to": "app/views/templates/{{name}}.jade" 18 | }, 19 | { 20 | "from": "style.styl.hbs", 21 | "to": "app/views/styles/_{{name}}.styl" 22 | }, 23 | { 24 | "from": "view_collection.coffee.hbs", 25 | "to": "app/views/{{name}}s.coffee" 26 | } 27 | ], 28 | "dependencies": [] 29 | } 30 | -------------------------------------------------------------------------------- /client/generators/module/model.coffee.hbs: -------------------------------------------------------------------------------- 1 | module.exports = class {{#camelize}}{{name}}{{/camelize}}Model extends Backbone.Model 2 | rootUrl: "{{name}}s/" -------------------------------------------------------------------------------- /client/generators/module/style.styl.hbs: -------------------------------------------------------------------------------- 1 | .{{name}} 2 | // {{#camelize}}{{name}}{{/camelize}} Module 3 | 4 | -------------------------------------------------------------------------------- /client/generators/module/template.jade.hbs: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /client/generators/module/view.coffee.hbs: -------------------------------------------------------------------------------- 1 | BaseView = require '../lib/base_view' 2 | 3 | module.exports = class {{#camelize}}{{name}}{{/camelize}}View extends BaseView 4 | template: require './templates/{{name}}' 5 | className: '{{name}}' 6 | -------------------------------------------------------------------------------- /client/generators/module/view_collection.coffee.hbs: -------------------------------------------------------------------------------- 1 | ViewCollection = require '../lib/view_collection' 2 | {{#camelize}}{{name}}{{/camelize}}sCollection = require '../collections/{{name}}s' 3 | {{#camelize}}{{name}}{{/camelize}}View = require './{{name}}' 4 | 5 | module.exports = class {{#camelize}}{{name}}{{/camelize}}sView extends ViewCollection 6 | el: '#{{name}}s' 7 | 8 | collection: new {{#camelize}}{{name}}{{/camelize}}sCollection() 9 | itemview: {{#camelize}}{{name}}{{/camelize}}View 10 | 11 | afterRender: -> 12 | @collection.on 'reset', => 13 | @renderAll() 14 | @collection.on 'add', (model) => 15 | @renderOne model 16 | -------------------------------------------------------------------------------- /client/generators/style/generator.json: -------------------------------------------------------------------------------- 1 | { 2 | "files": [{ 3 | "from": "style.styl.hbs", 4 | "to": "app/views/styles/_{{name}}.styl" 5 | }], 6 | "dependencies": [] 7 | } 8 | -------------------------------------------------------------------------------- /client/generators/style/style.styl.hbs: -------------------------------------------------------------------------------- 1 | .{{name}} 2 | // {{#camelize}}{{name}}{{/camelize}} Module 3 | -------------------------------------------------------------------------------- /client/generators/template/generator.json: -------------------------------------------------------------------------------- 1 | { 2 | "files": [{ 3 | "from": "template.hbs.hbs", 4 | "to": "app/views/templates/{{name}}.jade" 5 | }], 6 | "dependencies": [] 7 | } 8 | -------------------------------------------------------------------------------- /client/generators/template/template.hbs: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /client/generators/view/generator.json: -------------------------------------------------------------------------------- 1 | { 2 | "files": [{ 3 | "from": "view.coffee.hbs", 4 | "to": "app/views/{{name}}.coffee" 5 | }], 6 | "dependencies": [{ 7 | "name": "view_test", 8 | "params": "{{name}}" 9 | }] 10 | } 11 | -------------------------------------------------------------------------------- /client/generators/view/view.coffee.hbs: -------------------------------------------------------------------------------- 1 | BaseView = require '../lib/base_view' 2 | 3 | module.exports = class {{#camelize}}{{name}}{{/camelize}}View extends BaseView 4 | template: require './templates/{{name}}' 5 | className: '{{name}}' 6 | -------------------------------------------------------------------------------- /client/generators/view_test/generator.json: -------------------------------------------------------------------------------- 1 | { 2 | "files": [ 3 | { 4 | "from": "view_test.coffee.hbs", 5 | "to": "test/views/{{name}}.coffee" 6 | } 7 | ], 8 | "dependencies": [] 9 | } 10 | -------------------------------------------------------------------------------- /client/generators/view_test/view_test.coffee.hbs: -------------------------------------------------------------------------------- 1 | {{#camelize}}{{name}}{{/camelize}}View = require 'views/{{name}}' 2 | 3 | describe '{{#camelize}}{{name}}{{/camelize}}View', -> 4 | beforeEach -> 5 | @view = new {{#camelize}}{{name}}{{/camelize}}View() 6 | -------------------------------------------------------------------------------- /client/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "author": "Your Name", 3 | "name": "package-name", 4 | "description": "Package description", 5 | "version": "0.0.1", 6 | "homepage": "", 7 | "repository": { 8 | "type": "git", 9 | "url": "" 10 | }, 11 | "engines": { 12 | "node": "~0.6.10 || 0.8 || 0.9" 13 | }, 14 | "scripts": { 15 | "start": "brunch watch --server" 16 | }, 17 | "dependencies": { 18 | "javascript-brunch": "> 1.0 < 1.5", 19 | "coffee-script-brunch": "> 1.0 < 1.5", 20 | 21 | "css-brunch": "> 1.0 < 1.5", 22 | "stylus-brunch": "> 1.0 < 1.5", 23 | 24 | "jade-brunch": "> 1.0 < 1.5", 25 | 26 | "uglify-js-brunch": "> 1.0 < 1.5", 27 | "clean-css-brunch": "> 1.0 < 1.5", 28 | 29 | "auto-reload-brunch": "> 1.0 < 1.5", 30 | 31 | "async": ">= 0" 32 | }, 33 | "devDependencies": { 34 | "mocha": "0.14.0", 35 | "expect.js": "0.1.2", 36 | "ws": "0.4.21" 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /client/public/asc.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/seeker89/cozy-pfm/3e17567625fe81eb879255a4cdbc7d83f374614f/client/public/asc.gif -------------------------------------------------------------------------------- /client/public/bg.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/seeker89/cozy-pfm/3e17567625fe81eb879255a4cdbc7d83f374614f/client/public/bg.gif -------------------------------------------------------------------------------- /client/public/crossdomain.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 15 | 16 | -------------------------------------------------------------------------------- /client/public/desc.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/seeker89/cozy-pfm/3e17567625fe81eb879255a4cdbc7d83f374614f/client/public/desc.gif -------------------------------------------------------------------------------- /client/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/seeker89/cozy-pfm/3e17567625fe81eb879255a4cdbc7d83f374614f/client/public/favicon.ico -------------------------------------------------------------------------------- /client/public/fonts/fontawesome/FontAwesome.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/seeker89/cozy-pfm/3e17567625fe81eb879255a4cdbc7d83f374614f/client/public/fonts/fontawesome/FontAwesome.ttf -------------------------------------------------------------------------------- /client/public/fonts/fontawesome/README.md: -------------------------------------------------------------------------------- 1 | #Font Awesome 2.0 2 | ##the iconic font designed for use with Twitter Bootstrap 3 | 4 | The full suite of pictographic icons, examples, and documentation can be found at: 5 | http://fortawesome.github.com/Font-Awesome/ 6 | 7 | ##Contact 8 | - Email: dave@davegandy.com 9 | - Twitter: http://twitter.com/fortaweso_me 10 | - Work: Lead Product Designer @ http://kyru.us 11 | 12 | ##License 13 | Version 2.0 of the Font Awesome font, CSS, and LESS files are licensed under CC BY 3.0: 14 | http://creativecommons.org/licenses/by/3.0/ 15 | A mention of 'Font Awesome - http://fortawesome.github.com/Font-Awesome' 16 | in human-readable source code is considered acceptable attribution (most common on the 17 | web). If human readable source code is not available to the end user, a mention in an 'About' 18 | or 'Credits' screen is considered acceptable (most common in desktop or mobile software). 19 | -------------------------------------------------------------------------------- /client/public/fonts/fontawesome/fontawesome-webfont.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/seeker89/cozy-pfm/3e17567625fe81eb879255a4cdbc7d83f374614f/client/public/fonts/fontawesome/fontawesome-webfont.eot -------------------------------------------------------------------------------- /client/public/fonts/fontawesome/fontawesome-webfont.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/seeker89/cozy-pfm/3e17567625fe81eb879255a4cdbc7d83f374614f/client/public/fonts/fontawesome/fontawesome-webfont.ttf -------------------------------------------------------------------------------- /client/public/fonts/fontawesome/fontawesome-webfont.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/seeker89/cozy-pfm/3e17567625fe81eb879255a4cdbc7d83f374614f/client/public/fonts/fontawesome/fontawesome-webfont.woff -------------------------------------------------------------------------------- /client/public/fonts/fontello.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/seeker89/cozy-pfm/3e17567625fe81eb879255a4cdbc7d83f374614f/client/public/fonts/fontello.ttf -------------------------------------------------------------------------------- /client/public/fonts/glyphicons-halflings-regular.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/seeker89/cozy-pfm/3e17567625fe81eb879255a4cdbc7d83f374614f/client/public/fonts/glyphicons-halflings-regular.eot -------------------------------------------------------------------------------- /client/public/fonts/glyphicons-halflings-regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/seeker89/cozy-pfm/3e17567625fe81eb879255a4cdbc7d83f374614f/client/public/fonts/glyphicons-halflings-regular.ttf -------------------------------------------------------------------------------- /client/public/fonts/glyphicons-halflings-regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/seeker89/cozy-pfm/3e17567625fe81eb879255a4cdbc7d83f374614f/client/public/fonts/glyphicons-halflings-regular.woff -------------------------------------------------------------------------------- /client/public/fonts/maven-pro-light-100.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/seeker89/cozy-pfm/3e17567625fe81eb879255a4cdbc7d83f374614f/client/public/fonts/maven-pro-light-100.otf -------------------------------------------------------------------------------- /client/public/fonts/maven-pro-light-200.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/seeker89/cozy-pfm/3e17567625fe81eb879255a4cdbc7d83f374614f/client/public/fonts/maven-pro-light-200.otf -------------------------------------------------------------------------------- /client/public/fonts/maven-pro-light-300.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/seeker89/cozy-pfm/3e17567625fe81eb879255a4cdbc7d83f374614f/client/public/fonts/maven-pro-light-300.otf -------------------------------------------------------------------------------- /client/public/fonts/signika-bold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/seeker89/cozy-pfm/3e17567625fe81eb879255a4cdbc7d83f374614f/client/public/fonts/signika-bold.ttf -------------------------------------------------------------------------------- /client/public/fonts/signika-light.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/seeker89/cozy-pfm/3e17567625fe81eb879255a4cdbc7d83f374614f/client/public/fonts/signika-light.ttf -------------------------------------------------------------------------------- /client/public/fonts/signika-regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/seeker89/cozy-pfm/3e17567625fe81eb879255a4cdbc7d83f374614f/client/public/fonts/signika-regular.ttf -------------------------------------------------------------------------------- /client/public/humans.txt: -------------------------------------------------------------------------------- 1 | # humanstxt.org/ 2 | # The humans responsible & technology colophon 3 | 4 | # TEAM 5 | 6 | -- -- 7 | 8 | # THANKS 9 | 10 | 11 | 12 | # TECHNOLOGY COLOPHON 13 | 14 | HTML5, CSS3 15 | jQuery, Modernizr, 16 | Lodash, Backbone, 17 | Handlebars, Coffeescript, 18 | Stylus, Brunch 19 | -------------------------------------------------------------------------------- /client/public/icons/main_icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/seeker89/cozy-pfm/3e17567625fe81eb879255a4cdbc7d83f374614f/client/public/icons/main_icon.png -------------------------------------------------------------------------------- /client/public/images/Melamine-wood-003.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/seeker89/cozy-pfm/3e17567625fe81eb879255a4cdbc7d83f374614f/client/public/images/Melamine-wood-003.png -------------------------------------------------------------------------------- /client/public/images/arrow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/seeker89/cozy-pfm/3e17567625fe81eb879255a4cdbc7d83f374614f/client/public/images/arrow.png -------------------------------------------------------------------------------- /client/public/images/arrow_vertical.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/seeker89/cozy-pfm/3e17567625fe81eb879255a4cdbc7d83f374614f/client/public/images/arrow_vertical.png -------------------------------------------------------------------------------- /client/public/images/glyphicons-halflings-white.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/seeker89/cozy-pfm/3e17567625fe81eb879255a4cdbc7d83f374614f/client/public/images/glyphicons-halflings-white.png -------------------------------------------------------------------------------- /client/public/images/glyphicons-halflings.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/seeker89/cozy-pfm/3e17567625fe81eb879255a4cdbc7d83f374614f/client/public/images/glyphicons-halflings.png -------------------------------------------------------------------------------- /client/public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | Cozy PFM 10 | 11 | 12 | 17 | 18 | 19 | 20 | 21 | 22 | 25 | 26 | 27 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /client/public/loader.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/seeker89/cozy-pfm/3e17567625fe81eb879255a4cdbc7d83f374614f/client/public/loader.gif -------------------------------------------------------------------------------- /client/public/loader_big_blue.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/seeker89/cozy-pfm/3e17567625fe81eb879255a4cdbc7d83f374614f/client/public/loader_big_blue.gif -------------------------------------------------------------------------------- /client/public/loader_green.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/seeker89/cozy-pfm/3e17567625fe81eb879255a4cdbc7d83f374614f/client/public/loader_green.gif -------------------------------------------------------------------------------- /client/public/loader_inverse.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/seeker89/cozy-pfm/3e17567625fe81eb879255a4cdbc7d83f374614f/client/public/loader_inverse.gif -------------------------------------------------------------------------------- /client/public/pdf/factureSFR.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/seeker89/cozy-pfm/3e17567625fe81eb879255a4cdbc7d83f374614f/client/public/pdf/factureSFR.pdf -------------------------------------------------------------------------------- /client/public/pdf/factureSNCF.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/seeker89/cozy-pfm/3e17567625fe81eb879255a4cdbc7d83f374614f/client/public/pdf/factureSNCF.pdf -------------------------------------------------------------------------------- /client/public/robots.txt: -------------------------------------------------------------------------------- 1 | # robotstxt.org/ 2 | 3 | User-agent: * 4 | -------------------------------------------------------------------------------- /client/vendor/scripts/zoomico.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/seeker89/cozy-pfm/3e17567625fe81eb879255a4cdbc7d83f374614f/client/vendor/scripts/zoomico.png -------------------------------------------------------------------------------- /client/vendor/styles/helpers.css: -------------------------------------------------------------------------------- 1 | .chromeframe { margin: 0.2em 0; background: #ccc; color: #000; padding: 0.2em 0; } 2 | .ir { display: block; border: 0; text-indent: -999em; overflow: hidden; background-color: transparent; background-repeat: no-repeat; text-align: left; direction: ltr; *line-height: 0; } 3 | .ir br { display: none; } 4 | .hidden { display: none !important; visibility: hidden; } 5 | .visuallyhidden { border: 0; clip: rect(0 0 0 0); height: 1px; margin: -1px; overflow: hidden; padding: 0; position: absolute; width: 1px; } 6 | .visuallyhidden.focusable:active, .visuallyhidden.focusable:focus { clip: auto; height: auto; margin: 0; overflow: visible; position: static; width: auto; } 7 | .invisible { visibility: hidden; } 8 | .clearfix:before, .clearfix:after { content: ""; display: table; } 9 | .clearfix:after { clear: both; } 10 | .clearfix { *zoom: 1; } 11 | 12 | @media print { 13 | * { background: transparent !important; color: black !important; box-shadow:none !important; text-shadow: none !important; filter:none !important; -ms-filter: none !important; } 14 | a, a:visited { text-decoration: underline; } 15 | a[href]:after { content: " (" attr(href) ")"; } 16 | abbr[title]:after { content: " (" attr(title) ")"; } 17 | .ir a:after, a[href^="javascript:"]:after, a[href^="#"]:after { content: ""; } 18 | pre, blockquote { border: 1px solid #999; page-break-inside: avoid; } 19 | thead { display: table-header-group; } 20 | tr, img { page-break-inside: avoid; } 21 | img { max-width: 100% !important; } 22 | @page { margin: 0.5cm; } 23 | p, h2, h3 { orphans: 3; widows: 3; } 24 | h2, h3 { page-break-after: avoid; } 25 | } 26 | -------------------------------------------------------------------------------- /client/vendor/styles/sort.css: -------------------------------------------------------------------------------- 1 | /* table sorter */ 2 | table.tablesorter thead tr th { 3 | background-image: url(../bg.gif); 4 | background-repeat: no-repeat; 5 | background-position: center right; 6 | /* background-color: #F7F7F7; */ 7 | padding-right: 20px; 8 | cursor: pointer; 9 | } 10 | table.tablesorter thead tr .sorting_asc { 11 | background-image: url(../asc.gif); 12 | } 13 | table.tablesorter thead tr .sorting_desc { 14 | background-image: url(../desc.gif); 15 | } 16 | table.tablesorter thead tr .sorting_asc, table.tablesorter thead tr .sorting_desc { 17 | /* background-color: #dddddd; */ 18 | font-weight: bold; 19 | color: #34A6FF; 20 | } -------------------------------------------------------------------------------- /client/vendor/styles/tablesort_blue.css: -------------------------------------------------------------------------------- 1 | /* table sorter */ 2 | table.tablesorter thead tr .header { 3 | background-image: url(../bg.gif); 4 | background-repeat: no-repeat; 5 | background-position: center right; 6 | /* background-color: #F7F7F7; */ 7 | padding-right: 20px; 8 | cursor: pointer; 9 | } 10 | table.tablesorter thead tr .headerSortUp { 11 | background-image: url(../asc.gif); 12 | } 13 | table.tablesorter thead tr .headerSortDown { 14 | background-image: url(../desc.gif); 15 | } 16 | table.tablesorter thead tr .headerSortDown, table.tablesorter thead tr .headerSortUp { 17 | /* background-color: #dddddd; */ 18 | font-weight: bold; 19 | color: #34A6FF; 20 | } 21 | -------------------------------------------------------------------------------- /coffeelint.json: -------------------------------------------------------------------------------- 1 | { 2 | "indentation" : { 3 | "value" : 4, 4 | "level" : "error" 5 | }, 6 | "no_empty_param_list": { 7 | "level": "warn" 8 | } 9 | } -------------------------------------------------------------------------------- /log/production.log: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/seeker89/cozy-pfm/3e17567625fe81eb879255a4cdbc7d83f374614f/log/production.log -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "pfm", 3 | "version": "1.0.0", 4 | "engines": [ 5 | "node = 0.8.x" 6 | ], 7 | "description": "Personal Finance Manager you own and control", 8 | "license": "MIT", 9 | "repository": { 10 | "type": "git", 11 | "url": "https://github.com/mycozycloud/cozy-pfm.git" 12 | }, 13 | "main": "server.coffee", 14 | "dependencies": { 15 | "americano": "0.3.3", 16 | "americano-cozy": "0.2.2", 17 | "async": "0.2.10", 18 | "request-json": "0.4.8", 19 | "moment": "2.5.1", 20 | "cozy-notifications-helper": "1.0.2", 21 | "jade": "1.3.0", 22 | "nock": "0.27.2", 23 | "cozy-i18n-helper": "0.0.4", 24 | "printit": "0.1.3" 25 | }, 26 | "devDependencies": { 27 | "should": "3.1.4", 28 | "mocha": "1.18.2", 29 | "cozy-fixtures": "1.1.0", 30 | "coffeelint": "1.1.0" 31 | }, 32 | "scripts": { 33 | "test": "cake --use-js tests", 34 | "start": "node build/server.js" 35 | }, 36 | "cozy-displayName": "Mes Comptes", 37 | "cozy-permissions": { 38 | "Bank": { 39 | "description": "Les banques auxquelles vous pouvez accéder via l'application." 40 | }, 41 | "BankAccess": { 42 | "description": "Vos identifiants d'accès à votre banque sont stockés de façon sécurisée." 43 | }, 44 | "BankAccount": { 45 | "description": "Vos différents comptes bancaires." 46 | }, 47 | "BankOperation": { 48 | "description": "Une opération bancaire." 49 | }, 50 | "BankAlert": { 51 | "description": "Une alerte liée à vos comptes bancaires." 52 | }, 53 | "send mail to user": { 54 | "description": "A votre demande, des rapports journaliers, hebdomadaires ou mensuels peuvent vous être envoyés par email." 55 | }, 56 | "Notification": { 57 | "description": "Des notifications sont créées lorsque des alertes sont mises en place dans l'application." 58 | }, 59 | "CozyInstance": { 60 | "description": "Afin d'afficher le contenu dans votre langue, l'application doit accéder à vos préférences." 61 | } 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /server.coffee: -------------------------------------------------------------------------------- 1 | application = module.exports = (callback) -> 2 | 3 | americano = require 'americano' 4 | initialize = require './server/init' 5 | require './tests/mock-weboob' 6 | 7 | options = 8 | name: 'pfm' 9 | port: process.env.PORT or 9875 10 | host: process.env.HOST or "127.0.0.1" 11 | root: __dirname 12 | 13 | americano.start options, (app, server) -> 14 | initialize app, server, callback 15 | 16 | if not module.parent 17 | application() 18 | -------------------------------------------------------------------------------- /server/config.coffee: -------------------------------------------------------------------------------- 1 | americano = require 'americano' 2 | config = 3 | common: [ 4 | americano.bodyParser() 5 | americano.methodOverride() 6 | americano.errorHandler 7 | dumpExceptions: true 8 | showStack: true 9 | americano.static __dirname + '/../client/public', 10 | maxAge: 86400000 11 | require('cozy-i18n-helper').middleware 12 | ] 13 | 14 | development: [ 15 | americano.logger 'dev' 16 | ] 17 | 18 | production: [ 19 | americano.logger 'short' 20 | ] 21 | 22 | plugins: [ 23 | 'americano-cozy' 24 | ] 25 | 26 | module.exports = config -------------------------------------------------------------------------------- /server/controllers/bankaccesses.coffee: -------------------------------------------------------------------------------- 1 | BankAccess = require '../models/bankaccess' 2 | BankAccount = require '../models/bankaccount' 3 | 4 | module.exports.loadBankAccess = (req, res, next, bankAccessID) -> 5 | BankAccess.find bankAccessID, (err, access) => 6 | if err? or not access? 7 | res.send 404, error: "BankAccess not found" 8 | else 9 | delete access.password 10 | req.access = access 11 | next() 12 | 13 | module.exports.index = (req, res) -> 14 | BankAccess.all (err, accesses) -> 15 | if err? 16 | res.send 500, error: 'Server error occurred while retrieving data' 17 | else 18 | res.send 200, accesses 19 | 20 | module.exports.create = (req, res) -> 21 | BankAccess.addNewAccess req.body, (err, access) -> 22 | if err? 23 | if err.alreadyExist? 24 | res.send 409, error: "This bank access already exists" 25 | else 26 | msg = "Server error while creating bank access. -- #{err}" 27 | res.send 500, error: msg 28 | else 29 | res.send 201, access 30 | 31 | module.exports.destroy = (req, res) -> 32 | req.access.destroy (err) -> 33 | if err? 34 | res.send 500, error: "Server error while deleting the bank access" 35 | else 36 | res.send 204, success: true 37 | 38 | module.exports.update = (req, res) -> 39 | req.access.updateAttributes body, (err, access) -> 40 | if err? 41 | res.send 500, error: "Server error while saving bank access" 42 | else 43 | res.send 200, access 44 | 45 | module.exports.show = (req, res) -> 46 | res.send 200, req.access 47 | 48 | module.exports.getAccounts = (req, res) -> 49 | BankAccount.allFromBankAccess req.access, (err, accounts) -> 50 | if err 51 | res.send 500, error: 'Server error occurred while retrieving data' 52 | else 53 | res.send 200, accounts -------------------------------------------------------------------------------- /server/controllers/bankaccounts.coffee: -------------------------------------------------------------------------------- 1 | BankAccount = require '../models/bankaccount' 2 | BankOperation = require '../models/bankoperation' 3 | BankAccess = require '../models/bankaccess' 4 | 5 | module.exports.loadBankAccount = (req, res, next, accountID) -> 6 | BankAccount.find accountID, (err, account) => 7 | if err? or not account? 8 | res.send 404, error: "BankAccount not found" 9 | else 10 | req.account = account 11 | next() 12 | 13 | module.exports.index = (req, res) -> 14 | BankAccount.all (err, accounts) -> 15 | if err? 16 | res.send 500, error: 'Server error occurred while retrieving data' 17 | else 18 | res.send 200, accounts 19 | 20 | module.exports.destroy = (req, res) -> 21 | req.account.destroyWithOperations (err) -> 22 | if err? 23 | res.send 500, error: err 24 | else 25 | res.send 204, success: true 26 | 27 | module.exports.show = (req, res) -> 28 | res.send 200, req.account 29 | 30 | module.exports.getOperations = (req, res) -> 31 | BankOperation.allFromBankAccountDate req.account, (err, operations) -> 32 | if err? 33 | res.send 500, error: 'Server error occurred while retrieving data' 34 | else 35 | res.send 200, operations 36 | 37 | module.exports.retrieveOperations = (req, res) -> 38 | BankAccess.find req.account.bankAccess, (err, access) => 39 | if err? 40 | msg = "Server error occurred while retrieving data -- #{err}" 41 | res.send 500, error: msg 42 | else 43 | access.retrieveOperations (err) => 44 | if err? 45 | msg = "Server error occurred while retrieving data" 46 | res.send 500, error: "#{msg} -- #{err}" 47 | else 48 | res.send 200, req.account -------------------------------------------------------------------------------- /server/controllers/bankalerts.coffee: -------------------------------------------------------------------------------- 1 | BankAlert = require '../models/bankalert' 2 | 3 | module.exports.loadAlert = (req, res, next, alertID) -> 4 | BankAlert.find alertID, (err, alert) => 5 | if err? or not alert? 6 | res.send 404, error: "Bank Alert not found" 7 | else 8 | req.alert = alert 9 | next() 10 | 11 | module.exports.index = (req, res) -> 12 | BankAlert.all (err, alerts) -> 13 | if err? 14 | res.send 500, error: 'Server error occurred while retrieving data' 15 | else 16 | res.send 200, alerts 17 | 18 | module.exports.create = (req, res) -> 19 | BankAlert.create req.body, (err, alert) -> 20 | if err? 21 | res.send 500, error: "Server error while creating bank alert." 22 | else 23 | res.send 201, alert 24 | 25 | module.exports.destroy = (req, res) -> 26 | req.alert.destroy (err) -> 27 | if err? 28 | res.send 500, error: "Server error while deleting the bank alert" 29 | else 30 | res.send 204, success: true 31 | 32 | module.exports.update = (req, res) -> 33 | req.alert.updateAttributes req.body, (err, alert) -> 34 | if err? 35 | res.send 500, error: "Server error while saving bank alert" 36 | else 37 | res.send 200, alert 38 | 39 | module.exports.getForBankAccount = (req, res) -> 40 | BankAlert.allFromBankAccount id: req.params.accountID, (err , alerts) -> 41 | if err? 42 | res.send 500, error: "Server error while getting bank alerts" 43 | else 44 | res.send 200, alerts 45 | 46 | module.exports.show = (req, res) -> 47 | res.send 200, req.alert 48 | -------------------------------------------------------------------------------- /server/controllers/banks.coffee: -------------------------------------------------------------------------------- 1 | Bank = require '../models/bank' 2 | BankAccess = require '../models/bankaccess' 3 | BankAccount = require '../models/bankaccount' 4 | BankOperation = require '../models/bankoperation' 5 | 6 | module.exports.loadBank = (req, res, next, bankID) -> 7 | Bank.find bankID, (err, bank) => 8 | if err? or not bank? 9 | res.send 404, error: "Bank not found" 10 | else 11 | req.bank = bank 12 | next() 13 | 14 | module.exports.index = (req, res) -> 15 | doRespond = (err, banks) -> 16 | if err? or not banks? 17 | msg = "Couldn't retrieve banks -- #{err}" 18 | res.send 500, msg 19 | else 20 | res.send 200, banks 21 | if req.query.withAccountOnly? 22 | Bank.getBanksWithAccounts doRespond 23 | else 24 | Bank.all doRespond 25 | 26 | module.exports.show = (req, res) -> 27 | res.send 200, req.bank 28 | 29 | module.exports.getAccesses = (req, res) -> 30 | BankAccess.allFromBank req.bank, (err, accesses) -> 31 | if err? 32 | res.send 500, error: 'Server error occurred while retrieving data' 33 | else 34 | res.send 200, accesses 35 | 36 | module.exports.getAccounts = (req, res) -> 37 | BankAccount.allFromBank req.bank, (err, accounts) -> 38 | if err? 39 | res.send 500, error: 'Server error occurred while retrieving data' 40 | else 41 | res.send 200, accounts 42 | 43 | module.exports.destroy = (req, res) -> 44 | req.bank.destroyBankAccess (err) -> 45 | if err? 46 | msg = "Could not delete accesses for bank #{bank.name}" 47 | res.send 500, error: msg 48 | else 49 | res.send 204, success: true -------------------------------------------------------------------------------- /server/controllers/routes.coffee: -------------------------------------------------------------------------------- 1 | banks = require './banks' 2 | bankaccesses = require './bankaccesses' 3 | bankaccounts = require './bankaccounts' 4 | bankoperations = require './bankoperations' 5 | bankalerts = require './bankalerts' 6 | 7 | module.exports = 8 | 'banks': 9 | get: banks.index 10 | 'bankID': param: banks.loadBank 11 | 'banks/:bankID': 12 | get: banks.show 13 | delete: banks.destroy 14 | 'banks/getAccesses/:bankID': 15 | get: banks.getAccesses 16 | 'banks/getAccounts/:bankID': 17 | get: banks.getAccounts 18 | 19 | 'bankaccesses': 20 | get: bankaccesses.index 21 | post: bankaccesses.create 22 | 'bankAccessID': param: bankaccesses.loadBankAccess 23 | 'bankaccesses/:bankAccessID': 24 | get: bankaccesses.show 25 | put: bankaccesses.update 26 | delete: bankaccesses.destroy 27 | 'bankaccesses/getAccounts/:bankAccessID': 28 | get: bankaccesses.getAccounts 29 | 30 | 'bankaccounts': 31 | get: bankaccounts.index 32 | 'bankAccountID': param: bankaccounts.loadBankAccount 33 | 'bankaccounts/:bankAccountID': 34 | get: bankaccounts.show 35 | delete: bankaccounts.destroy 36 | 'bankaccounts/getOperations/:bankAccountID': 37 | get: bankaccounts.getOperations 38 | 'bankaccounts/retrieveOperations/:bankAccountID': 39 | get: bankaccounts.retrieveOperations 40 | 41 | 'bankoperations': 42 | get: bankoperations.index 43 | post: bankoperations.create 44 | 'bankOperationID': param: bankoperations.loadBankOperation 45 | 'bankoperations/:bankOperationID': 46 | get: bankoperations.show 47 | 'bankoperations/query': 48 | post: bankoperations.query 49 | 50 | 'bankalerts': 51 | get: bankalerts.index 52 | post: bankalerts.create 53 | 'bankAlertID': param: bankalerts.loadAlert 54 | 'bankalerts/:bankAlertID': 55 | get: bankalerts.show 56 | put: bankalerts.update 57 | delete: bankalerts.destroy 58 | 'bankalerts/getForBankAccount/:accountID': 59 | get: bankalerts.getForBankAccount 60 | -------------------------------------------------------------------------------- /server/init.coffee: -------------------------------------------------------------------------------- 1 | module.exports = (app, server, callback) -> 2 | 3 | Bank = require './models/bank' 4 | 5 | # Bank initialization 6 | Bank.all (err, banks) -> 7 | if err or banks?.length is 0 # if there aren't any banks 8 | async = require 'async' 9 | bankList = require "../tests/fixtures/banks-all.json" 10 | process = (bank, callback) -> 11 | newBank = 12 | name: bank.name 13 | uuid: bank.uuid 14 | websites: bank.websites 15 | Bank.create newBank, (err) -> 16 | if err? 17 | callback err 18 | else 19 | callback null 20 | 21 | async.each bankList, process, (err) -> 22 | if err? 23 | msg = "Couldn't add the bank to the database -- #{err}" 24 | console.log msg 25 | else 26 | msg = "Banks added to the database." 27 | console.log msg 28 | 29 | callback app, server if callback? 30 | 31 | else 32 | callback app, server if callback? 33 | 34 | # Start bank polling 35 | console.log "Start bank accounts polling..." 36 | poller = require './lib/accounts-poller' 37 | poller.start() 38 | 39 | # manage daily/weekly/monthly report 40 | console.log "Start alert watcher..." 41 | reportManager = require './lib/report-manager' 42 | reportManager.start() 43 | -------------------------------------------------------------------------------- /server/lib/accounts-poller.coffee: -------------------------------------------------------------------------------- 1 | async = require "async" 2 | moment = require "moment" 3 | BankAccess = require "../models/bankaccess" 4 | 5 | class AccountsPoller 6 | 7 | start: -> 8 | @prepareNextCheck() 9 | 10 | prepareNextCheck: -> 11 | # day after between 00:00am and 02:00am 12 | delta = Math.floor(Math.random() * 120) 13 | now = moment() 14 | nextUpdate = now.clone().add(1, 'days') 15 | .hours(0) 16 | .minutes(delta) 17 | .seconds(0) 18 | 19 | format = "DD/MM/YYYY [at] HH:mm:ss" 20 | msg = "> Next check of bank accounts on #{nextUpdate.format(format)}" 21 | console.log msg 22 | @timeout = setTimeout( 23 | () => 24 | @checkAllAccesses() 25 | , nextUpdate.diff(now)) 26 | 27 | checkAllAccesses: -> 28 | console.log "Checking new operations for all bank accesses..." 29 | BankAccess.retrieveOperationsForAllAccesses (err) => 30 | if err? 31 | console.log "An error occurred during access check -- #{err}" 32 | 33 | console.log "Bank accesses checked." 34 | @prepareNextCheck() 35 | 36 | module.exports = new AccountsPoller -------------------------------------------------------------------------------- /server/models/bank.coffee: -------------------------------------------------------------------------------- 1 | americano = require 'americano' 2 | async = require 'async' 3 | BankAccess = require './bankaccess' 4 | BankAccount = require './bankaccount' 5 | 6 | module.exports = Bank = americano.getModel 'bank', 7 | name: String 8 | uuid: String 9 | websites: (x) -> x 10 | 11 | Bank.all = (callback) -> 12 | Bank.request "all", callback 13 | 14 | Bank.getBanksWithAccounts = (callback) -> 15 | params = group: true 16 | BankAccount.rawRequest 'bankWithAccounts', params, (err, banks) -> 17 | 18 | if err? 19 | callback err, null 20 | else if not banks? 21 | callback null, [] 22 | else 23 | uuids = [] 24 | uuids.push bank.key for bank in banks 25 | 26 | Bank.getManyByUuid uuids, (err, banks) -> 27 | callback err, banks 28 | 29 | Bank.getManyByUuid = (uuids, callback) -> 30 | 31 | uuids = [uuids] if not (uuids instanceof Array) 32 | params = keys: uuids 33 | 34 | Bank.request "byUuid", params, callback 35 | 36 | # Destroy all bank accesses for a given bank 37 | Bank::destroyBankAccess = (callback) -> 38 | console.log "Deleting all accesses for bank #{@uuid}" 39 | BankAccess.allFromBank @, (err, accesses) -> 40 | 41 | if err? 42 | console.log "Could not get BankAccess from bank -- #{@uuid}" 43 | callback err 44 | else 45 | treatment = (access, callback) -> 46 | access.destroyAccounts callback 47 | 48 | async.eachSeries accesses, treatment, (err) -> 49 | callback err -------------------------------------------------------------------------------- /server/models/bankalert.coffee: -------------------------------------------------------------------------------- 1 | americano = require 'americano' 2 | 3 | module.exports = BankAlert = americano.getModel 'bankalert', 4 | bankAccount: String 5 | type: String # possible options are: report, balance, transaction 6 | frequency: String # only for reports : daily, weekly, monthly 7 | limit: Number # only for balance/transaction 8 | order: String # only for balance/transaction: gt, lt 9 | 10 | BankAlert.all = (callback) -> 11 | BankAlert.request "all", callback 12 | 13 | BankAlert.allFromBankAccount = (account, callback) -> 14 | params = key: account.id 15 | BankAlert.request "allByBankAccount", params, callback 16 | 17 | BankAlert.allByAccountAndType = (accountID, type, callback) -> 18 | params = key: [accountID, type] 19 | BankAlert.request "allByBankAccountAndType", params, callback 20 | 21 | BankAlert.allReportsByFrequency = (frequency, callback) -> 22 | params = key: ["report", frequency] 23 | BankAlert.request "allReportsByFrequency", params, callback 24 | 25 | BankAlert.destroyByAccount = (id, callback) -> 26 | BankAlert.requestDestroy "allByBankAccount", key: id, callback 27 | 28 | BankAlert::testTransaction = (operation) -> 29 | unless @type is "transaction" 30 | return false 31 | else 32 | alertLimit = Number @limit 33 | amount = Math.abs operation.amount 34 | return (@order is "lt" and amount <= alertLimit) or \ 35 | (@order is "gt" and amount >= alertLimit) 36 | 37 | BankAlert::testBalance = (account) -> 38 | unless @type is "balance" 39 | return false 40 | else 41 | alertLimit = Number @limit 42 | balance = account.getBalance() 43 | return (@order is "lt" and balance <= alertLimit) or \ 44 | (@order is "gt" and balance >= alertLimit) -------------------------------------------------------------------------------- /server/models/bankoperation.coffee: -------------------------------------------------------------------------------- 1 | americano = require 'americano' 2 | 3 | module.exports = BankOperation = americano.getModel 'bankoperation', 4 | bankAccount: String 5 | title: String 6 | date: Date 7 | amount: Number 8 | raw: String 9 | dateImport: Date 10 | 11 | BankOperation.all = (callback) -> 12 | BankOperation.request "all", callback 13 | 14 | BankOperation.allFromBankAccount = (account, callback) -> 15 | params = 16 | key: account.id 17 | BankOperation.request "allByBankAccount", params, callback 18 | 19 | BankOperation.allFromBankAccounts = (accountNums, callback) -> 20 | params = keys: accountNums 21 | BankOperation.request "allByBankAccount", params, callback 22 | 23 | BankOperation.allFromBankAccountDate = (account, callback) -> 24 | params = 25 | startkey: [account.accountNumber + "0"] 26 | endkey: [account.accountNumber] 27 | descending: true 28 | BankOperation.request "allByBankAccountAndDate", params, callback 29 | 30 | BankOperation.allLike = (operation, callback) -> 31 | date = new Date(operation.date).toISOString() 32 | params = 33 | key: [operation.bankAccount, date, \ 34 | operation.amount, operation.raw] 35 | BankOperation.request "allLike", params, callback 36 | 37 | BankOperation.destroyByAccount = (accountNum, callback) -> 38 | BankOperation.requestDestroy "allByBankAccount", key: accountNum, callback 39 | -------------------------------------------------------------------------------- /server/models/cozyinstance.coffee: -------------------------------------------------------------------------------- 1 | americano = require 'americano' 2 | 3 | module.exports = CozyInstance = americano.getModel 'CozyInstance', 4 | domain: String 5 | helpUrl: String 6 | locale: String 7 | 8 | CozyInstance.getInstance = (callback) -> 9 | CozyInstance.request 'all', (err, instances) -> 10 | if err 11 | callback err, null 12 | else if not(instances? and instances.length > 0) 13 | callback new Error 'No instance parameters found', null 14 | else 15 | callback null, instances[0] -------------------------------------------------------------------------------- /server/models/requests.coffee: -------------------------------------------------------------------------------- 1 | americano = require 'americano' 2 | 3 | allByName = (doc) -> emit doc.name, doc 4 | byUuid = (doc) -> emit doc.uuid, doc 5 | allByTitle = (doc) -> emit doc.title, doc 6 | allByBank = (doc) -> emit doc.bank, doc 7 | allByBankAccess = (doc) -> emit doc.bankAccess, doc 8 | allByBankAccount = (doc) -> emit doc.bankAccount, doc 9 | allReportsByFrequency = (doc) -> emit [doc.type, doc.frequency], doc 10 | allByBankAccountAndType = (doc) -> emit [doc.bankAccount, doc.type], doc 11 | allByBankAccountAndDate = (doc) -> emit [doc.bankAccount, doc.date], doc 12 | allAccessesLike = (doc) -> 13 | emit [doc.bank, doc.login, doc.password], doc 14 | allOperationsLike = (doc) -> 15 | emit [doc.bankAccount, doc.date, doc.amount.toFixed(2), doc.raw], doc 16 | getBalance = 17 | map: (doc) -> 18 | emit doc.bankAccount, doc.amount 19 | reduce: (keys, values, rereduce) -> 20 | sum values 21 | getBanksWithAccounts = 22 | map: (doc) -> 23 | emit doc.bank, 1 24 | reduce: (keys, values, rereduce) -> 25 | return 1 26 | 27 | module.exports = 28 | bank: 29 | all: allByName 30 | byUuid: byUuid 31 | bankaccess: 32 | all: americano.defaultRequests.all 33 | allByBank: allByBank 34 | allLike: allAccessesLike 35 | 36 | bankaccount: 37 | all: allByTitle 38 | allByBankAccess: allByBankAccess 39 | allByBank: allByBank 40 | bankWithAccounts: getBanksWithAccounts 41 | 42 | bankoperation: 43 | all: americano.defaultRequests.all 44 | allByBankAccount: allByBankAccount 45 | allByBankAccountAndDate: allByBankAccountAndDate 46 | allLike: allOperationsLike 47 | getBalance: getBalance 48 | 49 | bankalert: 50 | all: americano.defaultRequests.all 51 | allByBankAccount: allByBankAccount 52 | allReportsByFrequency: allReportsByFrequency 53 | allByBankAccountAndType: allByBankAccountAndType 54 | -------------------------------------------------------------------------------- /server/views/mail-report.jade: -------------------------------------------------------------------------------- 1 | html 2 | head 3 | title Votre rapport bancaire du #{today} 4 | body 5 | h1 Votre rapport bancaire du #{today} 6 | 7 | p Solde de vos comptes : 8 | ul 9 | - for(account in accounts) { 10 | li #{accounts[account].title} n°#{accounts[account].accountNumber} ( 11 | b #{accounts[account].getBalance()}€ 12 | | ) 13 | - } 14 | 15 | - if(Object.keys(operationsByAccount).length > 0) { 16 | p Nouvelles opérations importées : 17 | ul 18 | - var accountList = Object.keys(operationsByAccount); 19 | - for(account in accountList) { 20 | li Compte n°#{accountList[account]} 21 | ul 22 | - var operations = operationsByAccount[accountList[account]]; 23 | - for(operation in operations) { 24 | li #{operations[operation].title} - #{moment(operation.date).format("DD/MM/YYYY")} (#{operations[operation].amount}€) 25 | - } 26 | - } 27 | - } else { 28 | p Aucune nouvelle opération n'a été importée. 29 | - } 30 | -------------------------------------------------------------------------------- /tests/controllers/bankalerts.coffee: -------------------------------------------------------------------------------- 1 | should = require 'should' 2 | path = require 'path' 3 | fixtures = require 'cozy-fixtures' 4 | 5 | fixtures.setDefaultValues 6 | dirPath: path.resolve __dirname, '../fixtures/' 7 | silent: true 8 | removeBeforeLoad: false # we clean the DB before tests 9 | 10 | helpers = require '../helpers' 11 | client = helpers.getClient() 12 | 13 | describe "Bank Alerts Controller", -> 14 | 15 | before helpers.cleanDBWithRequests 16 | before helpers.startApp 17 | after helpers.stopApp 18 | after helpers.cleanDBWithRequests 19 | 20 | describe "When I add bank alerts", -> 21 | 22 | describe "When I retrieve them", -> 23 | it "The response should be a success" 24 | it "There should be x bank alerts" 25 | 26 | describe "When I retrieve one of them", -> 27 | it "The response should be a success" 28 | it "The alert should have the correct values" 29 | 30 | describe "When I update one of them", -> 31 | it "The response should be a success" 32 | it "The alert in the database should be updated" 33 | 34 | describe "When I destroy one of them", -> 35 | it "The response should be a success" 36 | it "The alert shouldn't be in the database anymore" 37 | 38 | describe "When I retrieve the alerts for a given bank account", -> 39 | it "The response should be a success" 40 | it "There should be x bank alerts" 41 | 42 | describe "When I create a bank alert", -> 43 | it "The response should be a success" 44 | it "It should be in the database" 45 | 46 | -------------------------------------------------------------------------------- /tests/fixtures/banks-mesinfos.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "docType": "Bank", 4 | "name": "Société Générale", 5 | "uuid": "societegenerale" 6 | }, 7 | { 8 | "docType": "Bank", 9 | "name": "La Banque Postale", 10 | "uuid": "bp" 11 | }, 12 | { 13 | "docType": "Bank", 14 | "name": "Crédit Coopératif", 15 | "uuid": "creditcooperatif" 16 | } 17 | ] 18 | -------------------------------------------------------------------------------- /tests/fixtures/weboob/accounts.coffee: -------------------------------------------------------------------------------- 1 | banks = require '../banks-all.json' 2 | output = {} 3 | for bank in banks 4 | output[bank.uuid] = [ 5 | { 6 | "accountNumber": "1234567890", 7 | "label": "Compte bancaire", 8 | "balance": "150" 9 | }, 10 | { 11 | "accountNumber": "0987654321", 12 | "label": "Livret A", 13 | "balance": "500" 14 | } 15 | ] 16 | 17 | 18 | module.exports = output -------------------------------------------------------------------------------- /tests/helpers.coffee: -------------------------------------------------------------------------------- 1 | fixtures = require 'cozy-fixtures' 2 | Client = require('request-json').JsonClient 3 | 4 | module.exports = helpers = {} 5 | 6 | # server management 7 | helpers.options = {} 8 | helpers.app = null 9 | 10 | if process.env.COVERAGE 11 | helpers.prefix = '../instrumented/' 12 | else if process.env.USE_JS 13 | helpers.prefix = '../build/' 14 | else 15 | helpers.prefix = '../' 16 | 17 | # server management 18 | helpers.options = 19 | serverHost: process.env.HOST or 'localhost' 20 | serverPort: process.env.PORT or 9875 21 | 22 | # set the configuration for the server 23 | process.env.HOST = helpers.options.serverHost 24 | process.env.PORT = helpers.options.serverPort 25 | 26 | # default client 27 | client = new Client "http://#{helpers.options.serverHost}:#{helpers.options.serverPort}/", jar: true 28 | helpers.getClient = -> return client 29 | 30 | initializeApplication = require "#{helpers.prefix}server" 31 | helpers.startApp = (done) -> 32 | @timeout 15000 33 | initializeApplication (app, server) => 34 | @app = app 35 | @app.server = server 36 | done() 37 | 38 | helpers.stopApp = (done) -> 39 | @timeout 10000 40 | @app.server.close done 41 | 42 | # database helper 43 | helpers.cleanDB = (done) -> 44 | @timeout 10000 45 | fixtures.resetDatabase callback: done 46 | 47 | helpers.cleanDBWithRequests = (done) -> 48 | @timeout 10000 49 | fixtures.resetDatabase removeAllRequests: true, callback: done 50 | -------------------------------------------------------------------------------- /tests/mock-weboob.coffee: -------------------------------------------------------------------------------- 1 | if not process.env.NODE_ENV? or process.env.NODE_ENV isnt 'production' 2 | 3 | nock = require 'nock' 4 | 5 | options = 6 | allowUnmocked: true 7 | 8 | #nock.recorder.rec() # enable or not the request recorder 9 | accounts = nock('http://localhost:9101', options) 10 | .persist() 11 | .log(console.log) 12 | .defaultReplyHeaders({'content-type': 'application/json; charset=utf-8'}) 13 | .filteringPath(/bank\/[a-z]+\//g, 'bank/societegenerale/') 14 | .filteringRequestBody((path) -> return {"login":"12345","password":"54321"}) 15 | .post('/connectors/bank/societegenerale/', {"login":"12345","password":"54321"}) 16 | .reply(200, require('./fixtures/weboob/accounts')) 17 | 18 | operations = nock('http://localhost:9101', options) 19 | .persist() 20 | .log(console.log) 21 | .defaultReplyHeaders({'content-type': 'application/json; charset=utf-8'}) 22 | .filteringPath(/bank\/[a-z]+\//g, 'bank/societegenerale/') 23 | .filteringRequestBody((path) -> return {"login":"12345","password":"54321"}) 24 | .post('/connectors/bank/societegenerale/history', {"login":"12345","password":"54321"}) 25 | .reply(200, require('./fixtures/weboob/operations')) 26 | --------------------------------------------------------------------------------