octodmin 0.1.0 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 68161108fbd0f208b9fe379eaefc1638d8a07a40
4
- data.tar.gz: 308e09d4fd3591b47d7a7621837aa12543e6f606
3
+ metadata.gz: 486c254e24ba8ecb343d9153f8a3fa520cc6fcf9
4
+ data.tar.gz: c4d51cf2c335bdeac72e50f7942c68f09b18ef40
5
5
  SHA512:
6
- metadata.gz: a3c62874c57613363f2d4ae5e8bb8e63892ffd50a91e853d2012a19c9a2db48ced8388fc1d8cd8467904df0c89e7c1909048315046cb0b4719af5b7afd57d138
7
- data.tar.gz: 11f6a5edc1cf7e8b057b45dbe9ab9581b00f2755c30e5c5cb5d60c679932d58e323c171bdeafd471dcf8a8b8e939a2508b81e9d206316cb82fa85caf69df7468
6
+ metadata.gz: 99d6b2bc5a38721a1ce9e10f6f270cb9041baf99353ed8a3a1669252266761140f26119d0362991c782ed819c839c1f52726cf946492901286a24caf76289983
7
+ data.tar.gz: de3ea218515c0c77229a62902a8848d570c4817f4b6db587e0bf312777d11b733fecd8dff3fd6cc3177b8533d29aee856a32ec79bdf7e5847d3ce0fb9ba4316e
@@ -5,5 +5,6 @@ before_script:
5
5
  - bower install
6
6
  script: bundle exec rake spec:coverage
7
7
  rvm:
8
+ - 2.0
8
9
  - 2.1
9
10
  - 2.2
@@ -1,3 +1,10 @@
1
+ v0.2.0
2
+ ------
3
+
4
+ * Support Ruby 2.0
5
+ * Disable posts refreshing because of race conditions
6
+ * Various UI fixes
7
+
1
8
  v0.1.0
2
9
  ------
3
10
 
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', '~> 0.1.0'
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
@@ -2,6 +2,7 @@
2
2
  #= require jquery-serialize-object
3
3
  #= require bootstrap
4
4
  #= require bootstrap-markdown
5
+ #= require bootstrap.growl/bootstrap-growl
5
6
  #= require spin.js/spin.js
6
7
  #= require react
7
8
  #= require react-loader
@@ -5,7 +5,7 @@
5
5
  site: React.PropTypes.object.isRequired
6
6
 
7
7
  getInitialState: ->
8
- { alert: null, success: null, loading: false }
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
- @setState(success: response.syncs.join("\n").replace(/\n/g, "<br>"))
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
- @setState(success: response.deploys.join("\n"))
30
- setTimeout(@removeSuccess, 5000)
28
+ $.growl(response.deploys.join("\n"), growlSuccess)
31
29
  $(document).trigger("fetchPosts")
32
30
 
33
31
  handleError: (error) ->
34
- @setState(alert: error.responseJSON?.errors.join("\n").replace(/\n/g, "<br>"))
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} onBlur={@handleBlur}>
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} onBlur={@handleBlur}>
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
- { alert: null, loading: false, posts: null }
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(alert: null, posts: response.posts) if @isMounted()
19
+ @setState(posts: response.posts) if @isMounted()
20
20
 
21
21
  handleError: (error) ->
22
- @setState(alert: "Could not load posts: #{error.statusText} (#{error.status})") if @isMounted()
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
- { alert: null, loading: false }
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
- @setState(alert: error.responseJSON?.errors.join(", "))
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
- { alert: null, loading: false }
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
- @setState(alert: "Could not load post: #{error.statusText} (#{error.status})")
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
- { alert: null, success: null, loading: false, post: null }
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(alert: null, post: response.posts)
231
+ @setState(post: response.posts)
241
232
 
242
233
  handleFormSuccess: (response) ->
243
- @setState(alert: null, success: "Post is updated")
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
- @setState(alert: error.responseJSON?.errors.join(", "))
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
- alert("Could not load site: #{error.statusText} (#{error.status})")
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
@@ -5,6 +5,7 @@
5
5
  "jquery-serialize-object": "~2.4.5",
6
6
  "bootstrap-sass": "~3.3.2",
7
7
  "bootstrap-markdown": "~2.8.0",
8
+ "bootstrap.growl": "~2.0.1",
8
9
  "spin.js": "~2.0.2",
9
10
  "react": "~0.12.0",
10
11
  "react-loader": "~1.1.0",
@@ -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.to_h
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"
@@ -1,3 +1,3 @@
1
1
  module Octodmin
2
- VERSION = "0.1.0"
2
+ VERSION = "0.2.0"
3
3
  end
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.1.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-05 00:00:00.000000000 Z
11
+ date: 2015-02-11 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: octopress