Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Pwa #5

Open
wants to merge 12 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
node_modules
14 changes: 14 additions & 0 deletions pwa/https.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# taken from http://www.piware.de/2011/01/creating-an-https-server-in-python/
# generate server.xml with the following command:
# openssl req -new -x509 -keyout server.pem -out server.pem -days 365 -nodes
# run as follows:
# python simple-https-server.py
# then in your browser, visit:
# https://localhost:4443

import BaseHTTPServer, SimpleHTTPServer
import ssl

httpd = BaseHTTPServer.HTTPServer(('localhost', 4443), SimpleHTTPServer.SimpleHTTPRequestHandler)
httpd.socket = ssl.wrap_socket (httpd.socket, certfile='./server.pem', server_side=True)
httpd.serve_forever()
67 changes: 67 additions & 0 deletions pwa/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
<!doctype html>
<html data-framework="vue">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="theme-color" content="#000000" />
<title>Vue.js • TodoMVC</title>
<link rel="stylesheet" href="/node_modules/todomvc-common/base.css">
<link rel="stylesheet" href="/node_modules/todomvc-app-css/index.css">
<link rel="manifest" href="/manifest.webmanifest">
<style> [v-cloak] { display: none; } </style>
</head>
<body>
<section class="todoapp" v-cloak>
<header class="header">
<h1>todos</h1>
<input class="new-todo" autofocus autocomplete="off" placeholder="What needs to be done?" v-model="newTodo" @keyup.enter="addTodo">
</header>
<section class="main" v-show="todos.length">
<input class="toggle-all" type="checkbox" v-model="allDone">
<ul class="todo-list">
<li class="todo" v-for="todo in filteredTodos" :key="todo.id" :class="{completed: todo.completed, editing: todo == editedTodo}">
<div class="view">
<input class="toggle" type="checkbox" v-model="todo.completed">
<label @dblclick="editTodo(todo)">{{todo.title}}</label>
<button class="destroy" @click="removeTodo(todo)"></button>
</div>
<input class="edit" type="text" v-model="todo.title" v-todo-focus="todo == editedTodo" @blur="doneEdit(todo)" @keyup.enter="doneEdit(todo)" @keyup.esc="cancelEdit(todo)">
</li>
</ul>
</section>
<footer class="footer" v-show="todos.length">
<span class="todo-count">
<strong v-text="remaining"></strong> {{pluralize('item', remaining)}} left
</span>
<ul class="filters">
<li><a href="#/all" :class="{selected: visibility == 'all'}">All</a></li>
<li><a href="#/active" :class="{selected: visibility == 'active'}">Active</a></li>
<li><a href="#/completed" :class="{selected: visibility == 'completed'}">Completed</a></li>
</ul>
<button class="clear-completed" @click="sync" >
Sync
</button>

</footer>
</section>
<footer class="info">
<p>Double-click to edit a todo</p>
<p>Written by <a href="http://evanyou.me">Evan You</a></p>
<p>Part of <a href="http://todomvc.com">TodoMVC</a></p>
</footer>
<script src="node_modules/todomvc-common/base.js"></script>
<script src="node_modules/director/build/director.js"></script>
<script src="node_modules/vue/dist/vue.js"></script>
<script src="node_modules/axios/dist/axios.min.js"></script>
<script src="js/store.js"></script>
<script src="js/app.js"></script>
<script src="js/routes.js"></script>
<script>
if ('serviceWorker' in navigator) {
navigator.serviceWorker
.register('sw.js')
.then(function () { console.log("Service Worker Registered"); });
}
</script>
</body>
</html>
143 changes: 143 additions & 0 deletions pwa/js/app.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
/*global Vue, todoStorage */

