1
0
mirror of https://github.com/kataras/iris.git synced 2025-12-19 10:57:05 +00:00

reorganization of _examples and add some new examples such as iris+groupcache+mysql+docker

Former-commit-id: ed635ee95de7160cde11eaabc0c1dcb0e460a620
This commit is contained in:
Gerasimos (Makis) Maropoulos
2020-06-07 15:26:06 +03:00
parent 9fdcb4c7fb
commit ed45c77be5
328 changed files with 4262 additions and 41621 deletions

View File

@@ -0,0 +1,66 @@
package controllers
import (
"github.com/kataras/iris/v12/_examples/mvc/vuejs-todo-mvc/src/todo"
"github.com/kataras/iris/v12"
"github.com/kataras/iris/v12/mvc"
"github.com/kataras/iris/v12/sessions"
"github.com/kataras/iris/v12/websocket"
)
// TodoController is our TODO app's web controller.
type TodoController struct {
Service todo.Service
Session *sessions.Session
NS *websocket.NSConn
}
// BeforeActivation called once before the server ran, and before
// the routes and dependencies binded.
// You can bind custom things to the controller, add new methods, add middleware,
// add dependencies to the struct or the method(s) and more.
func (c *TodoController) BeforeActivation(b mvc.BeforeActivation) {
// this could be binded to a controller's function input argument
// if any, or struct field if any:
b.Dependencies().Register(func(ctx iris.Context) (items []todo.Item) {
ctx.ReadJSON(&items)
return
}) // Note: from Iris v12.2 these type of dependencies are automatically resolved.
}
// Get handles the GET: /todos route.
func (c *TodoController) Get() []todo.Item {
return c.Service.Get(c.Session.ID())
}
// PostItemResponse the response data that will be returned as json
// after a post save action of all todo items.
type PostItemResponse struct {
Success bool `json:"success"`
}
var emptyResponse = PostItemResponse{Success: false}
// Post handles the POST: /todos route.
func (c *TodoController) Post(newItems []todo.Item) PostItemResponse {
if err := c.Service.Save(c.Session.ID(), newItems); err != nil {
return emptyResponse
}
return PostItemResponse{Success: true}
}
func (c *TodoController) Save(msg websocket.Message) error {
id := c.Session.ID()
c.NS.Conn.Server().Broadcast(nil, websocket.Message{
Namespace: msg.Namespace,
Event: "saved",
To: id,
Body: websocket.Marshal(c.Service.Get(id)),
})
return nil
}

View File

@@ -0,0 +1,63 @@
package main
import (
"strings"
"github.com/kataras/iris/v12/_examples/mvc/vuejs-todo-mvc/src/todo"
"github.com/kataras/iris/v12/_examples/mvc/vuejs-todo-mvc/src/web/controllers"
"github.com/kataras/iris/v12"
"github.com/kataras/iris/v12/mvc"
"github.com/kataras/iris/v12/sessions"
"github.com/kataras/iris/v12/websocket"
)
func main() {
app := iris.New()
// serve our app in public, public folder
// contains the client-side vue.js application,
// no need for any server-side template here,
// actually if you're going to just use vue without any
// back-end services, you can just stop afer this line and start the server.
app.HandleDir("/", "./public")
// configure the http sessions.
sess := sessions.New(sessions.Config{
Cookie: "iris_session",
})
// create a sub router and register the http controllers.
todosRouter := app.Party("/todos")
// create our mvc application targeted to /todos relative sub path.
todosApp := mvc.New(todosRouter)
// any dependencies bindings here...
todosApp.Register(
todo.NewMemoryService(),
)
todosController := new(controllers.TodoController)
// controllers registration here...
todosApp.Handle(todosController)
// Create a sub mvc app for websocket controller.
// Inherit the parent's dependencies.
todosWebsocketApp := todosApp.Party("/sync")
todosWebsocketApp.HandleWebsocket(todosController).
SetNamespace("todos").
SetEventMatcher(func(methodName string) (string, bool) {
return strings.ToLower(methodName), true
})
websocketServer := websocket.New(websocket.DefaultGorillaUpgrader, todosWebsocketApp)
idGenerator := func(ctx iris.Context) string {
id := sess.Start(ctx).ID()
return id
}
todosWebsocketApp.Router.Get("/", websocket.Handler(websocketServer, idGenerator))
// start the web server at http://localhost:8080
app.Listen(":8080")
}

View File

@@ -0,0 +1,2 @@
index.css is not here to reduce the disk space for the examples.
https://unpkg.com/todomvc-app-css@2.0.4/index.css is used instead.

View File

