alchemy_cms 2.1.rc6 → 2.1

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 (57) hide show
  1. data/app/assets/images/alchemy/lupe.cur +0 -0
  2. data/app/assets/javascripts/alchemy/alchemy.buttons.js +1 -1
  3. data/app/assets/javascripts/alchemy/alchemy.page_sorter.js +1 -0
  4. data/app/assets/stylesheets/alchemy/alchemy.css +11 -0
  5. data/app/assets/stylesheets/alchemy/base.css.scss +447 -2446
  6. data/app/assets/stylesheets/alchemy/buttons.css.scss +354 -0
  7. data/app/assets/stylesheets/alchemy/dashboard.css.scss +76 -0
  8. data/app/assets/stylesheets/alchemy/flags.css.scss +1 -1
  9. data/app/assets/stylesheets/alchemy/flash.css.scss +54 -0
  10. data/app/assets/stylesheets/alchemy/frame.css.scss +287 -0
  11. data/app/assets/stylesheets/alchemy/icons.css.scss +300 -0
  12. data/app/assets/stylesheets/alchemy/jquery-ui.alchemy.css.scss +3 -2
  13. data/app/assets/stylesheets/alchemy/jquery.sb.css.scss +1 -1
  14. data/app/assets/stylesheets/alchemy/login.css.scss +53 -0
  15. data/app/assets/stylesheets/alchemy/menubar.css.scss +26 -11
  16. data/app/assets/stylesheets/alchemy/modules.css.scss +31 -0
  17. data/app/assets/stylesheets/alchemy/pagination.css.scss +56 -0
  18. data/app/assets/stylesheets/alchemy/sitemap.css.scss +285 -0
  19. data/app/assets/stylesheets/alchemy/tables.css.scss +150 -0
  20. data/app/assets/stylesheets/alchemy/upload.css.scss +92 -0
  21. data/app/controllers/alchemy/admin/dashboard_controller.rb +1 -1
  22. data/app/controllers/alchemy/admin/pages_controller.rb +1 -1
  23. data/app/controllers/alchemy/admin/resources_controller.rb +35 -2
  24. data/app/controllers/alchemy/user_sessions_controller.rb +3 -0
  25. data/app/helpers/alchemy/admin/attachments_helper.rb +1 -1
  26. data/app/helpers/alchemy/admin/base_helper.rb +69 -20
  27. data/app/helpers/alchemy/pages_helper.rb +0 -55
  28. data/app/views/alchemy/admin/attachments/_attachment.html.erb +1 -1
  29. data/app/views/alchemy/admin/clipboard/index.html.erb +4 -1
  30. data/app/views/alchemy/admin/dashboard/index.html.erb +16 -11
  31. data/app/views/alchemy/admin/elements/_new_element_form.html.erb +4 -1
  32. data/app/views/alchemy/admin/layoutpages/_layoutpage.html.erb +1 -20
  33. data/app/views/alchemy/admin/layoutpages/index.html.erb +1 -1
  34. data/app/views/alchemy/admin/pages/index.html.erb +3 -3
  35. data/app/views/alchemy/admin/partials/_search_form.html.erb +7 -1
  36. data/app/views/alchemy/admin/resources/_form.html.erb +1 -1
  37. data/app/views/alchemy/admin/resources/_resource.html.erb +8 -5
  38. data/app/views/alchemy/admin/resources/_table.html.erb +1 -1
  39. data/app/views/alchemy/admin/resources/index.html.erb +4 -3
  40. data/app/views/alchemy/admin/trash/index.html.erb +3 -2
  41. data/app/views/alchemy/user_sessions/login.html.erb +2 -1
  42. data/app/views/layouts/alchemy/admin.html.erb +3 -4
  43. data/app/views/layouts/alchemy/login.html.erb +9 -8
  44. data/config/authorization_rules.rb +0 -1
  45. data/config/locales/alchemy.de.yml +1 -0
  46. data/config/locales/alchemy.en.yml +1 -0
  47. data/lib/alchemy/seeder.rb +1 -1
  48. data/lib/alchemy/version.rb +1 -1
  49. data/spec/integration/admin/pages_controller_spec.rb +45 -57
  50. data/spec/integration/admin/resources_spec.rb +19 -0
  51. data/spec/models/content_spec.rb +6 -5
  52. data/spec/support/alchemy/controller_hacks.rb +41 -0
  53. data/spec/support/alchemy/specs_helpers.rb +32 -0
  54. data/vendor/assets/javascripts/tiny_mce/plugins/autoresize/editor_plugin.js +137 -1
  55. metadata +55 -37
  56. data/app/views/alchemy/admin/languages/_language.html.erb +0 -36
  57. data/spec/support/controller_hacks.rb +0 -37