(function (exports) {

'use strict';

var filters = {
all: function (todos) {
return todos;
},
active: function (todos) {
return todos.filter(function (todo) {
return !todo.completed;
});
},
completed: function (todos) {
return todos.filter(function (todo) {
return todo.completed;
});
}
};

exports.app = new Vue({

// the root element that will be compiled
el: '.todoapp',

// app initial state
data: {
todos: todoStorage.fetch(),
newTodo: '',
editedTodo: null,
visibility: 'all'
},
// watch todos change for localStorage persistence
watch: {
todos: {
deep: true,
handler: todoStorage.save
}
},

// computed properties
// http://vuejs.org/guide/computed.html
computed: {
filteredTodos: function () {
return filters[this.visibility](this.todos);
},
remaining: function () {
return filters.active(this.todos).length;
},
allDone: {
get: function () {
return this.remaining === 0;
},
set: function (value) {
this.todos.forEach(function (todo) {
todo.completed = value;
});
}
}
},
mounted: function() {
this.sync();
},
// methods that implement data logic.
// note there's no DOM manipulation here at all.
methods: {

pluralize: function (word, count) {
return word + (count === 1 ? '' : 's');
},

addTodo: function () {
var value = this.newTodo && this.newTodo.trim();
if (!value) {
return;
}
this.todos.push({ title: value, completed: false, pendingOnlineCreation: true });
this.newTodo = '';
},

removeTodo: function (todo) {
var index = this.todos.indexOf(todo);
this.todos.splice(index, 1);
},

editTodo: function (todo) {
this.beforeEditCache = todo.title;
this.editedTodo = todo;
},

doneEdit: function (todo) {
if (!this.editedTodo) {
return;
}
this.editedTodo = null;
todo.title = todo.title.trim();
if (!todo.title) {
this.removeTodo(todo);
}
},

cancelEdit: function (todo) {
this.editedTodo = null;
todo.title = this.beforeEditCache;
},

removeCompleted: function () {
this.todos = filters.active(this.todos);
},

sync: function () {
Promise.all(
todoStorage
.fetch()
.filter((todo) => todo.pendingOnlineCreation)
.map(({ title, completed }) => {
return axios.post(
'https://4b6aadd7.ngrok.io/todos', { title, completed }
);
})
).then(() => {
axios.get('https://4b6aadd7.ngrok.io/todos').then(({ data }) => {
this.todos = data
});
});
}
},

// a custom directive to wait for the DOM to be updated
// before focusing on the input field.
// http://vuejs.org/guide/custom-directive.html
directives: {
'todo-focus': function (el, binding) {
if (binding.value) {
el.focus();
}
}
}
});

})(window);
24 changes: 24 additions & 0 deletions pwa/js/routes.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
/*global app, Router */

(function (app, Router) {

'use strict';

var router = new Router();

['all', 'active', 'completed'].forEach(function (visibility) {
router.on(visibility, function () {
app.visibility = visibility;
});
});

router.configure({
notfound: function () {
window.location.hash = '';
app.visibility = 'all';
}
});

router.init();

})(app, Router);
18 changes: 18 additions & 0 deletions pwa/js/store.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
/*jshint unused:false */

(function (exports) {

'use strict';

var STORAGE_KEY = 'todos-vuejs';

exports.todoStorage = {
fetch: function () {
return JSON.parse(localStorage.getItem(STORAGE_KEY) || '[]');
},
save: function (todos) {
localStorage.setItem(STORAGE_KEY, JSON.stringify(todos));
}
};

})(window);
Empty file added pwa/learn.json
Empty file.
38 changes: 38 additions & 0 deletions pwa/manifest.webmanifest
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
{
"name": "Whatsapp clone",
"short_name": "Whatsapp clone",
"start_url": "/",
"display": "standalone",
"background_color": "#fff",
"description": "Another todo list",
"theme_color": "#000000",
"icons": [{
"src": "https://image.freepik.com/free-icon/whatsapp-logo_318-49685.jpg",
"sizes": "48x48",
"type": "image/png"
}, {
"src": "https://image.freepik.com/free-icon/whatsapp-logo_318-49685.jpg",
"sizes": "72x72",
"type": "image/png"
}, {
"src": "https://image.freepik.com/free-icon/whatsapp-logo_318-49685.jpg",
"sizes": "96x96",
"type": "image/png"
}, {
"src": "https://image.freepik.com/free-icon/whatsapp-logo_318-49685.jpg",
"sizes": "144x144",
"type": "image/png"
}, {
"src": "https://image.freepik.com/free-icon/whatsapp-logo_318-49685.jpg",
"sizes": "168x168",
"type": "image/png"
}, {
"src": "https://image.freepik.com/free-icon/whatsapp-logo_318-49685.jpg",
"sizes": "192x192",
"type": "image/png"
}, {
"src": "https://image.freepik.com/free-icon/whatsapp-logo_318-49685.jpg",
"sizes": "512x512",
"type": "image/png"
}]
}
61 changes: 61 additions & 0 deletions pwa/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

10 changes: 10 additions & 0 deletions pwa/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"private": true,
"dependencies": {
"axios": "^0.17.1",
"director": "^1.2.0",
"todomvc-app-css": "^2.0.0",
"todomvc-common": "^1.0.1",
"vue": "^2.1.8"
}
}
Loading