bsw@2: local old_draft_id = param.get("old_draft_id", atom.integer) bsw@2: local new_draft_id = param.get("new_draft_id", atom.integer) bsw@1045: local initiative_id = param.get("initiative_id", atom.number) bsw@2: bsw@1045: if not old_draft_id bsw@1045: or not new_draft_id bsw@1045: or old_draft_id == new_draft_id bsw@1045: then bsw@1045: slot.reset_all() bsw@1045: slot.select("error", function() bsw@1045: ui.tag{ content = _"Please choose two different versions of the draft to compare" } bsw@1045: end ) bsw@1045: request.redirect{ bsw@1489: module = "initiative", view = "history", id = initiative_id bsw@1045: } bsw@10: return bsw@10: end bsw@10: bsw@2: if old_draft_id > new_draft_id then jbe@1226: old_draft_id, new_draft_id = new_draft_id, old_draft_id bsw@2: end bsw@2: bsw@2: local old_draft = Draft:by_id(old_draft_id) bsw@2: local new_draft = Draft:by_id(new_draft_id) bsw@2: bsw@1045: local initiative = new_draft.initiative bsw@1045: bsw@1045: if app.session.member then bsw@1045: initiative:load_everything_for_member_id(app.session.member_id) bsw@1045: initiative.issue:load_everything_for_member_id(app.session.member_id) bsw@1045: end bsw@1045: bsw@1045: bsw/jbe@1309: local old_draft_content = string.gsub(string.gsub(util.html_to_text(old_draft.content), "\n", " ###ENTER###\n"), " ", "\n") bsw/jbe@1309: local new_draft_content = string.gsub(string.gsub(util.html_to_text(new_draft.content), "\n", " ###ENTER###\n"), " ", "\n") bsw@95: jbe@1226: local key = multirand.string(24, "0123456789abcdefghijklmnopqrstuvwxyz") bsw@2: bsw@1230: local old_draft_filename = encode.file_path(WEBMCP_BASE_PATH, 'tmp', "diff-" .. key .. "-old.tmp") bsw@1230: local new_draft_filename = encode.file_path(WEBMCP_BASE_PATH, 'tmp', "diff-" .. key .. "-new.tmp") bsw@2: bsw@2: local old_draft_file = assert(io.open(old_draft_filename, "w")) bsw@95: old_draft_file:write(old_draft_content) bsw@2: old_draft_file:write("\n") bsw@2: old_draft_file:close() bsw@2: bsw@2: local new_draft_file = assert(io.open(new_draft_filename, "w")) bsw@95: new_draft_file:write(new_draft_content) bsw@2: new_draft_file:write("\n") bsw@2: new_draft_file:close() bsw@2: bsw/jbe@1309: local output, err, status = extos.pfilter(nil, "sh", "-c", "diff -a -U 1000000000 '" .. old_draft_filename .. "' '" .. new_draft_filename .. "' | grep --binary-files=text -v ^--- | grep --binary-files=text -v ^+++ | grep --binary-files=text -v ^@") bsw@2: bsw@2: os.remove(old_draft_filename) bsw@2: os.remove(new_draft_filename) bsw@2: bsw@95: local last_state = "first_run" bsw@95: bsw@95: local function process_line(line) bsw@95: local state_char = string.sub(line, 1, 1) bsw@95: local state bsw@95: if state_char == "+" then bsw@95: state = "added" bsw@95: elseif state_char == "-" then bsw@95: state = "removed" bsw@95: elseif state_char == " " then bsw@95: state = "unchanged" bsw@95: end bsw@95: local state_changed = false bsw@95: if state ~= last_state then bsw@95: if last_state ~= "first_run" then bsw@95: slot.put(" ") bsw@95: end bsw@95: last_state = state bsw@95: state_changed = true bsw@95: slot.put("") bsw@95: end bsw@95: bsw@95: line = string.sub(line, 2, #line) bsw@95: if line ~= "###ENTER###" then bsw@95: if not state_changed then bsw@95: slot.put(" ") bsw@95: end bsw/jbe@1309: --slot.put(encode.html(line)) bsw/jbe@1309: slot.put(line) bsw@95: else bsw@95: slot.put("
") bsw@95: end bsw@95: end bsw@95: bsw/jbe@1309: execute.view{ module = "issue", view = "_head", params = { issue = initiative.issue } } bsw/jbe@1309: bsw/jbe@1309: ui.grid{ content = function() bsw/jbe@1309: ui.cell_main{ content = function() bsw/jbe@1309: ui.container{ attr = { class = "mdl-card mdl-card__fullwidth mdl-shadow--2dp" }, content = function() bsw/jbe@1309: bsw/jbe@1309: ui.container{ attr = { class = "mdl-card__title mdl-card--border" }, content = function () bsw@1045: ui.heading { bsw/jbe@1309: attr = { class = "mdl-card__title-text" }, bsw/jbe@1309: content = function() bsw/jbe@1309: ui.link{ bsw/jbe@1309: module = "initiative", view = "show", id = initiative.id, bsw/jbe@1309: content = initiative.display_name bsw/jbe@1309: } bsw/jbe@1309: end bsw@1045: } bsw/jbe@1309: ui.container{ content = _("Comparision of revisions #{id1} and #{id2}", { bsw/jbe@1309: id1 = old_draft.id, bsw/jbe@1309: id2 = new_draft.id bsw/jbe@1309: } ) } bsw/jbe@1309: end } bsw/jbe@1309: bsw/jbe@1309: if app.session.member_id and not new_draft.initiative.revoked then bsw/jbe@1309: local supporter = app.session.member:get_reference_selector("supporters") bsw/jbe@1309: :add_where{ "initiative_id = ?", new_draft.initiative_id } bsw/jbe@1309: :optional_object_mode() bsw/jbe@1309: :exec() bsw/jbe@1309: if supporter and supporter.draft_id == old_draft.id and new_draft.id == initiative.current_draft.id then bsw/jbe@1309: ui.container { bsw/jbe@1309: attr = { class = "mdl-card__content mdl-card--no-bottom-pad mdl-card--notice" }, bsw/jbe@1309: content = _"The draft of this initiative has been updated!" bsw@1045: } bsw/jbe@1309: ui.container { bsw/jbe@1309: attr = { class = "mdl-card__actions mdl-card--action-border mdl-card--notice" }, bsw/jbe@1309: content = function () bsw/jbe@1309: ui.link{ bsw/jbe@1309: attr = { class = "mdl-button mdl-js-button mdl-button--raised" }, bsw/jbe@1309: text = _"refresh my support", bsw/jbe@1309: module = "initiative", bsw/jbe@1309: action = "add_support", bsw/jbe@1309: id = new_draft.initiative.id, bsw/jbe@1309: params = { draft_id = new_draft.id }, bsw/jbe@1309: routing = { bsw/jbe@1309: default = { bsw/jbe@1309: mode = "redirect", bsw/jbe@1309: module = "initiative", bsw/jbe@1309: view = "show", bsw/jbe@1309: id = new_draft.initiative.id bsw/jbe@1309: } bsw/jbe@1309: } bsw/jbe@1309: } bsw@1045: bsw/jbe@1309: slot.put("   ") bsw/jbe@1309: bsw/jbe@1309: ui.link{ bsw/jbe@1309: attr = { class = "mdl-button mdl-js-button mdl-button--raised" }, bsw/jbe@1309: text = _"remove my support", bsw/jbe@1309: module = "initiative", bsw/jbe@1309: action = "remove_support", bsw/jbe@1309: id = new_draft.initiative.id, bsw/jbe@1309: routing = { bsw/jbe@1309: default = { bsw/jbe@1309: mode = "redirect", bsw/jbe@1309: module = "initiative", bsw/jbe@1309: view = "show", bsw/jbe@1309: id = new_draft.initiative.id bsw/jbe@1309: } bsw/jbe@1309: } bsw/jbe@1309: } bsw/jbe@1309: bsw/jbe@1309: slot.put("   ") bsw/jbe@1309: bsw/jbe@1309: ui.link{ bsw/jbe@1309: attr = { class = "mdl-button mdl-js-button" }, bsw/jbe@1309: text = _"cancel", bsw/jbe@1309: module = "initiative", bsw/jbe@1309: view = "show", bsw/jbe@1309: id = new_draft.initiative.id, bsw/jbe@1309: } bsw/jbe@1309: end bsw@1045: } bsw/jbe@1309: end bsw/jbe@1309: end bsw@2: bsw/jbe@1309: ui.container { bsw/jbe@1309: attr = { class = "draft mdl-card__content mdl-card--border" }, bsw/jbe@1309: content = function () bsw/jbe@1309: if not status then bsw/jbe@1309: ui.field.text{ value = _"The drafts do not differ" } bsw/jbe@1309: else bsw/jbe@1309: ui.container{ bsw/jbe@1309: tag = "div", bsw/jbe@1309: attr = { class = "diff" }, bsw/jbe@1309: content = function() bsw/jbe@1309: output = output:gsub("[^\n\r]+", function(line) bsw/jbe@1309: process_line(line) bsw/jbe@1309: end) bsw/jbe@1309: end bsw/jbe@1309: } bsw/jbe@1309: end bsw@1045: end bsw@1045: } bsw@1496: bsw@1496: local old_files = File:new_selector() bsw@1496: :left_join("draft_attachment", nil, "draft_attachment.file_id = file.id") bsw@1496: :add_where{ "draft_attachment.draft_id = ?", old_draft.id } bsw@1496: :reset_fields() bsw@1496: :add_field("file.id") bsw@1496: :add_field("draft_attachment.title") bsw@1496: :add_field("draft_attachment.description") bsw@1496: :add_order_by("draft_attachment.id") bsw@1496: :exec() bsw@1496: bsw@1496: local new_files = File:new_selector() bsw@1496: :left_join("draft_attachment", nil, "draft_attachment.file_id = file.id") bsw@1496: :add_where{ "draft_attachment.draft_id = ?", new_draft.id } bsw@1496: :reset_fields() bsw@1496: :add_field("file.id") bsw@1496: :add_field("draft_attachment.title") bsw@1496: :add_field("draft_attachment.description") bsw@1496: :add_order_by("draft_attachment.id") bsw@1496: :exec() bsw@1496: bsw@1496: local added_files = {} bsw@1496: for i, new_file in ipairs(new_files) do bsw@1496: local added = true bsw@1496: for j, old_file in ipairs(old_files) do bsw@1496: if bsw@1496: old_file.file_id == new_file.file_id bsw@1496: and old_file.title == new_file.title bsw@1496: and old_file.description == new_file.description bsw@1496: then bsw@1496: added = false bsw@1496: end bsw@1496: end bsw@1496: if added then bsw@1496: table.insert(added_files, new_file) bsw@1496: end bsw@1496: end bsw@1496: bsw@1496: if #added_files > 0 then bsw@1496: ui.container { bsw@1496: attr = { class = "mdl-card__content mdl-card--border" }, bsw@1496: content = function() bsw@1496: ui.container{ content = _"Added attachments" } bsw@1496: for i, file in ipairs(added_files) do bsw@1496: ui.image{ module = "file", view = "show.jpg", id = file.id, params = { preview = true } } bsw@1496: ui.container{ content = file.title or "" } bsw@1496: ui.container{ content = file.description or "" } bsw@1496: slot.put("

") bsw@1496: end bsw@1496: end bsw@1496: } bsw@1496: end bsw@1496: bsw@1496: local removed_files = {} bsw@1496: for i, old_file in ipairs(old_files) do bsw@1496: local removed = true bsw@1496: for j, new_file in ipairs(new_files) do bsw@1496: if bsw@1496: old_file.file_id == new_file.file_id bsw@1496: and old_file.title == new_file.title bsw@1496: and old_file.description == new_file.description bsw@1496: then bsw@1496: removed = false bsw@1496: end bsw@1496: end bsw@1496: if removed then bsw@1496: table.insert(removed_files, old_file) bsw@1496: end bsw@1496: end bsw@1496: bsw@1496: bsw@1496: if #removed_files > 0 then bsw@1496: ui.container { bsw@1496: attr = { class = "mdl-card__content mdl-card--border" }, bsw@1496: content = function() bsw@1496: ui.container{ content = _"Removed attachments" } bsw@1496: for i, file in ipairs(removed_files) do bsw@1496: ui.image{ module = "file", view = "show.jpg", id = file.id, params = { preview = true } } bsw@1496: ui.container{ content = file.title or "" } bsw@1496: ui.container{ content = file.description or "" } bsw@1496: slot.put("

") bsw@1496: end bsw@1496: end bsw@1496: } bsw@1496: end bsw@1496: bsw@1496: ui.container { bsw@1496: attr = { class = "draft mdl-card__content mdl-card--border" }, bsw@1496: content = function () bsw@1496: end bsw@1496: } bsw@1496: bsw/jbe@1309: end } bsw/jbe@1309: end } bsw/jbe@1309: ui.cell_sidebar{ content = function() bsw/jbe@1309: bsw/jbe@1309: execute.view{ module = "issue", view = "_sidebar", params = { bsw/jbe@1309: initiative = initiative, bsw/jbe@1309: issue = initiative.issue bsw/jbe@1309: } } bsw@1045: bsw/jbe@1309: execute.view { bsw/jbe@1309: module = "issue", view = "_sidebar_whatcanido", bsw/jbe@1309: params = { initiative = initiative } bsw/jbe@1309: } bsw/jbe@1309: bsw/jbe@1309: execute.view { bsw/jbe@1309: module = "issue", view = "_sidebar_members", params = { bsw/jbe@1309: issue = initiative.issue, initiative = initiative bsw/jbe@1309: } bsw/jbe@1309: } bsw/jbe@1309: end } bsw/jbe@1309: end }