cortex-reaver 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.
Files changed (141) hide show
  1. data/README +1 -1
  2. data/bin/cortex_reaver +3 -4
  3. data/lib/cortex_reaver.rb +270 -110
  4. data/lib/cortex_reaver/cache.rb +23 -0
  5. data/lib/cortex_reaver/config.rb +178 -74
  6. data/lib/cortex_reaver/controller/admin.rb +64 -4
  7. data/lib/cortex_reaver/controller/comment.rb +4 -4
  8. data/lib/cortex_reaver/controller/controller.rb +3 -3
  9. data/lib/cortex_reaver/controller/journal.rb +4 -2
  10. data/lib/cortex_reaver/controller/main.rb +117 -26
  11. data/lib/cortex_reaver/controller/page.rb +7 -0
  12. data/lib/cortex_reaver/controller/photograph.rb +12 -10
  13. data/lib/cortex_reaver/controller/tag.rb +1 -1
  14. data/lib/cortex_reaver/controller/user.rb +7 -2
  15. data/lib/cortex_reaver/helper/attachments.rb +2 -2
  16. data/lib/cortex_reaver/helper/crud.rb +7 -7
  17. data/lib/cortex_reaver/helper/feeds.rb +56 -38
  18. data/lib/cortex_reaver/helper/form.rb +12 -16
  19. data/lib/cortex_reaver/helper/navigation.rb +35 -16
  20. data/lib/cortex_reaver/helper/photographs.rb +2 -2
  21. data/lib/cortex_reaver/helper/sidebar.rb +44 -0
  22. data/lib/cortex_reaver/helper/tags.rb +32 -9
  23. data/lib/cortex_reaver/helper/workflow.rb +2 -14
  24. data/lib/cortex_reaver/layout/blank.rhtml +27 -31
  25. data/lib/cortex_reaver/layout/text.rhtml +54 -67
  26. data/lib/cortex_reaver/migrations/014_convert_projects_to_pages.rb +79 -0
  27. data/lib/cortex_reaver/model/comment.rb +7 -8
  28. data/lib/cortex_reaver/model/page.rb +5 -3
  29. data/lib/cortex_reaver/model/photograph.rb +57 -13
  30. data/lib/cortex_reaver/model/tag.rb +1 -4
  31. data/lib/cortex_reaver/model/user.rb +6 -3
  32. data/lib/cortex_reaver/plugin.rb +1 -1
  33. data/lib/cortex_reaver/plugins/twitter.rb +185 -0
  34. data/lib/cortex_reaver/public/css/actions.css +31 -0
  35. data/lib/cortex_reaver/public/css/admin.css +50 -27
  36. data/lib/cortex_reaver/public/css/attachments.css +11 -0
  37. data/lib/cortex_reaver/public/css/autotags.css +38 -0
  38. data/lib/cortex_reaver/public/css/code.css +10 -2
  39. data/lib/cortex_reaver/public/css/colophon.css +10 -0
  40. data/lib/cortex_reaver/public/css/commments.css +7 -0
  41. data/lib/cortex_reaver/public/css/custom.css +1 -0
  42. data/lib/cortex_reaver/public/css/flash.css +17 -0
  43. data/lib/cortex_reaver/public/css/fonts.css +22 -0
  44. data/lib/cortex_reaver/public/css/form.css +15 -3
  45. data/lib/cortex_reaver/public/css/generics.css +39 -0
  46. data/lib/cortex_reaver/public/css/icons.css +4 -0
  47. data/lib/cortex_reaver/public/css/journals.css +3 -0
  48. data/lib/cortex_reaver/public/css/main.css +30 -312
  49. data/lib/cortex_reaver/public/css/pagination.css +50 -0
  50. data/lib/cortex_reaver/public/css/photo-show.css +87 -0
  51. data/lib/cortex_reaver/public/css/photo.css +28 -97
  52. data/lib/cortex_reaver/public/css/progress.css +35 -0
  53. data/lib/cortex_reaver/public/css/sidebar.css +83 -0
  54. data/lib/cortex_reaver/public/css/table-of-contents.css +26 -0
  55. data/lib/cortex_reaver/public/css/table.css +3 -0
  56. data/lib/cortex_reaver/public/css/tags.css +29 -0
  57. data/lib/cortex_reaver/public/css/text.css +19 -1
  58. data/lib/cortex_reaver/public/css/top_actions.css +50 -0
  59. data/lib/cortex_reaver/public/css/users.css +3 -0
  60. data/lib/cortex_reaver/public/images/admin/icons.png +0 -0
  61. data/lib/cortex_reaver/public/images/admin/icons.xcf +0 -0
  62. data/lib/cortex_reaver/public/images/background_tile.png +0 -0
  63. data/lib/cortex_reaver/public/images/edit_34.png +0 -0
  64. data/lib/cortex_reaver/public/images/edit_34_prelight.png +0 -0
  65. data/lib/cortex_reaver/public/images/elided.png +0 -0
  66. data/lib/cortex_reaver/public/images/grid_34.png +0 -0
  67. data/lib/cortex_reaver/public/images/grid_34_prelight.png +0 -0
  68. data/lib/cortex_reaver/public/images/next_11.png +0 -0
  69. data/lib/cortex_reaver/public/images/next_34.png +0 -0
  70. data/lib/cortex_reaver/public/images/next_34_prelight.png +0 -0
  71. data/lib/cortex_reaver/public/images/prev_11.png +0 -0
  72. data/lib/cortex_reaver/public/images/prev_34.png +0 -0
  73. data/lib/cortex_reaver/public/images/prev_34_prelight.png +0 -0
  74. data/lib/cortex_reaver/public/js/admin.js +15 -22
  75. data/lib/cortex_reaver/public/js/autotags.js +120 -0
  76. data/lib/cortex_reaver/public/js/jquery.autocomplete.js +135 -176
  77. data/lib/cortex_reaver/public/js/jquery.color.js +124 -0
  78. data/lib/cortex_reaver/public/js/jquery.corners.min.js +7 -0
  79. data/lib/cortex_reaver/public/js/jquery.hotkeys-0.7.9.js +244 -0
  80. data/lib/cortex_reaver/public/js/jquery.js +4361 -4
  81. data/lib/cortex_reaver/public/js/jquery.periodicalupdater.js +98 -0
  82. data/lib/cortex_reaver/public/js/photo.js +3 -32
  83. data/lib/cortex_reaver/public/robots.txt +3 -0
  84. data/lib/cortex_reaver/snippets/ramaze/cache/memcached.rb +13 -10
  85. data/lib/cortex_reaver/snippets/range.rb +9 -0
  86. data/lib/cortex_reaver/support/attachments.rb +12 -0
  87. data/lib/cortex_reaver/support/comments.rb +1 -3
  88. data/lib/cortex_reaver/support/renderer.rb +20 -17
  89. data/lib/cortex_reaver/support/sequenceable.rb +6 -6
  90. data/lib/cortex_reaver/support/tags.rb +15 -7
  91. data/lib/cortex_reaver/version.rb +1 -1
  92. data/lib/cortex_reaver/view/admin/configuration.rhtml +7 -0
  93. data/lib/cortex_reaver/view/admin/index.rhtml +3 -0
  94. data/lib/cortex_reaver/view/admin/regenerate_photo_sizes.rhtml +16 -0
  95. data/lib/cortex_reaver/view/adminbox.rhtml +34 -44
  96. data/lib/cortex_reaver/view/comments/comment.rhtml +1 -1
  97. data/lib/cortex_reaver/view/comments/form.rhtml +1 -2
  98. data/lib/cortex_reaver/view/comments/post_form.rhtml +2 -10
  99. data/lib/cortex_reaver/view/head.rhtml +11 -0
  100. data/lib/cortex_reaver/view/journals/journal.rhtml +3 -3
  101. data/lib/cortex_reaver/view/journals/show.rhtml +0 -4
  102. data/lib/cortex_reaver/view/js.rhtml +1 -0
  103. data/lib/cortex_reaver/view/pages/list.rhtml +3 -23
  104. data/lib/cortex_reaver/view/pages/row.rhtml +13 -0
  105. data/lib/cortex_reaver/view/photographs/grid.rhtml +30 -36
  106. data/lib/cortex_reaver/view/photographs/show.rhtml +42 -108
  107. data/lib/cortex_reaver/view/sidebar/explore_photos.rhtml +7 -0
  108. data/lib/cortex_reaver/view/sidebar/photographs.rhtml +15 -0
  109. data/lib/cortex_reaver/view/sidebar/sections.rhtml +4 -0
  110. data/lib/cortex_reaver/view/sidebar/twitter.rhtml +12 -0
  111. data/lib/cortex_reaver/view/tags/show.rhtml +0 -10
  112. data/lib/cortex_reaver/view/tracker.rhtml +0 -0
  113. data/lib/cortex_reaver/view/users/list.rhtml +1 -7
  114. data/lib/cortex_reaver/view/users/login.rhtml +1 -1
  115. metadata +103 -43
  116. data/lib/cortex_reaver/controller/project.rb +0 -53
  117. data/lib/cortex_reaver/helper/template.rb +0 -37
  118. data/lib/cortex_reaver/model/project.rb +0 -57
  119. data/lib/cortex_reaver/public/css/ramaze_error.css +0 -90
  120. data/lib/cortex_reaver/public/images/atom-xml-icon.png +0 -0
  121. data/lib/cortex_reaver/public/images/body.png +0 -0
  122. data/lib/cortex_reaver/public/images/border_bottom.png +0 -0
  123. data/lib/cortex_reaver/public/images/border_bottom_left.png +0 -0
  124. data/lib/cortex_reaver/public/images/border_bottom_right.png +0 -0
  125. data/lib/cortex_reaver/public/images/border_left.png +0 -0
  126. data/lib/cortex_reaver/public/images/border_right.png +0 -0
  127. data/lib/cortex_reaver/public/images/border_top.png +0 -0
  128. data/lib/cortex_reaver/public/images/border_top_left.png +0 -0
  129. data/lib/cortex_reaver/public/images/border_top_right.png +0 -0
  130. data/lib/cortex_reaver/public/images/header.png +0 -0
  131. data/lib/cortex_reaver/public/images/header.xcf +0 -0
  132. data/lib/cortex_reaver/public/images/indicator.gif +0 -0
  133. data/lib/cortex_reaver/public/images/rss-xml-icon.png +0 -0
  134. data/lib/cortex_reaver/public/images/sections.png +0 -0
  135. data/lib/cortex_reaver/public/images/sections_highlight.png +0 -0
  136. data/lib/cortex_reaver/public/js/jquery.autocompletefb.js +0 -125
  137. data/lib/cortex_reaver/view/photographs/sidebar.rhtml +0 -7
  138. data/lib/cortex_reaver/view/projects/form.rhtml +0 -14
  139. data/lib/cortex_reaver/view/projects/list.rhtml +0 -31
  140. data/lib/cortex_reaver/view/projects/show.rhtml +0 -42
  141. data/lib/proto/cortex_reaver.yaml +0 -47
