app/controllers/wiki.rb in Pimki-1.3.092 vs app/controllers/wiki.rb in Pimki-1.4.092

- old
+ new

@@ -1,8 +1,10 @@ require "cgi" require "redcloth_for_tex" +RenderedTodo = Struct.new( :text, :context, :due_date ) + class WikiController < ActionControllerServlet EXPORT_DIRECTORY = WikiService.storage_path unless const_defined?("EXPORT_DIRECTORY") def index if web_address @@ -110,21 +112,26 @@ parse_category set_menu_pages @pages_by_name = @pages_in_category.by_name @page_names_that_are_wanted = @pages_in_category.wanted_pages @pages_that_are_orphaned = @pages_in_category.orphaned_pages - case @req.query['Action'] - when 'Delete' # Handle page deletion - wiki.delete_page(web_address, @req.query['sel_page_name']) - redirect_action "list/" - - when 'Create' # Handle page creation - redirect_show @req.query['newpage'] - when 'Rename' # Handle page rename - wiki.rename_page(web_address, @req.query['sel_page_name'], @req.query['newpage']) - redirect_action "list/" + if @req.query['Action'] + redirect_action 'list/' if web.check_pass_on_edit and not authenticate + + case @req.query['Action'] + when 'Delete' # Handle page deletion + wiki.delete_page(web_address, @req.query['sel_page_name']) + redirect_action "list/" + + when 'Create' # Handle page creation + redirect_show @req.query['newpage'] + + when 'Rename' # Handle page rename + wiki.rename_page(web_address, @req.query['sel_page_name'], @req.query['newpage']) + redirect_action "list/" + end end end def export_html @@ -158,13 +165,20 @@ export_web_to_tex(file_path) unless FileTest.exists?(file_path) send_export(file_name, file_path) end + def edit_web #{{{ + parse_category + set_mm_options + end #}}} + def update_web redirect_show("HomePage") unless wiki.authenticate(@params["system_password"]) + set_mm_options + wiki.update_web( web.address, @params["address"], @params["name"], @params["markup"].intern, @params["color"], @params["additional_style"], @params["safe_mode"] ? true : false, @@ -172,11 +186,14 @@ @params["published"] ? true : false, @params["brackets_only"] ? true : false, @params["count_pages"] ? true : false, @params['mind_map_size'], @params['symbols_map'], - @params['links_map'] + @params['links_map'], + @params['enable_dclick_edit'], + @params['check_pass_on_edit'] == 'each_edit', + @prog, @graph_type, @missing, @show_authors, @show_leaves, @selected_categories ) redirect_show("HomePage", @params["address"]) end @@ -187,43 +204,99 @@ else redirect_show "HomePage" end end + FAR_FUTURE = Date.new(4000,1,1).freeze + TODO_RE = %r{<todo-tag context='(.*?)' due_date='(.*?)'><span class="todo"><strong>TODO(?:.*)?:</strong> (.*?)</span></todo-tag>} + def todo #{{{ parse_category set_menu_pages - @pages_by_name = @pages_in_category.by_name - @todo_items = Hash.new { Array.new } - @bliki_todo_items = Hash.new { Array.new } - @pages_by_name.each do |page| - if page.content =~ Todo.pattern + + @context = @params['context'] + @sort_order = @params['sort_order'] + + clear_render_cache # hack to make sure we don't have old-style rendered todos. + @todo_items = analyse_rendered_todo_items @pages_in_category.by_name + @bliki_todo_items = analyse_rendered_todo_items web.bliki.values + + @context_links = @todo_items.clone.update(@bliki_todo_items).map { |page, items| + # 'items' contain the full 'todo' info + items.map { |item| item.context } + }.flatten.compact.uniq.reject { |c| c.nil? || c.empty? }.map { |context| + @context == context ? + "[<span class='selected'>#{context}</span>]" : + "<a href='?context=#{context}#{"&sort_order=#{@sort_order}" if @sort_order}'>#{context}</a>" + } + + @todo_items = sort_and_filter_todo_items @todo_items, @sort_order, @context + @bliki_todo_items = sort_and_filter_todo_items @bliki_todo_items, @sort_order, @context + + end #}}} + + def analyse_rendered_todo_items pages + items = Hash.new { Array.new } + pages.each do |page| + if page.has_todos? # Page has todo items. Get the rendered version (marked-up and with links): + # I specifically don't use the todo chunkss because I want the fully marked-up + # text of the item. content = page.revisions.last.display_content - @todo_items[page] = content.scan /<span class="todo"><strong>TODO:<\/strong> (.*?)<\/span>/ + items[page] = content.scan(TODO_RE).map { |match| + RenderedTodo.new match[2], (match[0].empty? ? [] : match[0].split(',') ), (Date.parse(match[1]) rescue FAR_FUTURE) + } end end - @todo_items = @todo_items.sort_by { |page, items| page.name } - web.bliki.each do |pname, entry| - if entry.content =~ Todo.pattern - # Entry has todo items. Get the rendered version (marked-up and with links): - content = entry.revisions.last.display_content - @bliki_todo_items[entry] = content.scan /<span class="todo"><strong>TODO:<\/strong> (.*?)<\/span>/ - end + items + end + + def sort_and_filter_todo_items items, sort_order, context + case sort_order + when 'due_date' + result = items.map { |page, todos| + # sort the to items themselves + [page, todos.sort_by { |i| i.due_date } ] + }.sort_by { |page, todos| + # sort the pages by the one with the most urgent todo + todos.map{ |i| i.due_date }.min + } + + else # default = sort by page name + result = items.sort_by { |page, items| page.name } + end - @bliki_todo_items = @bliki_todo_items.sort_by { |entry, items| entry.name } - end #}}} + + if context + # filter the items to those that are in context + result = result.map { |page, items| + [ page, items.select { |item| item.context.include? context } ] + }.select { |page, items| not items.empty? } + end + result + end + + def get_todo_display_style due_date + # default is the muted 'darkred', to prevent to many bright red + # items on one page: (See also chunks/todo.rb) + (due_date <=> Date.today) > -1 ? "todoFuture" : "todo" + end + + def clear_render_cache do_redirect=false + web.refresh_revisions + redirect_show 'HomePage' if do_redirect + end def set_menu_pages #{{{ parse_category @all_pages = web.select { true } @menu_pages = case web.menu_type when 'all' then @all_pages.by_name when 'recent' then @all_pages.by_last_visited when 'viewed' then @all_pages.by_most_viewed when 'revised' then @all_pages.by_revision - when 'user' then @menu_content = web.rendered_menu; nil + when 'user' then @menu_content = web.menu_content.revisions.last.display_content; nil when 'category' then web.select { |page| page.in_category?(web.menu_category) } when 'linkers' web.select { |page| page.wiki_words.size > 0 }.sort_by { |page| page.name } @@ -248,39 +321,54 @@ end @color = web.color @authors = web.authors end #}}} -require 'pp' def mind #{{{ parse_category set_menu_pages + set_mm_options - @prog = @req.query['draw_type'] || 'neato' - @graph_type = @req.query['graph_type'] || 'normal' - missing = @pages_in_category.wanted_pages if @req.query['missing'] - show_authors = !@req.query.empty? && @req.query['show_authors'] == 'on' - show_leaves = @req.query.empty? || @req.query['show_leaves'] == 'on' - - # TODO: fix handling of multiple-select for whole application - @selected_categories = @req.body.split('&').map { |pair| - pair.split('=') }.select { |k,v| - k == 'selected_categs' }.map { |k,v| v } if @req.body - @selected_categories ||= [] - @selected_categories = [] if @selected_categories.include? 'all' - @pngFile = @mapFile = nil case @graph_type - when 'normal' then @pngFile, @mapFile = web.create_mind_map(@prog, missing, - show_authors, show_leaves, @selected_categories) - when 'author' then @pngFile, @mapFile = web.create_author_graph(@prog, - @selected_categories) - when 'category' then @pngFile, @mapFile = web.create_category_graph(@prog, - show_authors, @selected_categories) + when 'normal' + @pngFile, @mapFile = web.create_mind_map(@prog, @missing, + @show_authors, @show_leaves, @selected_categories) + + when 'author' + @pngFile, @mapFile = web.create_author_graph(@prog, @selected_categories) + + when 'category' + @pngFile, @mapFile = web.create_category_graph(@prog, + @show_authors, @selected_categories) end end #}}} + def set_mm_options #{{{ + if @req.query.empty? + @prog = web.mm_prog + @graph_type = web.mm_graph_type + @missing = @pages_in_category.wanted_pages if web.mm_show_missing + @show_authors = web.mm_show_authors + @show_leaves = web.mm_show_leaves + @selected_categories = web.mm_selected_categories + else + @prog = @req.query['draw_type'] || 'neato' + @graph_type = @req.query['graph_type'] || 'normal' + @missing = @pages_in_category.wanted_pages if @req.query['missing'] + @show_authors = @req.query['show_authors'] == 'on' + @show_leaves = @req.query.empty? || @req.query['show_leaves'] == 'on' + + # TODO: fix handling of multiple-select for whole application + @selected_categories = @req.body.split('&').map { |pair| + pair.split('=') }.select { |k,v| + k == 'selected_categs' }.map { |k,v| v } if @req.body + @selected_categories ||= [] + @selected_categories = [] if @selected_categories.include? 'all' + end + end #}}} + def edit_menu #{{{ @menu_type = web.menu_type @menu_content = web.menu_content @list_limit = web.menu_limit @list_limit += 1 if @list_limit >= -1 @@ -291,21 +379,22 @@ unless @req.query['action'] == 'Cancel Update' type = @req.query['type'] content = @req.query['content'] category = @req.query['category'] + author = @req.query['author'] limit = @req.query['limit'].to_i rescue nil limit = 20 unless limit limit -= 1 if limit >= 0 # need to go through the WikiService to persist the command: - wiki.save_menu_pref web_address, type, limit, content, category + wiki.save_menu_pref(web_address, type, limit, content, category, Author.new(author, remote_ip)) end + # redirect to the most recently viewed page, or the home page. if web_address - # redirect to the most recently viewed page, or the home page. pname = begin web.select{ true }.by_last_visited.first.name rescue "HomePage" end @@ -372,10 +461,11 @@ convert_tex_to_pdf(file_path + ".tex") send_export(file_name + ".pdf", file_path + ".pdf") end def new + redirect_show("HomePage") if web.check_pass_on_edit and not authenticate @page_name, @author = page_name, default_author end def edit @page = wiki.read_page(web_address, page_name) @@ -394,14 +484,19 @@ @page.unlock redirect_show end def save + if web.check_pass_on_edit and not authenticate + wiki.read_page(web_address, page_name).unlock if web.pages[page_name] + redirect_show("HomePage") + end + if web.pages[page_name] page = wiki.revise_page( web_address, page_name, @params["content"], Time.now, - Author.new(@params["author"], remote_ip) + Author.new(@params["author"], remote_ip), @params['edit_type'] ) page.unlock else page = wiki.write_page( @@ -418,23 +513,28 @@ @page = wiki.read_page(web_address, page_name) @revision = @page.revisions[@params["rev"].to_i] end def rollback + redirect_show("HomePage") if web.check_pass_on_edit and not authenticate + @page = wiki.read_page(web_address, page_name) - wiki.rollback_page(web_address, page_name, @params["rev"].to_i, Time.now, remote_ip) - redirect_show + @revision = @page.revisions[@params["rev"].to_i] end # Bliki ---------------------------------------------------------------------- def bliki_delete + redirect_bliki if web.check_pass_on_edit and not authenticate + wiki.delete_bliki_entry(web_address, page_name) redirect_bliki end def bliki_edit + redirect_bliki if web.check_pass_on_edit and not authenticate + @page = wiki.read_bliki_entry(web_address, page_name) if !@page.locked?(Time.now) || @params["break_lock"] @page.lock(Time.now, default_author) @author = default_author @@ -449,10 +549,12 @@ @page.unlock if @page redirect_bliki end def bliki_save + redirect_bliki if web.check_pass_on_edit and not authenticate + pname = page_name || @params["pagename"] if web.bliki[pname] page = wiki.revise_bliki_entry(web_address, pname, @params["content"], Time.now, @params["author"]) page.unlock else @@ -462,15 +564,19 @@ write_cookie("author", @params["author"]) redirect_bliki end def bliki_revision + parse_category + set_menu_pages @page = wiki.read_bliki_entry(web_address, page_name || @params['pagename']) @revision = @page.revisions[@params["rev"].to_i] || @page.revisions.last end def rollback_bliki + redirect_bliki if web.check_pass_on_edit and not authenticate + @page = wiki.read_bliki_entry(web_address, page_name) wiki.rollback_bliki_entry(web_address, page_name, @params["rev"].to_i, Time.now) redirect_bliki end @@ -533,11 +639,12 @@ def page_name CGI.unescape(request_path[2]) if request_path[2] end def authorized?(web_address) - (web && web.password.nil?) || + web.nil? || + web.password.nil? || (read_cookie(web_address) && read_cookie(web_address) == web.password) || password_check(@params["password"]) end def default_author @@ -594,10 +701,16 @@ def truncate(text, length = 30, truncate_string = "...") if text.length > length then text[0..(length - 3)] + truncate_string else text end end def render_markup_help - sub_template "#{web.markup}_help" + if web + markup = web.markup + markup = 'markdown' if markup.to_s =~ /markdown/ + sub_template("#{markup}_help") + else + '' + end end def send_export(file_name, file_path, content_type = "application/zip") @res["Content-Type"] = content_type @res["Content-Disposition"] = "attachment; filename=#{file_name}" \ No newline at end of file