@@ -0,0 +1,150 @@
1
+ @import "alchemy/defaults";
2
+
3
+ table {
4
+ border-style: none;
5
+ border-spacing: 0 $default-padding;
6
+ padding: 0;
7
+ font-size: inherit;
8
+ width: 100%;
9
+
10
+ td, th {
11
+ padding: $default-padding;
12
+ }
13
+
14
+ th {
15
+ text-align: left;
16
+ height: 22px;
17
+ vertical-align: top;
18
+ }
19
+ }
20
+
21
+ table tr td.tools {
22
+ width: 40px;
23
+ background-color: $light-gray;
24
+ white-space: nowrap;
25
+ }
26
+
27
+ td.input, td.label {
28
+ padding-top: 2px;
29
+ vertical-align: top;
30
+ }
31
+
32
+ td.input, td.submit, td.select {
33
+ text-align: right;
34
+ padding-right: 0;
35
+ }
36
+
37
+ td.value {
38
+ padding-left: 2*$default-padding;
39
+ }
40
+
41
+ td.label {
42
+ white-space: nowrap;
43
+ width: 80px;
44
+ padding: $default-padding 2*$default-padding 0 0;
45
+ line-height: 6*$default-padding;
46
+ }
47
+
48
+ td.label.mandatory:after {
49
+ content: '*';
50
+ }
51
+
52
+ td.heading {
53
+ padding: $default-padding 0;
54
+ font-weight: bold;
55
+ text-decoration: underline;
56
+ }
57
+
58
+ td.input input[type="checkbox"], td.input input[type="radio"] {
59
+ margin-top: 6px;
60
+ }
61
+
62
+ td.label.long {
63
+ width: 140px;
64
+ }
65
+
66
+ td.label.very_long {
67
+ width: 230px;
68
+ }
69
+
70
+ table tr td.tools a {
71
+ width: 19px;
72
+ height: 19px;
73
+ margin-right: 2px;
74
+ }
75
+
76
+ table tr td.tools.long {
77
+ width: 60px;
78
+ }
79
+
80
+ table tr td.icon {
81
+ background-color: $light-gray;
82
+ width: 20px;
83
+ text-align: center;
84
+ }
85
+
86
+ table.list tr:hover td {
87
+ background-color: #fffdef;
88
+ }
89
+
90
+ td.file_type {
91
+ width: 130px;
92
+ white-space: nowrap;
93
+ }
94
+
95
+ td.file_size {
96
+ width: 80px;
97
+ }
98
+
99
+ td.date {
100
+ width: 150px;
101
+ }
102
+
103
+ table td.right, table th.right {
104
+ text-align: right;
105
+ }
106
+
107
+ table td.center, table th.center {
108
+ text-align: center;
109
+ }
110
+
111
+ td.login {
112
+ width: 100px;
113
+ }
114
+
115
+ td.email {
116
+ width: 270px;
117
+ }
118
+
119
+ td.role {
120
+ width: 70px;
121
+ padding-right: 4px;
122
+ }
123
+
124
+ table td.rights {
125
+ width: 60px;
126
+ }
127
+ table.window_form {
128
+ width: 100%;
129
+ }
130
+
131
+ th.login_status {
132
+ width: 16px;
133
+ }
134
+
135
+ table tr.odd td {
136
+ background-color: #eaf3f9;
137
+ }
138
+
139
+ table tr.even td {
140
+ background-color: white;
141
+ }
142
+
143
+ td.label.middle {
144
+ padding-left: 2*$default-padding;
145
+ }
146
+
147
+ th.icon, td.icon {
148
+ background: none;
149
+ display: table-cell;
150
+ }
@@ -0,0 +1,92 @@
1
+ @import "alchemy/defaults";
2
+
3
+ a#uploadswitcher, a.underline {
4
+ text-decoration: underline;
5
+ }
6
+
7
+ #uploadProgressContainer {
8
+ overflow-x: hidden;
9
+ overflow-y: auto;
10
+ height: 234px;
11
+ }
12
+
13
+ #uploadProgressContainer .progressWrapper {
14
+ padding: 2*$default-padding;
15
+ background-color: $medium-gray;
16
+ position: relative;
17
+ margin-bottom: 8px;
18
+ border: 1px solid #9e9e9e;
19
+ @include rounded-corner;
20
+ }
21
+
22
+ #uploadProgressContainer .progressName,
23
+ #uploadProgressContainer .progressBarStatus {
24
+ margin-bottom: 4px;
25
+ }
26
+
27
+ #uploadProgressContainer .progressBarStatus {
28
+ font-size: 10px;
29
+ }
30
+
31
+ #uploadProgressContainer .progressName {
32
+ text-shadow: 0 1px 2px #FFFFFF;
33
+ }
34
+
35
+ #uploadProgressContainer .progressBarContainer {
36
+ background: #F9F9F9 image-url('alchemy/shading.png') repeat-x 0 0;
37
+ border:1px solid #9E9E9E;
38
+ @include rounded-corner;
39
+ height:16px;
40
+ overflow: hidden;
41
+ width:100%;
42
+ }
43
+
44
+ #uploadProgressContainer .progressBarInProgress {
45
+ background: #77AAD5 image-url('alchemy/shading.png') repeat-x 0 -75px;
46
+ height: 16px;
47
+ width: 0;
48
+ }
49
+
50
+ #uploadProgressContainer .progressBarComplete {
51
+ background: #00D827 image-url('alchemy/shading.png') repeat-x 0 -75px;
52
+ height: 16px;
53
+ width: 0;
54
+ }
55
+
56
+ #uploadProgressContainer .progressBarError {
57
+ background: #F00 image-url('alchemy/shading.png') repeat-x 0 -75px;
58
+ height: 16px;
59
+ width: 0;
60
+ }
61
+
62
+ #uploadProgressContainer .progressBarCanceled {
63
+ background: #E4E4E4 image-url('alchemy/shading.png') repeat-x 0 -75px;
64
+ height: 16px;
65
+ width: 0;
66
+ }
67
+
68
+ #uploadProgressContainer .progressCancel {
69
+ background: #f1f1f1 image-url('alchemy/icons.png') no-repeat -1px -72px;
70
+ border: 1px solid #9e9e9e;
71
+ @include rounded-corner;
72
+ width: 15px;
73
+ height: 16px;
74
+ position: absolute;
75
+ top: 8px;
76
+ right: 8px;
77
+ }
78
+
79
+ #swf_upload_container {
80
+ height: 60px;
81
+ }
82
+
83
+ #swf_upload_container .button {
84
+ float: right;
85
+ margin-top: 4*$default-margin;
86
+ font-size: 11px;
87
+ }
88
+
89
+ object.swfupload {
90
+ margin-top: 16px;
91
+ margin-bottom: 16px;
92
+ }
@@ -7,7 +7,7 @@ module Alchemy
7
7
  @clipboard_items = session[:clipboard]
