liprug 0.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.gitignore +16 -0
- data/Gemfile +4 -0
- data/Gemfile.lock +42 -0
- data/LICENSE.txt +22 -0
- data/README.md +42 -0
- data/Rakefile +1 -0
- data/config.ru +6 -0
- data/lib/liprug/config.rb +7 -0
- data/lib/liprug/model.rb +86 -0
- data/lib/liprug/public/js/app.js +33 -0
- data/lib/liprug/service/helpers.rb +21 -0
- data/lib/liprug/service/routes.rb +67 -0
- data/lib/liprug/service.rb +9 -0
- data/lib/liprug/version.rb +3 -0
- data/lib/liprug/views/admin.slim +118 -0
- data/lib/liprug/views/overview.slim +73 -0
- data/lib/liprug.rb +6 -0
- data/liprug.gemspec +29 -0
- metadata +160 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 3c2a0efd0372fc1dcc5d21a8d65d5911fed62e53
|
4
|
+
data.tar.gz: da31cd1f5c7c1a649d5d5bc4e5ea3eeb09eb3844
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: d59576b841a9f2b596fd75428baae63413c03011c3a5f8b3281fcd2155394653e6f4771ef20c6c25feed6f9ca4716b7c7142e6a79923721b6f6b373b86020d87
|
7
|
+
data.tar.gz: 86cac38dc47ea2c6c38e148aed5a28cc7361817c22e255b37264e62f602dd7e841a4690b19f5e4c4830bb0e3e9c9ee57d2fe6c4c3c7f88705a969d45dd3bbc89
|
data/.gitignore
ADDED
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,42 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
liprug (0.0.1)
|
5
|
+
rdiscount
|
6
|
+
redis
|
7
|
+
sinatra
|
8
|
+
slim
|
9
|
+
unicorn
|
10
|
+
|
11
|
+
GEM
|
12
|
+
remote: https://rubygems.org/
|
13
|
+
specs:
|
14
|
+
kgio (2.8.0)
|
15
|
+
rack (1.5.2)
|
16
|
+
rack-protection (1.5.0)
|
17
|
+
rack
|
18
|
+
raindrops (0.12.0)
|
19
|
+
rake (10.1.0)
|
20
|
+
rdiscount (2.1.6)
|
21
|
+
redis (3.0.4)
|
22
|
+
sinatra (1.4.3)
|
23
|
+
rack (~> 1.4)
|
24
|
+
rack-protection (~> 1.4)
|
25
|
+
tilt (~> 1.3, >= 1.3.4)
|
26
|
+
slim (2.0.1)
|
27
|
+
temple (~> 0.6.6)
|
28
|
+
tilt (>= 1.3.3, < 2.1)
|
29
|
+
temple (0.6.6)
|
30
|
+
tilt (1.4.1)
|
31
|
+
unicorn (4.6.3)
|
32
|
+
kgio (~> 2.6)
|
33
|
+
rack
|
34
|
+
raindrops (~> 0.7)
|
35
|
+
|
36
|
+
PLATFORMS
|
37
|
+
ruby
|
38
|
+
|
39
|
+
DEPENDENCIES
|
40
|
+
bundler (~> 1.3)
|
41
|
+
liprug!
|
42
|
+
rake
|
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2013 Exoscale
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,42 @@
|
|
1
|
+
liprug: simple status board
|
2
|
+
----------------------------
|
3
|
+
|
4
|
+

