octodmin 0.1.0 → 0.2.0
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 +4 -4
- data/.travis.yml +1 -0
- data/CHANGELOG.md +7 -0
- data/README.md +12 -10
- data/app/assets/javascripts/app.js.coffee +1 -0
- data/app/assets/javascripts/components/header.js.cjsx +6 -16
- data/app/assets/javascripts/components/posts.js.cjsx +12 -28
- data/app/assets/javascripts/components/router.js.cjsx +9 -2
- data/app/assets/stylesheets/app.scss +10 -0
- data/bower.json +1 -0
- data/lib/octodmin/post.rb +2 -2
- data/lib/octodmin/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 486c254e24ba8ecb343d9153f8a3fa520cc6fcf9
|
4
|
+
data.tar.gz: c4d51cf2c335bdeac72e50f7942c68f09b18ef40
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 99d6b2bc5a38721a1ce9e10f6f270cb9041baf99353ed8a3a1669252266761140f26119d0362991c782ed819c839c1f52726cf946492901286a24caf76289983
|
7
|
+
data.tar.gz: de3ea218515c0c77229a62902a8848d570c4817f4b6db587e0bf312777d11b733fecd8dff3fd6cc3177b8533d29aee856a32ec79bdf7e5847d3ce0fb9ba4316e
|
data/.travis.yml
CHANGED
data/CHANGELOG.md
CHANGED
data/README.md
CHANGED
@@ -14,7 +14,7 @@ Content management for Jekyll blogs
|
|
14
14
|
Add this line to your Jekyll project's Gemfile:
|
15
15
|
|
16
16
|
```ruby
|
17
|
-
gem 'octodmin'
|
17
|
+
gem 'octodmin'
|
18
18
|
```
|
19
19
|
|
20
20
|
And then execute:
|
@@ -76,15 +76,6 @@ post_ext: markdown
|
|
76
76
|
post_layout: post
|
77
77
|
```
|
78
78
|
|
79
|
-
Please note that Octodmin uses Octopress internally, so make sure you
|
80
|
-
there is proper config, for example:
|
81
|
-
|
82
|
-
```yaml
|
83
|
-
# Octopress
|
84
|
-
post_ext: markdown
|
85
|
-
post_layout: post
|
86
|
-
```
|
87
|
-
|
88
79
|
## Deployment
|
89
80
|
|
90
81
|
Since Octodmin is a simple Rack app, use your favorite Ruby application server.
|
@@ -95,6 +86,17 @@ When deploying Octodmin to a remote server, make sure you're able to run
|
|
95
86
|
`git pull`, `git push` and `octopress deploy` (if needed) successfully
|
96
87
|
in the shell of your remote user.
|
97
88
|
|
89
|
+
For basic HTTP authentication, use `Rack::Auth::Basic`.
|
90
|
+
Example for your `config.ru`:
|
91
|
+
|
92
|
+
```ruby
|
93
|
+
use Rack::Auth::Basic, "Octodmin" do |username, password|
|
94
|
+
[username, password] == [ENV["USERNAME"], ENV["PASSWORD"]]
|
95
|
+
end
|
96
|
+
```
|
97
|
+
|
98
|
+
Just set ENV variables and you're good to go.
|
99
|
+
|
98
100
|
## Development and testing
|
99
101
|
|
100
102
|
You would need `npm` and `bower`. Run `bower install` to install asset
|
@@ -5,7 +5,7 @@
|
|
5
5
|
site: React.PropTypes.object.isRequired
|
6
6
|
|
7
7
|
getInitialState: ->
|
8
|
-
{
|
8
|
+
{ loading: false }
|
9
9
|
|
10
10
|
handleSync: ->
|
11
11
|
return if @state.loading
|
@@ -21,23 +21,15 @@
|
|
21
21
|
@setState(loading: false)
|
22
22
|
|
23
23
|
handleSyncSuccess: (response) ->
|
24
|
-
|
25
|
-
setTimeout(@removeSuccess, 5000)
|
24
|
+
$.growl(response.syncs.join("\n").replace(/\n/g, "<br>"), growlSuccess)
|
26
25
|
$(document).trigger("fetchPosts")
|
27
26
|
|
28
27
|
handleDeploySuccess: (response) ->
|
29
|
-
|
30
|
-
setTimeout(@removeSuccess, 5000)
|
28
|
+
$.growl(response.deploys.join("\n"), growlSuccess)
|
31
29
|
$(document).trigger("fetchPosts")
|
32
30
|
|
33
31
|
handleError: (error) ->
|
34
|
-
|
35
|
-
|
36
|
-
removeSuccess: ->
|
37
|
-
@setState(success: null) if @isMounted()
|
38
|
-
|
39
|
-
handleBlur: ->
|
40
|
-
@setState(alert: null, success: null) if @isMounted()
|
32
|
+
$.growl(error.responseJSON?.errors.join("\n").replace(/\n/g, "<br>"), growlError)
|
41
33
|
|
42
34
|
render: ->
|
43
35
|
<div>
|
@@ -47,13 +39,13 @@
|
|
47
39
|
<Link to="app" className="navbar-brand"><i className="fa fa-fw fa-cog"></i> {@props.site.title}</Link>
|
48
40
|
</div>
|
49
41
|
<div className="navbar-right">
|
50
|
-
<button className="btn btn-primary navbar-btn #{'disabled' if @state.loading}" onClick={@handleSync}
|
42
|
+
<button className="btn btn-primary navbar-btn #{'disabled' if @state.loading}" onClick={@handleSync}>
|
51
43
|
<i className="fa fa-fw fa-refresh"></i> Sync
|
52
44
|
</button>
|
53
45
|
{if @props.site.octodmin.deploys
|
54
46
|
deploy = @props.site.octodmin.deploys[0]
|
55
47
|
|
56
|
-
<button className="btn btn-primary navbar-btn #{'disabled' if @state.loading}" onClick={@handleDeploy}
|
48
|
+
<button className="btn btn-primary navbar-btn #{'disabled' if @state.loading}" onClick={@handleDeploy}>
|
57
49
|
<i className="fa fa-fw fa-ship"></i> Deploy
|
58
50
|
</button>
|
59
51
|
}
|
@@ -63,7 +55,5 @@
|
|
63
55
|
</div>
|
64
56
|
</div>
|
65
57
|
</nav>
|
66
|
-
{<div className="alert alert-danger"><span dangerouslySetInnerHTML={{__html: @state.alert }}></span></div> if @state.alert}
|
67
|
-
{<div className="alert alert-success"><span dangerouslySetInnerHTML={{__html: @state.success }}></span></div> if @state.success}
|
68
58
|
</div>
|
69
59
|
)
|
@@ -5,7 +5,7 @@
|
|
5
5
|
site: React.PropTypes.object.isRequired
|
6
6
|
|
7
7
|
getInitialState: ->
|
8
|
-
{
|
8
|
+
{ loading: false, posts: null }
|
9
9
|
|
10
10
|
fetchPosts: ->
|
11
11
|
return if @state.loading
|
@@ -16,23 +16,20 @@
|
|
16
16
|
@setState(loading: false) if @isMounted()
|
17
17
|
|
18
18
|
handleSuccess: (response) ->
|
19
|
-
@setState(
|
19
|
+
@setState(posts: response.posts) if @isMounted()
|
20
20
|
|
21
21
|
handleError: (error) ->
|
22
|
-
|
22
|
+
$.growl("Could not load posts: #{error.statusText} (#{error.status})", growlError)
|
23
23
|
|
24
24
|
componentWillMount: ->
|
25
25
|
@fetchPosts()
|
26
26
|
$(document).on("fetchPosts", @fetchPosts)
|
27
|
-
@timer = setInterval(@fetchPosts, 5000)
|
28
27
|
|
29
28
|
componentWillUnmount: ->
|
30
29
|
$(document).off("fetchPosts", @fetchPosts)
|
31
|
-
clearInterval(@timer)
|
32
30
|
|
33
31
|
render: ->
|
34
32
|
<div>
|
35
|
-
{<div className="alert alert-danger">{@state.alert}</div> if @state.alert}
|
36
33
|
<NewPostPartial site={@props.site} />
|
37
34
|
|
38
35
|
<Loader loaded={!!@state.posts}>
|
@@ -59,7 +56,7 @@
|
|
59
56
|
site: React.PropTypes.object.isRequired
|
60
57
|
|
61
58
|
getInitialState: ->
|
62
|
-
{
|
59
|
+
{ loading: false }
|
63
60
|
|
64
61
|
form: ->
|
65
62
|
$(@refs.form.getDOMNode())
|
@@ -75,19 +72,16 @@
|
|
75
72
|
@setState(loading: false)
|
76
73
|
|
77
74
|
handleSuccess: (response) ->
|
78
|
-
@setState(alert: null)
|
79
75
|
@form()[0].reset()
|
80
76
|
$(document).trigger("fetchPosts")
|
81
77
|
@transitionTo("post_edit", post_id: response.posts.identifier)
|
82
78
|
|
83
79
|
handleError: (error) ->
|
84
|
-
|
80
|
+
$.growl(error.responseJSON?.errors.join(", "), growlError)
|
85
81
|
|
86
82
|
render: ->
|
87
83
|
<div className="panel panel-default">
|
88
84
|
<div className="panel-body">
|
89
|
-
{<div className="alert alert-danger">{@state.alert}</div> if @state.alert}
|
90
|
-
|
91
85
|
<form ref="form" className="form-inline" onSubmit={@handleSubmit}>
|
92
86
|
<fieldset className="row" disabled={@state.loading}>
|
93
87
|
<div className="col-sm-9 form-group form-group-lg">
|
@@ -110,7 +104,7 @@
|
|
110
104
|
post: React.PropTypes.object.isRequired
|
111
105
|
|
112
106
|
getInitialState: ->
|
113
|
-
{
|
107
|
+
{ loading: false }
|
114
108
|
|
115
109
|
panelClass: ->
|
116
110
|
if @props.post.added
|
@@ -159,23 +153,20 @@
|
|
159
153
|
@setState(loading: false)
|
160
154
|
|
161
155
|
handleSuccess: (response) ->
|
162
|
-
@setState(alert: null)
|
163
156
|
$(document).trigger("fetchPosts")
|
164
157
|
|
165
158
|
handleError: (error) ->
|
166
|
-
|
159
|
+
$.growl("Could not load post: #{error.statusText} (#{error.status})", growlError)
|
167
160
|
|
168
161
|
render: ->
|
169
162
|
<div className="panel panel-#{@panelClass()}">
|
170
163
|
<div className="panel-heading clearfix">
|
171
164
|
<h3 className="panel-title pull-left">{@props.post.title}</h3>
|
172
165
|
<div className="pull-right">
|
173
|
-
{moment((new Date(@props.post.date)).toISOString()).format("LLL")}
|
166
|
+
{moment((new Date(@props.post.date.replace(/-/g, "/"))).toISOString()).format("LLL")}
|
174
167
|
</div>
|
175
168
|
</div>
|
176
169
|
<div className="panel-body">
|
177
|
-
{<div className="alert alert-danger">{@state.alert}</div> if @state.alert}
|
178
|
-
|
179
170
|
<div className="row">
|
180
171
|
<div className="col-sm-9 excerpt" dangerouslySetInnerHTML={{__html: @props.post.excerpt }} />
|
181
172
|
<div className="col-sm-3 buttons">
|
@@ -205,7 +196,7 @@
|
|
205
196
|
site: React.PropTypes.object.isRequired
|
206
197
|
|
207
198
|
getInitialState: ->
|
208
|
-
{
|
199
|
+
{ loading: false, post: null }
|
209
200
|
|
210
201
|
form: ->
|
211
202
|
$(@refs.form.getDOMNode())
|
@@ -237,18 +228,14 @@
|
|
237
228
|
@setState(loading: false)
|
238
229
|
|
239
230
|
handleSuccess: (response) ->
|
240
|
-
@setState(
|
231
|
+
@setState(post: response.posts)
|
241
232
|
|
242
233
|
handleFormSuccess: (response) ->
|
243
|
-
|
244
|
-
setTimeout(@removeSuccess, 5000)
|
234
|
+
$.growl("Post is updated", growlSuccess)
|
245
235
|
@transitionTo("post_edit", post_id: response.posts.identifier)
|
246
236
|
|
247
237
|
handleError: (error) ->
|
248
|
-
|
249
|
-
|
250
|
-
removeSuccess: ->
|
251
|
-
@setState(success: null) if @isMounted()
|
238
|
+
$.growl(error.responseJSON?.errors.join(", "), growlError)
|
252
239
|
|
253
240
|
componentWillMount: ->
|
254
241
|
@fetchPost()
|
@@ -268,9 +255,6 @@
|
|
268
255
|
|
269
256
|
render: ->
|
270
257
|
<Loader loaded={!!@state.post}>
|
271
|
-
{<div className="alert alert-danger">{@state.alert}</div> if @state.alert}
|
272
|
-
{<div className="alert alert-success">{@state.success}</div> if @state.success}
|
273
|
-
|
274
258
|
{if @state.post
|
275
259
|
<form ref="form" className="form-horizontal post-edit" onSubmit={@handleSubmit}>
|
276
260
|
<fieldset disabled={@state.loading}>
|
@@ -7,6 +7,14 @@
|
|
7
7
|
@DefaultRoute = Router.DefaultRoute
|
8
8
|
@RouteHandler = Router.RouteHandler
|
9
9
|
|
10
|
+
@growlSuccess =
|
11
|
+
type: "success"
|
12
|
+
delay: 10000
|
13
|
+
|
14
|
+
@growlError =
|
15
|
+
type: "danger"
|
16
|
+
delay: 60000
|
17
|
+
|
10
18
|
@Container = React.createClass(
|
11
19
|
render: ->
|
12
20
|
<div className="container">
|
@@ -26,7 +34,7 @@
|
|
26
34
|
$("title").text("Octodmin – #{response.sites.title}")
|
27
35
|
|
28
36
|
handleError: (error) ->
|
29
|
-
|
37
|
+
$.growl("Could not load site: #{error.statusText} (#{error.status})", growlError)
|
30
38
|
|
31
39
|
componentWillMount: ->
|
32
40
|
@fetchSite()
|
@@ -50,7 +58,6 @@ routes =
|
|
50
58
|
<DefaultRoute handler={@Posts} />
|
51
59
|
</Route>
|
52
60
|
|
53
|
-
|
54
61
|
Router.run(routes, Router.HistoryLocation, (Handler) ->
|
55
62
|
React.render(<Handler />, document.getElementById("app"))
|
56
63
|
)
|
@@ -13,6 +13,10 @@ body {
|
|
13
13
|
padding-bottom: 20px;
|
14
14
|
}
|
15
15
|
|
16
|
+
.growl-animated {
|
17
|
+
padding: 10px 35px 10px 15px;
|
18
|
+
}
|
19
|
+
|
16
20
|
a, button, input, textarea, *:focus {
|
17
21
|
outline: 0 !important;
|
18
22
|
outline-style: none !important;
|
@@ -31,6 +35,12 @@ a, button, input, textarea, *:focus {
|
|
31
35
|
}
|
32
36
|
|
33
37
|
.panel {
|
38
|
+
&:not(.panel-default) {
|
39
|
+
.panel-heading {
|
40
|
+
color: #fff;
|
41
|
+
}
|
42
|
+
}
|
43
|
+
|
34
44
|
.panel-heading {
|
35
45
|
line-height: 26px;
|
36
46
|
|
data/bower.json
CHANGED
data/lib/octodmin/post.rb
CHANGED
@@ -68,9 +68,9 @@ module Octodmin
|
|
68
68
|
"force" => true,
|
69
69
|
})
|
70
70
|
|
71
|
-
options = @site.config["octodmin"]["front_matter"].keys.map do |key|
|
71
|
+
options = Hash[@site.config["octodmin"]["front_matter"].keys.map do |key|
|
72
72
|
[key, params[key]]
|
73
|
-
end
|
73
|
+
end]
|
74
74
|
|
75
75
|
content = params["content"].gsub("\r\n", "\n").strip
|
76
76
|
result = "---\n#{options.map { |k, v| "#{k}: \"#{v}\"" }.join("\n")}\n---\n\n#{content}\n"
|
data/lib/octodmin/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: octodmin
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Dmitry Krasnoukhov
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-02-
|
11
|
+
date: 2015-02-11 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: octopress
|