8
8
  @last_edited_pages = Page.all_last_edited_from(current_user)
9
9
  @locked_pages = Page.all_locked
10
- @online_users = User.all_online
10
+ @online_users = User.all_online.to_a.delete_if { |u| u == current_user }
11
11
  end
12
12
 
13
13
  end
@@ -27,7 +27,7 @@ module Alchemy
27
27
  @root_page = Page.language_root_for(session[:language_id])
28
28
  # Setting the locale to pages language. so the page content has its correct translation
29
29
  ::I18n.locale = @page.language_code
30
- render :layout => params[:layout].blank? ? 'alchemy/pages' : params[:layout] == 'none' ? false : params[:layout]
30
+ render :layout => layout_for_page
31
31
  end
32
32
 
33
33
  def new
@@ -6,7 +6,20 @@ module Alchemy
6
6
 
7
7
  before_filter :load_resource, :only => [:show, :edit, :update, :destroy]
8
8
 
9
- helper_method :resource_attributes, :resource_window_size, :resources_name, :resource_model, :resource_model_name, :resource_instance_variable, :resources_instance_variable, :namespaced_resources_name, :resource_namespaced?
9
+ helper_method(
10
+ :resource_attributes,
11
+ :resource_window_size,
12
+ :resources_name,
13
+ :resource_model,
14
+ :resource_model_name,
15
+ :resource_instance_variable,
16
+ :resources_instance_variable,
17
+ :namespaced_resources_name,
18
+ :resource_namespaced?,
19
+ :resources_permission,
20
+ :resource_url_scope,
21
+ :is_alchemy_module?
22
+ )
10
23
 
