Update to poodinis 8.0.1, use Value injection for MongoDBCollections, Use an ApplicationContext for registering of components, fix multiday events, use a string for description of events instead of a dynamic array of strings
This commit is contained in:
parent
974a741132
commit
64cc7e5b49
10 changed files with 88 additions and 54 deletions
2
.gitignore
vendored
2
.gitignore
vendored
|
@ -4,6 +4,6 @@ __dummy.html
|
||||||
*.o
|
*.o
|
||||||
*.obj
|
*.obj
|
||||||
__test__*__
|
__test__*__
|
||||||
calendar-webapp
|
calendar-webapp*
|
||||||
events.json
|
events.json
|
||||||
dub.selections.json
|
dub.selections.json
|
2
dub.json
2
dub.json
|
@ -5,7 +5,7 @@
|
||||||
],
|
],
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"vibe-d": "0.8.1-rc.2",
|
"vibe-d": "0.8.1-rc.2",
|
||||||
"poodinis": "~>8.0.0"
|
"poodinis": "~>8.0.1"
|
||||||
},
|
},
|
||||||
"description": "A simple webapplication to edit and view calendar entries",
|
"description": "A simple webapplication to edit and view calendar entries",
|
||||||
"copyright": "Copyright © 2017, Johannes Loher",
|
"copyright": "Copyright © 2017, Johannes Loher",
|
||||||
|
|
|
@ -1,3 +1,7 @@
|
||||||
.error {
|
.error {
|
||||||
color: red;
|
color: red;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
td.pre {
|
||||||
|
white-space: pre;
|
||||||
|
}
|
18
source/app.d
18
source/app.d
|
@ -1,15 +1,12 @@
|
||||||
module app;
|
module app;
|
||||||
|
|
||||||
import authenticator : Authenticator, MongoDBAuthenticator;
|
|
||||||
import calendarwebapp : CalendarWebapp;
|
import calendarwebapp : CalendarWebapp;
|
||||||
import configuration : StringInjector;
|
import configuration : Context;
|
||||||
import event : EventStore, MongoDBEventStore;
|
|
||||||
|
|
||||||
import poodinis;
|
import poodinis;
|
||||||
|
|
||||||
import vibe.core.log : logInfo;
|
import vibe.core.log : logInfo;
|
||||||
import vibe.db.mongo.client : MongoClient;
|
|
||||||
import vibe.db.mongo.mongo : connectMongoDB;
|
|
||||||
import vibe.http.fileserver : serveStaticFiles;
|
import vibe.http.fileserver : serveStaticFiles;
|
||||||
import vibe.http.router : URLRouter;
|
import vibe.http.router : URLRouter;
|
||||||
import vibe.http.server : HTTPServerSettings, listenHTTP, MemorySessionStore;
|
import vibe.http.server : HTTPServerSettings, listenHTTP, MemorySessionStore;
|
||||||
|
@ -17,16 +14,11 @@ import vibe.web.web : registerWebInterface;
|
||||||
|
|
||||||
shared static this()
|
shared static this()
|
||||||
{
|
{
|
||||||
auto dependencies = new shared DependencyContainer();
|
auto container = new shared DependencyContainer();
|
||||||
auto db = connectMongoDB("localhost");
|
container.registerContext!Context;
|
||||||
dependencies.register!MongoClient.existingInstance(db);
|
|
||||||
dependencies.register!(EventStore, MongoDBEventStore);
|
|
||||||
dependencies.register!(Authenticator, MongoDBAuthenticator);
|
|
||||||
dependencies.register!CalendarWebapp;
|
|
||||||
dependencies.register!(ValueInjector!string, StringInjector);
|
|
||||||
|
|
||||||
auto router = new URLRouter;
|
auto router = new URLRouter;
|
||||||
router.registerWebInterface(dependencies.resolve!CalendarWebapp);
|
router.registerWebInterface(container.resolve!CalendarWebapp);
|
||||||
router.get("*", serveStaticFiles("public"));
|
router.get("*", serveStaticFiles("public"));
|
||||||
|
|
||||||
auto settings = new HTTPServerSettings;
|
auto settings = new HTTPServerSettings;
|
||||||
|
|
|
@ -3,7 +3,7 @@ module authenticator;
|
||||||
import poodinis;
|
import poodinis;
|
||||||
|
|
||||||
import vibe.data.bson : Bson;
|
import vibe.data.bson : Bson;
|
||||||
import vibe.db.mongo.client : MongoClient;
|
import vibe.db.mongo.collection : MongoCollection;
|
||||||
|
|
||||||
interface Authenticator
|
interface Authenticator
|
||||||
{
|
{
|
||||||
|
@ -13,18 +13,12 @@ interface Authenticator
|
||||||
class MongoDBAuthenticator : Authenticator
|
class MongoDBAuthenticator : Authenticator
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
@Autowire MongoClient mongoClient;
|
@Value("users")
|
||||||
|
MongoCollection users;
|
||||||
@Value("Database name")
|
|
||||||
string databaseName;
|
|
||||||
|
|
||||||
@Value("Users collection name")
|
|
||||||
string usersCollectionName;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
bool checkUser(string username, string password) @safe
|
bool checkUser(string username, string password) @safe
|
||||||
{
|
{
|
||||||
auto users = mongoClient.getCollection(databaseName ~ "." ~ usersCollectionName);
|
|
||||||
auto result = users.findOne(["username" : username, "password" : password]);
|
auto result = users.findOne(["username" : username, "password" : password]);
|
||||||
return result != Bson(null);
|
return result != Bson(null);
|
||||||
}
|
}
|
||||||
|
|
|
@ -72,7 +72,7 @@ public:
|
||||||
enforce(end - begin >= 1.days,
|
enforce(end - begin >= 1.days,
|
||||||
"Mehrtägige Ereignisse müssen mindestens einen Tag dauern");
|
"Mehrtägige Ereignisse müssen mindestens einen Tag dauern");
|
||||||
auto event = Event(BsonObjectID.generate, begin, end, name,
|
auto event = Event(BsonObjectID.generate, begin, end, name,
|
||||||
description.replace("\r", "").split('\n'), type, shout);
|
description.replace("\r", ""), type, shout);
|
||||||
|
|
||||||
eventStore.addEvent(event);
|
eventStore.addEvent(event);
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,29 @@
|
||||||
module configuration;
|
module configuration;
|
||||||
|
|
||||||
import poodinis : ValueInjector;
|
import authenticator : Authenticator, MongoDBAuthenticator;
|
||||||
|
import calendarwebapp : CalendarWebapp;
|
||||||
|
import event : EventStore, MongoDBEventStore;
|
||||||
|
|
||||||
|
import poodinis;
|
||||||
|
|
||||||
|
import vibe.db.mongo.client : MongoClient;
|
||||||
|
import vibe.db.mongo.collection : MongoCollection;
|
||||||
|
import vibe.db.mongo.mongo : connectMongoDB;
|
||||||
|
|
||||||
|
class Context : ApplicationContext
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
override void registerDependencies(shared(DependencyContainer) container)
|
||||||
|
{
|
||||||
|
auto mongoClient = connectMongoDB("localhost");
|
||||||
|
container.register!MongoClient.existingInstance(mongoClient);
|
||||||
|
container.register!(EventStore, MongoDBEventStore);
|
||||||
|
container.register!(Authenticator, MongoDBAuthenticator);
|
||||||
|
container.register!CalendarWebapp;
|
||||||
|
container.register!(ValueInjector!string, StringInjector);
|
||||||
|
container.register!(ValueInjector!MongoCollection, MongoCollectionInjector);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
class StringInjector : ValueInjector!string
|
class StringInjector : ValueInjector!string
|
||||||
{
|
{
|
||||||
|
@ -13,12 +36,26 @@ public:
|
||||||
// dfmt off
|
// dfmt off
|
||||||
config = ["Database name" : "CalendarWebapp",
|
config = ["Database name" : "CalendarWebapp",
|
||||||
"Users collection name": "users",
|
"Users collection name": "users",
|
||||||
"Entries collection name" : "entries"];
|
"Events collection name" : "events"];
|
||||||
// dfmt on
|
// dfmt on
|
||||||
}
|
}
|
||||||
|
|
||||||
string get(string key) const @safe pure nothrow
|
override string get(string key) const @safe pure nothrow
|
||||||
{
|
{
|
||||||
return config[key];
|
return config[key];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class MongoCollectionInjector : ValueInjector!MongoCollection
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
@Autowire MongoClient mongoClient;
|
||||||
|
@Value("Database name")
|
||||||
|
string databaseName;
|
||||||
|
|
||||||
|
public:
|
||||||
|
override MongoCollection get(string key) @safe
|
||||||
|
{
|
||||||
|
return mongoClient.getCollection(databaseName ~ "." ~ key);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -9,7 +9,7 @@ import std.typecons : Nullable;
|
||||||
|
|
||||||
import vibe.data.bson : Bson, BsonObjectID, deserializeBson, serializeToBson;
|
import vibe.data.bson : Bson, BsonObjectID, deserializeBson, serializeToBson;
|
||||||
import vibe.data.serialization : serializationName = name;
|
import vibe.data.serialization : serializationName = name;
|
||||||
import vibe.db.mongo.client : MongoClient;
|
import vibe.db.mongo.collection : MongoCollection;
|
||||||
|
|
||||||
interface EventStore
|
interface EventStore
|
||||||
{
|
{
|
||||||
|
@ -25,14 +25,12 @@ class MongoDBEventStore : EventStore
|
||||||
public:
|
public:
|
||||||
Event getEvent(BsonObjectID id) @safe
|
Event getEvent(BsonObjectID id) @safe
|
||||||
{
|
{
|
||||||
return mongoClient.getCollection(databaseName ~ "." ~ entriesCollectionName)
|
return events.findOne(["_id" : id]).deserializeBson!Event;
|
||||||
.findOne(["_id" : id]).deserializeBson!Event;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
InputRange!Event getAllEvents() @safe
|
InputRange!Event getAllEvents() @safe
|
||||||
{
|
{
|
||||||
return mongoClient.getCollection(databaseName ~ "." ~ entriesCollectionName)
|
return events.find().map!(deserializeBson!Event).inputRangeObject;
|
||||||
.find().map!(deserializeBson!Event).inputRangeObject;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void addEvent(Event event) @safe
|
void addEvent(Event event) @safe
|
||||||
|
@ -40,31 +38,24 @@ public:
|
||||||
if (!event.id.valid)
|
if (!event.id.valid)
|
||||||
event.id = BsonObjectID.generate;
|
event.id = BsonObjectID.generate;
|
||||||
|
|
||||||
mongoClient.getCollection(databaseName ~ "." ~ entriesCollectionName)
|
events.insert(event.serializeToBson);
|
||||||
.insert(event.serializeToBson);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
InputRange!Event getEventsBeginningBetween(Date begin, Date end) @safe
|
InputRange!Event getEventsBeginningBetween(Date begin, Date end) @safe
|
||||||
{
|
{
|
||||||
return mongoClient.getCollection(databaseName ~ "." ~ entriesCollectionName)
|
return events.find(["$and" : [["date" : ["$gte" : begin.serializeToBson]], ["date"
|
||||||
.find(["$and" : [["date" : ["$gte" : begin.serializeToBson]], ["date"
|
|
||||||
: ["$lte" : end.serializeToBson]]]]).map!(deserializeBson!Event)
|
: ["$lte" : end.serializeToBson]]]]).map!(deserializeBson!Event)
|
||||||
.inputRangeObject;
|
.inputRangeObject;
|
||||||
}
|
}
|
||||||
|
|
||||||
void removeEvent(BsonObjectID id) @safe
|
void removeEvent(BsonObjectID id) @safe
|
||||||
{
|
{
|
||||||
mongoClient.getCollection(databaseName ~ "." ~ entriesCollectionName).remove(["_id" : id]);
|
events.remove(["_id" : id]);
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@Autowire MongoClient mongoClient;
|
@Value("events")
|
||||||
|
MongoCollection events;
|
||||||
@Value("Database name")
|
|
||||||
string databaseName;
|
|
||||||
|
|
||||||
@Value("Entries collection name")
|
|
||||||
string entriesCollectionName;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
enum EventType
|
enum EventType
|
||||||
|
@ -82,7 +73,7 @@ struct Event
|
||||||
@serializationName("date") Date begin;
|
@serializationName("date") Date begin;
|
||||||
@serializationName("end_date") Nullable!Date end;
|
@serializationName("end_date") Nullable!Date end;
|
||||||
string name;
|
string name;
|
||||||
@serializationName("desc") string[] description;
|
@serializationName("desc") string description;
|
||||||
@serializationName("etype") EventType type;
|
@serializationName("etype") EventType type;
|
||||||
bool shout;
|
bool shout;
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,15 +21,15 @@ block content
|
||||||
- showerror("description");
|
- showerror("description");
|
||||||
tr
|
tr
|
||||||
td
|
td
|
||||||
label(for="begin") Von
|
label(for="multiday") Mehrtägig
|
||||||
|
td
|
||||||
|
input#multiday(name="multiday", type="checkbox")
|
||||||
|
tr
|
||||||
|
td
|
||||||
|
label#beginLabel(for="begin") Datum
|
||||||
td
|
td
|
||||||
input#begin(value="", name="begin", type="date")
|
input#begin(value="", name="begin", type="date")
|
||||||
- showerror("begin");
|
- showerror("begin");
|
||||||
tr
|
|
||||||
td
|
|
||||||
label(for="end") Bis
|
|
||||||
td
|
|
||||||
input#end(value="", name="end", type="date")
|
|
||||||
- showerror("end");
|
- showerror("end");
|
||||||
tr
|
tr
|
||||||
td
|
td
|
||||||
|
@ -55,3 +55,19 @@ block content
|
||||||
input#submitButton(type="submit", value="Ereignis erstellen")
|
input#submitButton(type="submit", value="Ereignis erstellen")
|
||||||
- if (_error.msg && _error.field == "")
|
- if (_error.msg && _error.field == "")
|
||||||
p.error= _error.msg
|
p.error= _error.msg
|
||||||
|
script(type="text/javascript").
|
||||||
|
document.getElementById('multiday').onclick = function() {
|
||||||
|
var table = document.getElementById("fieldTable");
|
||||||
|
var beginLabel = document.getElementById("beginLabel");
|
||||||
|
if ( this.checked ) {
|
||||||
|
var row = table.insertRow(4);
|
||||||
|
var cell1 = row.insertCell(0);
|
||||||
|
var cell2 = row.insertCell(1);
|
||||||
|
cell1.innerHTML = "<label for='end'>Bis</label>";
|
||||||
|
cell2.innerHTML = "<input id='end' value='' name='end' type='date'>";
|
||||||
|
beginLabel.innerHTML = "Von";
|
||||||
|
} else {
|
||||||
|
table.deleteRow(4);
|
||||||
|
beginLabel.innerHTML = "Datum";
|
||||||
|
}
|
||||||
|
};
|
|
@ -17,7 +17,7 @@ block content
|
||||||
td #{event.name}
|
td #{event.name}
|
||||||
tr
|
tr
|
||||||
td desc
|
td desc
|
||||||
td #{event.description}
|
td.pre #{event.description}
|
||||||
tr
|
tr
|
||||||
td etype
|
td etype
|
||||||
td #{event.type}
|
td #{event.type}
|
||||||
|
|
Loading…
Reference in a new issue