mirror of
https://gitlab.silvrtree.co.uk/martind2000/temptest.git
synced 2025-01-10 20:45:07 +00:00
init
This commit is contained in:
commit
d332140d32
55
.eslintrc.json
Normal file
55
.eslintrc.json
Normal file
@ -0,0 +1,55 @@
|
||||
{
|
||||
"parserOptions": {
|
||||
"ecmaVersion": 6,
|
||||
"sourceType": "module",
|
||||
"ecmaFeatures": {
|
||||
"jsx": false
|
||||
}
|
||||
},
|
||||
"env": {
|
||||
"browser": true,
|
||||
"node": true,
|
||||
"es6": true
|
||||
},
|
||||
"rules": {
|
||||
"arrow-spacing": "error",
|
||||
"block-scoped-var": "error",
|
||||
"block-spacing": "error",
|
||||
"brace-style": ["error", "stroustrup", {}],
|
||||
"camelcase": "error",
|
||||
"comma-dangle": ["error", "never"],
|
||||
"comma-spacing": ["error", { "before": false, "after": true }],
|
||||
"comma-style": [1, "last"],
|
||||
"consistent-this": [1, "_this"],
|
||||
"curly": [1, "multi"],
|
||||
"eol-last": 1,
|
||||
"eqeqeq": 1,
|
||||
"func-names": 1,
|
||||
"indent": ["error", 2, { "SwitchCase": 1 }],
|
||||
"lines-around-comment": ["error", { "beforeBlockComment": true, "allowArrayStart": true }],
|
||||
"max-len": [1, 120, 2], // 2 spaces per tab, max 80 chars per line
|
||||
"new-cap": 1,
|
||||
"newline-before-return": "error",
|
||||
"no-array-constructor": 1,
|
||||
"no-inner-declarations": [1, "both"],
|
||||
"no-mixed-spaces-and-tabs": 1,
|
||||
"no-multi-spaces": 2,
|
||||
"no-new-object": 1,
|
||||
"no-shadow-restricted-names": 1,
|
||||
"object-curly-spacing": ["error", "always"],
|
||||
"padded-blocks": ["error", { "blocks": "never", "switches": "always" }],
|
||||
"prefer-const": "error",
|
||||
"prefer-template": "error",
|
||||
"one-var": 0,
|
||||
"quote-props": ["error", "always"],
|
||||
"quotes": [1, "single"],
|
||||
"radix": 1,
|
||||
"semi": [1, "always"],
|
||||
"space-before-blocks": [1, "always"],
|
||||
"space-infix-ops": 1,
|
||||
"vars-on-top": 1,
|
||||
"no-multiple-empty-lines": ["error", { "max": 1, "maxEOF": 1 }],
|
||||
"spaced-comment": ["error", "always", { "markers": ["/"] }]
|
||||
}
|
||||
|
||||
}
|
146
.gitignore
vendored
Normal file
146
.gitignore
vendored
Normal file
@ -0,0 +1,146 @@
|
||||
# Created by .ignore support plugin (hsz.mobi)
|
||||
### Node template
|
||||
# Logs
|
||||
logs
|
||||
*.log
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
|
||||
# Runtime data
|
||||
pids
|
||||
*.pid
|
||||
*.seed
|
||||
*.pid.lock
|
||||
|
||||
# Directory for instrumented libs generated by jscoverage/JSCover
|
||||
lib-cov
|
||||
|
||||
# Coverage directory used by tools like istanbul
|
||||
coverage
|
||||
|
||||
# nyc test coverage
|
||||
.nyc_output
|
||||
|
||||
# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
|
||||
.grunt
|
||||
|
||||
# Bower dependency directory (https://bower.io/)
|
||||
bower_components
|
||||
|
||||
# node-waf configuration
|
||||
.lock-wscript
|
||||
|
||||
# Compiled binary addons (https://nodejs.org/api/addons.html)
|
||||
build/Release
|
||||
|
||||
# Dependency directories
|
||||
node_modules/
|
||||
jspm_packages/
|
||||
|
||||
# Typescript v1 declaration files
|
||||
typings/
|
||||
|
||||
# Optional npm cache directory
|
||||
.npm
|
||||
|
||||
# Optional eslint cache
|
||||
.eslintcache
|
||||
|
||||
# Optional REPL history
|
||||
.node_repl_history
|
||||
|
||||
# Output of 'npm pack'
|
||||
*.tgz
|
||||
|
||||
# Yarn Integrity file
|
||||
.yarn-integrity
|
||||
|
||||
# dotenv environment variables file
|
||||
.env
|
||||
|
||||
### macOS template
|
||||
# General
|
||||
.DS_Store
|
||||
.AppleDouble
|
||||
.LSOverride
|
||||
|
||||
# Icon must end with two \r
|
||||
Icon
|
||||
|
||||
# Thumbnails
|
||||
._*
|
||||
|
||||
# Files that might appear in the root of a volume
|
||||
.DocumentRevisions-V100
|
||||
.fseventsd
|
||||
.Spotlight-V100
|
||||
.TemporaryItems
|
||||
.Trashes
|
||||
.VolumeIcon.icns
|
||||
.com.apple.timemachine.donotpresent
|
||||
|
||||
# Directories potentially created on remote AFP share
|
||||
.AppleDB
|
||||
.AppleDesktop
|
||||
Network Trash Folder
|
||||
Temporary Items
|
||||
.apdisk
|
||||
### JetBrains template
|
||||
# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and Webstorm
|
||||
# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
|
||||
|
||||
.idea/
|
||||
# User-specific stuff:
|
||||
.idea/**/workspace.xml
|
||||
.idea/**/tasks.xml
|
||||
.idea/dictionaries
|
||||
|
||||
# Sensitive or high-churn files:
|
||||
.idea/**/dataSources/
|
||||
.idea/**/dataSources.ids
|
||||
.idea/**/dataSources.xml
|
||||
.idea/**/dataSources.local.xml
|
||||
.idea/**/sqlDataSources.xml
|
||||
.idea/**/dynamic.xml
|
||||
.idea/**/uiDesigner.xml
|
||||
|
||||
# Gradle:
|
||||
.idea/**/gradle.xml
|
||||
.idea/**/libraries
|
||||
|
||||
# CMake
|
||||
cmake-build-debug/
|
||||
|
||||
# Mongo Explorer plugin:
|
||||
.idea/**/mongoSettings.xml
|
||||
|
||||
## File-based project format:
|
||||
*.iws
|
||||
|
||||
## Plugin-specific files:
|
||||
|
||||
# IntelliJ
|
||||
out/
|
||||
|
||||
# mpeltonen/sbt-idea plugin
|
||||
.idea_modules/
|
||||
|
||||
# JIRA plugin
|
||||
atlassian-ide-plugin.xml
|
||||
|
||||
# Cursive Clojure plugin
|
||||
.idea/replstate.xml
|
||||
|
||||
# Crashlytics plugin (for Android Studio and IntelliJ)
|
||||
com_crashlytics_export_strings.xml
|
||||
crashlytics.properties
|
||||
crashlytics-build.properties
|
||||
fabric.properties
|
||||
|
||||
# Elastic Beanstalk Files
|
||||
.elasticbeanstalk/*
|
||||
!.elasticbeanstalk/*.cfg.yml
|
||||
!.elasticbeanstalk/*.global.yml
|
||||
/src/bundle.js
|
||||
/src/bundle.js.map
|
69
Readme.md
Normal file
69
Readme.md
Normal file
@ -0,0 +1,69 @@
|
||||
# Wipro OpenWeatherMap App
|
||||
|
||||
|
||||
## Intro
|
||||
|
||||
An application written in Javascript, utilising Backbone on the front end and Express on the back end.
|
||||
|
||||
The application is a single HTML page displaying the 5 day weather forecast for a location of my choice. In this case it is [Glasgow City](http://nurl.co/QD).
|
||||
|
||||
A live version of the application can be viewed at: [http://wiprotest-dev.eu-west-1.elasticbeanstalk.com](http://wiprotest-dev.eu-west-1.elasticbeanstalk.com)
|
||||
|
||||
## Installation
|
||||
|
||||
To install this application, it should be cloned from the repo:
|
||||
|
||||
```
|
||||
|
||||
git clone https://github.com/martind2000/wiprotest.git
|
||||
|
||||
```
|
||||
|
||||
Once the code has been retrieved you have to install the node packages:
|
||||
|
||||
```
|
||||
|
||||
npm install
|
||||
|
||||
```
|
||||
|
||||
This will install and build the app.
|
||||
|
||||
## How to use
|
||||
|
||||
Once the node packages have been installed the application is almost ready to run.
|
||||
|
||||
An OpenWeatherMap API key is required, if you do not already have one, then you can get one for free by going to this address: [http://openweathermap.org/appid](http://openweathermap.org/appid)
|
||||
|
||||
Once an APPID key has been obtained the application can be run by using the following
|
||||
|
||||
```
|
||||
|
||||
openweatherAPI=<APPID> npm start
|
||||
|
||||
```
|
||||
|
||||
replace \<APPID\> with your appid, such as:
|
||||
|
||||
```
|
||||
|
||||
openweatherAPI=b1b15e88fa797225412429c1 npm start
|
||||
|
||||
```
|
||||
|
||||
## Test
|
||||
|
||||
This application is currently tested using Mocha and Expect.js. The test is in the /test folder.
|
||||
|
||||
To run the test, run the following command.
|
||||
|
||||
```
|
||||
|
||||
npm test
|
||||
|
||||
```
|
||||
|
||||
## Todo
|
||||
|
||||
* Enhance the build process to merge the font and weather icon css, the Material UI css and the colour css into one file to reduce the number of server requests from 3 to 1.
|
||||
* Better testing. Currently the tests are simple for brevity, however I would like to implement Browser testing to ensure the view portion of the code is working as intended.
|
29
gulp/backbone.js
Normal file
29
gulp/backbone.js
Normal file
@ -0,0 +1,29 @@
|
||||
'use strict';
|
||||
const gulp = require('gulp');
|
||||
const browserify = require('gulp-browserify');
|
||||
const rename = require('gulp-rename');
|
||||
|
||||
const buffer = require('vinyl-buffer');
|
||||
const sourcemaps = require('gulp-sourcemaps');
|
||||
|
||||
gulp.task('bundleBackbone', function() {
|
||||
// Single entry point to browserify
|
||||
gulp.src(['./src/backbone/js/app.js'])
|
||||
.pipe(browserify({
|
||||
'insertGlobals' : true,
|
||||
'debug' : true
|
||||
}))
|
||||
.pipe(buffer())
|
||||
// optional, remove if you dont want sourcemaps
|
||||
.pipe(sourcemaps.init({ 'loadMaps': true })) // loads map from browserify file
|
||||
// Add transformation tasks to the pipeline here.
|
||||
.pipe(sourcemaps.write('./src/backbone/')) // writes .map file
|
||||
.pipe(rename('bundle.js'))
|
||||
// .pipe(uglify())
|
||||
.pipe(gulp.dest('./src/backbone/'));
|
||||
});
|
||||
|
||||
gulp.task('buildBackbone', ['bundleBackbone'], function() {
|
||||
gulp.watch('src/backbone/js/**/*.js', ['bundleBackbone']);
|
||||
});
|
||||
|
5
gulpfile.js
Normal file
5
gulpfile.js
Normal file
@ -0,0 +1,5 @@
|
||||
const gulp = require('gulp');
|
||||
|
||||
const requireDir = require('require-dir');
|
||||
|
||||
requireDir('./gulp');
|
39
old-gulpfile.js
Normal file
39
old-gulpfile.js
Normal file
@ -0,0 +1,39 @@
|
||||
'use strict';
|
||||
|
||||
const watchify = require('watchify');
|
||||
const browserify = require('browserify');
|
||||
const gulp = require('gulp');
|
||||
const source = require('vinyl-source-stream');
|
||||
const buffer = require('vinyl-buffer');
|
||||
const gutil = require('gulp-util');
|
||||
const sourcemaps = require('gulp-sourcemaps');
|
||||
const assign = require('lodash.assign');
|
||||
|
||||
// add custom browserify options here
|
||||
const customOpts = {
|
||||
entries: ['./src/js/app.js'],
|
||||
debug: true
|
||||
};
|
||||
const opts = assign({}, watchify.args, customOpts);
|
||||
const b = watchify(browserify(opts));
|
||||
|
||||
// add transformations here
|
||||
// i.e. b.transform(coffeeify);
|
||||
|
||||
gulp.task('js', bundle); // so you can run `gulp js` to build the file
|
||||
b.on('update', bundle); // on any dep update, runs the bundler
|
||||
b.on('log', gutil.log); // output build logs to terminal
|
||||
|
||||
function bundle() {
|
||||
return b.bundle()
|
||||
// log errors if they happen
|
||||
.on('error', gutil.log.bind(gutil, 'Browserify Error'))
|
||||
.pipe(source('bundle.js'))
|
||||
// optional, remove if you don't need to buffer file contents
|
||||
.pipe(buffer())
|
||||
// optional, remove if you dont want sourcemaps
|
||||
.pipe(sourcemaps.init({loadMaps: true})) // loads map from browserify file
|
||||
// Add transformation tasks to the pipeline here.
|
||||
.pipe(sourcemaps.write('./')) // writes .map file
|
||||
.pipe(gulp.dest('./src'));
|
||||
}
|
7651
package-lock.json
generated
Normal file
7651
package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
52
package.json
Normal file
52
package.json
Normal file
@ -0,0 +1,52 @@
|
||||
{
|
||||
"name": "wiprotest",
|
||||
"version": "1.0.0",
|
||||
"description": "Wipro Weather Test",
|
||||
"main": "server.js",
|
||||
"scripts": {
|
||||
"build": "gulp js",
|
||||
"prestart": "browserify -g uglifyify src/backbone/js/app.js -o src/backbone/bundle.js",
|
||||
"test": "./node_modules/mocha/bin/mocha --reporter spec",
|
||||
"postinstall": "browserify -g uglifyify src/backbone/js/app.js -o src/backbone/bundle.js",
|
||||
"start": "node server.js"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/martind2000/wiprotest.git"
|
||||
},
|
||||
"author": "Martin Donnelly <martind2000@gmail.com>",
|
||||
"license": "ISC",
|
||||
"bugs": {
|
||||
"url": "https://github.com/martind2000/wiprotest/issues"
|
||||
},
|
||||
"homepage": "https://github.com/martind2000/wiprotest#readme",
|
||||
"dependencies": {
|
||||
"apicache": "^1.1.0",
|
||||
"backbone": "^1.3.3",
|
||||
"browserify": "^14.4.0",
|
||||
"express": "^4.16.1",
|
||||
"jquery": "^3.2.1",
|
||||
"log4js": "^2.3.4",
|
||||
"moment": "^2.18.1",
|
||||
"openweather-apis": "^3.3.2",
|
||||
"react": "^16.0.0",
|
||||
"uglifyify": "^4.0.4",
|
||||
"underscore": "^1.8.3"
|
||||
},
|
||||
"devDependencies": {
|
||||
"expect.js": "^0.3.1",
|
||||
"gulp": "^3.9.1",
|
||||
"gulp-browserify": "^0.5.1",
|
||||
"gulp-rename": "^1.2.2",
|
||||
"gulp-sourcemaps": "^2.6.1",
|
||||
"gulp-tasks": "0.0.2",
|
||||
"gulp-uglify": "^3.0.0",
|
||||
"lodash.assign": "^4.2.0",
|
||||
"mocha": "^3.5.3",
|
||||
"require-dir": "^0.3.2",
|
||||
"sinon": "^4.0.0",
|
||||
"vinyl-buffer": "^1.0.0",
|
||||
"vinyl-source-stream": "^1.1.0",
|
||||
"watchify": "^3.9.0"
|
||||
}
|
||||
}
|
34
server.js
Normal file
34
server.js
Normal file
@ -0,0 +1,34 @@
|
||||
const express = require('express');
|
||||
const path = require('path');
|
||||
const apicache = require('apicache');
|
||||
const logger = require('log4js').getLogger('Server');
|
||||
const weather = require('./server/weather');
|
||||
|
||||
logger.level = 'debug';
|
||||
|
||||
const app = express();
|
||||
const port = process.env.PORT || 3000;
|
||||
|
||||
const sitePath = 'src';
|
||||
|
||||
apicache.options({ 'debug': true });
|
||||
const cache = apicache.middleware;
|
||||
|
||||
app.use(express.static(path.join(__dirname, sitePath)));
|
||||
|
||||
app.get('/weather', cache('20 minutes'), (req, res) => {
|
||||
weather.doGetOpenWeather()
|
||||
.then((d) => {
|
||||
res.send(d);
|
||||
}).catch((e) => {
|
||||
logger.error(e);
|
||||
res.status(500).send('There was an error!');
|
||||
});
|
||||
});
|
||||
|
||||
app.listen(port, (err) => {
|
||||
if (err)
|
||||
return logger.error('Server error:', err);
|
||||
|
||||
logger.info(`Weather Server is listening on ${port}`);
|
||||
});
|
25
server/weather.js
Normal file
25
server/weather.js
Normal file
@ -0,0 +1,25 @@
|
||||
|
||||
const logger = require('log4js').getLogger('Weather');
|
||||
const weather = require('openweather-apis');
|
||||
|
||||
logger.level = 'debug';
|
||||
|
||||
const openWeatherApiKey = process.env.openweatherAPI || '';
|
||||
|
||||
weather.setAPPID(openWeatherApiKey);
|
||||
weather.setLang('en');
|
||||
weather.setCity('Glasgow City');
|
||||
|
||||
function doGetOpenWeather() {
|
||||
return new Promise((resolve, reject) => {
|
||||
weather.getWeatherForecastForDays(5, function(err, wData) {
|
||||
if (err)
|
||||
return reject(err);
|
||||
else
|
||||
return resolve(wData);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
module.exports.doGetOpenWeather = doGetOpenWeather;
|
||||
|
24
src/angular/index.html
Normal file
24
src/angular/index.html
Normal file
@ -0,0 +1,24 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<title>Weather - Angular</title>
|
||||
<link href="//fonts.googleapis.com/css?family=Roboto+Slab:700-Ubuntu:500-Roboto:regular" rel="stylesheet">
|
||||
<link href="//cdn.muicss.com/mui-0.9.26/css/mui.min.css" rel="stylesheet" type="text/css"/>
|
||||
<link href="//cdnjs.cloudflare.com/ajax/libs/weather-icons/2.0.9/css/weather-icons.css" rel="stylesheet" type="text/css"/>
|
||||
<link href="/css/common.css" rel="stylesheet" type="text/css"/>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<div class="mui-container">
|
||||
<div class="mui--text-display3">Weather Angular</div>
|
||||
<div id="weather"></div>
|
||||
</div>
|
||||
<script src="//cdn.muicss.com/mui-0.9.26/js/mui.min.js"></script>
|
||||
|
||||
</body>
|
||||
|
||||
</html>
|
||||
|
24
src/aurelia/index.html
Normal file
24
src/aurelia/index.html
Normal file
@ -0,0 +1,24 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<title>Weather - Aurelia</title>
|
||||
<link href="//fonts.googleapis.com/css?family=Roboto+Slab:700-Ubuntu:500-Roboto:regular" rel="stylesheet">
|
||||
<link href="//cdn.muicss.com/mui-0.9.26/css/mui.min.css" rel="stylesheet" type="text/css"/>
|
||||
<link href="//cdnjs.cloudflare.com/ajax/libs/weather-icons/2.0.9/css/weather-icons.css" rel="stylesheet" type="text/css"/>
|
||||
<link href="/css/common.css" rel="stylesheet" type="text/css"/>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<div class="mui-container">
|
||||
<div class="mui--text-display3">Weather Aurelia</div>
|
||||
<div id="weather"></div>
|
||||
</div>
|
||||
<script src="//cdn.muicss.com/mui-0.9.26/js/mui.min.js"></script>
|
||||
|
||||
</body>
|
||||
|
||||
</html>
|
||||
|
19690
src/backbone/bundle.js
Normal file
19690
src/backbone/bundle.js
Normal file
File diff suppressed because it is too large
Load Diff
24
src/backbone/index.html
Normal file
24
src/backbone/index.html
Normal file
@ -0,0 +1,24 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<title>Weather - Backbone</title>
|
||||
<link href="//fonts.googleapis.com/css?family=Roboto+Slab:700-Ubuntu:500-Roboto:regular" rel="stylesheet">
|
||||
<link href="//cdn.muicss.com/mui-0.9.26/css/mui.min.css" rel="stylesheet" type="text/css"/>
|
||||
<link href="//cdnjs.cloudflare.com/ajax/libs/weather-icons/2.0.9/css/weather-icons.css" rel="stylesheet" type="text/css"/>
|
||||
<link href="/css/common.css" rel="stylesheet" type="text/css"/>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<div class="mui-container">
|
||||
<div class="mui--text-display3">Weather</div>
|
||||
<div id="weather"></div>
|
||||
</div>
|
||||
<script src="//cdn.muicss.com/mui-0.9.26/js/mui.min.js"></script>
|
||||
<script type='module' src="bundle.js"></script>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
|
4
src/backbone/js/app.js
Normal file
4
src/backbone/js/app.js
Normal file
@ -0,0 +1,4 @@
|
||||
const WView = require('./view/weather');
|
||||
|
||||
window.wview = new WView({ 'el': document.getElementById('weather') });
|
||||
|
34
src/backbone/js/collection/weather.js
Normal file
34
src/backbone/js/collection/weather.js
Normal file
@ -0,0 +1,34 @@
|
||||
const moment = require('moment');
|
||||
const Backbone = require('backbone');
|
||||
|
||||
function reduceOpenWeather(item) {
|
||||
// Openweather returns timestamps in seconds. Moment requires them in milliseconds.
|
||||
|
||||
const ts = moment(item.dt * 1000);
|
||||
const weatherBlock = item.weather[0];
|
||||
|
||||
return {
|
||||
'timestamp': item.dt,
|
||||
'icon': `wi-owm-${weatherBlock.id}`,
|
||||
'summary': weatherBlock.description,
|
||||
'tempHigh': parseInt(item.temp.max, 10),
|
||||
'tempLow': parseInt(item.temp.min, 10),
|
||||
'datelong': ts.format(),
|
||||
'time': item.dt,
|
||||
'date': ts.format('D/M'),
|
||||
'day': ts.format('ddd')
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
const WCollection = Backbone.Collection.extend({
|
||||
'url': '/weather',
|
||||
'parse': function(data) {
|
||||
return data.list.map((item) => {
|
||||
// Reduce the data
|
||||
return reduceOpenWeather(item);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
module.exports = WCollection;
|
41
src/backbone/js/view/weather.js
Normal file
41
src/backbone/js/view/weather.js
Normal file
@ -0,0 +1,41 @@
|
||||
const $ = require('jquery');
|
||||
const _ = require('underscore');
|
||||
const Backbone = require('backbone');
|
||||
const WCollection = require('../collection/weather');
|
||||
|
||||
const WView = Backbone.View.extend({
|
||||
'tagName': 'div',
|
||||
'template': _.template(`
|
||||
<% _.each(data, function(item) {%>
|
||||
<div class="card mui--z1 mui-col-md-6 mui-col-lg-4">
|
||||
<div class="mui-col-md-3">
|
||||
<div class="mui--text-accent mui--text-title day mui--text-center"><%= item.day %></div>
|
||||
<div class="mui--text-dark-secondary mui--text-subhead mui--text-center"><%= item.date %></div>
|
||||
</div>
|
||||
<div class="mui-col-md-9">
|
||||
<div>
|
||||
<i class="mui--text-headline wi <%= item.icon %>"></i>
|
||||
<span class="mui--text-display1 temp<%=item.tempHigh %>"><%= item.tempHigh %>°</span> /
|
||||
<span class="mui--text-headline temp<%=item.tempLow %>"><%= item.tempLow %>°</span></div>
|
||||
<div class="mui--text-caption summary"><%= item.summary %></div>
|
||||
</div>
|
||||
</div>
|
||||
<% });
|
||||
%>`),
|
||||
'initialize': function() {
|
||||
_.bindAll(this, 'render');
|
||||
this.collection = new WCollection();
|
||||
this.listenTo(this.collection, 'reset sync', _.debounce(_.bind(this.render), 128));
|
||||
this.collection.fetch();
|
||||
},
|
||||
'render': function() {
|
||||
if (this.collection.length !== 0) {
|
||||
const data = { 'data':this.collection.toJSON() };
|
||||
this.$el.html(this.template(data));
|
||||
}
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
module.exports = WView;
|
||||
|
85
src/css/common.css
Normal file
85
src/css/common.css
Normal file
@ -0,0 +1,85 @@
|
||||
body {
|
||||
background-color: #eee;
|
||||
}
|
||||
|
||||
.card {
|
||||
position: relative;
|
||||
background-color: #fff;
|
||||
min-height:72px;
|
||||
}
|
||||
|
||||
.mui--text-display4, .mui--text-display3 {
|
||||
font-family: "Roboto Slab", "Helvetica Neue", Helvetica, Arial;
|
||||
}
|
||||
|
||||
.temp0, .temp1, .temp2, .temp3, .temp4, .temp5 {
|
||||
color: rgb(80,181,221)
|
||||
}
|
||||
|
||||
.temp6 {
|
||||
color: rgb(78,178,206)
|
||||
}
|
||||
|
||||
.temp7 {
|
||||
color: rgb(76, 176, 190)
|
||||
}
|
||||
|
||||
.temp8 {
|
||||
color: rgb(73, 173, 175)
|
||||
}
|
||||
|
||||
.temp9 {
|
||||
color: rgb(72, 171, 159)
|
||||
}
|
||||
|
||||
.temp10 {
|
||||
color: rgb(70, 168, 142)
|
||||
}
|
||||
|
||||
.temp11 {
|
||||
color: rgb(68, 166, 125)
|
||||
}
|
||||
|
||||
.temp12 {
|
||||
color: rgb(66, 164, 108)
|
||||
}
|
||||
|
||||
.temp13 {
|
||||
color: rgb(102, 173, 94)
|
||||
}
|
||||
|
||||
.temp14 {
|
||||
color: rgb(135, 190, 64)
|
||||
}
|
||||
|
||||
.temp15 {
|
||||
color: rgb(179, 204, 26)
|
||||
}
|
||||
|
||||
.temp16 {
|
||||
color: rgb(214, 213, 28)
|
||||
}
|
||||
|
||||
.temp17 {
|
||||
color: rgb(249, 202, 3)
|
||||
}
|
||||
|
||||
.temp18 {
|
||||
color: rgb(246, 181, 3)
|
||||
}
|
||||
|
||||
.temp19 {
|
||||
color: rgb(244, 150, 26)
|
||||
}
|
||||
|
||||
.temp20 {
|
||||
color: rgb(236, 110, 5)
|
||||
}
|
||||
|
||||
.day {
|
||||
font-family: "Roboto Slab", "Helvetica Neue", Helvetica, Arial, sans-serif;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
.summary::first-letter {
|
||||
text-transform: capitalize
|
||||
}
|
24
src/ember/index.html
Normal file
24
src/ember/index.html
Normal file
@ -0,0 +1,24 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<title>Weather - Ember</title>
|
||||
<link href="//fonts.googleapis.com/css?family=Roboto+Slab:700-Ubuntu:500-Roboto:regular" rel="stylesheet">
|
||||
<link href="//cdn.muicss.com/mui-0.9.26/css/mui.min.css" rel="stylesheet" type="text/css"/>
|
||||
<link href="//cdnjs.cloudflare.com/ajax/libs/weather-icons/2.0.9/css/weather-icons.css" rel="stylesheet" type="text/css"/>
|
||||
<link href="/css/common.css" rel="stylesheet" type="text/css"/>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<div class="mui-container">
|
||||
<div class="mui--text-display3">Weather Ember</div>
|
||||
<div id="weather"></div>
|
||||
</div>
|
||||
<script src="//cdn.muicss.com/mui-0.9.26/js/mui.min.js"></script>
|
||||
|
||||
</body>
|
||||
|
||||
</html>
|
||||
|
24
src/es2016/index.html
Normal file
24
src/es2016/index.html
Normal file
@ -0,0 +1,24 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<title>Weather - ES2016</title>
|
||||
<link href="//fonts.googleapis.com/css?family=Roboto+Slab:700-Ubuntu:500-Roboto:regular" rel="stylesheet">
|
||||
<link href="//cdn.muicss.com/mui-0.9.26/css/mui.min.css" rel="stylesheet" type="text/css"/>
|
||||
<link href="//cdnjs.cloudflare.com/ajax/libs/weather-icons/2.0.9/css/weather-icons.css" rel="stylesheet" type="text/css"/>
|
||||
<link href="/css/common.css" rel="stylesheet" type="text/css"/>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<div class="mui-container">
|
||||
<div class="mui--text-display3">Weather ES2016</div>
|
||||
<div id="weather"></div>
|
||||
</div>
|
||||
<script src="//cdn.muicss.com/mui-0.9.26/js/mui.min.js"></script>
|
||||
|
||||
</body>
|
||||
|
||||
</html>
|
||||
|
BIN
src/favicon.ico
Normal file
BIN
src/favicon.ico
Normal file
Binary file not shown.
After Width: | Height: | Size: 5.4 KiB |
62
src/index.html
Normal file
62
src/index.html
Normal file
@ -0,0 +1,62 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<title>TestMVC</title>
|
||||
<link href="//fonts.googleapis.com/css?family=Roboto+Slab:700-Ubuntu:500-Roboto:regular" rel="stylesheet">
|
||||
<link href="//cdn.muicss.com/mui-0.9.26/css/mui.min.css" rel="stylesheet" type="text/css"/>
|
||||
<link href="//cdnjs.cloudflare.com/ajax/libs/weather-icons/2.0.9/css/weather-icons.css" rel="stylesheet" type="text/css"/>
|
||||
<link href="css/common.css" rel="stylesheet" type="text/css"/>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<div class="mui-container">
|
||||
<div class="mui--text-display4">TestMVC</div>
|
||||
<div class="mui-row">
|
||||
<div class="mui-col-md-4">
|
||||
<div class="mui--text-headline">Introduction</div>
|
||||
<div class="mui--text-body2">Blah blah blah</div>
|
||||
</div>
|
||||
<div class="mui-col-md-8">
|
||||
<div class="mui--text-headline">Examples</div>
|
||||
<div class="mui--text-accent">Pure Javascript</div>
|
||||
<div class="mui-row">
|
||||
<div class="mui-col-md-3 mui--text-center">
|
||||
<a href="backbone/index.html" class="mui-btn">Backbone</a>
|
||||
</div>
|
||||
<div class="mui-col-md-3 mui--text-center">
|
||||
<a href="react/index.html" class="mui-btn" disabled>React</a>
|
||||
</div>
|
||||
<div class="mui-col-md-3 mui--text-center">
|
||||
<a href="aurelia/index.html" class="mui-btn" disabled>Aurelia</a>
|
||||
</div>
|
||||
<div class="mui-col-md-3 mui--text-center">
|
||||
<a href="angular/index.html" class="mui-btn" disabled>Angular</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="mui-row">
|
||||
<div class="mui-col-md-3 mui--text-center">
|
||||
<a href="ember/index.html" class="mui-btn" disabled>Ember</a>
|
||||
</div>
|
||||
<div class="mui-col-md-3 mui--text-center">
|
||||
<a href="knockout/index.html" class="mui-btn" disabled>Knockout</a>
|
||||
</div>
|
||||
<div class="mui-col-md-3 mui--text-center">
|
||||
<a href="vue/index.html" class="mui-btn" disabled>Vue</a>
|
||||
</div>
|
||||
<div class="mui-col-md-3 mui--text-center">
|
||||
<a href="es2016/index.html" class="mui-btn" disabled>ES2016</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<script src="//cdn.muicss.com/mui-0.9.26/js/mui.min.js"></script>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
|
24
src/knockout/index.html
Normal file
24
src/knockout/index.html
Normal file
@ -0,0 +1,24 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<title>Weather - Knockout</title>
|
||||
<link href="//fonts.googleapis.com/css?family=Roboto+Slab:700-Ubuntu:500-Roboto:regular" rel="stylesheet">
|
||||
<link href="//cdn.muicss.com/mui-0.9.26/css/mui.min.css" rel="stylesheet" type="text/css"/>
|
||||
<link href="//cdnjs.cloudflare.com/ajax/libs/weather-icons/2.0.9/css/weather-icons.css" rel="stylesheet" type="text/css"/>
|
||||
<link href="/css/common.css" rel="stylesheet" type="text/css"/>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<div class="mui-container">
|
||||
<div class="mui--text-display3">Weather Knockout</div>
|
||||
<div id="weather"></div>
|
||||
</div>
|
||||
<script src="//cdn.muicss.com/mui-0.9.26/js/mui.min.js"></script>
|
||||
|
||||
</body>
|
||||
|
||||
</html>
|
||||
|
24
src/react/index.html
Normal file
24
src/react/index.html
Normal file
@ -0,0 +1,24 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<title>Weather - React</title>
|
||||
<link href="//fonts.googleapis.com/css?family=Roboto+Slab:700-Ubuntu:500-Roboto:regular" rel="stylesheet">
|
||||
<link href="//cdn.muicss.com/mui-0.9.26/css/mui.min.css" rel="stylesheet" type="text/css"/>
|
||||
<link href="//cdnjs.cloudflare.com/ajax/libs/weather-icons/2.0.9/css/weather-icons.css" rel="stylesheet" type="text/css"/>
|
||||
<link href="/css/common.css" rel="stylesheet" type="text/css"/>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<div class="mui-container">
|
||||
<div class="mui--text-display3">Weather React</div>
|
||||
<div id="weather"></div>
|
||||
</div>
|
||||
<script src="//cdn.muicss.com/mui-0.9.26/js/mui.min.js"></script>
|
||||
|
||||
</body>
|
||||
|
||||
</html>
|
||||
|
24
src/vue/index.html
Normal file
24
src/vue/index.html
Normal file
@ -0,0 +1,24 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<title>Weather - Vue</title>
|
||||
<link href="//fonts.googleapis.com/css?family=Roboto+Slab:700-Ubuntu:500-Roboto:regular" rel="stylesheet">
|
||||
<link href="//cdn.muicss.com/mui-0.9.26/css/mui.min.css" rel="stylesheet" type="text/css"/>
|
||||
<link href="//cdnjs.cloudflare.com/ajax/libs/weather-icons/2.0.9/css/weather-icons.css" rel="stylesheet" type="text/css"/>
|
||||
<link href="/css/common.css" rel="stylesheet" type="text/css"/>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<div class="mui-container">
|
||||
<div class="mui--text-display3">Weather Vue</div>
|
||||
<div id="weather"></div>
|
||||
</div>
|
||||
<script src="//cdn.muicss.com/mui-0.9.26/js/mui.min.js"></script>
|
||||
|
||||
</body>
|
||||
|
||||
</html>
|
||||
|
90
test/collection.js
Normal file
90
test/collection.js
Normal file
@ -0,0 +1,90 @@
|
||||
const Backbone = require('backbone');
|
||||
const _ = require('underscore');
|
||||
const WCollection = require('../src/js/collection/weather');
|
||||
const expect = require('expect.js');
|
||||
const sinon = require('sinon');
|
||||
|
||||
const wData = { 'city':{ 'id':3333231, 'name':'Glasgow City', 'coord':{ 'lon':-4.25, 'lat':55.8667 }, 'country':'GB', 'population':0 }, 'cod':'200', 'message':1.3268098, 'cnt':5, 'list':[{ 'dt':1506945600, 'temp':{ 'day':10.69, 'min':9.99, 'max':10.69, 'night':10.22, 'eve':10.69, 'morn':10.69 }, 'pressure':1001.71, 'humidity':94, 'weather':[{ 'id':500, 'main':'Rain', 'description':'light rain', 'icon':'10d' }], 'speed':7.6, 'deg':279, 'clouds':92, 'rain':0.99 }, { 'dt':1507032000, 'temp':{ 'day':11.13, 'min':9.52, 'max':11.28, 'night':10.11, 'eve':10.33, 'morn':9.52 }, 'pressure':1014.59, 'humidity':80, 'weather':[{ 'id':500, 'main':'Rain', 'description':'light rain', 'icon':'10d' }], 'speed':7.43, 'deg':285, 'clouds':88, 'rain':0.44 }, { 'dt':1507118400, 'temp':{ 'day':10.98, 'min':8.26, 'max':10.98, 'night':8.26, 'eve':9.29, 'morn':10 }, 'pressure':1007.06, 'humidity':93, 'weather':[{ 'id':501, 'main':'Rain', 'description':'moderate rain', 'icon':'10d' }], 'speed':8.77, 'deg':267, 'clouds':92, 'rain':8.52 }, { 'dt':1507204800, 'temp':{ 'day':10.77, 'min':5.92, 'max':10.79, 'night':5.92, 'eve':9.56, 'morn':6.4 }, 'pressure':1012.43, 'humidity':91, 'weather':[{ 'id':500, 'main':'Rain', 'description':'light rain', 'icon':'10d' }], 'speed':7.26, 'deg':291, 'clouds':64 }, { 'dt':1507291200, 'temp':{ 'day':9.28, 'min':5.88, 'max':12.7, 'night':10.84, 'eve':12.7, 'morn':5.88 }, 'pressure':1001.13, 'humidity':0, 'weather':[{ 'id':501, 'main':'Rain', 'description':'moderate rain', 'icon':'10d' }], 'speed':4.32, 'deg':189, 'clouds':100, 'rain':9.37 }] };
|
||||
|
||||
const wResult = [
|
||||
{
|
||||
'date': '2/10',
|
||||
'datelong': '2017-10-02T13:00:00+01:00',
|
||||
'day': 'Mon',
|
||||
'icon': 'wi-owm-500',
|
||||
'summary': 'light rain',
|
||||
'tempHigh': 10,
|
||||
'tempLow': 9,
|
||||
'time': 1506945600,
|
||||
'timestamp': 1506945600
|
||||
},
|
||||
{
|
||||
'date': '3/10',
|
||||
'datelong': '2017-10-03T13:00:00+01:00',
|
||||
'day': 'Tue',
|
||||
'icon': 'wi-owm-500',
|
||||
'summary': 'light rain',
|
||||
'tempHigh': 11,
|
||||
'tempLow': 9,
|
||||
'time': 1507032000,
|
||||
'timestamp': 1507032000
|
||||
},
|
||||
{
|
||||
'date': '4/10',
|
||||
'datelong': '2017-10-04T13:00:00+01:00',
|
||||
'day': 'Wed',
|
||||
'icon': 'wi-owm-501',
|
||||
'summary': 'moderate rain',
|
||||
'tempHigh': 10,
|
||||
'tempLow': 8,
|
||||
'time': 1507118400,
|
||||
'timestamp': 1507118400
|
||||
},
|
||||
{
|
||||
'date': '5/10',
|
||||
'datelong': '2017-10-05T13:00:00+01:00',
|
||||
'day': 'Thu',
|
||||
'icon': 'wi-owm-500',
|
||||
'summary': 'light rain',
|
||||
'tempHigh': 10,
|
||||
'tempLow': 5,
|
||||
'time': 1507204800,
|
||||
'timestamp': 1507204800
|
||||
},
|
||||
{
|
||||
'date': '6/10',
|
||||
'datelong': '2017-10-06T13:00:00+01:00',
|
||||
'day': 'Fri',
|
||||
'icon': 'wi-owm-501',
|
||||
'summary': 'moderate rain',
|
||||
'tempHigh': 12,
|
||||
'tempLow': 5,
|
||||
'time': 1507291200,
|
||||
'timestamp': 1507291200
|
||||
}
|
||||
];
|
||||
|
||||
describe('Weather Collection', () => {
|
||||
let collection;
|
||||
|
||||
sinon.stub(Backbone, 'sync').yieldsTo('success', wData);
|
||||
|
||||
beforeEach(() => {
|
||||
collection = new WCollection();
|
||||
});
|
||||
|
||||
it('should create an empty collection', () => {
|
||||
expect(collection.length).to.be(0);
|
||||
});
|
||||
|
||||
it('Should fetch the data', () => {
|
||||
collection.fetch();
|
||||
expect(collection.length).to.be(5);
|
||||
});
|
||||
|
||||
it('Should reduce the data', () => {
|
||||
collection.fetch();
|
||||
expect(collection.toJSON()).to.eql(wResult);
|
||||
});
|
||||
});
|
||||
|
Loading…
Reference in New Issue
Block a user