11
24
  def index
12
25
  if !params[:query].blank?
@@ -84,7 +97,7 @@ module Alchemy
84
97
  if resource_namespaced?
85
98
  @namespaced_resources_name ||= "#{resource_namespace}_#{resources_name}".underscore
86
99
  else
87
- @namespaced_resources_name ||= resource_model_name
100
+ @namespaced_resources_name ||= resources_name
88
101
  end
89
102
  end
90
103
 
@@ -129,6 +142,26 @@ module Alchemy
129
142
  @resource_namespace ||= self.class.to_s.split("::").first
130
143
  end
131
144
 
145
+ def resource_url_scope
146
+ if is_alchemy_module?
147
+ eval(alchemy_module['engine_name'])
148
+ else
149
+ main_app
150
+ end
151
+ end
152
+
153
+ def is_alchemy_module?
154
+ !alchemy_module.nil? && !alchemy_module['engine_name'].blank?
155
+ end
156
+
157
+ def alchemy_module
158
+ @alchemy_module ||= module_definition_for(:controller => params[:controller], :action => 'index')
159
+ end
160
+
161
+ def resources_permission
162
+ (resource_namespaced? ? "#{resource_namespace.underscore}_admin_#{resources_name}" : "admin_#{resources_name}").to_sym
163
+ end
164
+
132
165
  end
133
166
  end
134
167
  end
@@ -1,6 +1,8 @@
1
1
  module Alchemy
2
2
  class UserSessionsController < Alchemy::BaseController
3
+
3
4
  before_filter :check_user_count, :only => :login
5
+
4
6
  layout 'alchemy/login'
5
7
 
6
8
  helper 'Alchemy::Admin::Base'
@@ -49,6 +51,7 @@ module Alchemy
49
51
  end
50
52
 
51
53
  def leave
54
+ ::I18n.locale = current_user.language.to_sym
52
55
  render :layout => false
53
56
  end
54
57
 
@@ -3,7 +3,7 @@ module Alchemy
3
3
  module AttachmentsHelper
4
4
 
5
5
  def mime_to_human mime
6
- Alchemy::I18n.t("alchemy.mime_types.#{mime}", :default => t('document'))
6
+ Alchemy::I18n.t(mime, :scope => :mime_types, :default => t('document'))
7
7
  end
8
8
 
9
9
  end
@@ -1,11 +1,22 @@
1
1
  module Alchemy
2
2
  module Admin
3
+
4
+ # This module contains helper methods for rendering overlay windows, toolbar buttons and confirmation windows.
5
+ #
6
+ # The most important helpers for module developers are:
7
+ #
8
+ # * toolbar
9
+ # * toolbar_button
10
+ # * link_to_overlay_window
11
+ # * link_to_confirmation_window
12
+ #
3
13
  module BaseHelper
4
14
 
5
15
  # This helper renders the link for an overlay window.
