vapid 0.1.1 → 0.1.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.
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