| rev | line source | 
| bsw@2 | 1 local old_draft_id = param.get("old_draft_id", atom.integer) | 
| bsw@2 | 2 local new_draft_id = param.get("new_draft_id", atom.integer) | 
| bsw@2 | 3 | 
| bsw@10 | 4 if not old_draft_id or not new_draft_id then | 
| bsw@10 | 5   slot.put( _"Please choose two versions of the draft to compare") | 
| bsw@10 | 6   return | 
| bsw@10 | 7 end | 
| bsw@10 | 8 | 
| bsw@10 | 9 if old_draft_id == new_draft_id then | 
| bsw@10 | 10   slot.put( _"Please choose two different versions of the draft to compare") | 
| bsw@10 | 11   return | 
| bsw@10 | 12 end | 
| bsw@10 | 13 | 
| bsw@2 | 14 if old_draft_id > new_draft_id then | 
| bsw@2 | 15   local tmp = old_draft_id | 
| bsw@2 | 16   old_draft_id = new_draft_id | 
| bsw@2 | 17   new_draft_id = tmp | 
| bsw@2 | 18 end | 
| bsw@2 | 19 | 
| bsw@2 | 20 local old_draft = Draft:by_id(old_draft_id) | 
| bsw@2 | 21 local new_draft = Draft:by_id(new_draft_id) | 
| bsw@2 | 22 | 
| poelzi@160 | 23 execute.view{ | 
| poelzi@160 | 24   module = "draft", | 
| poelzi@160 | 25   view = "_head", | 
| poelzi@160 | 26   params = { draft = new_draft} | 
| poelzi@160 | 27 } | 
| poelzi@159 | 28 | 
| bsw@727 | 29 ui.title(_"Diff") | 
| poelzi@159 | 30 | 
| poelzi@159 | 31 if app.session.member_id and not new_draft.initiative.revoked then | 
| poelzi@159 | 32   local supporter = Supporter:new_selector():add_where{"member_id = ?", app.session.member_id}:count() | 
| poelzi@159 | 33   if supporter then | 
| poelzi@159 | 34     ui.container{ | 
| poelzi@159 | 35       attr = { class = "draft_updated_info" }, | 
| poelzi@159 | 36       content = function() | 
| poelzi@159 | 37         slot.put(_"The draft of this initiative has been updated!") | 
| poelzi@159 | 38         slot.put(" ") | 
| poelzi@159 | 39         ui.link{ | 
| poelzi@159 | 40           text   = _"Refresh support to current draft", | 
| poelzi@159 | 41           module = "initiative", | 
| poelzi@159 | 42           action = "add_support", | 
| poelzi@159 | 43           id     = new_draft.initiative.id, | 
| poelzi@159 | 44           routing = { | 
| poelzi@159 | 45             default = { | 
| poelzi@159 | 46               mode = "redirect", | 
| poelzi@159 | 47               module = "initiative", | 
| poelzi@159 | 48               view = "show", | 
| poelzi@159 | 49               id = new_draft.initiative.id | 
| poelzi@159 | 50             } | 
| poelzi@159 | 51           } | 
| poelzi@159 | 52         } | 
| poelzi@159 | 53       end | 
| poelzi@159 | 54     } | 
| poelzi@159 | 55   end | 
| poelzi@159 | 56 end | 
| poelzi@159 | 57 | 
| bsw@95 | 58 local old_draft_content = string.gsub(string.gsub(old_draft.content, "\n", " ###ENTER###\n"), " ", "\n") | 
| bsw@95 | 59 local new_draft_content = string.gsub(string.gsub(new_draft.content, "\n", " ###ENTER###\n"), " ", "\n") | 
| bsw@95 | 60 | 
| bsw@2 | 61 local key = multirand.string(26, "123456789bcdfghjklmnpqrstvwxyz"); | 
| bsw@2 | 62 | 
| bsw@2 | 63 local old_draft_filename = encode.file_path(request.get_app_basepath(), 'tmp', "diff-" .. key .. "-old.tmp") | 
| bsw@2 | 64 local new_draft_filename = encode.file_path(request.get_app_basepath(), 'tmp', "diff-" .. key .. "-new.tmp") | 
| bsw@2 | 65 | 
| bsw@2 | 66 local old_draft_file = assert(io.open(old_draft_filename, "w")) | 
| bsw@95 | 67 old_draft_file:write(old_draft_content) | 
| bsw@2 | 68 old_draft_file:write("\n") | 
| bsw@2 | 69 old_draft_file:close() | 
| bsw@2 | 70 | 
| bsw@2 | 71 local new_draft_file = assert(io.open(new_draft_filename, "w")) | 
| bsw@95 | 72 new_draft_file:write(new_draft_content) | 
| bsw@2 | 73 new_draft_file:write("\n") | 
| bsw@2 | 74 new_draft_file:close() | 
| bsw@2 | 75 | 
| bsw@728 | 76 local output, err, status = extos.pfilter(nil, "sh", "-c", "diff -U 1000000000 '" .. old_draft_filename .. "' '" .. new_draft_filename .. "' | grep -v ^--- | grep -v ^+++ | grep -v ^@") | 
| bsw@2 | 77 | 
| bsw@2 | 78 os.remove(old_draft_filename) | 
| bsw@2 | 79 os.remove(new_draft_filename) | 
| bsw@2 | 80 | 
| bsw@95 | 81 local last_state = "first_run" | 
| bsw@95 | 82 | 
| bsw@95 | 83 local function process_line(line) | 
| bsw@95 | 84   local state_char = string.sub(line, 1, 1) | 
| bsw@95 | 85   local state | 
| bsw@95 | 86   if state_char == "+" then | 
| bsw@95 | 87     state = "added" | 
| bsw@95 | 88   elseif state_char == "-" then | 
| bsw@95 | 89     state = "removed" | 
| bsw@95 | 90   elseif state_char == " " then | 
| bsw@95 | 91     state = "unchanged" | 
| bsw@95 | 92   end | 
| bsw@95 | 93   local state_changed = false | 
| bsw@95 | 94   if state ~= last_state then | 
| bsw@95 | 95     if last_state ~= "first_run" then | 
| bsw@95 | 96       slot.put("</span> ") | 
| bsw@95 | 97     end | 
| bsw@95 | 98     last_state = state | 
| bsw@95 | 99     state_changed = true | 
| bsw@95 | 100     slot.put("<span class=\"diff_" .. tostring(state) .. "\">") | 
| bsw@95 | 101   end | 
| bsw@95 | 102 | 
| bsw@95 | 103   line = string.sub(line, 2, #line) | 
| bsw@95 | 104   if line ~= "###ENTER###" then | 
| bsw@95 | 105     if not state_changed then | 
| bsw@95 | 106       slot.put(" ") | 
| bsw@95 | 107     end | 
| bsw@95 | 108     slot.put(line) | 
| bsw@95 | 109   else | 
| bsw@95 | 110     slot.put("<br />") | 
| bsw@95 | 111   end | 
| bsw@95 | 112 end | 
| bsw@95 | 113 | 
| bsw@2 | 114 if not status then | 
| bsw@2 | 115   ui.field.text{ value = _"The drafts do not differ" } | 
| bsw@2 | 116 else | 
| bsw@95 | 117   ui.container{ | 
| bsw@95 | 118     tag = "div", | 
| bsw@95 | 119     attr = { class = "diff" }, | 
| bsw@95 | 120     content = function() | 
| bsw@95 | 121       output = output:gsub("[^\n\r]+", function(line) | 
| bsw@95 | 122         process_line(line) | 
| bsw@95 | 123       end) | 
| bsw@2 | 124     end | 
| bsw@95 | 125   } | 
| bsw@2 | 126 end | 
| bsw@2 | 127 |