16
+ #
6
17
  # We use this for our fancy modal overlay windows in the Alchemy cockpit.
7
18
  #
8
- # Options:
19
+ # === Options:
9
20
  #
10
21
  # :size [String] # String with format of "WidthxHeight". I.E. ("420x280")
11
22
  # :title [String] # Text for the overlay title bar.
@@ -35,7 +46,7 @@ module Alchemy
35
46
  )
36
47
  end
37
48
 
38
- # Used for rendering the folder link in Admin::Pages.index sitemap.
49
+ # (internal) Used for rendering the folder link in +Admin::Pages#index+ sitemap.
39
50
  def sitemapFolderLink(page)
40
51
  return '' if page.level == 1
41
52
  if page.folded?(current_user.id)
@@ -94,6 +105,19 @@ module Alchemy
94
105
  filter_field.html_safe
95
106
  end
96
107
 
108
+ # Returns a link that opens a modal confirmation window.
109
+ #
110
+ # === Parameters:
111
+ #
112
+ # 1. The content inside the <a> tag
113
+ # 2. The message that is displayed in the overlay window
114
+ # 3. The url that gets opened after confirmation (Note: This is an Ajax request with a method of DELETE!)
115
+ # 4. html options get passed to the link
116
+ #
117
+ # === Example:
118
+ #
119
+ # <%= link_to_confirmation_window('delete', 'Do you really want to delete this comment?', '/admin/comments/1') %>
120
+ #
97
121
  def link_to_confirmation_window(link_string = "", message = "", url = "", html_options = {})
98
122
  title = t("please_confirm")
99
123
  ok_lable = t("Yes")
@@ -107,9 +131,12 @@ module Alchemy
107
131
 
108
132
  # Returns an Array build for passing it to the options_for_select helper inside an essence editor partial.
109
133
  # Usefull for the select_values options from the render_essence_editor helpers.
110
- # Options:
111
- # * :from_page (String, Page) - Return only elements from this page. You can either pass a Page instance, or a page_layout name
112
- # * :elements_with_name (Array, String) - Return only elements with this name(s).
134
+ #
135
+ # == Options:
136
+ #
137
+ # :from_page [String, Page] # Return only elements from this page. You can either pass a Page instance, or a page_layout name
138
+ # :elements_with_name [Array, String] # Return only elements with this name(s).
139
+ #
113
140
  def elements_for_essence_editor_select(options={})
114
141
  defaults = {
115
142
  :from_page => nil,
@@ -132,9 +159,13 @@ module Alchemy
132
159
  select_options
133
160
  end
134
161
 
135
- # Returns all Pages found in the database as an array for the rails select_tag helper.
136
- # You can pass a collection of pages to only returns these pages as array.
137
- # Pass an Page.name or Page.id as second parameter to pass as selected for the options_for_select helper.
162
+ # Returns all public pages found in the database as an Array suitable or the Rails +select_tag+ helper.
163
+ #
164
+ # * You can pass a collection of pages so it only returns these pages and does not query the database.
165
+ # * Pass a +Page#name+ or +Page#id+ as second parameter to be passed as selected item to the +options_for_select+ helper.
166
+ # * The trhird parameter is used as prompt message in the select tag
167
+ # * The last parameter is the method that is called on the page object to get the value that is passed with the params of the form.
168
+ #
138
169
  def pages_for_select(pages = nil, selected = nil, prompt = "", page_attribute = :id)
139
170
  result = [[prompt.blank? ? t('Choose page') : prompt, ""]]
140
171
  if pages.blank?
@@ -241,11 +272,12 @@ module Alchemy
241
272
  ['main_navi_entry', admin_mainnavi_active?(navigation) ? 'active' : nil].compact.join(" ")
242
273
  end
243
274
 
275
+ # (internal) Checks if all options we need for the image cropper are provided
244
276
  def necessary_options_for_cropping_provided?(options)
245
277
  options[:crop].to_s == 'true' && !options[:image_size].blank?
246
278
  end
247
279
 
248
- # Renders translated Module Names for html title element.
280
+ # (internal) Renders translated Module Names for html title element.
249
281
  def render_alchemy_title
250
282
  if content_for?(:title)
251
283
  title = content_for(:title)
@@ -255,7 +287,7 @@ module Alchemy
255
287
  "Alchemy CMS - #{title}"
256
288
  end
257
289
 
258
- # Returns max image count as integer or nil. Used for the picture editor in element editor views.
290
+ # (internal) Returns max image count as integer or nil. Used for the picture editor in element editor views.
259
291
  def max_image_count
260
292
  return nil if !@options
261
293
  if @options[:maximum_amount_of_images].blank?
@@ -270,6 +302,7 @@ module Alchemy
270
302
  end
271
303
  end
272
304
 
305
+ # (internal) Renders a select tag for all items in the clipboard
273
306
  def clipboard_select_tag(items, html_options = {})
274
307
  options = [[t('Please choose'), ""]]
275
308
  items.each do |item|
@@ -287,7 +320,7 @@ module Alchemy
287
320
 
288
321
  # Renders a toolbar button for the Alchemy toolbar
289
322
  #
290
- # Options:
323
+ # == Options:
291
324
  #
292
325
  # :icon [String] # Icon class. See base.css.sccs for available icons, or make your own.
293
326
  # :label [String] # Text for button label.
@@ -304,7 +337,8 @@ module Alchemy
304
337
  :overlay => true,
305
338
  :skip_permission_check => false,
306
339
  :active => false,
307
- :link_options => {}
340
+ :link_options => {},
341
+ :overlay_options => {}
308
342
  }
