diff --git a/.travis.yml b/.travis.yml index 93d808c..5dc368a 100644 --- a/.travis.yml +++ b/.travis.yml @@ -4,6 +4,10 @@ services: before_install: - docker build -t bcbc/workstand:production . after_success: - - bash -c 'echo $TRAVIS_BRANCH' - docker login -u="$DOCKER_USERNAME" -p="$DOCKER_PASSWORD"; - - docker push bcbc/workstand:production; \ No newline at end of file + - export REPO=bcbc/workstand + - export TAG=`if [ "$TRAVIS_BRANCH" == "master" ]; then echo "production"; else echo $TRAVIS_BRANCH ; fi` + - docker build -f Dockerfile -t $REPO:$COMMIT . + - docker tag $REPO:$COMMIT $REPO:$TAG + - docker tag $REPO:$COMMIT $REPO:travis-$TRAVIS_BUILD_NUMBER + - docker push $REPO \ No newline at end of file diff --git a/bikeshop_project/.flake8 b/bikeshop_project/.flake8 new file mode 100644 index 0000000..79a16af --- /dev/null +++ b/bikeshop_project/.flake8 @@ -0,0 +1,2 @@ +[flake8] +max-line-length = 120 \ No newline at end of file diff --git a/bikeshop_project/assets/js/components/SignIn.jsx b/bikeshop_project/assets/js/components/SignIn.jsx index 3fef0c2..7f8bafe 100644 --- a/bikeshop_project/assets/js/components/SignIn.jsx +++ b/bikeshop_project/assets/js/components/SignIn.jsx @@ -1,8 +1,5 @@ -import ContentAdd from 'material-ui/svg-icons/content/add'; import fetch from 'isomorphic-fetch'; -import FloatingActionButton from 'material-ui/FloatingActionButton'; import moment from 'moment'; -import { polyFill } from 'es6-promise'; import React from 'react'; import RaisedButton from 'material-ui/RaisedButton'; @@ -150,9 +147,6 @@ export default class SignIn extends React.Component {
- - -
); diff --git a/bikeshop_project/assets/js/components/SignedInList.jsx b/bikeshop_project/assets/js/components/SignedInList.jsx index 25e413b..a8a9775 100644 --- a/bikeshop_project/assets/js/components/SignedInList.jsx +++ b/bikeshop_project/assets/js/components/SignedInList.jsx @@ -1,3 +1,5 @@ +import ContentAdd from 'material-ui/svg-icons/content/add'; +import FloatingActionButton from 'material-ui/FloatingActionButton'; import _ from 'lodash'; import React, { PropTypes } from 'react'; import { Table, TableBody, TableHeader, TableHeaderColumn, TableRow, TableRowColumn } from 'material-ui/Table'; @@ -50,6 +52,9 @@ export default class SignedInList extends React.Component { return (

Members signed in

+ + + diff --git a/bikeshop_project/assets/js/members/components/MemberTable/index.jsx b/bikeshop_project/assets/js/members/components/MemberTable/index.jsx index 44eb40c..f99476c 100644 --- a/bikeshop_project/assets/js/members/components/MemberTable/index.jsx +++ b/bikeshop_project/assets/js/members/components/MemberTable/index.jsx @@ -1,9 +1,8 @@ import React from 'react'; -import { polyFill } from 'es6-promise'; import fetch from 'isomorphic-fetch'; import { Table, TableBody, TableHeader, TableHeaderColumn, TableRow, TableRowColumn } from 'material-ui/Table'; import FlatButton from 'material-ui/FlatButton'; -import { Toolbar, ToolbarGroup, ToolbarSeparator, ToolbarTitle } from 'material-ui/Toolbar'; +import { Toolbar, ToolbarGroup} from 'material-ui/Toolbar'; import TextField from 'material-ui/TextField'; import RaisedButton from 'material-ui/RaisedButton'; diff --git a/bikeshop_project/bikeshop/settings/base.py b/bikeshop_project/bikeshop/settings/base.py index 563b27e..3f35fd8 100644 --- a/bikeshop_project/bikeshop/settings/base.py +++ b/bikeshop_project/bikeshop/settings/base.py @@ -142,7 +142,7 @@ COMPRESS_PRECOMPILERS = ( WEBPACK_LOADER = { 'DEFAULT': { 'CACHE': False, - 'BUNDLE_DIR_NAME': 'bundles/', # must end with slash + 'BUNDLE_DIR_NAME': 'bundles/', # must end with slash 'STATS_FILE': os.path.join(BASE_DIR, '../webpack-stats.json'), 'POLL_INTERVAL': 0.1, 'IGNORE': ['.+\.hot-update.js', '.+\.map'] @@ -159,4 +159,4 @@ HAYSTACK_CONNECTIONS = { HAYSTACK_SIGNAL_PROCESSOR = 'haystack.signals.RealtimeSignalProcessor' LOGIN_REDIRECT_URL = 'home' -LOGIN_URL = 'login' \ No newline at end of file +LOGIN_URL = 'login' diff --git a/bikeshop_project/bikeshop/settings/development.py b/bikeshop_project/bikeshop/settings/development.py index 6d85226..2d8ddb2 100644 --- a/bikeshop_project/bikeshop/settings/development.py +++ b/bikeshop_project/bikeshop/settings/development.py @@ -1,5 +1,6 @@ +import os import sys -from .base import * +from .base import * # noqa # SECURITY WARNING: keep the secret key used in production secret! @@ -10,8 +11,9 @@ DEBUG = True ALLOWED_HOSTS = [] -if 'test' in sys.argv or 'test_coverage' in sys.argv: #Covers regular testing and django-coverage - DATABASES['default']['ENGINE'] = 'django.db.backends.sqlite3' +# Covers regular testing and django-coverage +if 'test' in sys.argv or 'test_coverage' in sys.argv: + DATABASES['default']['ENGINE'] = 'django.db.backends.sqlite3' # noqa LOGGING = { 'version': 1, @@ -39,22 +41,16 @@ LOGGING = { }, } -INSTALLED_APPS += [ +INSTALLED_APPS += [ # noqa 'corsheaders', - # 'debug_toolbar' ] -MIDDLEWARE_CLASSES.insert(0, 'django.middleware.common.CommonMiddleware') +MIDDLEWARE_CLASSES.insert(0, 'django.middleware.common.CommonMiddleware') # noqa # MIDDLEWARE_CLASSES += [ # 'debug_toolbar.middleware.DebugToolbarMiddleware' # ] -# Don't worry about IP addresses, just show the toolbar. -DEBUG_TOOLBAR_CONFIG = { - 'SHOW_TOOLBAR_CALLBACK': lambda *args: True -} - CORS_ORIGIN_ALLOW_ALL = True -ALLOWED_HOSTS = ['workstand.docker'] +ALLOWED_HOSTS = ['workstand.docker','localhost'] diff --git a/bikeshop_project/bikeshop/settings/production.py b/bikeshop_project/bikeshop/settings/production.py index e50f654..e9d6db3 100644 --- a/bikeshop_project/bikeshop/settings/production.py +++ b/bikeshop_project/bikeshop/settings/production.py @@ -1,4 +1,5 @@ -from .base import * +import os +from .base import * # noqa # SECURITY WARNING: keep the secret key used in production secret! @@ -40,9 +41,9 @@ LOGGING = { WEBPACK_LOADER = { 'DEFAULT': { 'CACHE': True, - 'BUNDLE_DIR_NAME': 'dist/', # must end with slash - 'STATS_FILE': os.path.join(BASE_DIR, '../webpack-stats-prod.json'), + 'BUNDLE_DIR_NAME': 'dist/', # must end with slash + 'STATS_FILE': os.path.join(BASE_DIR, '../webpack-stats-prod.json'), # noqa 'POLL_INTERVAL': 0.1, 'IGNORE': ['.+\.hot-update.js', '.+\.map'] } -} \ No newline at end of file +} diff --git a/bikeshop_project/bikeshop/utils/member_import.py b/bikeshop_project/bikeshop/utils/member_import.py index 33c6596..90a0dc2 100644 --- a/bikeshop_project/bikeshop/utils/member_import.py +++ b/bikeshop_project/bikeshop/utils/member_import.py @@ -1,6 +1,4 @@ import csv -import json -import sys import os import requests @@ -12,7 +10,6 @@ from core.models import Membership, Payment from registration.models import Member - def email_generator(): url = 'http://randomword.setgetgo.com/get.php' local = [] diff --git a/bikeshop_project/core/admin.py b/bikeshop_project/core/admin.py index f9acfdf..d4610b4 100644 --- a/bikeshop_project/core/admin.py +++ b/bikeshop_project/core/admin.py @@ -6,6 +6,6 @@ admin.site.register([Membership, Payment]) @admin.register(Visit) -class VistAdmin(admin.ModelAdmin): +class VisitAdmin(admin.ModelAdmin): ordering = ('created_at',) list_display = ('member', 'purpose', 'created_at') diff --git a/bikeshop_project/core/forms.py b/bikeshop_project/core/forms.py index 2fce3f8..f14ca45 100644 --- a/bikeshop_project/core/forms.py +++ b/bikeshop_project/core/forms.py @@ -1,5 +1,5 @@ import logging -from django.forms import BooleanField, CharField, CheckboxInput, RadioSelect, ModelForm, TextInput, HiddenInput, ChoiceField +from django.forms import BooleanField, CharField, CheckboxInput, RadioSelect, ModelForm, TextInput, HiddenInput from registration.models import Member diff --git a/bikeshop_project/core/models.py b/bikeshop_project/core/models.py index 79d14d5..042f07f 100644 --- a/bikeshop_project/core/models.py +++ b/bikeshop_project/core/models.py @@ -62,7 +62,7 @@ class Visit(models.Model): (DONATE, 'donate'), (STAFF, 'staff'), ) - + member = models.ForeignKey( 'registration.Member', on_delete=models.CASCADE diff --git a/bikeshop_project/core/templates/dashboard.html b/bikeshop_project/core/templates/dashboard.html index 309e409..5f81ad5 100644 --- a/bikeshop_project/core/templates/dashboard.html +++ b/bikeshop_project/core/templates/dashboard.html @@ -58,3 +58,10 @@
{% render_bundle 'signin' %} {% endblock %} + +{% block scripts %} + {% render_bundle 'babelPolyfill' %} + {% if DEBUG %} + {% render_bundle 'webpack' %} + {% endif %} +{% endblock %} diff --git a/bikeshop_project/core/tests.py b/bikeshop_project/core/tests.py index 7ce503c..a39b155 100644 --- a/bikeshop_project/core/tests.py +++ b/bikeshop_project/core/tests.py @@ -1,3 +1 @@ -from django.test import TestCase - # Create your tests here. diff --git a/bikeshop_project/core/views.py b/bikeshop_project/core/views.py index 8c1bc97..2f28218 100644 --- a/bikeshop_project/core/views.py +++ b/bikeshop_project/core/views.py @@ -1,5 +1,6 @@ import logging +from django.conf import settings from django.contrib import messages from django.core.urlresolvers import reverse from django.http import HttpResponseRedirect @@ -18,13 +19,14 @@ logger = logging.getLogger(__name__) @method_decorator(login_required, name='dispatch') class DashboardView(View): def get(self, request): - return TemplateResponse(request, 'dashboard.html') + return TemplateResponse(request, 'dashboard.html', context={'DEBUG': settings.DEBUG}) + @method_decorator(login_required, name='dispatch') class NewMembershipView(TemplateView): template_name = 'membership_form.html' - def get(self, request, member_id): + def get(self, request, member_id, **kwargs): membership_form = MembershipForm(initial=dict(member=member_id)) payment_form = PaymentForm() return self.render_to_response(dict(membership_form=membership_form, payment_form=payment_form)) diff --git a/bikeshop_project/package.json b/bikeshop_project/package.json index a2c7dd3..775ec42 100644 --- a/bikeshop_project/package.json +++ b/bikeshop_project/package.json @@ -4,14 +4,13 @@ "description": "A membership management app for the BCBC.", "main": "index.js", "scripts": { - "build": "node_modules/.bin/webpack --config webpack.config.js --progress --colors", - "build-production": "node_modules/.bin/webpack --config webpack.prod.config.js --progress --colors", - "watch": "node server.js" -}, + "build": "node_modules/.bin/webpack --config webpack.config.js --progress --colors", + "build-production": "node_modules/.bin/webpack --config webpack.prod.config.js --progress --colors", + "watch": "node server.js" + }, "author": "", "license": "ISC", "dependencies": { - "es6-promise": "^3.2.1", "isomorphic-fetch": "^2.2.1", "material-ui": "^0.16.6", "moment": "^2.13.0", @@ -25,10 +24,15 @@ "babel": "^6.5.2", "babel-core": "^6.9.1", "babel-loader": "^6.2.4", + "babel-polyfill": "^6.22.0", "babel-preset-es2015": "^6.9.0", "babel-preset-react": "^6.5.0", "babel-preset-stage-0": "^6.5.0", "css-loader": "^0.23.1", + "eslint": "^3.9.1", + "eslint-plugin-import": "^2.1.0", + "eslint-plugin-jsx-a11y": "^2.2.3", + "eslint-plugin-react": "^6.6.0", "extract-text-webpack-plugin": "^1.0.1", "i": "^0.3.5", "node-sass": "^3.4.2", @@ -40,10 +44,6 @@ "sass-loader": "^3.2.0", "style-loader": "^0.13.1", "toolbox-loader": "0.0.3", - "webpack-dev-server": "^1.14.1", - "eslint": "^3.9.1", - "eslint-plugin-jsx-a11y": "^2.2.3", - "eslint-plugin-import": "^2.1.0", - "eslint-plugin-react": "^6.6.0" + "webpack-dev-server": "^1.14.1" } } diff --git a/bikeshop_project/registration/admin.py b/bikeshop_project/registration/admin.py index 841275d..571fe1f 100644 --- a/bikeshop_project/registration/admin.py +++ b/bikeshop_project/registration/admin.py @@ -35,4 +35,4 @@ class CustomUserAdmin(UserAdmin): class MemberAdmin(admin.ModelAdmin): list_display = ('get_full_name',) ordering = ('last_name',) - search_fields = ('email', 'first_name', 'last_name') \ No newline at end of file + search_fields = ('email', 'first_name', 'last_name') diff --git a/bikeshop_project/registration/forms.py b/bikeshop_project/registration/forms.py index a1da26d..369a024 100644 --- a/bikeshop_project/registration/forms.py +++ b/bikeshop_project/registration/forms.py @@ -1,10 +1,11 @@ -from django.forms import ModelForm, EmailInput, TextInput, DateInput, CheckboxSelectMultiple, CharField, CheckboxInput, BooleanField +from django.forms import ModelForm, EmailInput, TextInput, DateInput, CheckboxInput, BooleanField from django.utils import timezone from registration.models import Member class MemberForm(ModelForm): - waiver_substitute = BooleanField(required=False, label='I have read and agree to the above terms & conditions.', widget=CheckboxInput(attrs={'class': 'mdl-checkbox__input'})) + waiver_substitute = BooleanField(required=False, label='I have read and agree to the above terms & conditions.', + widget=CheckboxInput(attrs={'class': 'mdl-checkbox__input'})) class Meta: model = Member diff --git a/bikeshop_project/registration/serializers.py b/bikeshop_project/registration/serializers.py index f060691..9b67b32 100644 --- a/bikeshop_project/registration/serializers.py +++ b/bikeshop_project/registration/serializers.py @@ -10,4 +10,4 @@ class MemberSerializer(ModelSerializer): class Meta: model = Member - fields = ('first_name', 'last_name', 'email', 'id') \ No newline at end of file + fields = ('first_name', 'last_name', 'email', 'id') diff --git a/bikeshop_project/registration/tests/test_views.py b/bikeshop_project/registration/tests/test_views.py index ad3c23c..31b630d 100644 --- a/bikeshop_project/registration/tests/test_views.py +++ b/bikeshop_project/registration/tests/test_views.py @@ -8,10 +8,8 @@ from django.test import Client, TestCase from core.models import Visit from model_mommy import mommy -from copy import copy from ..models import CustomUser, Member -from ..views import MemberFormView logger = logging.getLogger('bikeshop') @@ -37,7 +35,7 @@ class TestMemberFormView(TestCase): 'last_name': 'Last', 'post_code': 'H0H0H0', } - response = c.post(url, data=member_data) + c.post(url, data=member_data) new_member = Member.objects.get(first_name='First', last_name='Last') self.assertTrue(new_member) diff --git a/bikeshop_project/registration/views.py b/bikeshop_project/registration/views.py index a0cd442..cee46dc 100644 --- a/bikeshop_project/registration/views.py +++ b/bikeshop_project/registration/views.py @@ -58,7 +58,8 @@ class MemberFormView(View): class MemberSearchView(View): def get(self, request, query): sqs = SearchQuerySet().models(Member).autocomplete(text=query)[:5] - results = [dict(name=result.object.get_full_name(), email=result.object.email, id=result.object.id) for result in sqs] + results = [dict(name=result.object.get_full_name(), email=result.object.email, id=result.object.id) + for result in sqs] data = json.dumps(dict(results=results)) diff --git a/bikeshop_project/webpack.base.config.js b/bikeshop_project/webpack.base.config.js index cc7c36e..d3082bc 100644 --- a/bikeshop_project/webpack.base.config.js +++ b/bikeshop_project/webpack.base.config.js @@ -1,38 +1,35 @@ -var path = require("path") -var webpack = require('webpack') -var BundleTracker = require('webpack-bundle-tracker') - +const path = require('path'); const autoprefixer = require('autoprefixer'); +require('babel-polyfill'); module.exports = { - context: __dirname, + context: __dirname, + + entry: { + signin: './assets/js/index', + members: './assets/js/members/index', + babelPolyfill: 'babel-polyfill', + }, - entry: { - signin: './assets/js/index', - members: './assets/js/members/index', - }, + output: { + path: path.resolve('./assets/bundles/'), + filename: '[name]-[hash].js', + }, - output: { - path: path.resolve('./assets/bundles/'), - filename: "[name]-[hash].js" - }, + plugins: [ - plugins: [ - - ], // add all common plugins here + ], // add all common plugins here - module: { - loaders: [ - - ] - }, + module: { + loaders: [], + }, - resolve: { - modulesDirectories: [ - 'node_modules', - 'bower_components' - ], - extensions: ['', '.js', '.jsx', '.scss'] - }, - postcss: [autoprefixer] -} \ No newline at end of file + resolve: { + modulesDirectories: [ + 'node_modules', + 'bower_components', + ], + extensions: ['', '.js', '.jsx', '.scss'], + }, + postcss: [autoprefixer], +}; diff --git a/bikeshop_project/webpack.dev.config.js b/bikeshop_project/webpack.dev.config.js index 0f4ada6..8d55b75 100644 --- a/bikeshop_project/webpack.dev.config.js +++ b/bikeshop_project/webpack.dev.config.js @@ -1,45 +1,47 @@ -var path = require("path") -var webpack = require('webpack') -var BundleTracker = require('webpack-bundle-tracker') +const webpack = require('webpack'); +const BundleTracker = require('webpack-bundle-tracker'); const ExtractTextPlugin = require('extract-text-webpack-plugin'); +require('babel-polyfill'); -var config = require('./webpack.base.config.js') + +const config = require('./webpack.base.config.js'); // Use webpack dev server config.entry = { - webpack: [ - 'webpack-dev-server/client?http://webpack.docker:3000', - 'webpack/hot/only-dev-server', - ], - signin: './assets/js/index', - members: './assets/js/members/index', -} + webpack: [ + 'webpack-dev-server/client?http://localhost:3000', + 'webpack/hot/only-dev-server', + ], + signin: './assets/js/index', + members: './assets/js/members/index', + babelPolyfill: 'babel-polyfill', +}; // override django's STATIC_URL for webpack bundles -config.output.publicPath = 'http://webpack.docker:3000/assets/bundles/' +config.output.publicPath = 'http://localhost:3000/assets/bundles/'; config.devtool = 'eval-source-map'; // Add HotModuleReplacementPlugin and BundleTracker plugins config.plugins = config.plugins.concat([ - new webpack.HotModuleReplacementPlugin(), - new webpack.NoErrorsPlugin(), - new BundleTracker({filename: './webpack-stats.json'}), - new ExtractTextPlugin('react-toolbox.css', {allChunks: true}), -]) + new webpack.HotModuleReplacementPlugin(), + new webpack.NoErrorsPlugin(), + new BundleTracker({ filename: './webpack-stats.json' }), + new ExtractTextPlugin('react-toolbox.css', { allChunks: true }), +]); // Add a loader for JSX files with react-hot enabled config.module.loaders.push( - { - test: /\.jsx?$/, - exclude: /node_modules/, - loaders: ['react-hot','babel-loader'] - - }, - { - test: /(\.scss|\.css)$/, - loader: ExtractTextPlugin.extract('style', 'css?sourceMap&modules&importLoaders=1&localIdentName=[name]__[local]___[hash:base64:5]!postcss!sass?sourceMap!toolbox') - } -) - -module.exports = config \ No newline at end of file + { + test: /\.jsx?$/, + exclude: /node_modules/, + loaders: ['react-hot', 'babel-loader'], + + }, + { + test: /(\.scss|\.css)$/, + loader: ExtractTextPlugin.extract('style', 'css?sourceMap&modules&importLoaders=1&localIdentName=[name]__[local]___[hash:base64:5]!postcss!sass?sourceMap!toolbox'), + } +); + +module.exports = config; diff --git a/docker-compose.dev.yml b/docker-compose.dev.yml index 0bee4d4..5222490 100644 --- a/docker-compose.dev.yml +++ b/docker-compose.dev.yml @@ -9,7 +9,7 @@ services: - "8000:8000" - "62260:62260" volumes: - - ./bikeshop_project:/code + - ./bikeshop_project:/code:rw redis: restart: always db: diff --git a/requirements/development.txt b/requirements/development.txt index 1ba3966..8aba8d0 100644 --- a/requirements/development.txt +++ b/requirements/development.txt @@ -2,3 +2,4 @@ -r testing.txt django-debug-toolbar django-cors-headers +flake8