@@ -0,0 +1,73 @@
<!doctype html>
<html data-framework="vue">
<head>
<meta charset="utf-8">
<title>Iris + Vue.js • TodoMVC</title>
<link rel="stylesheet" href="https://unpkg.com/todomvc-app-css@2.0.4/index.css">
<!-- this needs to be loaded before guide's inline scripts -->
<script src="https://vuejs.org/js/vue.js"></script>
<!-- $http -->
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
<!-- -->
<script src="https://unpkg.com/director@1.2.8/build/director.js"></script>
<script src="https://cdn.jsdelivr.net/npm/neffos.js@latest/dist/neffos.min.js"></script>
<style>
[v-cloak] {
display: none;
}
</style>
</head>
<body>
<section class="todoapp">
<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" v-cloak>
<input class="toggle-all" type="checkbox" v-model="allDone">
<ul class="todo-list">
<li v-for="todo in filteredTodos" class="todo" :key="todo.id"
:class="{ completed: todo.completed, editing: todo == editedTodo }">
<div class="view">
<!-- v-model="todo.completed" -->
<input class="toggle" type="checkbox" @click="completeTodo(todo)">
<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" v-cloak>
<span class="todo-count">
<strong>{{ remaining }}</strong> {{ remaining | pluralize }} 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="removeCompleted" v-show="todos.length > remaining">
Clear completed
</button>
</footer>
</section>
<footer class="info">
<p>Double-click to edit a todo</p>
</footer>
<script src="/js/app.js"></script>
</body>
</html>

View File

@@ -0,0 +1,214 @@
// Full spec-compliant TodoMVC with Iris
// and hash-based routing in ~200 effective lines of JavaScript.
var ws;
((async () => {
const events = {
todos: {
saved: function (ns, msg) {
app.todos = msg.unmarshal()
// or make a new http fetch
// fetchTodos(function (items) {
// app.todos = msg.unmarshal()
// });
}
}
};
const conn = await neffos.dial("ws://localhost:8080/todos/sync", events);
ws = await conn.connect("todos");
})()).catch(console.error);
function fetchTodos(onComplete) {
axios.get("/todos").then(response => {
if (response.data === null) {
return;
}
onComplete(response.data);
});
}
var todoStorage = {
fetch: function () {
var todos = [];
fetchTodos(function (items) {
for (var i = 0; i < items.length; i++) {
todos.push(items[i]);
}
});
return todos;
},
save: function (todos) {
axios.post("/todos", JSON.stringify(todos)).then(response => {
if (!response.data.success) {
window.alert("saving had a failure");
return;
}
// console.log("send: save");
ws.emit("save")
});
}
}
// visibility filters
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
})
}
}
// app Vue instance
var app = new Vue({
// app initial state
data: {
todos: todoStorage.fetch(),
newTodo: '',
editedTodo: null,
visibility: 'all'
},
// we will not use the "watch" as it works with the fields like "hasChanges"
// and callbacks to make it true but let's keep things very simple as it's just a small getting started.
// // watch todos change for persistence
// watch: {
// todos: {
// handler: function (todos) {
// if (app.hasChanges) {
// todoStorage.save(todos);
// app.hasChanges = false;
// }
// },
// deep: true
// }
// },
// 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
})
this.notifyChange();
}
}
},
filters: {
pluralize: function (n) {
return n === 1 ? 'item' : 'items'
}
},
// methods that implement data logic.
// note there's no DOM manipulation here at all.
methods: {
notifyChange: function () {
todoStorage.save(this.todos)
},
addTodo: function () {
var value = this.newTodo && this.newTodo.trim()
if (!value) {
return
}
this.todos.push({
id: this.todos.length + 1, // just for the client-side.
title: value,
completed: false
})
this.newTodo = ''
this.notifyChange();
},
completeTodo: function (todo) {
if (todo.completed) {
todo.completed = false;
} else {
todo.completed = true;
}
this.notifyChange();
},
removeTodo: function (todo) {
this.todos.splice(this.todos.indexOf(todo), 1)
this.notifyChange();
},
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);
}
this.notifyChange();
},
cancelEdit: function (todo) {
this.editedTodo = null
todo.title = this.beforeEditCache
},
removeCompleted: function () {
this.todos = filters.active(this.todos);
this.notifyChange();
}
},
// 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()
}
}
}
})
// handle routing
function onHashChange() {
var visibility = window.location.hash.replace(/#\/?/, '')
if (filters[visibility]) {
app.visibility = visibility
} else {
window.location.hash = ''
app.visibility = 'all'
}
}
window.addEventListener('hashchange', onHashChange)
onHashChange()
// mount
app.$mount('.todoapp');

View File

@@ -0,0 +1,2 @@
vue.js is not here to reduce the disk space for the examples.
Instead https://vuejs.org/js/vue.js is used instead.