refactor with bootstrap 4
This commit is contained in:
parent
b486aff415
commit
14d0253ccb
25
.eslintrc
Normal file
25
.eslintrc
Normal file
|
@ -0,0 +1,25 @@
|
|||
{
|
||||
"ecmaFeatures": {
|
||||
"jsx": true,
|
||||
"modules": true
|
||||
},
|
||||
"env": {
|
||||
"browser": true,
|
||||
"node": true
|
||||
},
|
||||
"parser": "babel-eslint",
|
||||
"rules": {
|
||||
// "quotes": [2, "single"],
|
||||
"jsx-quotes": 2,
|
||||
"strict": [
|
||||
2,
|
||||
"never"
|
||||
],
|
||||
"react/jsx-uses-react": 2,
|
||||
"react/jsx-uses-vars": 2,
|
||||
"react/react-in-jsx-scope": 2
|
||||
},
|
||||
"plugins": [
|
||||
"react"
|
||||
]
|
||||
}
|
52
.jshintrc
52
.jshintrc
|
@ -1,52 +0,0 @@
|
|||
{
|
||||
"esnext": true,
|
||||
"camelcase": true,
|
||||
"devel": false,
|
||||
"asi": false,
|
||||
"boss": false,
|
||||
"eqnull": false,
|
||||
"es5": true,
|
||||
"moz": false,
|
||||
"evil": false,
|
||||
"expr": true,
|
||||
"funcscope": true,
|
||||
"iterator": false,
|
||||
"lastsemic": false,
|
||||
"laxbreak": false,
|
||||
"laxcomma": false,
|
||||
"loopfunc": false,
|
||||
"multistr": true,
|
||||
"noyield": false,
|
||||
"notypeof": false,
|
||||
"proto": false,
|
||||
"scripturl": false,
|
||||
"shadow": false,
|
||||
"sub": false,
|
||||
"supernew": false,
|
||||
"validthis": false,
|
||||
"plusplus": false,
|
||||
"jquery": true,
|
||||
"mocha": false,
|
||||
"node": true,
|
||||
"latedef": true,
|
||||
"quotmark": "single",
|
||||
"maxparams": 6,
|
||||
"maxdepth": 5,
|
||||
"maxerr": 50,
|
||||
"globalstrict": false,
|
||||
"globals": {
|
||||
"inject": true,
|
||||
"angular": true,
|
||||
"require": true,
|
||||
"process": true,
|
||||
"module": true,
|
||||
"describe": true,
|
||||
"beforeEach": true,
|
||||
"afterEach": true,
|
||||
"it": true,
|
||||
"expect": true,
|
||||
"__dirname": true,
|
||||
"exports": true,
|
||||
"spyOn": true
|
||||
}
|
||||
}
|
|
@ -1,6 +0,0 @@
|
|||
language: node_js
|
||||
node_js:
|
||||
- "node"
|
||||
before_script:
|
||||
- npm install -g gulp-cli
|
||||
script: gulp build
|
3
build.sh
3
build.sh
|
@ -7,7 +7,6 @@ composer install
|
|||
cp -rv src/{backend.php,config.sample.php} dist/
|
||||
|
||||
# build Javascript frontend
|
||||
npm install
|
||||
gulp build
|
||||
npm run build
|
||||
|
||||
echo "done"
|
57
dist/bundle_65d8f46de4091cada75c.js
vendored
Normal file
57
dist/bundle_65d8f46de4091cada75c.js
vendored
Normal file
File diff suppressed because one or more lines are too long
2
dist/index.html
vendored
2
dist/index.html
vendored
|
@ -1 +1 @@
|
|||
<!DOCTYPE html> <html lang=de> <head> <meta charset=utf-8> <title>Mailbox</title> <meta name=viewport content="width=device-width,initial-scale=1"> <meta name=mobile-web-app-capable content=yes> <meta name=apple-mobile-web-app-capable content=yes> <meta name=apple-mobile-web-app-status-bar-style content=black> <meta name=description content=Mailbox> <link rel=icon href="data:;base64,iVBORw0KGgo="> </head> <body ng-app=app ng-cloak> <div ui-view></div> <footer> <p>Powered by <a href=https://github.com/synox/disposable-mailbox><strong>synox/disposable-mailbox</strong></a> | <a href=https://github.com/synox/disposable-mailbox><span class="octicon octicon-mark-github"></span> Fork me on github</a></p> </footer> <script type="text/javascript" src="mailbox_1ad13ef2ffe2df84a4e6.js"></script></body> </html>
|
||||
<!DOCTYPE html> <html lang=de> <head> <meta charset=utf-8> <title>Mailbox</title> <meta name=viewport content="width=device-width,initial-scale=1,shrink-to-fit=no"> <meta name=mobile-web-app-capable content=yes> <meta name=apple-mobile-web-app-capable content=yes> <meta name=apple-mobile-web-app-status-bar-style content=black> <meta name=description content=Mailbox> <link rel=icon href="data:;base64,iVBORw0KGgo="> </head> <body ng-app=app ng-cloak> <app></app> <footer> <p>Powered by <a href=https://github.com/synox/disposable-mailbox><strong>synox/disposable-mailbox</strong></a> | <a href=https://github.com/synox/disposable-mailbox><span class="octicon octicon-mark-github"></span> Fork me on github</a></p> </footer> <script type="text/javascript" src="bundle_65d8f46de4091cada75c.js"></script></body> </html>
|
53
dist/mailbox_1ad13ef2ffe2df84a4e6.js
vendored
53
dist/mailbox_1ad13ef2ffe2df84a4e6.js
vendored
File diff suppressed because one or more lines are too long
|
@ -1,73 +0,0 @@
|
|||
import gulp from 'gulp';
|
||||
import path from 'path';
|
||||
import webpack from 'webpack';
|
||||
import WebpackDevServer from 'webpack-dev-server';
|
||||
import karma from 'karma';
|
||||
import ip from 'ip';
|
||||
import webpackConfig from './webpack.config';
|
||||
import del from 'del';
|
||||
|
||||
|
||||
gulp.task('clean', function () {
|
||||
return del([
|
||||
'dist/*.js',
|
||||
'target/build']
|
||||
);
|
||||
});
|
||||
|
||||
/**
|
||||
* Gulp-Task: Fuehrt webpack aus und startet den Development-Server
|
||||
*/
|
||||
gulp.task('dev-server', () => {
|
||||
return new WebpackDevServer(webpack(webpackConfig.development), {
|
||||
hot: true,
|
||||
contentBase: './dist/',
|
||||
watchOptions: {
|
||||
aggregateTimeout: 100, poll: 300
|
||||
}, stats: {
|
||||
colors: true
|
||||
}
|
||||
}).listen(3000, 'localhost', function (err) {
|
||||
if (err) {
|
||||
console.error(err);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
/**
|
||||
* Gulp-Task: Fuehrt die Karma-Tests auf dem PhantomJS Browser aus
|
||||
*/
|
||||
gulp.task('test-phantomjs', (done) => {
|
||||
|
||||
let hostname = process.env.host || ip.address();
|
||||
let externalport = process.env.externalport || 7777;
|
||||
|
||||
return new karma.Server({
|
||||
configFile: __dirname + '/karma.conf.js',
|
||||
hostname: hostname,
|
||||
port: externalport,
|
||||
browsers: ['PhantomJS']
|
||||
}, done).start();
|
||||
});
|
||||
|
||||
|
||||
gulp.task('webpack-prod', [], (done) => {
|
||||
return webpack(webpackConfig.production, done);
|
||||
});
|
||||
|
||||
|
||||
gulp.task('build', ['test-phantomjs', 'clean', 'webpack-prod'], (done) => {
|
||||
return gulp
|
||||
.src(path.join('target', 'build', '*'))
|
||||
.pipe(gulp.dest('dist'));
|
||||
});
|
||||
|
||||
gulp.task('build-skipTests', ['clean', 'webpack-prod'], (done) => {
|
||||
return gulp
|
||||
.src(path.join('target', 'build', '*'))
|
||||
.pipe(gulp.dest('dist'));
|
||||
});
|
||||
|
||||
|
||||
gulp.task('default', ['dev-server']);
|
112
karma.conf.js
112
karma.conf.js
|
@ -1,112 +0,0 @@
|
|||
var ip = require('ip');
|
||||
var webjsConfig = require('./shared.build.config');
|
||||
|
||||
module.exports = function (config) {
|
||||
|
||||
var seleniumWebgrid = {
|
||||
hostname: 'webtestgrid.myhost.com',
|
||||
port: 4444
|
||||
};
|
||||
|
||||
config.set({
|
||||
|
||||
hostname: ip.address(),
|
||||
|
||||
basePath: __dirname,
|
||||
|
||||
// frameworks to use
|
||||
// available frameworks: https://npmjs.org/browse/keyword/karma-adapter
|
||||
frameworks: ['jasmine'],
|
||||
|
||||
/* list of files/patterns to load in the browser
|
||||
Fuer den Phantomjs wird fuer die Methode 'bind' ein Polyfill geladen
|
||||
da der Browser die Methode nicht kennt und diese von den Frameworks verwendet wird */
|
||||
files: [
|
||||
'./node_modules/phantomjs-polyfill/bind-polyfill.js', {
|
||||
pattern: 'spec.bundle.js', watched: false
|
||||
}
|
||||
],
|
||||
|
||||
// files to exclude
|
||||
exclude: [],
|
||||
|
||||
// preprocess matching files before serving them to the browser
|
||||
// available preprocessors: https://npmjs.org/browse/keyword/karma-preprocessor
|
||||
preprocessors: {
|
||||
'spec.bundle.js': ['webpack', 'sourcemap', 'coverage']
|
||||
},
|
||||
|
||||
webpack: {
|
||||
debug: true, devtool: 'inline-source-map', module: {
|
||||
loaders: webjsConfig.webpackLoaders
|
||||
}
|
||||
},
|
||||
|
||||
webpackServer: {
|
||||
// prevent console spamming when running in Karma!
|
||||
noInfo: true
|
||||
},
|
||||
|
||||
// available reporters: https://npmjs.org/browse/keyword/karma-reporter
|
||||
reporters: ['progress', 'junit', 'coverage'],
|
||||
|
||||
// enable colors in the output
|
||||
colors: true,
|
||||
|
||||
// level of logging
|
||||
// possible values: config.LOG_DISABLE || config.LOG_ERROR || config.LOG_WARN || config.LOG_INFO || config.LOG_DEBUG
|
||||
logLevel: config.LOG_INFO,
|
||||
|
||||
// toggle whether to watch files and rerun tests upon incurring changes
|
||||
autoWatch: false,
|
||||
|
||||
// Browser-Konfiguration auf dem Selenium Grid
|
||||
customLaunchers: {
|
||||
'SeleniumCH': {
|
||||
base: 'WebDriver',
|
||||
config: seleniumWebgrid,
|
||||
browserName: 'chrome'
|
||||
},
|
||||
'SeleniumFF': {
|
||||
base: 'WebDriver',
|
||||
config: seleniumWebgrid,
|
||||
browserName: 'firefox'
|
||||
},
|
||||
'SeleniumIE': {
|
||||
base: 'WebDriver',
|
||||
config: seleniumWebgrid,
|
||||
browserName: 'internet explorer',
|
||||
'x-ua-compatible': 'IE=edge'
|
||||
}
|
||||
},
|
||||
|
||||
// start these browsers
|
||||
// available browser launchers: https://npmjs.org/browse/keyword/karma-launcher
|
||||
browsers: ['PhantomJS'], // Test auf dem PhantomJS
|
||||
// browsers: ['SeleniumFF', 'SeleniumCH', 'SeleniumIE'], // Test auf dem Selenium-Webgrid
|
||||
|
||||
// if true, Karma runs tests once and exits
|
||||
singleRun: true,
|
||||
|
||||
plugins: [
|
||||
'karma-junit-reporter',
|
||||
'karma-jasmine',
|
||||
'karma-coverage',
|
||||
'karma-phantomjs-launcher',
|
||||
'karma-webpack',
|
||||
'karma-sourcemap-loader',
|
||||
'karma-webdriver-launcher'
|
||||
],
|
||||
|
||||
// Coverage & JUnit Report fuer SonarQube
|
||||
junitReporter: {
|
||||
outputDir: 'target/surefire', suite: 'unit'
|
||||
}, coverageReporter: {
|
||||
reporters: [
|
||||
{
|
||||
type: 'lcov', dir: 'target/surefire', subdir: '.'
|
||||
}
|
||||
]
|
||||
}
|
||||
});
|
||||
};
|
99
package.json
99
package.json
|
@ -2,65 +2,52 @@
|
|||
"name": "disposable-mailbox",
|
||||
"version": "0.0.1",
|
||||
"description": "disposable-mailbox",
|
||||
"homepage": "https://github.com/synox/disposable-mailbox",
|
||||
"dependencies": {
|
||||
"angular": "^1.5.2",
|
||||
"angular-sanitize": "^1.5.6",
|
||||
"angular-stickyfill": "^0.1.0",
|
||||
"angular-ui-bootstrap": "^1.3.3",
|
||||
"angular-ui-router": "^1.0.0-beta.1",
|
||||
"autolinker": "^0.27.0",
|
||||
"babel-polyfill": "^6.9.1",
|
||||
"bootstrap": "^3.3.6",
|
||||
"phonetic": "^0.1.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"angular-mocks": "^1.5.2",
|
||||
"babel-core": "^6.10.4",
|
||||
"babel-loader": "^6.2.4",
|
||||
"babel-preset-es2015": "^6.9.0",
|
||||
"browser-sync": "^2.10.0",
|
||||
"browser-sync-webpack-plugin": "^1.0.0",
|
||||
"css-loader": "^0.23.1",
|
||||
"del": "^2.2.1",
|
||||
"file-loader": "^0.9.0",
|
||||
"gulp": "^3.9.0",
|
||||
"gulp-esdoc": "^0.2.0",
|
||||
"gulp-file-inline": "^1.3.6",
|
||||
"html-loader": "^0.4.3",
|
||||
"html-webpack-plugin": "^2.15.0",
|
||||
"ip": "^1.0.2",
|
||||
"isparta-loader": "^2.0.0",
|
||||
"jasmine-core": "^2.3.4",
|
||||
"json-loader": "^0.5.3",
|
||||
"karma": "^1.1.0",
|
||||
"karma-coverage": "^1.0.0",
|
||||
"karma-jasmine": "~1.0.2",
|
||||
"karma-junit-reporter": "^1.1.0",
|
||||
"karma-phantomjs-launcher": "^1.0.1",
|
||||
"karma-sourcemap-loader": "^0.3.4",
|
||||
"karma-webdriver-launcher": "^1.0.4",
|
||||
"karma-webpack": "^1.5.1",
|
||||
"ng-annotate-webpack-plugin": "^0.1.2",
|
||||
"node-libs-browser": "^1.0.0",
|
||||
"node-sass": "^3.8.0",
|
||||
"node.extend": "^1.1.5",
|
||||
"phantomjs": "^2.1.7",
|
||||
"phantomjs-polyfill": "0.0.2",
|
||||
"proxy-middleware": "^0.15.0",
|
||||
"raw-loader": "^0.5.1",
|
||||
"sass-loader": "^4.0.0",
|
||||
"style-loader": "^0.13.0",
|
||||
"url-loader": "^0.5.6",
|
||||
"webpack": "^1.13.1",
|
||||
"webpack-dev-server": "^1.12.1"
|
||||
"scripts": {
|
||||
"start": "node server.js",
|
||||
"build": "NODE_ENV=production webpack -p",
|
||||
"size": "NODE_ENV=production webpack --json | webpack-bundle-size-analyzer ",
|
||||
"lint": "./node_modules/eslint/bin/eslint.js src"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/synox/disposable-mailbox.git"
|
||||
},
|
||||
"license": "CC-BY-NC-SA-4.0",
|
||||
"scripts": {
|
||||
"test": "gulp test-phantomjs"
|
||||
}
|
||||
"homepage": "https://github.com/synox/disposable-mailbox",
|
||||
"dependencies": {
|
||||
"angular": "^1.5.2",
|
||||
"angular-sanitize": "^1.5.6",
|
||||
"angular-stickyfill": "^0.1.0",
|
||||
"hasher": "^1.2.0",
|
||||
"autolinker": "^0.27.0",
|
||||
"babel-polyfill": "^6.9.1",
|
||||
"bootstrap": "^4.0.0-alpha.3",
|
||||
"phonetic": "^0.1.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"babel-core": "^6.0.20",
|
||||
"babel-eslint": "^4.1.3",
|
||||
"babel-loader": "^6.0.1",
|
||||
"babel-preset-es2015": "^6.0.15",
|
||||
"babel-preset-react": "^6.0.15",
|
||||
"babel-preset-stage-0": "^6.0.15",
|
||||
"css-loader": "^0.23.1",
|
||||
"eslint": "^1.10.3",
|
||||
"eslint-plugin-react": "^3.6.2",
|
||||
"file-loader": "^0.9.0",
|
||||
"html-loader": "^0.4.3",
|
||||
"html-webpack-plugin": "^2.15.0",
|
||||
"json-loader": "^0.5.4",
|
||||
"node-sass": "^3.8.0",
|
||||
"react-hot-loader": "^1.3.0",
|
||||
"sass-loader": "^4.0.0",
|
||||
"style-loader": "^0.13.0",
|
||||
"uglify-loader": "^1.3.0",
|
||||
"url-loader": "^0.5.6",
|
||||
"webpack": "^1.12.2",
|
||||
"webpack-bundle-size-analyzer": "^2.0.2",
|
||||
"webpack-dev-server": "^1.12.1",
|
||||
"webpack-merge": "^0.14.1",
|
||||
"webpack-validator": "^2.2.3"
|
||||
},
|
||||
"license": "CC-BY-NC-SA-4.0"
|
||||
}
|
||||
|
|
14
server.js
Normal file
14
server.js
Normal file
|
@ -0,0 +1,14 @@
|
|||
var webpack = require('webpack');
|
||||
var WebpackDevServer = require('webpack-dev-server');
|
||||
var config = require('./webpack.config');
|
||||
|
||||
new WebpackDevServer(webpack(config), {
|
||||
hot: false,
|
||||
historyApiFallback: true
|
||||
}).listen(3000, 'localhost', function (err, result) {
|
||||
if (err) {
|
||||
return console.log(err);
|
||||
}
|
||||
|
||||
console.log('Listening at http://localhost:3000/');
|
||||
});
|
|
@ -1,33 +0,0 @@
|
|||
/*
|
||||
* @author u215942 (Stefan Zeller)
|
||||
* @version: 1.0.1
|
||||
* @since 04.04.2016
|
||||
*/
|
||||
|
||||
exports.webpackLoaders = [
|
||||
{
|
||||
test: /\.js$/, exclude: [/node_modules/],
|
||||
loader: 'babel',
|
||||
query: {
|
||||
// https://github.com/babel/babel-loader#options
|
||||
cacheDirectory: true,
|
||||
presets: ['es2015']
|
||||
}
|
||||
}, {
|
||||
test: /\.json$/, loader: 'json'
|
||||
}, {
|
||||
test: /\.html$/, loader: 'html'
|
||||
}, {
|
||||
test: /\.css$/, loader: 'style!css'
|
||||
}, {
|
||||
test: /\.scss$/, loader: 'style!css!sass'
|
||||
}, {
|
||||
test: /\.(jpe?g|png|gif|svg)$/i, loader: 'url'
|
||||
}, {
|
||||
test: /\.(woff|woff2)$/, loader: 'url?mimetype=application/font-woff'
|
||||
}, {
|
||||
test: /\.ttf$/, loader: 'url'
|
||||
}, {
|
||||
test: /\.eot$/, loader: 'url'
|
||||
}
|
||||
];
|
|
@ -1,5 +0,0 @@
|
|||
import 'angular';
|
||||
import 'angular-mocks';
|
||||
|
||||
let context = require.context('./src/mailbox', true, /\.spec\.js/);
|
||||
context.keys().forEach(context);
|
117
src/app.js
117
src/app.js
|
@ -1,20 +1,123 @@
|
|||
// Vendor-Imports
|
||||
import angular from "angular";
|
||||
import uiRouter from "angular-ui-router";
|
||||
import uiBootstrap from "angular-ui-bootstrap";
|
||||
import "bootstrap/dist/css/bootstrap.css";
|
||||
import "bootstrap/scss/bootstrap.scss";
|
||||
import "babel-polyfill";
|
||||
import angularStickyfill from "angular-stickyfill";
|
||||
import "angular-stickyfill/dist/angular-stickyfill.css";
|
||||
import Mailbox from "./mailbox/mailbox";
|
||||
import {cleanUsername, generateRandomUsername} from "./util";
|
||||
import hasher from "hasher";
|
||||
import Header from "./components/header/header";
|
||||
import List from "./components/list/list";
|
||||
import Mail from "./components/mail/mail";
|
||||
|
||||
|
||||
class AppController {
|
||||
/*@ngInject*/
|
||||
constructor($http, $log, config, $interval) {
|
||||
this.$interval = $interval;
|
||||
this.$http = $http;
|
||||
this.config = config;
|
||||
this.$log = $log;
|
||||
this.$log.log('start controller');
|
||||
this.address = null;
|
||||
this.username = null;
|
||||
this.mails = [];
|
||||
this.state = {isUpdating: false};
|
||||
}
|
||||
|
||||
$onInit() {
|
||||
this.$log.debug("init");
|
||||
|
||||
hasher.changed.add(this.onHashChange.bind(this));
|
||||
hasher.initialized.add(this.onHashChange.bind(this)); //add initialized listener (to grab initial value in case it is already set)
|
||||
hasher.init(); //initialize hasher (start listening for history changes)
|
||||
|
||||
this.intervalPromise = this.$interval(() => this.updateMails(), this.config.reload_interval_ms);
|
||||
}
|
||||
|
||||
$onDestroy() {
|
||||
this.$interval.cancel(this.intervalPromise);
|
||||
}
|
||||
|
||||
onHashChange(hash) {
|
||||
this.updateUsername(hash);
|
||||
}
|
||||
|
||||
onChangeUsername({username}) {
|
||||
this.updateUsername(username);
|
||||
}
|
||||
|
||||
onGotoRandom() {
|
||||
let username = generateRandomUsername();
|
||||
this.updateUsername(username);
|
||||
}
|
||||
|
||||
loadEmails(username) {
|
||||
return this.$http.get(this.config.backend_url, {params: {username: username, action: "get"}})
|
||||
.then(response=> {
|
||||
return response.data;
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
loadEmailsAsync(username) {
|
||||
this.$log.debug("updating mails for ", username);
|
||||
this.state.isUpdating = true;
|
||||
this.loadEmails(this.username).then(data=> {
|
||||
this.mails = data.mails;
|
||||
this.address = data.address;
|
||||
this.username = data.username;
|
||||
this.state.isUpdating = false;
|
||||
this.$log.debug("received mails for ", username);
|
||||
});
|
||||
}
|
||||
|
||||
updateMails() {
|
||||
if (this.username) {
|
||||
this.loadEmailsAsync(this.username);
|
||||
}
|
||||
}
|
||||
|
||||
updateUsername(username) {
|
||||
this.username = cleanUsername(username);
|
||||
if (this.username.length > 0) {
|
||||
hasher.setHash(this.username);
|
||||
this.address = this.username; // use username until real address has been loaded
|
||||
this.updateMails();
|
||||
} else {
|
||||
this.address = null;
|
||||
this.mails = [];
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Interne Modul-Imports
|
||||
|
||||
angular.module('app', [
|
||||
uiRouter, uiBootstrap, Mailbox.name, angularStickyfill
|
||||
List, Mail, angularStickyfill, Header
|
||||
])
|
||||
|
||||
.component('app', {
|
||||
template: `
|
||||
<header
|
||||
username="$ctrl.username"
|
||||
address="$ctrl.address"
|
||||
mailcount="$ctrl.mails.length"
|
||||
on-change-username="$ctrl.onChangeUsername($event)"
|
||||
on-goto-random="$ctrl.onGotoRandom($event)">
|
||||
</header>
|
||||
|
||||
<inbox
|
||||
mails="$ctrl.mails"
|
||||
username="$ctrl.username"
|
||||
address="$ctrl.address"
|
||||
state="$ctrl.state">
|
||||
</inbox>
|
||||
`,
|
||||
controller: AppController
|
||||
})
|
||||
|
||||
.constant('config', {
|
||||
'backend_url': 'http://dubgo.com/m2/backend.php',
|
||||
'backend_url': './backend.php',
|
||||
'reload_interval_ms': 10000
|
||||
})
|
||||
|
|
82
src/components/header/header.js
Normal file
82
src/components/header/header.js
Normal file
|
@ -0,0 +1,82 @@
|
|||
import angular from "angular";
|
||||
import "./header.scss";
|
||||
|
||||
class HeaderController {
|
||||
/*@ngInject*/
|
||||
constructor($log) {
|
||||
this.$log = $log;
|
||||
this.inputFieldUsername = "";
|
||||
}
|
||||
|
||||
$onInit() {
|
||||
this.inputFieldUsername = this.address;
|
||||
}
|
||||
|
||||
$onChanges(changes) {
|
||||
if (changes.address) {
|
||||
this.inputFieldUsername = this.username;
|
||||
this.address = this.address;
|
||||
}
|
||||
}
|
||||
|
||||
gotoMailbox(username) {
|
||||
this.onChangeUsername({
|
||||
$event: {
|
||||
username: username
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
randomize() {
|
||||
this.onGotoRandom();
|
||||
}
|
||||
}
|
||||
|
||||
const HeaderComponent = {
|
||||
bindings: {
|
||||
address: '<',
|
||||
username: '<',
|
||||
mailcount: '<',
|
||||
onChangeUsername: '&',
|
||||
onGotoRandom: '&'
|
||||
},
|
||||
controller: HeaderController,
|
||||
template: `
|
||||
<div class="nav-container">
|
||||
<div class="container">
|
||||
<nav class="navbar navbar-light">
|
||||
<a class="navbar-brand"><span class="octicon-inbox"></span>
|
||||
|
||||
{{$ctrl.address}}
|
||||
|
||||
<span ng-if="$ctrl.mailcount" class="tag tag-pill tag-default">{{$ctrl.mailcount}}</span>
|
||||
</a>
|
||||
|
||||
|
||||
<ul class="nav navbar-nav">
|
||||
|
||||
<button type="button nav-link" class="btn btn-outline-primary pull-xs-right"
|
||||
ng-click="$ctrl.randomize()">
|
||||
<span class="glyphicon glyphicon-random"></span>
|
||||
randomize
|
||||
</button>
|
||||
|
||||
<form class="form-inline pull-xs-right" ng-submit="$ctrl.gotoMailbox($ctrl.inputFieldUsername)">
|
||||
<input ng-model="$ctrl.inputFieldUsername"
|
||||
placeholder="username"
|
||||
type="text" class="form-control"/>
|
||||
<button type="submit" class="btn btn-outline-success">login</button>
|
||||
</form>
|
||||
|
||||
</ul>
|
||||
</nav>
|
||||
</div>
|
||||
</div>
|
||||
`
|
||||
};
|
||||
|
||||
|
||||
export default angular
|
||||
.module('header', [])
|
||||
.component('header', HeaderComponent)
|
||||
.name;
|
11
src/components/header/header.scss
Normal file
11
src/components/header/header.scss
Normal file
|
@ -0,0 +1,11 @@
|
|||
.nav-container {
|
||||
background-color: #D9E2E9;
|
||||
//heigh: 300px;
|
||||
}
|
||||
|
||||
.octicon-inbox {
|
||||
display: inline-block;
|
||||
width: 26px;
|
||||
height: 23px;
|
||||
background: url('octicon-inbox.gif') no-repeat;
|
||||
}
|
BIN
src/components/header/octicon-inbox.gif
Normal file
BIN
src/components/header/octicon-inbox.gif
Normal file
Binary file not shown.
After Width: | Height: | Size: 262 B |
25
src/components/list/list.html
Normal file
25
src/components/list/list.html
Normal file
|
@ -0,0 +1,25 @@
|
|||
<main>
|
||||
<div class="container min-height">
|
||||
<p ng-if="!$ctrl.username">
|
||||
Use the buttons above to create a new inbox, or open a specific mailbox.
|
||||
</p>
|
||||
|
||||
<div ng-if="$ctrl.username && $ctrl.mails.length == 0">
|
||||
<div class="waiting-screen">
|
||||
<h1>{{$ctrl.address}}</h1>
|
||||
<p class="lead">Inbox is empty.</p>
|
||||
<p><br/>
|
||||
<img src="spinner.gif">
|
||||
<br/></p>
|
||||
<p class="lead">Emails to {{address}} will be automatically displayed on this page. </p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div ng-if="$ctrl.username" ng-repeat="mail in $ctrl.mails | orderBy:'-date' track by $index"
|
||||
class="email-table">
|
||||
<mail mail="mail"></mail>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</main>
|
29
src/components/list/list.js
Normal file
29
src/components/list/list.js
Normal file
|
@ -0,0 +1,29 @@
|
|||
import angular from "angular";
|
||||
import template from "./list.html";
|
||||
import "./list.scss";
|
||||
|
||||
|
||||
class ListController {
|
||||
/*@ngInject*/
|
||||
constructor($log) {
|
||||
this.$log = $log;
|
||||
|
||||
// @Input:
|
||||
// this.mails = [];
|
||||
// this.username = null;
|
||||
// this.address = null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
export default angular.module('mailbox.inbox', [])
|
||||
.component('inbox', {
|
||||
template, controller: ListController,
|
||||
bindings: {
|
||||
address: '<',
|
||||
username: '<',
|
||||
mails: '<',
|
||||
state: '<'
|
||||
}
|
||||
})
|
||||
.name;
|
18
src/components/list/list.scss
Normal file
18
src/components/list/list.scss
Normal file
|
@ -0,0 +1,18 @@
|
|||
|
||||
body {
|
||||
background: #eeeeee;
|
||||
}
|
||||
|
||||
footer p {
|
||||
margin-top: 50px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.email-table {
|
||||
margin-top: 20px;
|
||||
}
|
||||
|
||||
div.min-height {
|
||||
min-height: 400px;
|
||||
}
|
||||
|
Before Width: | Height: | Size: 30 KiB After Width: | Height: | Size: 30 KiB |
38
src/components/mail/mail.html
Normal file
38
src/components/mail/mail.html
Normal file
|
@ -0,0 +1,38 @@
|
|||
<section class="email">
|
||||
<div class="row sticky-header" ec-stickyfill>
|
||||
<div class="col-sm-12 email-summary">{{$ctrl.mail.subject}}</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-sm-12 email-headers">
|
||||
<dl>
|
||||
<dt>To:</dt>
|
||||
<dd>{{$ctrl.mail.toString}}</dd>
|
||||
<div ng-if="$ctrl.mail.cc" ng-repeat="(address,name) in $ctrl.mail.cc">
|
||||
<dt>CC:</dt>
|
||||
<dd>{{address}}</dd>
|
||||
</div>
|
||||
<dt>From:</dt>
|
||||
<dd>{{$ctrl.mail.fromName}} <{{$ctrl.mail.fromAddress}}></dd>
|
||||
<dt>Date:</dt>
|
||||
<dd>{{$ctrl.mail.date}}</dd>
|
||||
</dl>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mail-content" ng-init="htmlTabActive=false">
|
||||
|
||||
|
||||
<button ng-show="htmlTabActive" class="btn btn-outline-info btn-sm" ng-click="htmlTabActive=false">show text
|
||||
</button>
|
||||
<button ng-show="$ctrl.mail.textHtml && !htmlTabActive" class="btn btn-outline-info btn-sm"
|
||||
ng-click="htmlTabActive=true">show html
|
||||
</button>
|
||||
|
||||
<div ng-if="!htmlTabActive" ng-bind-html="$ctrl.mail.textPlain | nl2br | autolink "></div>
|
||||
<div ng-if="htmlTabActive" class="mail-conent" ng-bind-html="$ctrl.mail.textHtml"></div>
|
||||
|
||||
</div>
|
||||
</section>
|
||||
|
||||
|
|
@ -1,18 +1,23 @@
|
|||
import angular from 'angular';
|
||||
import uiRouter from 'angular-ui-router';
|
||||
import ngSanitize from 'angular-sanitize';
|
||||
import Autolinker from 'autolinker';
|
||||
|
||||
import template from './mail.html';
|
||||
import controller from './mail.controller';
|
||||
import './mail.scss';
|
||||
import angular from "angular";
|
||||
import ngSanitize from "angular-sanitize";
|
||||
import Autolinker from "autolinker";
|
||||
import template from "./mail.html";
|
||||
import "./mail.scss";
|
||||
|
||||
|
||||
export default angular.module('mailbox.inbox.mail', [uiRouter, ngSanitize])
|
||||
class MailController {
|
||||
/*@ngInject*/
|
||||
constructor() {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default angular.module('mailbox.inbox.mail', [ngSanitize])
|
||||
.component('mail', {
|
||||
template, controller,
|
||||
template,
|
||||
controller: MailController,
|
||||
bindings: {
|
||||
mail: '='
|
||||
mail: '<'
|
||||
}
|
||||
})
|
||||
// http://stackoverflow.com/a/20033625/79461
|
||||
|
@ -29,4 +34,4 @@ export default angular.module('mailbox.inbox.mail', [uiRouter, ngSanitize])
|
|||
return Autolinker.link(data, {truncate: {length: 50, location: 'middle', newWindow: true}});
|
||||
}
|
||||
}
|
||||
);
|
||||
).name;
|
55
src/components/mail/mail.scss
Normal file
55
src/components/mail/mail.scss
Normal file
|
@ -0,0 +1,55 @@
|
|||
$email-border-color: #7C96AB;
|
||||
$email-summary-background: white;
|
||||
$email-header-background: white;
|
||||
|
||||
.sticky-header {
|
||||
top: 0;
|
||||
z-index: 1000;
|
||||
}
|
||||
|
||||
.email {
|
||||
.email-summary {
|
||||
font-weight: bold;
|
||||
border-top: 5px solid $email-border-color;
|
||||
border-bottom: 1px solid $email-border-color;
|
||||
padding: 10px;
|
||||
background-color: $email-summary-background;
|
||||
}
|
||||
|
||||
.email-headers {
|
||||
background-color: $email-header-background;
|
||||
|
||||
dl {
|
||||
padding: 0 0 4px;
|
||||
color: black;
|
||||
overflow: hidden;
|
||||
|
||||
dt {
|
||||
float: left;
|
||||
color: black;
|
||||
margin: 0 3px 0 0;
|
||||
}
|
||||
dd {
|
||||
display: block;
|
||||
overflow: hidden;
|
||||
margin-bottom: .3rem;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.mail-content {
|
||||
background-color: white;
|
||||
padding-left: 20px;
|
||||
overflow: hidden;
|
||||
}
|
||||
}
|
||||
|
||||
.waiting-screen {
|
||||
padding: 40px 15px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
div.min-height {
|
||||
min-height: 400px;
|
||||
}
|
||||
|
|
@ -3,7 +3,7 @@
|
|||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Mailbox</title>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
||||
<meta name="mobile-web-app-capable" content="yes">
|
||||
<meta name="apple-mobile-web-app-capable" content="yes">
|
||||
<meta name="apple-mobile-web-app-status-bar-style" content="black">
|
||||
|
@ -13,12 +13,14 @@
|
|||
</head>
|
||||
<body ng-app="app" ng-cloak>
|
||||
|
||||
<div ui-view></div>
|
||||
<app></app>
|
||||
|
||||
<!--<div ui-view></div>-->
|
||||
|
||||
<footer>
|
||||
<p>Powered by <a href="https://github.com/synox/disposable-mailbox"><strong>synox/disposable-mailbox</strong></a>
|
||||
| <a href="https://github.com/synox/disposable-mailbox"><span class="octicon octicon-mark-github"></span> Fork me on github</a></p>
|
||||
| <a href="https://github.com/synox/disposable-mailbox"><span class="octicon octicon-mark-github"></span> Fork
|
||||
me on github</a></p>
|
||||
</footer>
|
||||
|
||||
|
||||
|
|
|
@ -1,84 +0,0 @@
|
|||
import phonetic from 'phonetic';
|
||||
|
||||
class MailboxController {
|
||||
/*@ngInject*/
|
||||
constructor($log, $interval, config, mailboxService, $rootScope, $stateParams, $state) {
|
||||
this.$rootScope = $rootScope;
|
||||
this.$log = $log;
|
||||
this.$interval = $interval;
|
||||
this.config = config;
|
||||
this.mailboxService = mailboxService;
|
||||
this.mails = [];
|
||||
this.$stateParams = $stateParams;
|
||||
this.$state = $state;
|
||||
this.address = null; // is set when mails are loaded
|
||||
this.state = 'home';
|
||||
}
|
||||
|
||||
$onInit() {
|
||||
if (this.getCurrentUsername()) {
|
||||
this.state = 'loading';
|
||||
this.address = this.getCurrentUsername(); // use username until real address has been loaded
|
||||
this.intervalPromise = this.$interval(() => this.loadMails(), this.config.reload_interval_ms);
|
||||
this.loadMails();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static cleanUsername(username) {
|
||||
return username.replace(/[@].*$/, '');
|
||||
}
|
||||
|
||||
gotoMailbox(username) {
|
||||
username = MailboxController.cleanUsername(username);
|
||||
this.address = username; // use username until real address has been loaded
|
||||
this.$state.go('inbox', {username: username});
|
||||
}
|
||||
|
||||
gotoRandomAddress() {
|
||||
let username = this.generateRandomUsername();
|
||||
this.gotoMailbox(username);
|
||||
}
|
||||
|
||||
generateRandomUsername() {
|
||||
let username = phonetic.generate({syllables: 3, phoneticSimplicity: 1});
|
||||
if (Math.random() >= 0.5) {
|
||||
username += this.getRandomInt(30, 99);
|
||||
}
|
||||
return username.toLowerCase();
|
||||
}
|
||||
|
||||
getRandomInt(min, max) {
|
||||
return Math.floor(Math.random() * (max - min)) + min;
|
||||
}
|
||||
|
||||
$onDestroy() {
|
||||
this.$log.debug("destroying controller");
|
||||
this.$interval.cancel(this.intervalPromise);
|
||||
}
|
||||
|
||||
|
||||
loadMails() {
|
||||
this.mailboxService.loadEmails(this.getCurrentUsername())
|
||||
.then(data => {
|
||||
|
||||
this.mails = data.mails;
|
||||
if (this.mails.length !== 0) {
|
||||
this.state = 'list';
|
||||
} else {
|
||||
this.state = 'empty';
|
||||
}
|
||||
this.address = data.address;
|
||||
this.loadingData = false;
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
getCurrentUsername() {
|
||||
return this.$stateParams.username;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
export default MailboxController;
|
|
@ -1,77 +0,0 @@
|
|||
<div class="navbar" role="navigation">
|
||||
<div class="container">
|
||||
|
||||
<div class="hidden-xs">
|
||||
<div class="navbar-header">
|
||||
<a class="navbar-brand"><span class="octicon-inbox"></span> Mailbox</a>
|
||||
</div>
|
||||
|
||||
<form class="navbar-form navbar-left">
|
||||
<a class="btn btn-default" ng-click="$ctrl.gotoRandomAddress()" role="button">
|
||||
<span class="glyphicon glyphicon-random" aria-hidden="true"></span>
|
||||
create random
|
||||
</a>
|
||||
</form>
|
||||
|
||||
|
||||
<form class="navbar-form navbar-left" role="search" ng-submit="$ctrl.gotoMailbox($ctrl.address)">
|
||||
<input ng-model="$ctrl.address" type='text' class="form-control"/>
|
||||
<button type="submit" class="btn btn-default">open</button>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
|
||||
<form ng-submit="$ctrl.gotoMailbox($ctrl.address)">
|
||||
<div class="form-inline visible-xs-block">
|
||||
<div class="form-group col-xs-4">
|
||||
<span class="octicon-inbox"></span></a>
|
||||
<a class="btn btn-default" ng-click="$ctrl.gotoRandomAddress()" role="button">
|
||||
<span class="glyphicon glyphicon-random" aria-hidden="true"></span>
|
||||
</a>
|
||||
</div>
|
||||
<div class="form-group col-xs-6">
|
||||
<input ng-model="$ctrl.address" type='text' class="form-control"/>
|
||||
</div>
|
||||
<div class="form-group col-xs-2">
|
||||
<button type="submit" class="btn btn-default">open</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<main>
|
||||
<div class="container min-height" ng-switch="$ctrl.state">
|
||||
|
||||
<p ng-switch-when="home">
|
||||
Use the buttons above to create a new inbox, or open a specific mailbox.
|
||||
</p>
|
||||
|
||||
|
||||
<div ng-switch-when="list" ng-repeat="mail in $ctrl.mails | orderBy:'-date' track by $index"
|
||||
class="email-table">
|
||||
<mail mail="mail"></mail>
|
||||
</div>
|
||||
|
||||
<div ng-switch-when="loading" class="waiting-screen">
|
||||
<h1> </h1>
|
||||
<p class="lead">Loading Mails</p>
|
||||
<p><br/>
|
||||
<img src="spinner.gif">
|
||||
<br/>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div ng-switch-when="empty">
|
||||
<div class="waiting-screen">
|
||||
<h1>{{$ctrl.address}}</h1>
|
||||
<p class="lead">Inbox is empty.</p>
|
||||
<p><br/>
|
||||
<img src="spinner.gif">
|
||||
<br/></p>
|
||||
<p class="lead">Emails to {{address}} will be automatically displayed on this page. </p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
|
@ -1,14 +0,0 @@
|
|||
import angular from 'angular';
|
||||
import uiRouter from 'angular-ui-router';
|
||||
|
||||
import template from './inbox.html';
|
||||
import controller from './inbox.controller';
|
||||
import './inbox.scss';
|
||||
|
||||
export default angular.module('mailbox.inbox', [uiRouter])
|
||||
.component('inbox', {
|
||||
template, controller,
|
||||
bindings: {
|
||||
data: '<'
|
||||
}
|
||||
})
|
|
@ -1,33 +0,0 @@
|
|||
body {
|
||||
background: #eeeeee;
|
||||
}
|
||||
|
||||
footer p {
|
||||
margin-top: 50px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.email-table {
|
||||
margin-top: 20px;
|
||||
background: white;
|
||||
}
|
||||
|
||||
.waiting-screen {
|
||||
padding: 40px 15px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
div.min-height {
|
||||
min-height: 400px;
|
||||
}
|
||||
|
||||
.navbar {
|
||||
background-color: #D9E2E9;
|
||||
}
|
||||
|
||||
.octicon-inbox {
|
||||
display: inline-block;
|
||||
width: 26px;
|
||||
height: 23px;
|
||||
background: url('octicon-inbox.png') no-repeat;
|
||||
}
|
|
@ -1,4 +0,0 @@
|
|||
describe('not tests', () => {
|
||||
it('should run anyway', () => {
|
||||
});
|
||||
});
|
Binary file not shown.
Before Width: | Height: | Size: 7.0 KiB |
|
@ -1,8 +0,0 @@
|
|||
class MailController {
|
||||
/*@ngInject*/
|
||||
constructor() {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default MailController;
|
|
@ -1,45 +0,0 @@
|
|||
<section class="email">
|
||||
<div class="row sticky-header" ec-stickyfill>
|
||||
<div class="col-sm-12 email-summary">{{$ctrl.mail.subject}}</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-sm-12 email-headers">
|
||||
<dl>
|
||||
<dt>To:</dt>
|
||||
<dd>{{$ctrl.mail.toString}}</dd>
|
||||
<div ng-if="$ctrl.mail.cc" ng-repeat="(address,name) in $ctrl.mail.cc">
|
||||
<dt>CC:</dt>
|
||||
<dd>{{address}}</dd>
|
||||
</div>
|
||||
<dt>From:</dt>
|
||||
<dd>{{$ctrl.mail.fromName}} <{{$ctrl.mail.fromAddress}}></dd>
|
||||
<dt>Date:</dt>
|
||||
<dd>{{$ctrl.mail.date}}</dd>
|
||||
</dl>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div class="row email-tabs">
|
||||
<!-- if there is no html content, just show text: -->
|
||||
<div ng-if="!$ctrl.mail.textHtml" ng-bind-html="$ctrl.mail.textPlain | nl2br | autolink" class="mail-conent">
|
||||
</div>
|
||||
|
||||
<!-- else show tabs with plain text and html:-->
|
||||
<uib-tabset ng-if="$ctrl.mail.textHtml" active="1">
|
||||
<uib-tab index="1">
|
||||
<uib-tab-heading><i class="glyphicon glyphicon-align-left"></i> text</uib-tab-heading>
|
||||
<div class="mail-conent" ng-bind-html="$ctrl.mail.textPlain | nl2br | autolink "></div>
|
||||
</uib-tab>
|
||||
|
||||
<uib-tab index="2" select="htmlActive=true">
|
||||
<uib-tab-heading><i class="glyphicon glyphicon-picture"></i> html</uib-tab-heading>
|
||||
<!-- only load htl content when tab is activated. this avoids loading images from other servers.-->
|
||||
<div class="mail-conent" ng-if="htmlActive" ng-bind-html="$ctrl.mail.textHtml"></div>
|
||||
</uib-tab>
|
||||
|
||||
</uib-tabset>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
|
|
@ -1,77 +0,0 @@
|
|||
$email-border-color: #7C96AB;
|
||||
$email-summary-background: white;
|
||||
$email-header-background: white;
|
||||
|
||||
$tab-button-color: white;
|
||||
$tab-button-color-inactive: #e0e0e0;
|
||||
$tab-content-background: white;
|
||||
|
||||
.sticky-header {
|
||||
top: 0;
|
||||
z-index: 1000;
|
||||
}
|
||||
|
||||
.email {
|
||||
.email-summary {
|
||||
font-weight: bold;
|
||||
border-top: 5px solid $email-border-color;
|
||||
border-bottom: 1px solid $email-border-color;
|
||||
padding: 10px;
|
||||
background-color: $email-summary-background;
|
||||
}
|
||||
|
||||
.email-headers {
|
||||
background-color: $email-header-background;
|
||||
|
||||
dl {
|
||||
padding: 0 0 4px;
|
||||
color: black;
|
||||
overflow: hidden;
|
||||
|
||||
dt {
|
||||
float: left;
|
||||
color: black;
|
||||
margin: 0 3px 0 0;
|
||||
}
|
||||
dd {
|
||||
display: block;
|
||||
overflow: hidden;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.email-tabs {
|
||||
background-color: $email-header-background;
|
||||
border-bottom: 1px solid $email-border-color;
|
||||
|
||||
.nav {
|
||||
padding-left: 10px;
|
||||
}
|
||||
|
||||
.mail-conent {
|
||||
background-color: $tab-content-background;
|
||||
padding: 20px;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
/* Tab Button (disabled)*/
|
||||
.nav-tabs > li.disabled > a:hover,
|
||||
.nav-tabs > li.disabled > a:focus {
|
||||
background-color: $tab-button-color-inactive;
|
||||
}
|
||||
|
||||
/* Tab Button (incative)*/
|
||||
.nav-tabs > li > a {
|
||||
background-color: $tab-button-color-inactive;
|
||||
}
|
||||
|
||||
/* Tab Button (active)*/
|
||||
.nav-tabs > li.active > a,
|
||||
.nav-tabs > li.active > a:hover,
|
||||
.nav-tabs > li.active > a:focus {
|
||||
background-color: $tab-button-color;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -1,19 +0,0 @@
|
|||
import angular from 'angular';
|
||||
import uiRouter from 'angular-ui-router';
|
||||
import Service from './service/mailbox.service'
|
||||
import Inbox from './inbox/inbox';
|
||||
import Mail from './mail/mail'
|
||||
|
||||
let module = angular.module('mailbox', [uiRouter, Inbox.name, Mail.name])
|
||||
.config(/*@ngInject*/($stateProvider, $urlRouterProvider) => {
|
||||
|
||||
$urlRouterProvider.otherwise('/');
|
||||
|
||||
$stateProvider.state('inbox', {
|
||||
url: '/:username',
|
||||
component: 'inbox'
|
||||
});
|
||||
})
|
||||
.service('mailboxService', Service);
|
||||
|
||||
export default module;
|
|
@ -1,18 +0,0 @@
|
|||
class MailboxService {
|
||||
/*@ngInject*/
|
||||
constructor($http, $log, $state, $stateParams, config) {
|
||||
this.$http = $http;
|
||||
this.config = config;
|
||||
}
|
||||
|
||||
loadEmails(username) {
|
||||
return this.$http.get(this.config.backend_url, {params: {username: username, action: "get"}})
|
||||
.then(response=> {
|
||||
return response.data;
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default MailboxService;
|
17
src/util.js
Normal file
17
src/util.js
Normal file
|
@ -0,0 +1,17 @@
|
|||
import phonetic from "phonetic";
|
||||
|
||||
export function generateRandomUsername() {
|
||||
let username = phonetic.generate({syllables: 3, phoneticSimplicity: 1});
|
||||
if (Math.random() >= 0.5) {
|
||||
username += this.getRandomInt(30, 99);
|
||||
}
|
||||
return username.toLowerCase();
|
||||
}
|
||||
|
||||
function getRandomInt(min, max) {
|
||||
return Math.floor(Math.random() * (max - min)) + min;
|
||||
}
|
||||
|
||||
export function cleanUsername(username) {
|
||||
return username.replace(/[@].*$/, '');
|
||||
}
|
|
@ -1,90 +1,123 @@
|
|||
var webpack = require('webpack');
|
||||
var extend = require('node.extend');
|
||||
var path = require('path');
|
||||
var browserSyncPlugin = require('browser-sync-webpack-plugin');
|
||||
var ngAnnotatePlugin = require('ng-annotate-webpack-plugin');
|
||||
var HtmlWebpackPlugin = require('html-webpack-plugin');
|
||||
var webjsConfig = require('./shared.build.config');
|
||||
var url = require('url');
|
||||
var proxyMiddleware = require('proxy-middleware');
|
||||
var validate = require('webpack-validator');
|
||||
var merge = require('webpack-merge');
|
||||
|
||||
/**
|
||||
* Gemeinsame Konfigurationsdatei fuer Webpack (der Teil, der fuer alle Umgebungen gleich ist)
|
||||
* @type {} Webpack Konfiguration
|
||||
*/
|
||||
var commonConfig = {
|
||||
var TARGET = process.env.npm_lifecycle_event;
|
||||
|
||||
// based on https://github.com/gaearon/react-hot-boilerplate
|
||||
const commonConfig = {
|
||||
context: path.resolve(__dirname, 'src'),
|
||||
// Einstiegspunkt fuer Webpack
|
||||
entry: {
|
||||
mailbox: './app.js'
|
||||
// angular: 'angular',
|
||||
// anguboot: 'angular-ui-bootstrap',
|
||||
// angurouter: 'angular-ui-router',
|
||||
// bootcss: 'bootstrap/dist/css/bootstrap.css',
|
||||
// angusan: 'angular-sanitize',
|
||||
// autolinker: 'autolinker',
|
||||
// babelpolyfill: 'babel-polyfill',
|
||||
// phonetic: 'phonetic'
|
||||
},
|
||||
entry: [
|
||||
'./app.js'
|
||||
],
|
||||
output: {
|
||||
path: path.join(__dirname, 'dist'),
|
||||
filename: '[name]bundle.js'
|
||||
},
|
||||
// Modulkonfiguration fuer alle Dateitypen, welcher Loader soll verwendet werden
|
||||
module: {
|
||||
loaders: webjsConfig.webpackLoaders
|
||||
},
|
||||
resolve: {
|
||||
fallback: path.join(__dirname, 'node_modules')
|
||||
},
|
||||
resolveLoader: {fallback: path.join(__dirname, 'node_modules')}
|
||||
};
|
||||
|
||||
/**
|
||||
* Production Konfigurationsdatei fuer Webpack (der Teil, der nur fuer den produktiven Build ist)
|
||||
* @type {} Webpack Konfiguration
|
||||
*/
|
||||
var production = extend({}, commonConfig, {
|
||||
output: {
|
||||
path: path.join(__dirname, 'target/build'),
|
||||
filename: '[name]_[hash].js'
|
||||
filename: 'bundle_[hash].js'
|
||||
},
|
||||
plugins: [
|
||||
new ngAnnotatePlugin({add: true}),
|
||||
new webpack.optimize.DedupePlugin(),
|
||||
new webpack.NoErrorsPlugin(),
|
||||
new webpack.optimize.UglifyJsPlugin({
|
||||
minimize: true,
|
||||
compress: {
|
||||
warnings: true
|
||||
},
|
||||
sourceMap: false
|
||||
}),
|
||||
// add js files
|
||||
new HtmlWebpackPlugin({
|
||||
template: './index.html'
|
||||
})
|
||||
]
|
||||
});
|
||||
|
||||
// development config
|
||||
|
||||
// forward requests (you may also have to change "backend_url" in app.js
|
||||
var proxyOptions = url.parse('http://localhost:8080');
|
||||
proxyOptions.route = '/backend.php';
|
||||
|
||||
var development = extend({}, commonConfig, {
|
||||
plugins: [
|
||||
new browserSyncPlugin({
|
||||
proxy: 'localhost:3000',
|
||||
middleware: proxyMiddleware(proxyOptions)
|
||||
}),
|
||||
new HtmlWebpackPlugin({
|
||||
template: './index.html'
|
||||
})
|
||||
],
|
||||
watch: true,
|
||||
devtool: 'source-map'
|
||||
});
|
||||
module: {
|
||||
loaders: [
|
||||
{
|
||||
test: /\.json$/, loader: 'json'
|
||||
}, {
|
||||
test: /\.html$/, loader: 'html'
|
||||
}, {
|
||||
test: /\.css$/, loader: 'style!css'
|
||||
}, {
|
||||
test: /\.scss$/, loader: 'style!css!sass'
|
||||
}, {
|
||||
test: /\.(jpe?g|png|gif|svg)$/i, loader: 'url'
|
||||
}, {
|
||||
test: /\.(woff|woff2)$/, loader: 'url?mimetype=application/font-woff'
|
||||
}, {
|
||||
test: /\.ttf$/, loader: 'url'
|
||||
}, {
|
||||
test: /\.eot$/, loader: 'url'
|
||||
}
|
||||
|
||||
]
|
||||
}
|
||||
};
|
||||
|
||||
var config;
|
||||
switch (TARGET) {
|
||||
case 'size':
|
||||
case 'build':
|
||||
config = merge(commonConfig, {
|
||||
plugins: [
|
||||
new webpack.optimize.DedupePlugin(),
|
||||
new webpack.optimize.UglifyJsPlugin({
|
||||
minimize: true,
|
||||
compress: {
|
||||
warnings: false
|
||||
}
|
||||
}),
|
||||
new webpack.DefinePlugin({
|
||||
DEVELOPMENT: JSON.stringify(false)
|
||||
}),
|
||||
new webpack.DefinePlugin({
|
||||
'process.env': {
|
||||
'NODE_ENV': JSON.stringify('production')
|
||||
}
|
||||
})
|
||||
|
||||
],
|
||||
// without react-hot in prod
|
||||
module: {
|
||||
loaders: [
|
||||
{
|
||||
test: /\.js$/, exclude: [/node_modules/],
|
||||
loader: 'babel',
|
||||
query: {
|
||||
// https://github.com/babel/babel-loader#options
|
||||
cacheDirectory: true,
|
||||
presets: ['es2015']
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
});
|
||||
break;
|
||||
default:
|
||||
// develop
|
||||
config = merge(commonConfig, {
|
||||
devtool: 'eval',
|
||||
plugins: [
|
||||
new webpack.HotModuleReplacementPlugin(),
|
||||
new webpack.DefinePlugin({
|
||||
DEVELOPMENT: JSON.stringify(true)
|
||||
})
|
||||
],
|
||||
module: {
|
||||
loaders: [
|
||||
{
|
||||
test: /\.js$/,
|
||||
loaders: ['babel'],
|
||||
include: path.join(__dirname, 'src')
|
||||
},
|
||||
]
|
||||
}
|
||||
|
||||
});
|
||||
// replace entry instead of merge
|
||||
config.entry = [
|
||||
'webpack-dev-server/client?http://localhost:3000',
|
||||
'webpack/hot/only-dev-server',
|
||||
'./app.js'
|
||||
];
|
||||
}
|
||||
|
||||
if (TARGET === "size") {
|
||||
// no validation with size target
|
||||
module.exports = config;
|
||||
} else {
|
||||
module.exports = validate(config);
|
||||
}
|
||||
|
||||
module.exports = {production: production, development: development};
|
Loading…
Reference in New Issue
Block a user