|
5
|
+
|
6
|
+
The idea behind liprug is to give you a simple tool
|
7
|
+
to communicate your operational status to clients.
|
8
|
+
|
9
|
+
The main objectives behind liprug were:
|
10
|
+
|
11
|
+
* Simple deployment compatible with heroku and AWS
|
12
|
+
* All-in-one solution
|
13
|
+
* Simple administration
|
14
|
+
|
15
|
+
### Deployment
|
16
|
+
|
17
|
+
You can deploy to heroku or any host provider. It is advised to set up liprug to operate
|
18
|
+
behind SSL only.
|
19
|
+
|
20
|
+
### Configuration
|
21
|
+
|
22
|
+
Configuration is done through environment variables, here are the relevant ones:
|
23
|
+
|
24
|
+
* `REDIS_URL` or `REDISTOGO_URL`: url of redis host for storage
|
25
|
+
* `LIPRUG_BRAND_HEADER`: text you want shown on the header bar
|
26
|
+
* `LIPRUG_BRAND_CONTACT`: if present, a "report issue" button will show up in the bar, with this value as href
|
27
|
+
* `LIPRUG_BRAND_SCRIPT`: if present, a script to be inserted in the page, to track analytics for instance
|
28
|
+
* `LIPRUG_CREDENTIALS`: colon separated user and password
|
29
|
+
|
30
|
+
### Usage
|
31
|
+
|
32
|
+
The main URL shows current service status, the `/admin` URL allows input and modifications
|
33
|
+
|
34
|
+
### Roadmap
|
35
|
+
|
36
|
+
* Additional authentication methods to admin interface
|
37
|
+
* Per-service history
|
38
|
+
* Typed service data to allow graphs
|
39
|
+
|
40
|
+
### Authors
|
41
|
+
|
42
|
+
liprug is a production of [exoscale](https://exoscale.ch)
|
data/Rakefile
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require "bundler/gem_tasks"
|
data/config.ru
ADDED
data/lib/liprug/model.rb
ADDED
@@ -0,0 +1,86 @@
|
|
1
|
+
require 'redis'
|
2
|
+
require 'json'
|
3
|
+
require 'uri'
|
4
|
+
require 'liprug/config'
|
5
|
+
|
6
|
+
module Liprug
|
7
|
+
class Model
|
8
|
+
def self.connect!
|
9
|
+
url = Liprug::Config['REDISTOGO_URL']
|
10
|
+
url ||= Liprug::Config['REDIS_URL']
|
11
|
+
url ||= "redis://127.0.0.1"
|
12
|
+
|
13
|
+
uri = URI.parse(url)
|
14
|
+
options = {:host => uri.host}
|
15
|
+
options[:port] = uri.port if uri.port
|
16
|
+
options[:password] = uri.password if uri.password
|
17
|
+
|
18
|
+
Redis.new(options)
|
19
|
+
end
|
20
|
+
|
21
|
+
def self.fetch
|
22
|
+
redis = connect!
|
23
|
+
services = redis.smembers 'services'
|
24
|
+
{
|
25
|
+
:brand => {
|
26
|
+
:script => Liprug::Config['LIPRUG_BRAND_SCRIPT'] || '',
|
27
|
+
:name => Liprug::Config['LIPRUG_BRAND_HEADER'] || 'status board',
|
28
|
+
:contact => Liprug::Config['LIPRUG_BRAND_CONTACT']
|
29
|
+
},
|
30
|
+
:services => services.map do |service|
|
31
|
+
{
|
32
|
+
service => JSON.parse(redis.get("service:#{service}"),
|
33
|
+
:symbolize_names => true)
|
34
|
+
}
|
35
|
+
end.reduce({}) do |e1,e2|
|
36
|
+
e1.merge e2
|
37
|
+
end,
|
38
|
+
:past => redis.lrange('events_past', 0, -1).map do |event|
|
39
|
+
JSON.parse event, :symbolize_names => true
|
40
|
+
end,
|
41
|
+
:upcoming => redis.lrange('events_upcoming', 0, -1).map do |event|
|
42
|
+
JSON.parse event, :symbolize_names => true
|
43
|
+
end
|
44
|
+
}
|
45
|
+
end
|
46
|
+
|
47
|
+
def self.add_status service, status
|
48
|
+
redis = connect!
|
49
|
+
redis.sadd "services", service
|
50
|
+
redis.set "service:#{service}", status.to_json
|
51
|
+
end
|
52
|
+
|
53
|
+
def self.delete_service service
|
54
|
+
redis = connect!
|
55
|
+
redis.srem "services", service
|
56
|
+
redis.del "service:#{service}"
|
57
|
+
end
|
58
|
+
|
59
|
+
def self.add_upcoming_event event
|
60
|
+
redis = connect!
|
61
|
+
event[:date] = Time.new.asctime
|
62
|
+
event = event.to_json
|
63
|
+
redis.lpush "events_upcoming", event
|
64
|
+
end
|
65
|
+
|
66
|
+
def self.add_past_event event
|
67
|
+
redis = connect!
|
68
|
+
event[:date] = Time.new.asctime
|
69
|
+
event = event.to_json
|
70
|
+
redis.lpush "events_past", event
|
71
|
+
end
|
72
|
+
|
73
|
+
def self.delete_upcoming_event index
|
74
|
+
redis = connect!
|
75
|
+
redis.lset "events_upcoming", index, "XXXXX"
|
76
|
+
redis.lrem "events_upcoming", 1, "XXXXX"
|
77
|
+
end
|
78
|
+
|
79
|
+
def self.delete_past_event index
|
80
|
+
redis = connect!
|
81
|
+
redis.lset "events_past", index, "XXXXX"
|
82
|
+
redis.lrem "events_past", 1, "XXXXX"
|
83
|
+
end
|
84
|
+
|
85
|
+
end
|
86
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
$(document).ready(function () {
|
2
|
+
$("td.delete-service").each(function(index, el) {
|
3
|
+
var b = $(el).find("button");
|
4
|
+
var id = b.attr("id");
|
5
|
+
b.click(function (ev) {
|
6
|
+
ev.preventDefault();
|
7
|
+
$.ajax({url: '/api/services/' + id,
|
8
|
+
type: 'DELETE'});
|
9
|
+
});
|
10
|
+
});
|
11
|
+
|
12
|
+
$("td.delete-past-event").each(function(index, el) {
|
13
|
+
|
14
|
+
var b = $(el).find("button");
|
15
|
+
var id = b.attr("id");
|
16
|
+
b.click(function (ev) {
|
17
|
+
ev.preventDefault();
|
18
|
+
$.ajax({url: '/api/past/' + id,
|
19
|
+
type: 'DELETE'});
|
20
|
+
});
|
21
|
+
});
|
22
|
+
|
23
|
+
$("td.delete-upcoming-event").each(function(index, el) {
|
24
|
+
|
25
|
+
var b = $(el).find("button");
|
26
|
+
var id = b.attr("id");
|
27
|
+
b.click(function (ev) {
|
28
|
+
ev.preventDefault();
|
29
|
+
$.ajax({url: '/api/upcoming/' + id,
|
30
|
+
type: 'DELETE'});
|
31
|
+
});
|
32
|
+
});
|
33
|
+
});
|
@@ -0,0 +1,21 @@
|
|
1
|
+
require 'sinatra'
|
2
|
+
require 'liprug/config'
|
3
|
+
|
4
|
+
module Liprug
|
5
|
+
class Service < Sinatra::Base
|
6
|
+
helpers do
|
7
|
+
|
8
|
+
def authorized?
|
9
|
+
creds = (Liprug::Config['LIPRUG_CREDENTIALS'] || ":").split ":"
|
10
|
+
@auth ||= Rack::Auth::Basic::Request.new(request.env)
|
11
|
+
@auth.provided? and @auth.basic? and @auth.credentials and @auth.credentials == creds
|
12
|
+
end
|
13
|
+
|
14
|
+
def protected!
|
15
|
+
return if authorized?
|
16
|
+
headers['WWW-Authenticate'] = 'Basic realm="Restricted Area"'
|
17
|
+
halt 401, "Not authorized"
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,67 @@
|
|
1
|
+
require 'sinatra'
|
2
|
+
require 'rdiscount'
|
3
|
+
require 'slim'
|
4
|
+
require 'liprug/model'
|
5
|
+
require 'liprug/service/helpers'
|
6
|
+
|
7
|
+
module Liprug
|
8
|
+
class Service < Sinatra::Base
|
9
|
+
|
10
|
+
get '/' do
|
11
|
+
slim :overview, :locals => Liprug::Model.fetch
|
12
|
+
end
|
13
|
+
|
14
|
+
get '/admin' do
|
15
|
+
protected!
|
16
|
+
slim :admin, :locals => Liprug::Model.fetch
|
17
|
+
end
|
18
|
+
|
19
|
+
post '/api/services' do
|
20
|
+
protected!
|
21
|
+
Liprug::Model.add_status(params[:name],
|
22
|
+
{
|
23
|
+
:class => params[:class],
|
24
|
+
:message => params[:message]
|
25
|
+
})
|
26
|
+
redirect "/admin"
|
27
|
+
end
|
28
|
+
|
29
|
+
delete '/api/services/:service' do
|
30
|
+
protected!
|
31
|
+
Liprug::Model.delete_service params[:service]
|
32
|
+
redirect "/admin"
|
33
|
+
end
|
34
|
+
|
35
|
+
post '/api/past' do
|
36
|
+
protected!
|
37
|
+
Liprug::Model.add_past_event({
|
38
|
+
:class => params[:class],
|
39
|
+
:message => params[:message]
|
40
|
+
})
|
41
|
+
redirect "/admin"
|
42
|
+
end
|
43
|
+
|
44
|
+
post '/api/upcoming' do
|
45
|
+
protected!
|
46
|
+
Liprug::Model.add_upcoming_event({
|
47
|
+
:class => params[:class],
|
48
|
+
:message => params[:message]
|
49
|
+
})
|
50
|
+
redirect "/admin"
|
51
|
+
end
|
52
|
+
|
53
|
+
delete '/api/past/:event' do
|
54
|
+
protected!
|
55
|
+
Liprug::Model.delete_past_event params[:event].to_i
|
56
|
+
|
57
|
+
redirect "/admin"
|
58
|
+
end
|
59
|
+
|
60
|
+
delete '/api/upcoming/:event' do
|
61
|
+
protected!
|
62
|
+
Liprug::Model.delete_upcoming_event params[:event].to_i
|
63
|
+
|
64
|
+
redirect "/admin"
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
@@ -0,0 +1,118 @@
|
|
1
|
+
doctype html
|
2
|
+
html
|
3
|
+
head
|
4
|
+
title Status Board
|
5
|
+
meta name="viewport" content="width=device-width, initial-scale=1.0"
|
6
|
+
link rel="stylesheet" type="text/css" href="//netdna.bootstrapcdn.com/bootstrap/3.0.0/css/bootstrap.min.css"
|
7
|
+
body
|
8
|
+
|
9
|
+
nav.navbar.navbar-default role="navigation"
|
10
|
+
div.navbar-header
|
11
|
+
a.navbar-brand href="/" status admin
|
12
|
+
|
13
|
+
div.container
|
14
|
+
div.row
|
15
|
+
|
16
|
+
div.col-md-8.col-md-offset-2
|
17
|
+
|
18
|
+
h2 Services
|
19
|
+
|
20
|
+
form.form-horizontal role="form" method="POST" action="/api/services"
|
21
|
+
div.form-group
|
22
|
+
label.col-lg-2.control-label for="name" Service Name
|
23
|
+
div.col-lg-6
|
24
|
+
input.form-control type="text" id="name" name="name"
|
25
|
+
div.form-group
|
26
|
+
label.col-lg-2.control-label for="class" Status class
|
27
|
+
div.col-lg-6
|
28
|
+
div
|
29
|
+
input type="radio" id="class" name="class" value="success" success
|
30
|
+
div
|
31
|
+
input type="radio" id="class" name="class" value="danger" danger
|
32
|
+
div
|
33
|
+
input type="radio" id="class" name="class" value="warning" warning
|
34
|
+
div.form-group
|
35
|
+
label.col-lg-2.control-label for="message" Message
|
36
|
+
div.col-lg-6
|
37
|
+
input.form-control type="text" id="message" name="message"
|
38
|
+
div.form-group
|
39
|
+
div.col-lg-offset-2.col-lg-6
|
40
|
+
button.btn.btn-default type="submit" update
|
41
|
+
|
42
|
+
table.table.table-bordered.table-striped
|
43
|
+
tbody
|
44
|
+
- for name,status in services do
|
45
|
+
tr
|
46
|
+
td #{name}
|
47
|
+
td.delete-service
|
48
|
+
button.btn.btn-primary.pull-right id="#{name}"
|
49
|
+
span.glyphicon.glyphicon-trash
|
50
|
+
| delete
|
51
|
+
|
52
|
+
h2 Upcoming Events
|
53
|
+
|
54
|
+
form.form-horizontal role="form" method="POST" action="/api/upcoming"
|
55
|
+
div.form-group
|
56
|
+
label.col-lg-2.control-label for="class" Status class
|
57
|
+
div.col-lg-6
|
58
|
+
div
|
59
|
+
input type="radio" id="event-class" name="class" value="info" info
|
60
|
+
div
|
61
|
+
input type="radio" id="event-class" name="class" value="success" success
|
62
|
+
div
|
63
|
+
input type="radio" id="event-class" name="class" value="danger" danger
|
64
|
+
div
|
65
|
+
input type="radio" id="event-class" name="class" value="warning" warning
|
66
|
+
div.form-group
|
67
|
+
label.col-lg-2.control-label for="message" Message
|
68
|
+
div.col-lg-6
|
69
|
+
textarea.form-control id="event-message" name="message"
|
70
|
+
div.form-group
|
71
|
+
div.col-lg-offset-2.col-lg-6
|
72
|
+
button.btn.btn-default type="submit" update
|
73
|
+
|
74
|
+
table.table.table-bordered.table-striped
|
75
|
+
tbody
|
76
|
+
- for event, index in upcoming.each_with_index do
|
77
|
+
tr
|
78
|
+
td #{event[:message]}
|
79
|
+
td.delete-upcoming-event
|
80
|
+
button.btn.btn-primary.pull-right id="#{index}"
|
81
|
+
span.glyphicon.glyphicon-trash
|
82
|
+
| delete
|
83
|
+
|
84
|
+
h2 Past Events
|
85
|
+
|
86
|
+
form.form-horizontal role="form" method="POST" action="/api/past"
|
87
|
+
div.form-group
|
88
|
+
label.col-lg-2.control-label for="class" Status class
|
89
|
+
div.col-lg-6
|
90
|
+
div
|
91
|
+
input type="radio" id="event-class" name="class" value="info" info
|
92
|
+
div
|
93
|
+
input type="radio" id="event-class" name="class" value="success" success
|
94
|
+
div
|
95
|
+
input type="radio" id="event-class" name="class" value="danger" danger
|
96
|
+
div
|
97
|
+
input type="radio" id="event-class" name="class" value="warning" warning
|
98
|
+
div.form-group
|
99
|
+
label.col-lg-2.control-label for="message" Message
|
100
|
+
div.col-lg-6
|
101
|
+
textarea.form-control id="event-message" name="message"
|
102
|
+
div.form-group
|
103
|
+
div.col-lg-offset-2.col-lg-6
|
104
|
+
button.btn.btn-default type="submit" update
|
105
|
+
|
106
|
+
table.table.table-bordered.table-striped
|
107
|
+
tbody
|
108
|
+
- for event, index in past.each_with_index do
|
109
|
+
tr
|
110
|
+
td #{event[:message]}
|
111
|
+
td.delete-past-event
|
112
|
+
button.btn.btn-primary.pull-right id="#{index}"
|
113
|
+
span.glyphicon.glyphicon-trash
|
114
|
+
| delete
|
115
|
+
|
116
|
+
|
117
|
+
script type="text/javascript" src="//ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"
|
118
|
+
script type="text/javascript" src="/js/app.js"
|
@@ -0,0 +1,73 @@
|
|
1
|
+
doctype html
|
2
|
+
html
|
3
|
+
head
|
4
|
+
title Status Board
|
5
|
+
meta name="viewport" content="width=device-width, initial-scale=1.0"
|
6
|
+
link rel="stylesheet" type="text/css" href="//netdna.bootstrapcdn.com/bootstrap/3.0.0/css/bootstrap.min.css"
|
7
|
+
body
|
8
|
+
|
9
|
+
style type="text/css"
|
10
|
+
| .bs-callout {
|
11
|
+
| margin: 20px 0;
|
12
|
+
| padding: 15px 30px 15px 15px;
|
13
|
+
| border-left: 5px solid #eee;
|
14
|
+
| }
|
15
|
+
| .bs-callout h4 { margin-top: 0; }
|
16
|
+
| .bs-callout p:last-child { margin-bottom: 0; }
|
17
|
+
| .bs-callout code, .bs-callout .highlight {background-color: #fff;}
|
18
|
+
| .bs-callout-danger {background-color: #fcf2f2; border-color: #dFb5b4;}
|
19
|
+
| .bs-callout-warning {background-color: #fefbed; border-color: #f1e7bc;}
|
20
|
+
| .bs-callout-info {background-color: #f0f7fd; border-color: #d0e3f0;}
|
21
|
+
| .bs-callout-success {background-color: #dff0d8; border-color: #d6e9c6;}
|
22
|
+
|
23
|
+
== brand[:script]
|
24
|
+
|
25
|
+
nav.navbar.navbar-default role="navigation"
|
26
|
+
div.navbar-header
|
27
|
+
button.navbar-toggle data-toggle="collapse" data-target=".navbar-main-collapse"
|
28
|
+
span.sr-only Toggle Navigation
|
29
|
+
span.icon-bar
|
30
|
+
span.icon-bar
|
31
|
+
span.icon-bar
|
32
|
+
a.navbar-brand href="/" #{brand[:name]}
|
33
|
+
|
34
|
+
- if brand[:contact]
|
35
|
+
nav.collapse.navbar-collapse.navbar-main-collapse role="navigation"
|
36
|
+
a.navbar-btn.navbar-right.btn.btn-info.btn-sm href="#{brand[:contact]}" Report issue
|
37
|
+
|
38
|
+
div.container
|
39
|
+
div.row
|
40
|
+
div.col-md-8.col-md-offset-2
|
41
|
+
h2 Services
|
42
|
+
|
43
|
+
table.table.table-bordered.table-striped
|
44
|
+
thead
|
45
|
+
tr
|
46
|
+
th Service
|
47
|
+
th Status
|
48
|
+
tbody
|
49
|
+
- for name in services.keys.sort do
|
50
|
+
tr
|
51
|
+
td #{name}
|
52
|
+
td class="#{services[name][:class]}"
|
53
|
+
| #{services[name][:message]}
|
54
|
+
|
55
|
+
h2 Upcoming Events
|
56
|
+
- for event in upcoming do
|
57
|
+
div class="bs-callout bs-callout-#{event[:class]}"
|
58
|
+
p
|
59
|
+
small
|
60
|
+
i On #{event[:date]}
|
61
|
+
div
|
62
|
+
== RDiscount.new(event[:message]).to_html
|
63
|
+
h2 Latest Events
|
64
|
+
- for event in past do
|
65
|
+
div class="bs-callout bs-callout-#{event[:class]}"
|
66
|
+
p
|
67
|
+
small
|
68
|
+
i On #{event[:date]}
|
69
|
+
div
|
70
|
+
== RDiscount.new(event[:message]).to_html
|
71
|
+
script type="text/javascript" src="//ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"
|
72
|
+
script type="text/javascript" src="//netdna.bootstrapcdn.com/bootstrap/3.0.0/js/bootstrap.min.js"
|
73
|
+
|
data/lib/liprug.rb
ADDED
data/liprug.gemspec
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'liprug/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "liprug"
|
8
|
+
spec.version = Liprug::VERSION
|
9
|
+
spec.authors = ["Pierre-Yves Ritschard"]
|
10
|
+
spec.email = ["pyr@spootnik.org"]
|
11
|
+
spec.description = %q{simple operational dashboard}
|
12
|
+
spec.summary = %q{operational dashboard}
|
13
|
+
spec.homepage = "https://github.com/exoscale/liprug"
|
14
|
+
spec.license = "MIT"
|
15
|
+
|
16
|
+
spec.files = `git ls-files`.split($/)
|
17
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
18
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
|
+
spec.require_paths = ["lib"]
|
20
|
+
|
21
|
+
spec.add_dependency "sinatra"
|
22
|
+
spec.add_dependency "slim"
|
23
|
+
spec.add_dependency "redis"
|
24
|
+
spec.add_dependency "rdiscount"
|
25
|
+
spec.add_dependency "unicorn"
|
26
|
+
|
27
|
+
spec.add_development_dependency "bundler", "~> 1.3"
|
28
|
+
spec.add_development_dependency "rake"
|
29
|
+
end
|
metadata
ADDED
@@ -0,0 +1,160 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: liprug
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.2
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Pierre-Yves Ritschard
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2013-11-06 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: sinatra
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - '>='
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - '>='
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: slim
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - '>='
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - '>='
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: redis
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - '>='
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :runtime
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - '>='
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: rdiscount
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - '>='
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
type: :runtime
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - '>='
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: unicorn
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - '>='
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '0'
|
76
|
+
type: :runtime
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - '>='
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '0'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: bundler
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - ~>
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '1.3'
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - ~>
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '1.3'
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: rake
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - '>='
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: '0'
|
104
|
+
type: :development
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - '>='
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: '0'
|
111
|
+
description: simple operational dashboard
|
112
|
+
email:
|
113
|
+
- pyr@spootnik.org
|
114
|
+
executables: []
|
115
|
+
extensions: []
|
116
|
+
extra_rdoc_files: []
|
117
|
+
files:
|
118
|
+
- .gitignore
|
119
|
+
- Gemfile
|
120
|
+
- Gemfile.lock
|
121
|
+
- LICENSE.txt
|
122
|
+
- README.md
|
123
|
+
- Rakefile
|
124
|
+
- config.ru
|
125
|
+
- lib/liprug.rb
|
126
|
+
- lib/liprug/config.rb
|
127
|
+
- lib/liprug/model.rb
|
128
|
+
- lib/liprug/public/js/app.js
|
129
|
+
- lib/liprug/service.rb
|
130
|
+
- lib/liprug/service/helpers.rb
|
131
|
+
- lib/liprug/service/routes.rb
|
132
|
+
- lib/liprug/version.rb
|
133
|
+
- lib/liprug/views/admin.slim
|
134
|
+
- lib/liprug/views/overview.slim
|
135
|
+
- liprug.gemspec
|
136
|
+
homepage: https://github.com/exoscale/liprug
|
137
|
+
licenses:
|
138
|
+
- MIT
|
139
|
+
metadata: {}
|
140
|
+
post_install_message:
|
141
|
+
rdoc_options: []
|
142
|
+
require_paths:
|
143
|
+
- lib
|
144
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
145
|
+
requirements:
|
146
|
+
- - '>='
|
147
|
+
- !ruby/object:Gem::Version
|
148
|
+
version: '0'
|
149
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
150
|
+
requirements:
|
151
|
+
- - '>='
|
152
|
+
- !ruby/object:Gem::Version
|
153
|
+
version: '0'
|
154
|
+
requirements: []
|
155
|
+
rubyforge_project:
|
156
|
+
rubygems_version: 2.0.0
|
157
|
+
signing_key:
|
158
|
+
specification_version: 4
|
159
|
+
summary: operational dashboard
|
160
|
+
test_files: []
|