vapid 0.1.1 → 0.1.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (46) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +16 -0
  3. data/lib/vapid/assets/images/vapid/favicon.ico +0 -0
  4. data/lib/vapid/assets/images/vapid/logo.png +0 -0
  5. data/lib/vapid/assets/images/vapid/logo_inverse.png +0 -0
  6. data/lib/vapid/assets/javascripts/vapid/{admin.coffee → dashboard.coffee} +0 -0
  7. data/lib/vapid/assets/stylesheets/vapid/dashboard.scss +25 -0
  8. data/lib/vapid/assets/stylesheets/vapid/dashboard/_base.scss +36 -0
  9. data/lib/vapid/assets/stylesheets/vapid/dashboard/_fonts.scss +14 -0
  10. data/lib/vapid/assets/stylesheets/vapid/dashboard/_modal.scss +53 -0
  11. data/lib/vapid/assets/stylesheets/vapid/dashboard/_sidebar.scss +22 -0
  12. data/lib/vapid/assets/stylesheets/vapid/dashboard/_variables.scss +6 -0
  13. data/lib/vapid/cli.rb +45 -13
  14. data/lib/vapid/controllers/{admin_controller.rb → dashboard_controller.rb} +60 -64
  15. data/lib/vapid/generator_template/Gemfile.tt +1 -7
  16. data/lib/vapid/generator_template/assets/javascripts/site.js +0 -0
  17. data/lib/vapid/generator_template/assets/stylesheets/site.css +0 -0
  18. data/lib/vapid/generator_template/templates/index.html.erb +84 -24
  19. data/lib/vapid/generator_template/templates/layouts/default.html.erb +3 -14
  20. data/lib/vapid/models/record.rb +22 -0
  21. data/lib/vapid/models/user.rb +7 -2
  22. data/lib/vapid/server.rb +5 -5
  23. data/lib/vapid/version.rb +1 -1
  24. data/lib/vapid/views/{admin → dashboard}/install.html.erb +3 -3
  25. data/lib/vapid/views/{admin → dashboard}/login.html.erb +2 -2
  26. data/lib/vapid/views/dashboard/overview/index.html.erb +3 -0
  27. data/lib/vapid/views/dashboard/records/_form_fields.erb +5 -0
  28. data/lib/vapid/views/dashboard/records/edit.html.erb +10 -0
  29. data/lib/vapid/views/{admin → dashboard}/records/index.html.erb +6 -8
  30. data/lib/vapid/views/dashboard/records/new.html.erb +6 -0
  31. data/lib/vapid/views/dashboard/settings/edit.html.erb +22 -0
  32. data/lib/vapid/views/errors/404.html.erb +4 -1
  33. data/lib/vapid/views/errors/500.html.erb +4 -1
  34. data/lib/vapid/views/layouts/dashboard.html.erb +47 -0
  35. data/lib/vapid/views/layouts/modal.html.erb +21 -0
  36. data/lib/vapid/views/shared/_flash.html.erb +5 -0
  37. metadata +27 -16
  38. data/lib/vapid/assets/stylesheets/vapid/admin.scss +0 -72
  39. data/lib/vapid/generator_template/assets/stylesheets/application.css +0 -120
  40. data/lib/vapid/views/admin/overview/index.html.erb +0 -1
  41. data/lib/vapid/views/admin/records/_form.erb +0 -9
  42. data/lib/vapid/views/admin/records/edit.html.erb +0 -5
  43. data/lib/vapid/views/admin/records/new.html.erb +0 -3
  44. data/lib/vapid/views/layouts/admin.html.erb +0 -41
  45. data/lib/vapid/views/layouts/admin_form.html.erb +0 -22
  46. data/lib/vapid/views/layouts/error.html.erb +0 -11
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 504471e3bef72a241996ded672149874d00f0eaf
4
- data.tar.gz: 109650d32dbb7d98efb77346628f72168ad6ca4f
3
+ metadata.gz: 556c2464ab664d12716b9aa0e667dd11d663edc5
4
+ data.tar.gz: a56555d344f0277090d06c52d8a7efd0809fc464
5
5
  SHA512:
6
- metadata.gz: ed753ed4e16155ce5562d4059a09c61ad3f5fe9a3dc7658569e4b7e46c21b9e7809c2583d4dba9a14fb9aec1dc0b59465ea2dcbdc265a9e8da8ed15d91e6de0a
7
- data.tar.gz: 7b177df1ded95804960165af8578b4213a17dbf63dfd5519b5c0ef62c881c109343efedf3f981dadde1063024ff457809d3d26aad1d6475e59dff2518861ace6
6
+ metadata.gz: 92a59742ea2b378905fa5d59d329ce49cf278d52515fce565ca1019a734c6bb8894d292293f7c4482f5e860da14699c290b1c98be835fb33a8f9c53548021f7e
7
+ data.tar.gz: 2d259c98b3ad956e51c11ea98cda9714236188a0c503d4976a7722c141dc44ebea479a2af47018ea9ca9544d6e7aa636e5c5c33145a10a3bed56a5752ec0c8b5
@@ -0,0 +1,16 @@
1
+ # Changelog
2
+
3
+ ## 0.1.2
4
+ * Changed dashboard route from `/admin` to `/dashboard`
5
+ * Updated styles to match new design
6
+ * Users can now edit login email and password
7
+ * `--reset-login` option for `vapid build`
8
+ * Let user specify which DB in their own Gemfile
9
+ * New design for generator example
10
+
11
+ ## 0.1.1
12
+ * Fix SIGTERM bug (UPDATE: definitely did not fix it)
13
+ * Changes to get hosting prototype up and running
14
+
15
+ ## 0.1.0
16
+ * Initial release
@@ -0,0 +1,25 @@
1
+ //= require semantic-ui/components/reset
2
+ //= require semantic-ui/components/button
3
+ //= require semantic-ui/components/divider
4
+ //= require semantic-ui/components/form
5
+ //= require semantic-ui/components/grid
6
+ //= require semantic-ui/components/header
7
+ //= require semantic-ui/components/icon
8
+ //= require semantic-ui/components/image
9
+ //= require semantic-ui/components/message
10
+ //= require semantic-ui/components/menu
11
+ //= require semantic-ui/components/segment
12
+ //= require semantic-ui/components/sidebar
13
+ //= require semantic-ui/components/site
14
+ //= require semantic-ui/components/table
15
+ //= require trix/dist/trix
16
+ //= require_self
17
+
18
+ // Pre-semantic
19
+ @import "./dashboard/variables";
20
+
21
+ // Dashboard
22
+ @import "./dashboard/base";
23
+ @import "./dashboard/fonts";
24
+ @import "./dashboard/modal";
25
+ @import "./dashboard/sidebar";
@@ -0,0 +1,36 @@
1
+ html, body {
2
+ font-size: 16px;
3
+ }
4
+
5
+ .hidden {
6
+ display: none !important;
7
+ }
8
+
9
+ .header-group {
10
+ padding-top: 0 !important;
11
+ }
12
+
13
+ #flash {
14
+ margin-top: 0.5em;
15
+
16
+ & + h1, {
17
+ margin-top: 0.5em;
18
+ }
19
+
20
+ & + .header-group, {
21
+ margin-top: 1.5em;
22
+ }
23
+ }
24
+
25
+ form[data-delete=true] {
26
+ input[type=submit] {
27
+ background: none;
28
+ border: none;
29
+ padding: 0;
30
+ color: $blue;
31
+
32
+ &:hover {
33
+ color: $darkBlue;
34
+ }
35
+ }
36
+ }
@@ -0,0 +1,14 @@
1
+ @font-face {
2
+ font-family: 'Icons';
3
+ src: url("../../semantic-ui/themes/default/assets/fonts/icons.eot");
4
+ src: url("../../semantic-ui/themes/default/assets/fonts/icons.eot?#iefix") format('embedded-opentype'),
5
+ url("../../semantic-ui/themes/default/assets/fonts/icons.woff2") format('woff2'),
6
+ url("../../semantic-ui/themes/default/assets/fonts/icons.woff") format('woff'),
7
+ url("../../semantic-ui/themes/default/assets/fonts/icons.ttf") format('truetype'),
8
+ url("../../semantic-ui/themes/default/assets/fonts/icons.svg#icons") format('svg');
9
+ font-style: normal;
10
+ font-weight: normal;
11
+ font-variant: normal;
12
+ text-decoration: inherit;
13
+ text-transform: none;
14
+ }
@@ -0,0 +1,53 @@
1
+ body.modal {
2
+ background: white;
3
+ color: $grey;
4
+
5
+ a {
6
+ color: $grey;
7
+ text-decoration: underline;
8
+ }
9
+
10
+ .ui.form {
11
+ input[type=text],
12
+ input[type=email],
13
+ input[type=password] {
14
+ padding: 0 0 0.5em;
15
+ margin-bottom: 0.5em;
16
+ font-weight: bold;
17
+ color: $grey;
18
+ background: none;
19
+ border-color: $grey;
20
+ border-width: 0 0 1px;
21
+ border-radius: 0;
22
+ }
23
+
24
+ label {
25
+ color: $grey;
26
+ }
27
+ }
28
+
29
+ .ui.header {
30
+ color: white;
31
+
32
+ .sub.header {
33
+ color: #9e9e9e;
34
+ }
35
+ }
36
+
37
+ .logo {
38
+ max-width: 10em;
39
+ }
40
+
41
+ & > .grid {
42
+ margin-top: 0em;
43
+ height: 100%;
44
+ }
45
+
46
+ #flash {
47
+ margin-bottom: 1.5em;
48
+ }
49
+
50
+ .column {
51
+ max-width: 27rem;
52
+ }
53
+ }
@@ -0,0 +1,22 @@
1
+ .sidebar {
2
+ $sidebar-nav-width: 20em;
3
+ width: $sidebar-nav-width;
4
+
5
+ .logo {
6
+ max-width: 7em;
7
+ margin: 0.5em 0 0.25em;
8
+ }
9
+
10
+ > .item:last-of-type:before {
11
+ display: none;
12
+ }
13
+
14
+ &.left.visible {
15
+ ~ .fixed,
16
+ ~ .pusher {
17
+ padding: 0em 1em 1em;
18
+ width: calc(100vw - #{$sidebar-nav-width});
19
+ transform: translate3d($sidebar-nav-width, 0, 0);
20
+ }
21
+ }
22
+ }
@@ -0,0 +1,6 @@
1
+ $import-google-fonts: false !default;
2
+ $font-family: "Helvetica Neue", Helvetica, sans-serif;
3
+
4
+ $grey: #1b1c1d;
5
+ $blue: #4183C4;
6
+ $darkBlue: #1e70bf;
@@ -33,28 +33,31 @@ module Vapid
33
33
 
34
34
  desc "server", "Start the server"
35
35
  map %w(s -s --server) => :server
36
- method_option :port, aliases: %w(-p), type: :numeric
37
- method_option :bind, aliases: %w(-b), type: :string
36
+ method_option :port, aliases: %w(-p), type: :numeric, default: 4567
37
+ method_option :bind, aliases: %w(-b), type: :string, default: "localhost"
38
38
  def server(target = ".")
39
39
  say "== The Vapid server is loading"
40
40
  inside_target(target) do
41
- Thread.new { Server.run! options }
42
- Guard.start guardfile_contents: GUARDFILE, watchdir: target, no_interactions: true
41
+ fork do
42
+ Guard.start guardfile_contents: GUARDFILE, watchdir: target, no_interactions: true
43
+ end
44
+ Server.run! options.merge directory: target
43
45
  end
44
46
  say "== The Vapid server is now shut down"
45
47
  end
46
48
 
47
49
  desc "build", "Updates the data model as described in your templates"
48
50
  map %w(b -b --build) => :build
51
+ method_option :reset_login, aliases: %w(-r), type: :boolean, default: false
49
52
  def build(target = ".")
50
53
  inside_target(target) do
51
54
  Models.migrate!
52
- ensure_user_exists
55
+ ensure_user_exists(options.reset_login)
53
56
 
54
57
  say "== Parsing templates for fields"
55
58
  template_files = Dir[File.join(target, "templates", "**/*")].reject { |f| File.directory? f }
56
59
  Builder.build!(template_files) do |filepath|
57
- say " * #{filepath}"
60
+ say_status :parse, filepath
58
61
  end
59
62
  say "== Build complete"
60
63
  end
@@ -70,7 +73,7 @@ module Vapid
70
73
 
71
74
  def inside_target(target, &block)
72
75
  if !File.exist? File.join(target, "config.ru")
73
- say "== Could not find a Vapid project in #{expanded_target(target)}"
76
+ say_status :error, "Could not find a Vapid project in #{expanded_target(target)}", :red
74
77
  else
75
78
  FileUtils.mkdir_p File.join(target, ".cache")
76
79
  inside(target, &block)
@@ -81,12 +84,41 @@ module Vapid
81
84
  File.expand_path(target)
82
85
  end
83
86
 
84
- def ensure_user_exists
85
- return if Models::User.any?
86
- say "== Creating an admin login"
87
- email = ask "What is your email address?", default: "admin@example.com"
88
- password = ask "Enter a password:", default: "password", echo: false
89
- Models::User.create email: email, password: password
87
+ def ensure_user_exists(force)
88
+ return if !force && Models::User.any?
89
+
90
+ action = force ? "Resetting your" : "Create an"
91
+ say "== #{action} admin login"
92
+
93
+ user = Models::User.first || Models::User.new
94
+ email = user.email
95
+ install_code = Settings.install_code
96
+
97
+ loop do
98
+ user.email = ask "What is your email address?", default: email
99
+ user.valid?
100
+ break unless user.errors[:email].any?
101
+ say_status :error, "Email #{user.errors[:email].to_sentence}", :red
102
+ end
103
+
104
+ loop do
105
+ user.password = ask("Enter a password:", echo: false)
106
+ user.valid?
107
+ say ""
108
+ break unless user.errors[:password].any?
109
+ say_status :error, "Password #{user.errors[:password].to_sentence}", :red
110
+ end
111
+
112
+ loop do
113
+ code = ask "Enter the install code (found in config/settings.yml):", default: code
114
+ break if code.casecmp(install_code) == 0
115
+ say_status :error, "Invalid install code", :red
116
+ end if install_code
117
+
118
+ unless user.save
119
+ say_status :error, "#{user.errors.full_messages.to_sentence}\n", :red
120
+ raise
121
+ end
90
122
  end
91
123
  end
92
124
  end
@@ -1,8 +1,8 @@
1
1
  # rubocop:disable Metrics/BlockLength
2
2
  module Vapid
3
3
  module Controllers
4
- # Admin routes
5
- module AdminController
4
+ # Dashboard routes
5
+ module DashboardController
6
6
  extend Sinatra::Extension
7
7
 
8
8
  # Custom form builder for records
@@ -12,7 +12,7 @@ module Vapid
12
12
  @name = name
13
13
  @value = @directive.new(name).send :deserialize_input, value
14
14
 
15
- label(name) +
15
+ label(name, caption: "#{name.to_s.humanize}") +
16
16
  template.content_tag(:div) do
17
17
  form_field + preview + destroy
18
18
  end
@@ -47,37 +47,37 @@ module Vapid
47
47
  app.helpers do
48
48
  def installed!
49
49
  if ActiveRecord::Migrator.current_version.zero? || !Models::User.any?
50
- redirect "/admin/install" unless admin_action == "install"
50
+ redirect "/dashboard/install" unless dashboard_action == "install"
51
51
  false
52
52
  else
53
- redirect "/admin" if admin_action == "install"
53
+ redirect "/dashboard" if dashboard_action == "install"
54
54
  true
55
55
  end
56
56
  end
57
57
 
58
58
  def authenticated!
59
59
  if !current_user
60
- redirect "/admin/login" unless %w(login logout).include?(admin_action)
60
+ redirect "/dashboard/login" unless %w(login logout).include?(dashboard_action)
61
61
  false
62
62
  else
63
63
  true
64
64
  end
65
65
  end
66
66
 
67
- def admin_action
67
+ def dashboard_action
68
68
  request.path_info.split("/")[2]
69
69
  end
70
70
 
71
- def render_admin_template(template)
72
- render_view template, layout: :admin
71
+ def render_dashboard_template(template)
72
+ render_view template, layout: :dashboard
73
73
  end
74
74
 
75
75
  def render_auth_template(template)
76
- render_view template, layout: :admin_form
76
+ render_view template, layout: :modal
77
77
  end
78
78
 
79
- def admin_partial(template, options = {}, &block)
80
- partial "admin/#{template}", options, &block
79
+ def dashboard_partial(template, options = {}, &block)
80
+ partial "dashboard/#{template}", options, &block
81
81
  end
82
82
 
83
83
  def record_form_for(name, *args, &block)
@@ -95,7 +95,7 @@ module Vapid
95
95
  "/#{group.records.first.id}/edit"
96
96
  end
97
97
 
98
- "/admin/groups/#{group.id}/records#{path}"
98
+ "/dashboard/groups/#{group.id}/records#{path}"
99
99
  end
100
100
 
101
101
  def flash_class(level)
@@ -132,11 +132,11 @@ module Vapid
132
132
  end
133
133
  # rubocop:enable Lint/NestedMethodDefinition
134
134
 
135
- app.before("/admin/?*") do
135
+ app.before("/dashboard/?*") do
136
136
  @groups = all_groups if installed! && authenticated!
137
137
  end
138
138
 
139
- app.namespace "/admin/?" do
139
+ app.namespace "/dashboard/?" do
140
140
  # TODO: Namespace before filters are currently broken on Sinatra 2.0
141
141
  # before do
142
142
  # @groups = all_groups if installed! && authenticated!
@@ -145,12 +145,12 @@ module Vapid
145
145
  # end
146
146
 
147
147
  get do
148
- render_admin_template "admin/overview/index"
148
+ render_dashboard_template "dashboard/overview/index"
149
149
  end
150
150
 
151
151
  get "/login/?" do
152
152
  @user = Models::User.new
153
- render_auth_template "admin/login"
153
+ render_auth_template "dashboard/login"
154
154
  end
155
155
 
156
156
  post "/login/?" do
@@ -158,22 +158,22 @@ module Vapid
158
158
 
159
159
  if user
160
160
  session[:user_id] = user.id
161
- redirect "/admin"
161
+ redirect "/dashboard"
162
162
  else
163
- flash[:error] = "Could not log in"
164
- redirect back
163
+ @user = Models::User.new email: params[:vapid_models_user][:email]
164
+ flash.now[:error] = "Invalid Email or password."
165
+ render_auth_template "dashboard/login"
165
166
  end
166
167
  end
167
168
 
168
169
  get "/logout/?" do
169
170
  session.delete(:user_id)
170
- flash[:success] = "Successfully logged out"
171
- redirect "/admin/login"
171
+ redirect "/dashboard/login"
172
172
  end
173
173
 
174
174
  get "/install/?" do
175
175
  @code = Settings.install_code
176
- render_auth_template "/admin/install"
176
+ render_auth_template "/dashboard/install"
177
177
  end
178
178
 
179
179
  post "/install/?" do
@@ -186,42 +186,56 @@ module Vapid
186
186
  if (@code.nil? || @code.casecmp(params[:code]) == 0) && user.save
187
187
  run_builder
188
188
  session[:user_id] = user.id
189
- flash[:success] = "Successfully created admin account"
190
- redirect "/admin"
189
+ flash[:success] = "Successfully created admin account."
190
+ redirect "/dashboard"
191
191
  else
192
- flash.now[:error] = "Could not create admin account"
193
- render_auth_template "/admin/install"
192
+ flash.now[:error] = "Could not create admin account."
193
+ render_auth_template "/dashboard/install"
194
194
  end
195
195
  end
196
196
 
197
197
  get "/build/?" do
198
198
  run_builder
199
- flash[:success] = "Site build complete"
200
- redirect "/admin"
199
+ flash[:success] = "Site build complete."
200
+ redirect "/dashboard"
201
+ end
202
+
203
+ get "/settings/?" do
204
+ render_dashboard_template "dashboard/settings/edit"
205
+ end
206
+
207
+ post "/settings/?" do
208
+ attrs = if params[:password].blank?
209
+ params.slice(:email)
210
+ else
211
+ params.slice(:email, :password, :password_confirmation)
212
+ end
213
+
214
+ if current_user.update_attributes attrs
215
+ flash[:success] = "Settings updated."
216
+ redirect "/dashboard/settings"
217
+ else
218
+ flash.now[:error] = current_user.errors.full_messages.to_sentence
219
+ render_dashboard_template "dashboard/settings/edit"
220
+ end
201
221
  end
202
222
 
203
223
  get "/groups/:group_id/records/?" do
204
224
  @group = current_group
205
225
  @user = Vapid::Models::User.new
206
226
 
207
- render_admin_template "admin/records/index"
227
+ render_dashboard_template "dashboard/records/index"
208
228
  end
209
229
 
210
230
  post "/groups/:group_id/records/?" do
211
231
  @group = current_group
212
232
  @record = @group.records.build(params[:record])
213
233
 
214
- # TODO: Externalize this into a function (see update method below)
215
- params[:record]["content"].each do |key, val|
216
- content_type = current_group.fields[key]
217
- @record.content[key] = Directives[content_type].serialize_input(val)
218
- end
219
-
220
- if @record.save
221
- flash[:success] = "Record created"
234
+ if @record.update_content params[:record]["content"]
235
+ flash[:success] = "Record created."
222
236
  livereload
223
237
  else
224
- flash[:error] = "Problem creating record"
238
+ flash[:error] = "Problem creating record."
225
239
  end
226
240
  redirect group_or_records_path(@group)
227
241
  end
@@ -230,36 +244,18 @@ module Vapid
230
244
  @group = current_group
231
245
  @record = @group.records.build
232
246
 
233
- render_admin_template "admin/records/new"
247
+ render_dashboard_template "dashboard/records/new"
234
248
  end
235
249
 
236
250
  post "/groups/:group_id/records/:id/?" do
237
251
  @group = current_group
238
252
  @record = current_record
239
253
 
240
- # TODO: Externalize this into a function (see create method above)
241
- params[:record]["content"].each do |key, val|
242
- # if val.is_a?(Hash) && val[:tempfile]
243
- # FileUtils.mkdir_p(settings.project_uploads)
244
- # File.open File.join(settings.project_uploads, val[:filename]), "wb" do |file|
245
- # file.write val[:tempfile].read
246
- # end
247
- # val = "/uploads/#{val[:filename]}"
248
- # end
249
-
250
- content_type = current_group.fields[key]
251
- @record.content[key] = Directives[content_type].serialize_input(val)
252
- end
253
-
254
- params[:_destroy] && params[:_destroy].each do |key, _val|
255
- @record.content[key] = nil
256
- end
257
-
258
- if @record.save
259
- flash[:success] = "Record updated"
254
+ if @record.update_content params[:record]["content"], params[:_destroy]
255
+ flash[:success] = "Record updated."
260
256
  livereload
261
257
  else
262
- flash.now[:error] = "Problem updating record"
258
+ flash.now[:error] = "Problem updating record."
263
259
  end
264
260
  redirect group_or_records_path(@group)
265
261
  end
@@ -269,10 +265,10 @@ module Vapid
269
265
  @record = current_record
270
266
 
271
267
  if @record.destroy
272
- flash[:success] = "Record deleted"
268
+ flash[:success] = "Record deleted."
273
269
  livereload
274
270
  else
275
- flash[:error] = "Problem deleting record"
271
+ flash[:error] = "Problem deleting record."
276
272
  end
277
273
  redirect group_or_records_path(@group)
278
274
  end
@@ -281,7 +277,7 @@ module Vapid
281
277
  @group = current_group
282
278
  @record = current_record
283
279
 
284
- render_admin_template "admin/records/edit"
280
+ render_dashboard_template "dashboard/records/edit"
285
281
  end
286
282
  end
287
283
  end