309
343
  options = defaults.merge(options)
310
344
  button = content_tag('div', :class => 'button_with_label' + (options[:active] ? ' active' : '')) do
@@ -340,12 +374,12 @@ module Alchemy
340
374
  end
341
375
  end
342
376
 
343
- # Renders the alchemy backend toolbar
377
+ # Renders the Alchemy backend toolbar
344
378
  #
345
- # Options are:
379
+ # == Options
346
380
  #
347
- # buttons [Array] # Pass an Array with button options. They will be passed to toolbar_button helper. For options see +toolbar_button+
348
- # search [Boolean] # Show searchfield. Default true.
381
+ # :buttons [Array] # Pass an Array with button options. They will be passed to toolbar_button helper. For options see toolbar_button
382
+ # :search [Boolean] # Show searchfield. Default true.
349
383
  #
350
384
  def toolbar(options = {})
351
385
  defaults = {
@@ -362,16 +396,31 @@ module Alchemy
362
396
  end
363
397
  end
364
398
 
365
- # Renders the partial for a resource record in the resources table.
366
- # This helper has a nice fallback. If your resource has a partial for a single record named like the resouce model name (i.e. language) then this partial will be rendered.
367
- # Otherwise the resource parital from +resources/resource+
399
+ # Renders the row for a resource record in the resources table.
400
+ #
401
+ # This helper has a nice fallback. If you create a partial for your record then this partial will be rendered.
402
+ #
403
+ # Otherwise the default +app/views/alchemy/admin/resources/_resource.html.erb+ partial gets rendered.
404
+ #
405
+ # == Example
406
+ #
407
+ # For a resource named +Comment+ you can create a partial named +_comment.html.erb+
408
+ #
409
+ # # app/views/admin/comments/_comment.html.erb
410
+ # <tr>
411
+ # <td><%= comment.title %></td>
412
+ # <td><%= comment.body %></td>
413
+ # </tr>
414
+ #
415
+ # NOTE: Alchemy gives you a local variable named like your resource
416
+ #
368
417
  def render_resources
369
418
  render resources_instance_variable
370
419
  rescue ActionView::MissingTemplate
371
420
  render :partial => 'resource', :collection => resources_instance_variable
372
421
  end
373
422
 
374
- # Used by upload form
423
+ # (internal) Used by upload form
375
424
  def new_asset_path_with_session_information(asset_type)
376
425
  session_key = Rails.application.config.session_options[:key]
377
426
  if asset_type == "picture"