@@ -0,0 +1,98 @@
1
+ /**
2
+ * PeriodicalUpdater - jQuery plugin for timed, decaying ajax calls
3
+ *
4
+ * Smokejumper Version by Robert Fischer, Smokejumper IT
5
+ * Based on version from http://www.360innovate.co.uk
6
+ *
7
+ * Copyright (c) 2009 by the following:
8
+ * * Robert Fischer (http://smokejumperit.com)
9
+ * * 360innovate (http://www.360innovate.co.uk)
10
+ * Dual licensed under the MIT and GPL licenses:
11
+ * http://www.opensource.org/licenses/mit-license.php
12
+ * http://www.gnu.org/licenses/gpl.html
13
+ *
14
+ * Version: 2.0
15
+ */
16
+
17
+ (function($) {
18
+ $.PeriodicalUpdater = function(url, options, callback){
19
+
20
+ var settings = jQuery.extend(true, {
21
+ url: url, // URL of ajax request
22
+ cache: false, // By default, don't allow caching
23
+ method: 'GET', // method; get or post
24
+ data: '', // array of values to be passed to the page - e.g. {name: "John", greeting: "hello"}
25
+ minTimeout: 1000, // starting value for the timeout in milliseconds
26
+ maxTimeout: 8000, // maximum length of time between requests
27
+ multiplier: 2 // if set to 2, timerInterval will double each time the response hasn't changed (up to maxTimeout)
28
+ }, options);
29
+
30
+ // set some initial values, then begin
31
+ var prevContent = null;
32
+ var knowIsSame = false;
33
+ var timerInterval = settings.minTimeout;
34
+
35
+ // Function to boost the timer (nop unless multiplier > 1)
36
+ var boostPeriod = function() { return; };
37
+ if(settings.multiplier > 1) {
38
+ boostPeriod = function() {
39
+ timerInterval = timerInterval * settings.multiplier;
40
+
41
+ if(timerInterval > settings.maxTimeout) {
42
+ timerInterval = settings.maxTimeout;
43
+ }
44
+ };
45
+ }
46
+
47
+ var PeriodicalTimer = null; // Getting a handle on this for some reason
48
+
49
+ // Construct the settings for $.ajax based on settings
50
+ var ajaxSettings = jQuery.extend(true, {}, settings);
51
+ if(settings.type && !ajaxSettings.dataType) ajaxSettings.dataType = settings.type;
52
+ if(settings.sendData) ajaxSettings.data = settings.sendData;
53
+ ajaxSettings.type = settings.method; // 'type' is used internally for jQuery. Who knew?
54
+ ajaxSettings.ifModified = false;
55
+ ajaxSettings.success = function(data) {
56
+ if(knowIsSame || (prevContent || prevContent == "") && prevContent == data) {
57
+ boostPeriod();
58
+ } else {
59
+ if(console) {
60
+ console.log("Change in data: old data is " + prevContent + " and new data is " + data);
61
+ }
62
+ prevContent = data;
63
+ timerInterval = settings.minTimeout;
64
+ if(callback) {
65
+ callback(data);
66
+ }
67
+ }
68
+ PeriodicalTimer = setTimeout(getdata, timerInterval);
69
+ if(settings.success) { settings.success(data); }
70
+ };
71
+ ajaxSettings.error = function (XMLHttpRequest, textStatus) {
72
+ if(knowIsSame || textStatus == "notmodified") {
73
+ boostPeriod();
74
+ } else {
75
+ if(console) {
76
+ console.log("Resetting due to error: " + textStatus);
77
+ }
78
+ prevContent = null;
79
+ timerInterval = settings.minTimeout;
80
+ }
81
+ PeriodicalTimer = setTimeout(getdata, timerInterval);
82
+ if(settings.error) { settings.error(XMLHttpRequest, textStatus); }
83
+ };
84
+
85
+ var oldRawData = null;
86
+ ajaxSettings.dataFilter = function (data, type) {
87
+ if(settings.dataFilter) data = settings.dataFilter(data, type);
88
+ knowIsSame = (data && oldRawData && data == oldRawData);
89
+ oldRawData = data;
90
+ return data;
91
+ };
92
+
93
+ function getdata() { $.ajax(ajaxSettings); }
94
+
95
+ // Make the first call
96
+ $(function() { getdata(); });
97
+ };
98
+ })(jQuery);
@@ -1,33 +1,4 @@
1
- $(window).load(function() {
2
- var bar = $('#bar');
3
- var photo = $('#photo');
4
- var canvas = $('#canvas');
5
- var timeout;
6
-
7
- canvas.hover(
8
- function() {
9
- if (timeout) clearTimeout(timeout);
10
- if (bar.is(':animated')) {
11
- bar.stop();
12
- bar.css('opacity', 1);
13
- bar.show();
14
- } else {
15
- bar.fadeIn('fast');
16
- }
17
- },
18
- function() {
19
- timeout = setTimeout("$('#bar').fadeOut('slow');", 1000);
20
- }
21
- )
22
-
23
- // Adjust margins for bar
24
- bar.css('margin-bottom', (- $('#bar').height()));
25
-
26
- // Resize canvas to photo
27
- canvas.width(photo.width());
28
- canvas.height(photo.height());
29
-
30
- // Resize bar to photo width
31
- bar.css('position', 'absolute');
32
- bar.width(photo.width());
1
+ $(document).ready(function() {
2
+ $('.frame').corners("10px");
3
+ $('.frame .comment').corners("6px");
33
4
  });
@@ -0,0 +1,3 @@
1
+ User-agent: *
2
+ Allow: /
3
+ Sitemap: /sitemap.xml
@@ -1,14 +1,17 @@
1
1
  module Ramaze
2
- class MemcachedCache
3
- # I can't figure out a good way to specify the parameters Ramaze::Cache
4
- # uses when instantiating new caches, so I'm just going to override the
5
- # setup here. Innate hardcodes the app name as "pristine". :(
6
- def cache_setup(host, user, app, name)
7
- app = Ramaze.options.app.name
8
- @namespace = [host, user, app, name].compact.join('-')
9
- options = {:namespace => @namespace}.merge(OPTIONS)
10
- servers = options.delete(:servers)
11
- @store = ::MemCache.new(servers, options)
2
+ class Cache
3
+ class MemCache
4
+ # I can't figure out a good way to specify the parameters Ramaze::Cache
5
+ # uses when instantiating new caches, so I'm just going to override the
6
+ # setup here. Innate hardcodes the app name as "pristine". :(
7
+ def cache_setup(host, user, app, name)
8
+ app = Ramaze.options.app.name
9
+ @namespace = [host, user, app, name].compact.join('-')
10
+ options = {:namespace => @namespace}.merge(OPTIONS)
11
+ servers = options.delete(:servers)
12
+ @store = ::MemCache.new(servers, options)
13
+ @warned = false
14
+ end
12
15
  end
13
16
  end
14
17
  end
@@ -0,0 +1,9 @@
1
+ class Range
2
+ # Constructs the smallest range which covers this and other.
3
+ def |(other)
4
+ my_end, other_end = self.end, other.end
5
+ my_end -= 1 if self.exclude_end?
6
+ other_end -= 1 if other.exclude_end?
7
+ [self.begin, other.begin].min .. [my_end, other_end].max
8
+ end
9
+ end
@@ -130,6 +130,10 @@ module Sequel
130
130
  @name = name
131
131
  end
132
132
 
133
+ def ==(other)
134
+ self.class == other.class and self.path == other.path rescue false
135
+ end
136
+
133
137
  # Deletes the file on disk, which effectively deletes the attachment.
134
138
  def delete
135
139
  FileUtils.remove_file local_path
@@ -209,6 +213,10 @@ module Sequel
209
213
  end
210
214
  end
211
215
 
216
+ def inspect
217
+ "#<CortexReaver::Attachment #{local_path}"
218
+ end
219
+
212
220
  # Returns the local path to this file.
213
221
  def local_path
214
222
  path :local
@@ -235,6 +243,10 @@ module Sequel
235
243
  def reset_permissions
236
244
  FileUtils.chmod(DEFAULT_MODE, path(:local))
237
245
  end
246
+
247
+ def to_s
248
+ local_path
249
+ end
238
250
  end
239
251
  end
240
252
  end
@@ -14,9 +14,7 @@ module Sequel
14
14
  module InstanceMethods
15
15
  # When we delete a model that has comments, remove the comments too.
16
16
  def before_destroy
17
- Ramaze::Log.debug 'remove_comments'
18
17
  return false if super == false
19
- Ramaze::Log.debug 'removing comments'
20
18
 
21
19
  comments = self.comments
22
20
  remove_all_comments
@@ -47,7 +45,7 @@ module Sequel
47
45
  # Returns the parent of a given comment. Caches, pass true to refresh.
48
46
  def parent(refresh = false)
49
47
  if refresh or @parent_cache.nil?
50
- [:comment, :journal, :photograph, :project, :page].each do |p|
48
+ [:comment, :journal, :photograph, :page].each do |p|
51
49
  if self.respond_to?(p) and parent = self.send(p)
52
50
  # We found an applicable parent.
53
51
  @parent_cache = parent
@@ -9,8 +9,6 @@ module CortexReaver
9
9
  module Renderer
10
10
 
11
11
  require 'bluecloth'
12
- require 'hpricot'
13
- require 'coderay'
14
12
  require 'sanitize'
15
13
 
16
14
  # Renders plain text and html to html. If parse_code isn't true, only
@@ -28,7 +26,7 @@ module CortexReaver
28
26
  until text.empty? do
29
27
  if level < 1
30
28
  # Find start of code block
31
- j = text.index('<code>') || text.length
29
+ j = text.index(/<code.*?>/) || text.length
32
30
  j -= 1 if j != 0
33
31
  level += 1
34
32
 
@@ -131,26 +129,31 @@ module CortexReaver
131
129
  def syntax_highlight(text)
132
130
  return text if text.nil?
133
131
 
134
- text.gsub(/<cr:code\s.*?(lang="(.*?)").*?>(.*?)<\/cr:code>/m) do |match|
135
- lang = $2
132
+ text = text.gsub(/<cr:code([^>]+lang="([a-z0-9]+)".*?)?>(.*?)<\/cr:code>/m) do |match|
133
+ lang = $2 || 'text'
136
134
  code = $3
137
135
 
138
- # Replace entities
139
- code.gsub!('&', '&quot;')
136
+ # Tempfile...
137
+ Tempfile.open('cortex-reaver') do |f|
138
+ f.write code.strip
139
+ f.close
140
140
 
141
- unless lang.empty?
142
- # Parse with CodeRay.
143
- code = '<div class="code"><code>' + CodeRay.scan(code, lang.to_sym).html.strip + '</code></div>'
141
+ system('vim -f +"set filetype=' + lang + '" +"syn on" +"let html_use_css = 1" +"let html_use_encoding = \"UTF-8\"" +"let use_xhtml = 1" +"run! syntax/2html.vim" +"wq" +"q" ' + f.path)
142
+
143
+ code = File.read(f.path + '.html')
144
+ File.delete(f.path + '.html')
145
+ f.unlink
144
146
  end
145
147
 
146
- # Using white-space: pre is a nice option, but I haven't figured out
147
- # how to make it work with fluid layouts. So, I'm going with line
148
- # wrapping and explicit HTML entities; since we're already marking
149
- # up the code for syntax, might as well go all the way. Plus,
150
- # this still pastes cleanly, but displays like a terminal.
151
- code.gsub!("\n", '<br />')
152
- code.gsub!(/( {2})/) { |match| '&nbsp;' * $1.length }
148
+ # Slice out preamble
149
+ code.sub!(/^.*?<pre>/m, '')
150
+ code.sub!(/<\/pre>.*$/m, '')
151
+
152
+ # Wrap
153
+ code = '<code class="block">' + code.strip + '</code>'
154
+ code
153
155
  end
156
+ text
154
157
  end
155
158
 
156
159
  def sanitize_html(html)
@@ -114,9 +114,9 @@ module Sequel
114
114
  # refresh.
115
115
  def next(refresh_cache = false)
116
116
  if refresh_cache
117
- @next = sequence.filter(sequence_order > send(sequence_order)).limit(1).first
117
+ @next = sequence.filter{|o| o.__send__(sequence_order) > send(sequence_order)}.limit(1).first
118
118
  else
119
- @next ||= sequence.filter(sequence_order > send(sequence_order)).limit(1).first
119
+ @next ||= sequence.filter{|o| o.__send__(sequence_order) > send(sequence_order)}.limit(1).first
120
120
  end
121
121
  end
122
122
 
@@ -132,16 +132,16 @@ module Sequel
132
132
 
133
133
  # Returns the number of succeeding records
134
134
  def next_count
135
- sequence.filter(sequence_order > send(sequence_order)).count
135
+ sequence.filter{|o| o.__send__(sequence_order) > send(sequence_order)}.count
136
136
  end
137
137
 
138
138
  # Returns the previous record in the sequence. Caches--use
139
139
  # previous(true) to refresh.
140
140
  def previous(refresh_cache = false)
141
141
  if refresh_cache
142
- @previous = sequence.filter(sequence_order < send(sequence_order)).reverse.limit(1).first
142
+ @previous = sequence.filter{|o| p o; o.__send__(sequence_order) < send(sequence_order)}.reverse.limit(1).first
143
143
  else
144
- @previous ||= sequence.filter(sequence_order < send(sequence_order)).reverse.limit(1).first
144
+ @previous ||= sequence.filter{|o| o.__send__(sequence_order) < send(sequence_order)}.reverse.limit(1).first
145
145
  end
146
146
  end
147
147
 
@@ -157,7 +157,7 @@ module Sequel
157
157
 
158
158
  # Returns the number of preceding records
159
159
  def previous_count
160
- sequence.filter(sequence_order < send(sequence_order)).count
160
+ sequence.filter{|o| o.__send__(sequence_order) < send(sequence_order)}.count
161
161
  end
162
162
 
163
163
  alias :position :previous_count
@@ -11,10 +11,9 @@ module Sequel
11
11
  # Returns all models with ALL the following tags:
12
12
  def tagged_with(tags, all=true)
13
13
  # Find map between this model and tags, e.g. pages_tags
14
- map = [table_name.to_s, 'tags'].sort.join('_').to_sym
15
-
16
- # The name in the mapping table which points to us
17
- own_id = (table_name.to_s.singularize + '_id').to_sym
14
+ reflection = self.association_reflection(:tags)
15
+ map = reflection[:join_table]
16
+ own_id = reflection[:left_key]
18
17
 
19
18
  # The tag IDs to search for
20
19
  ids = tags.map { |t| t.id }
@@ -59,9 +58,7 @@ module Sequel
59
58
 
60
59
  # Remove tags on deletion
61
60
  def before_destroy
62
- Ramaze::Log.debug 'remove tags'
63
61
  return false unless super
64
- Ramaze::Log.debug 'removing tags'
65
62
 
66
63
  tags.each do |tag|
67
64
  tag.count -= 1
@@ -73,10 +70,21 @@ module Sequel
73
70
  end
74
71
  remove_all_tags
75
72
 
76
-
77
73
  true
78
74
  end
79
75
 
76
+ # Finds related models by tags.
77
+ def related_by_tags
78
+ # Find map between this model and tags, e.g. pages_tags
79
+ reflection = self.association_reflection(:tags)
80
+ map = reflection[:join_table]
81
+ own_id = reflection[:left_key]
82
+ tags = self.tags.map(:id)
83
+ self.class.filter(
84
+ CortexReaver.db[map].filter(:tag_id => tags).group_and_count(own_id).reverse.map(:photograph_ids)
85
+ )
86
+ end
87
+
80
88
  # Set tags from a string, or array of tags. Finds existing tags or
81
89
  # creates new ones. Also updates tag counts.
82
90
  def tags=(tags)
@@ -1,6 +1,6 @@
1
1
  module CortexReaver
2
2
  APP_NAME = 'Cortex Reaver'
3
- APP_VERSION = '0.1.0'
3
+ APP_VERSION = '0.2.0'
4
4
  APP_AUTHOR = 'Kyle Kingsbury'
5
5
  APP_EMAIL = 'aphyr@aphyr.com'
6
6
  APP_URL = 'http://aphyr.com'
@@ -0,0 +1,7 @@
1
+ <h2>Configuration</h2>
2
+
3
+ <form class="edit-form" action="<%= CortexReaver::AdminController.r :configuration %>" method="post">
4
+ <% config = CortexReaver.config %>
5
+ <%= form_p 'view.sections', :type => :textarea, :description => config.view.schema[:sections][:desc], :default => CortexReaver.config.view.sections.map{ |p| p.join(' ') }.join("\n") %>
6
+ <input type="submit" value="Update Configuration" />
7
+ </form>
@@ -1,6 +1,9 @@
1
1
  <h2>Administration</h2>
2
2
 
3
3
  <ul>
4
+ <li><%= a('Configure site', rs(:configuration)) %></li>
5
+ <li><%= a('Regenerate thumbnails', rs(:regenerate_photo_sizes)) %></li>
6
+ <li><%= a('Regenerate rendered body caches', rs(:regenerate_caches)) %></li>
4
7
  <li><%= a('Update comment counts', rs(:update_comments)) %></li>
5
8
  <li><%= a('Update tags', rs(:update_tags)) %></li>
6
9
  </ul>
@@ -0,0 +1,16 @@
1
+ <h2>Regenerating Photographs</h2>
2
+ <div class="progress"><div class="bar"></div></div>
3
+
4
+ <script type="text/javascript">
5
+ /* <![CDATA[ */
6
+
7
+ $.PeriodicalUpdater('<%= rs('regenerate_photo_sizes_status')%>',
8
+ {type: 'json'},
9
+ function(response) {
10
+ response.total
11
+ $('.progress').html('<div class="percent-bar" style="width:' + (response.i/response.total * ($('.progress').width() - 4)) + 'px">' + response.i + '</div>' + response.total);
12
+ }
13
+ );
14
+
15
+ /* ]]> */
16
+ </script>
@@ -1,51 +1,41 @@
1
- <div id="adminbox">
1
+ <div class="admin bar">
2
2
  <% if user.admin? or user.contributor? or user.editor? or user.moderator? %>
3
- <table class="actions-table">
4
- <tr>
5
- <td class="title">Sections</td>
6
- <td>
7
- <ul class="actions">
8
- <li><a href="/pages">Pages</a></li>
9
- <li><a href="/projects">Projects</a></li>
10
- <li><a href="/journals">Journals</a></li>
11
- <li><a href="/photographs">Photographs</a></li>
12
- <li><a href="/comments">Comments</a></li>
13
- <li><a href="/tags">Tags</a></li>
14
- <% if user.admin? %>
15
- <li><a href="/users">Users</a></li>
16
- <li><a href="/admin">Admin</a></li>
17
- <% end %>
18
- </ul>
19
- </td>
20
- </tr>
21
- <% if workflows %>
22
- <tr>
23
- <td class="title">Actions</td>
24
- <td>
25
- <ul class="actions">
26
- <% workflows.each do |name, href| %>
27
- <li>
28
- <a href="<%= href %>"
29
- <%= name.to_s[/delete|destroy/i] ? "onclick = \"return confirm('Are you sure you want to delete #{@title.gsub(/'"/, '')}?');\"" : '' %>>
30
- <%= name %>
31
- </a>
32
- </li>
33
- <% end %>
34
- </ul>
35
- </td>
36
- </tr>
37
- <% end %>
38
- </table>
39
3
 
40
- <div id="admin_user_actions">
41
- <a href="/users/logout">Log out</a>
42
- </div>
4
+ <ul class="user actions">
5
+ <li><a class="button exit" href="/users/logout">Log out</a></li>
6
+ </ul>
7
+
8
+ <% if workflows %>
9
+ <ul class="workflow actions">
10
+ <% workflows.each do |name, href, classes| %>
11
+ <li>
12
+ <a class="button <%=classes.join(' ')%>" title="<%= attr_h name %>" href="<%= href %>"
13
+ <%= name.to_s[/delete|destroy/i] ? "onclick = \"return confirm('Are you sure you want to delete #{@title.gsub(/'"/, '')}?');\"" : '' %>>
14
+ <%= name %>
15
+ </a>
16
+ </li>
17
+ <% end %>
18
+ </ul>
19
+ <% end %>
20
+
21
+ <ul class="navigation actions">
22
+ <li><a class="button journals" href="/journals" title="Journals">Journals</a></li>
23
+ <li><a class="button photographs" href="/photographs" title="Photographs">Photographs</a></li>
24
+ <li><a class="button pages" href="/pages" title="Pages">Pages</a></li>
25
+ <li><a class="button comments" href="/comments" title="Comments">Comments</a></li>
26
+ <li><a class="button tags" href="/tags" title="Tags">Tags</a></li>
27
+ <% if user.admin? %>
28
+ <li><a class="button users" href="/users" title="Users">Users</a></li>
29
+ <li><a class="button admin" href="/admin" title="Admin">Admin</a></li>
30
+ <% end %>
31
+ </ul>
32
+
43
33
  <% elsif session[:user] %>
44
- <div id="admin_user_actions">
45
- <a href="/users/logout">Log out</a>
46
- </div>
34
+ <ul class="user actions">
35
+ <li><a class="button exit" href="/users/logout">Log out</a></li>
36
+ </ul>
47
37
  <% else %>
48
- <form action="/users/login" method="post">
38
+ <form id="login" action="/users/login" method="post">
49
39
  <p>
50
40
  <label for="admin_login">Login</label> <input type="text" name="login" id="admin_login" />
51
41
  <label for="admin_password">Password</label> <input type="password" name="password" id="admin_password" />