# HG changeset patch
# User bsw
# Date 1581431076 -3600
# Node ID ed3c40911ae1bc6f41c628d1afa4eb823e19b375
# Parent 17e7082c377a6db8798087b037eec588c1cd42c0
Completed image attachments feature
diff -r 17e7082c377a -r ed3c40911ae1 app/main/draft/_action/add.lua
--- a/app/main/draft/_action/add.lua Mon Feb 10 21:10:49 2020 +0100
+++ b/app/main/draft/_action/add.lua Tue Feb 11 15:24:36 2020 +0100
@@ -1,24 +1,270 @@
-local draft_text = param.get("content")
+local initiative
+local new_initiative
+local draft_id
+local status
+
+if param.get("initiative_id", atom.integer) then
+
+ local function donew()
+ local draft_text = param.get("content")
+
+ if not draft_text then
+ return false
+ end
+
+ local draft_text = util.wysihtml_preproc(draft_text)
+
+ local valid_html, error_message = util.html_is_safe(draft_text)
+ if not valid_html then
+ slot.put_into("error", _("Draft contains invalid formatting or character sequence: #{error_message}", { error_message = error_message }) )
+ return false
+ end
+
+ if config.initiative_abstract then
+ local abstract = param.get("abstract")
+ if not abstract then
+ return false
+ end
+ abstract = encode.html(abstract)
+ draft_text = abstract .. "" .. draft_text
+ end
+
+ draft_id = Draft:update_content(
+ app.session.member.id,
+ param.get("initiative_id", atom.integer),
+ param.get("formatting_engine"),
+ draft_text,
+ nil,
+ param.get("preview") or param.get("edit")
+ )
+ return draft_id and true or false
+ end
+
+ status = donew()
+
+else
+
+ local function donew()
+ local issue
+ local area
-if not draft_text then
- return false
-end
+ local issue_id = param.get("issue_id", atom.integer)
+ if issue_id then
+ issue = Issue:new_selector():add_where{"id=?",issue_id}:for_share():single_object_mode():exec()
+ if issue.closed then
+ slot.put_into("error", _"This issue is already closed.")
+ return false
+ elseif issue.fully_frozen then
+ slot.put_into("error", _"Voting for this issue has already begun.")
+ return false
+ elseif issue.phase_finished then
+ slot.put_into("error", _"Current phase is already closed.")
+ return false
+ end
+ area = issue.area
+ else
+ local area_id = param.get("area_id", atom.integer)
+ area = Area:new_selector():add_where{"id=?",area_id}:single_object_mode():exec()
+ if not area.active then
+ slot.put_into("error", "Invalid area.")
+ return false
+ end
+ end
+
+ if not app.session.member:has_voting_right_for_unit_id(area.unit_id) then
+ return execute.view { module = "index", view = "403" }
+ end
+
+ local policy_id = param.get("policy_id", atom.integer)
+ local policy
+ if policy_id then
+ policy = Policy:by_id(policy_id)
+ end
-local draft_text = util.wysihtml_preproc(draft_text)
+ if not issue then
+ if policy_id == -1 then
+ slot.put_into("error", _"Please choose a policy")
+ return false
+ end
+ if not policy.active then
+ slot.put_into("error", "Invalid policy.")
+ return false
+ end
+ if policy.polling and not app.session.member:has_polling_right_for_unit_id(area.unit_id) then
+ return execute.view { module = "index", view = "403" }
+ end
+ if not area:get_reference_selector("allowed_policies")
+ :add_where{ "policy.id = ?", policy_id }
+ :optional_object_mode()
+ :exec()
+ then
+ slot.put_into("error", "policy not allowed")
+ return false
+ end
+ end
+
+ local is_polling = (issue and param.get("polling", atom.boolean)) or (policy and policy.polling) or false
+
+ local tmp = db:query({ "SELECT text_entries_left, initiatives_left FROM member_contingent_left WHERE member_id = ? AND polling = ?", app.session.member.id, is_polling }, "opt_object")
+ if not tmp or tmp.initiatives_left < 1 then
+ slot.put_into("error", _"Sorry, your contingent for creating initiatives has been used up. Please try again later.")
+ return false
+ end
+ if tmp and tmp.text_entries_left < 1 then
+ slot.put_into("error", _"Sorry, you have reached your personal flood limit. Please be slower...")
+ return false
+ end
+
+ local name = param.get("name")
+
+ local name = util.trim(name)
+
+ if #name < 3 then
+ slot.put_into("error", _"Please enter a meaningful title for your initiative!")
+ return false
+ end
+
+ if #name > 140 then
+ slot.put_into("error", _"This title is too long!")
+ return false
+ end
-local valid_html, error_message = util.html_is_safe(draft_text)
-if not valid_html then
- slot.put_into("error", _("Draft contains invalid formatting or character sequence: #{error_message}", { error_message = error_message }) )
- return false
-end
+ local timing
+ if not issue and policy.free_timeable then
+ local free_timing_string = util.trim(param.get("free_timing"))
+ if not free_timing_string or #free_timing_string < 1 then
+ slot.put_into("error", _"Choose timing")
+ return false
+ end
+ local available_timings
+ if config.free_timing and config.free_timing.available_func then
+ available_timings = config.free_timing.available_func(policy)
+ if available_timings == false then
+ slot.put_into("error", "error in free timing config")
+ return false
+ end
+ end
+ if available_timings then
+ local timing_available = false
+ for i, available_timing in ipairs(available_timings) do
+ if available_timing.id == free_timing_string then
+ timing_available = true
+ end
+ end
+ if not timing_available then
+ slot.put_into("error", _"Invalid timing")
+ return false
+ end
+ end
+ timing = config.free_timing.calculate_func(policy, free_timing_string)
+ if not timing then
+ slot.put_into("error", "error in free timing config")
+ return false
+ end
+ end
+
+ local draft_text = param.get("content")
+
+ if not draft_text then
+ slot.put_into("error", "no draft text")
+ return false
+ end
+
+ local draft_text = util.wysihtml_preproc(draft_text)
+
+ local valid_html, error_message = util.html_is_safe(draft_text)
+ if not valid_html then
+ slot.put_into("error", _("Draft contains invalid formatting or character sequence: #{error_message}", { error_message = error_message }) )
+ return false
+ end
+
+ if config.initiative_abstract then
+ local abstract = param.get("abstract")
+ if not abstract then
+ slot.put_into("error", "no abstract")
+ return false
+ end
+ abstract = encode.html(abstract)
+ draft_text = abstract .. "" .. draft_text
+ end
+
+ local location = param.get("location")
+ if location == "" then
+ location = nil
+ end
+
+ if param.get("preview") or param.get("edit") then
+ return false
+ end
-if config.initiative_abstract then
- local abstract = param.get("abstract")
- if not abstract then
- return false
+ initiative = Initiative:new()
+
+ if not issue then
+ issue = Issue:new()
+ issue.area_id = area.id
+ issue.policy_id = policy_id
+
+ if policy.polling then
+ issue.accepted = 'now'
+ issue.state = 'discussion'
+ initiative.polling = true
+
+ if policy.free_timeable then
+ issue.discussion_time = timing.discussion
+ issue.verification_time = timing.verification
+ issue.voting_time = timing.voting
+ end
+
+ end
+
+ issue:save()
+
+ if config.etherpad then
+ local result = net.curl(
+ config.etherpad.api_base
+ .. "api/1/createGroupPad?apikey=" .. config.etherpad.api_key
+ .. "&groupID=" .. config.etherpad.group_id
+ .. "&padName=Issue" .. tostring(issue.id)
+ .. "&text=" .. request.get_absolute_baseurl() .. "issue/show/" .. tostring(issue.id) .. ".html"
+ )
+ end
+ end
+
+ if param.get("polling", atom.boolean) and app.session.member:has_polling_right_for_unit_id(area.unit_id) then
+ initiative.polling = true
+ end
+ initiative.issue_id = issue.id
+ initiative.name = name
+ initiative:save()
+
+ new_initiative = initiative
+
+ local draft = Draft:new()
+ draft.initiative_id = initiative.id
+ draft.formatting_engine = formatting_engine
+ draft.content = draft_text
+ draft.location = location
+ draft.author_id = app.session.member.id
+ draft:save()
+
+ draft_id = draft.id
+
+ local initiator = Initiator:new()
+ initiator.initiative_id = initiative.id
+ initiator.member_id = app.session.member.id
+ initiator.accepted = true
+ initiator:save()
+
+ if not is_polling then
+ local supporter = Supporter:new()
+ supporter.initiative_id = initiative.id
+ supporter.member_id = app.session.member.id
+ supporter.draft_id = draft.id
+ supporter:save()
+ end
+
end
- abstract = encode.html(abstract)
- draft_text = abstract .. "" .. draft_text
+ status = donew()
end
if config.attachments then
@@ -80,76 +326,78 @@
fh:write(json.export(file_uploads))
fh:write("\n")
fh:close()
-end
+
+ if draft_id then
+ local file_upload_session = param.get("file_upload_session")
+ file_upload_session = string.gsub(file_upload_session, "[^A-Za-z0-9]", "")
-local draft_id = Draft:update_content(
- app.session.member.id,
- param.get("initiative_id", atom.integer),
- param.get("formatting_engine"),
- draft_text,
- nil,
- param.get("preview") or param.get("edit")
-)
+ local draft_attachments = DraftAttachment:new_selector()
+ :add_where{ "draft_attachment.draft_id = ?", draft_id }
+ :exec()
+
+ for i, draft_attachment in ipairs(draft_attachments) do
+ if param.get("file_delete_" .. draft_attachment.file_id, atom.boolean) then
+ draft_attachment:destroy()
+ end
+ end
-if draft_id and config.attachments then
- local file_upload_session = param.get("file_upload_session")
- file_upload_session = string.gsub(file_upload_session, "[^A-Za-z0-9]", "")
+ local file_uploads = json.array()
+ local filename = encode.file_path(WEBMCP_BASE_PATH, 'tmp', "file_upload-" .. file_upload_session .. ".json")
+ local fh = io.open(filename, "r")
+ if fh then
+ file_uploads = json.import(fh:read("*a"))
+ end
+ for i, file_upload in ipairs(file_uploads) do
+ local filename = encode.file_path(WEBMCP_BASE_PATH, 'tmp', "file_upload-" .. file_upload_session .. "-" .. file_upload.id .. ".jpg")
+ local data
+ local fh = io.open(filename, "r")
+ if fh then
+ data = fh:read("*a")
+ end
+ local filename = encode.file_path(WEBMCP_BASE_PATH, 'tmp', "file_upload-" .. file_upload_session .. "-" .. file_upload.id .. ".preview.jpg")
+ local data_preview
+ local fh = io.open(filename, "r")
+ if fh then
+ data_preview = fh:read("*a")
+ end
+
+ local hash = moonhash.sha3_512(data)
- local draft_attachments = DraftAttachment:new_selector()
- :add_where{ "draft_attachment.draft_id = ?", draft_id }
- :exec()
+ local file = File:new_selector()
+ :add_where{ "hash = ?", hash }
+ :add_where{ "content_type = ?", "image/jpeg" }
+ :optional_object_mode()
+ :exec()
- for i, draft_attachment in ipairs(draft_attachments) do
- if param.get("file_delete_" .. draft_attachment.file_id, atom.boolean) then
- draft_attachment:destroy()
+ if not file then
+ file = File:new()
+ file.content_type = "image/jpeg"
+ file.hash = hash
+ file.data = data
+ file.preview_content_type = "image/jpeg"
+ file.preview_data = data_preview
+ file:save()
+ end
+
+ local draft_attachment = DraftAttachment:new()
+ draft_attachment.draft_id = draft_id
+ draft_attachment.file_id = file.id
+ draft_attachment.title = file_upload.title
+ draft_attachment.description = file_upload.description
+ draft_attachment:save()
end
end
- local file_uploads = json.array()
- local filename = encode.file_path(WEBMCP_BASE_PATH, 'tmp', "file_upload-" .. file_upload_session .. ".json")
- local fh = io.open(filename, "r")
- if fh then
- file_uploads = json.import(fh:read("*a"))
- end
- for i, file_upload in ipairs(file_uploads) do
- local filename = encode.file_path(WEBMCP_BASE_PATH, 'tmp', "file_upload-" .. file_upload_session .. "-" .. file_upload.id .. ".jpg")
- local data
- local fh = io.open(filename, "r")
- if fh then
- data = fh:read("*a")
- end
- local filename = encode.file_path(WEBMCP_BASE_PATH, 'tmp', "file_upload-" .. file_upload_session .. "-" .. file_upload.id .. ".preview.jpg")
- local data_preview
- local fh = io.open(filename, "r")
- if fh then
- data_preview = fh:read("*a")
- end
-
- local hash = moonhash.sha3_512(data)
-
- local file = File:new_selector()
- :add_where{ "hash = ?", hash }
- :add_where{ "content_type = ?", "image/jpeg" }
- :optional_object_mode()
- :exec()
-
- if not file then
- file = File:new()
- file.content_type = "image/jpeg"
- file.hash = hash
- file.data = data
- file.preview_content_type = "image/jpeg"
- file.preview_data = data_preview
- file:save()
- end
-
- local draft_attachment = DraftAttachment:new()
- draft_attachment.draft_id = draft_id
- draft_attachment.file_id = file.id
- draft_attachment.title = file_upload.title
- draft_attachment.description = file_upload.description
- draft_attachment:save()
- end
end
-return draft_id and true or false
+print(new_initiative, status)
+if new_initiative and status ~= false then
+ request.redirect{
+ module = "initiative",
+ view = "show",
+ id = new_initiative.id
+ }
+end
+
+return status
+
diff -r 17e7082c377a -r ed3c40911ae1 app/main/draft/diff.lua
--- a/app/main/draft/diff.lua Mon Feb 10 21:10:49 2020 +0100
+++ b/app/main/draft/diff.lua Tue Feb 11 15:24:36 2020 +0100
@@ -190,6 +190,98 @@
end
end
}
+
+ local old_files = File:new_selector()
+ :left_join("draft_attachment", nil, "draft_attachment.file_id = file.id")
+ :add_where{ "draft_attachment.draft_id = ?", old_draft.id }
+ :reset_fields()
+ :add_field("file.id")
+ :add_field("draft_attachment.title")
+ :add_field("draft_attachment.description")
+ :add_order_by("draft_attachment.id")
+ :exec()
+
+ local new_files = File:new_selector()
+ :left_join("draft_attachment", nil, "draft_attachment.file_id = file.id")
+ :add_where{ "draft_attachment.draft_id = ?", new_draft.id }
+ :reset_fields()
+ :add_field("file.id")
+ :add_field("draft_attachment.title")
+ :add_field("draft_attachment.description")
+ :add_order_by("draft_attachment.id")
+ :exec()
+
+ local added_files = {}
+ for i, new_file in ipairs(new_files) do
+ local added = true
+ for j, old_file in ipairs(old_files) do
+ if
+ old_file.file_id == new_file.file_id
+ and old_file.title == new_file.title
+ and old_file.description == new_file.description
+ then
+ added = false
+ end
+ end
+ if added then
+ table.insert(added_files, new_file)
+ end
+ end
+
+ if #added_files > 0 then
+ ui.container {
+ attr = { class = "mdl-card__content mdl-card--border" },
+ content = function()
+ ui.container{ content = _"Added attachments" }
+ for i, file in ipairs(added_files) do
+ ui.image{ module = "file", view = "show.jpg", id = file.id, params = { preview = true } }
+ ui.container{ content = file.title or "" }
+ ui.container{ content = file.description or "" }
+ slot.put("
")
+ end
+ end
+ }
+ end
+
+ local removed_files = {}
+ for i, old_file in ipairs(old_files) do
+ local removed = true
+ for j, new_file in ipairs(new_files) do
+ if
+ old_file.file_id == new_file.file_id
+ and old_file.title == new_file.title
+ and old_file.description == new_file.description
+ then
+ removed = false
+ end
+ end
+ if removed then
+ table.insert(removed_files, old_file)
+ end
+ end
+
+
+ if #removed_files > 0 then
+ ui.container {
+ attr = { class = "mdl-card__content mdl-card--border" },
+ content = function()
+ ui.container{ content = _"Removed attachments" }
+ for i, file in ipairs(removed_files) do
+ ui.image{ module = "file", view = "show.jpg", id = file.id, params = { preview = true } }
+ ui.container{ content = file.title or "" }
+ ui.container{ content = file.description or "" }
+ slot.put("
")
+ end
+ end
+ }
+ end
+
+ ui.container {
+ attr = { class = "draft mdl-card__content mdl-card--border" },
+ content = function ()
+ end
+ }
+
end }
end }
ui.cell_sidebar{ content = function()
diff -r 17e7082c377a -r ed3c40911ae1 app/main/draft/new.lua
--- a/app/main/draft/new.lua Mon Feb 10 21:10:49 2020 +0100
+++ b/app/main/draft/new.lua Tue Feb 11 15:24:36 2020 +0100
@@ -1,24 +1,68 @@
-local initiative = Initiative:by_id(param.get("initiative_id"))
-initiative:load_everything_for_member_id(app.session.member_id)
-initiative.issue:load_everything_for_member_id(app.session.member_id)
+local issue
+local area
+local area_id
-if initiative.issue.closed then
- slot.put_into("error", _"This issue is already closed.")
- return
-elseif initiative.issue.half_frozen then
- slot.put_into("error", _"This issue is already frozen.")
- return
-elseif initiative.issue.phase_finished then
- slot.put_into("error", _"Current phase is already closed.")
- return
+local issue_id = param.get("issue_id", atom.integer)
+if issue_id then
+ issue = Issue:new_selector():add_where{"id=?",issue_id}:single_object_mode():exec()
+ issue:load_everything_for_member_id(app.session.member_id)
+ area = issue.area
+else
+ area_id = param.get("area_id", atom.integer)
+ if area_id then
+ area = Area:new_selector():add_where{"id=?",area_id}:single_object_mode():exec()
+ area:load_delegation_info_once_for_member_id(app.session.member_id)
+ end
+end
+
+local polling = param.get("polling", atom.boolean)
+
+local policy_id = param.get("policy_id", atom.integer)
+local policy
+
+local preview = param.get("preview")
+
+if #(slot.get_content("error")) > 0 then
+ preview = false
+end
+
+if policy_id then
+ policy = Policy:by_id(policy_id)
end
-local draft = initiative.current_draft
-if config.initiative_abstract then
- draft.abstract = string.match(draft.content, "(.+)")
- if draft.abstract then
- draft.content = string.match(draft.content, "(.*)")
+
+
+
+local initiative_id = param.get("initiative_id")
+local initiative = Initiative:by_id(initiative_id)
+local draft
+if initiative then
+ initiative:load_everything_for_member_id(app.session.member_id)
+ initiative.issue:load_everything_for_member_id(app.session.member_id)
+
+ if initiative.issue.closed then
+ slot.put_into("error", _"This issue is already closed.")
+ return
+ elseif initiative.issue.half_frozen then
+ slot.put_into("error", _"This issue is already frozen.")
+ return
+ elseif initiative.issue.phase_finished then
+ slot.put_into("error", _"Current phase is already closed.")
+ return
end
+
+ draft = initiative.current_draft
+ if config.initiative_abstract then
+ draft.abstract = string.match(draft.content, "(.+)")
+ if draft.abstract then
+ draft.content = string.match(draft.content, "(.*)")
+ end
+ end
+end
+
+if not initiative and not issue and not area then
+ ui.heading{ content = _"Missing parameter" }
+ return false
end
ui.form{
@@ -26,13 +70,17 @@
attr = { class = "vertical section", enctype = 'multipart/form-data' },
module = "draft",
action = "add",
- params = { initiative_id = initiative.id },
+ params = {
+ area_id = area and area.id,
+ issue_id = issue and issue.id or nil,
+ initiative_id = initiative_id
+ },
routing = {
ok = {
mode = "redirect",
module = "initiative",
view = "show",
- id = initiative.id
+ id = initiative_id
}
},
content = function()
@@ -41,11 +89,30 @@
ui.cell_main{ content = function()
ui.container{ attr = { class = "mdl-card mdl-shadow--2dp mdl-card__fullwidth" }, content = function()
ui.container{ attr = { class = "mdl-card__title mdl-card--border" }, content = function()
- ui.heading { attr = { class = "mdl-card__title-text" }, level = 2, content = initiative.display_name }
+ if initiative then
+ ui.heading { attr = { class = "mdl-card__title-text" }, level = 2, content = initiative.display_name }
+ elseif param.get("name") then
+ ui.heading { attr = { class = "mdl-card__title-text" }, level = 2, content = param.get("name") }
+ elseif issue then
+ ui.heading { attr = { class = "mdl-card__title-text" }, level = 2, content = _("New competing initiative in issue '#{issue}'", { issue = issue.name }) }
+ elseif area then
+ ui.heading { attr = { class = "mdl-card__title-text" }, level = 2, content = _("New issue in area '#{area}'", { area = area.name }) }
+ end
end }
ui.container{ attr = { class = "mdl-card__content mdl-card--border" }, content = function()
+
+-- -------- PREVIEW
if param.get("preview") then
ui.sectionRow( function()
+ if not issue and not initiative then
+ ui.container { content = policy.name }
+ end
+ if param.get("free_timing") then
+ ui.container { content = param.get("free_timing") }
+ end
+ slot.put("
")
+ ui.field.hidden{ name = "policy_id", value = param.get("policy_id") }
+ ui.field.hidden{ name = "name", value = param.get("name") }
if config.initiative_abstract then
ui.field.hidden{ name = "abstract", value = param.get("abstract") }
ui.container{
@@ -72,31 +139,35 @@
)
file_upload_session = string.gsub(file_upload_session, "[^A-Za-z0-9]", "")
ui.field.hidden{ name = "file_upload_session", value = file_upload_session }
- local files = File:new_selector()
- :left_join("draft_attachment", nil, "draft_attachment.file_id = file.id")
- :add_where{ "draft_attachment.draft_id = ?", initiative.current_draft.id }
- :reset_fields()
- :add_field("file.id")
- :add_field("draft_attachment.title")
- :add_field("draft_attachment.description")
- :add_order_by("draft_attachment.id")
- :exec()
+ if initiative then
+ local files = File:new_selector()
+ :left_join("draft_attachment", nil, "draft_attachment.file_id = file.id")
+ :add_where{ "draft_attachment.draft_id = ?", initiative.current_draft.id }
+ :reset_fields()
+ :add_field("file.id")
+ :add_field("draft_attachment.title")
+ :add_field("draft_attachment.description")
+ :add_order_by("draft_attachment.id")
+ :exec()
- if #files > 0 then
- ui.container {
- content = function()
- for i, file in ipairs(files) do
- if param.get("file_delete_" .. file.id, atom.boolean) then
- ui.field.hidden{ name = "file_delete_" .. file.id, value = "1" }
- else
- ui.image{ module = "file", view = "show.jpg", id = file.id, params = { preview = true } }
- ui.container{ content = file.title or "" }
- ui.container{ content = file.description or "" }
- slot.put("
")
+ if #files > 0 then
+ ui.container {
+ content = function()
+ for i, file in ipairs(files) do
+ if param.get("file_delete_" .. file.id, atom.boolean) then
+ ui.field.hidden{ name = "file_delete_" .. file.id, value = "1" }
+ else
+ ui.image{ module = "file", view = "show.jpg", id = file.id, params = { preview = true } }
+ ui.container{ content = function()
+ ui.tag{ tag = "strong", content = file.title or "" }
+ end }
+ ui.container{ content = file.description or "" }
+ slot.put("
")
+ end
end
end
- end
- }
+ }
+ end
end
local filename = encode.file_path(WEBMCP_BASE_PATH, 'tmp', "file_upload-" .. file_upload_session .. ".json")
local fh = io.open(filename, "r")
@@ -106,7 +177,9 @@
ui.image{ module = "draft", view = "show_file_upload", params = {
file_upload_session = file_upload_session, file_id = file_upload.id, preview = true
} }
- ui.container{ content = file_upload.title or "" }
+ ui.container{ content = function()
+ ui.tag{ tag = "strong", content = file_upload.title or "" }
+ end }
ui.container{ content = file_upload.description or "" }
slot.put("
")
end
@@ -139,47 +212,108 @@
ui.link{
attr = { class = "mdl-button mdl-js-button mdl-button--raised mdl-js-ripple-effect" },
content = _"Cancel",
- module = "initiative",
+ module = initiative and "initiative" or "area",
view = "show",
- id = initiative.id
+ id = initiative_id or area_id
}
end )
+-- -------- EDIT
else
- ui.sectionRow( function()
- if config.initiative_abstract then
- ui.container { content = _"Enter abstract:" }
- ui.container{ attr = { class = "mdl-textfield mdl-js-textfield mdl-textfield--expandable mdl-textfield__fullwidth" }, content = function()
+
+ if not issue_id and not initiative_id then
+ local tmp = { { id = -1, name = "" } }
+ for i, allowed_policy in ipairs(area.allowed_policies) do
+ if not allowed_policy.polling or app.session.member:has_polling_right_for_unit_id(area.unit_id) then
+ tmp[#tmp+1] = allowed_policy
+ end
+ end
+ ui.container{ content = _"Please choose a policy for the new issue:" }
+ ui.field.select{
+ name = "policy_id",
+ foreign_records = tmp,
+ foreign_id = "id",
+ foreign_name = "name",
+ value = param.get("policy_id", atom.integer) or area.default_policy and area.default_policy.id
+ }
+ if policy and policy.free_timeable then
+ local available_timings
+ if config.free_timing and config.free_timing.available_func then
+ available_timings = config.free_timing.available_func(policy)
+ if available_timings == false then
+ slot.put_into("error", "error in free timing config")
+ return false
+ end
+ end
+ ui.heading{ level = 4, content = _"Free timing:" }
+ if available_timings then
+ ui.field.select{
+ name = "free_timing",
+ foreign_records = available_timings,
+ foreign_id = "id",
+ foreign_name = "name",
+ value = param.get("free_timing")
+ }
+ else
ui.field.text{
- name = "abstract",
- multiline = true,
- attr = { id = "abstract", style = "height: 20ex; width: 100%;" },
- value = param.get("abstract")
+ name = "free_timing",
+ value = param.get("free_timing")
}
- end }
+ end
end
-
- ui.container { content = _"Enter your proposal and/or reasons:" }
- ui.field.wysihtml{
- name = "content",
- multiline = true,
- attr = { id = "draft", style = "height: 50ex; width: 100%;" },
- value = param.get("content")
- }
- if not issue or issue.state == "admission" or issue.state == "discussion" then
- ui.container { content = _"You can change your text again anytime during admission and discussion phase" }
- else
- ui.container { content = _"You cannot change your text again later, because this issue is already in verfication phase!" }
- end
+ end
+
+ if issue and issue.policy.polling and app.session.member:has_polling_right_for_unit_id(area.unit_id) then
+ slot.put("
")
+ ui.field.boolean{ name = "polling", label = _"No admission needed", value = polling }
+ end
+
+ if not initiative then
+ ui.container{ attr = { class = "mdl-textfield mdl-js-textfield mdl-textfield--floating-label mdl-card__fullwidth" }, content = function ()
+ ui.field.text{
+ attr = { id = "lf-initiative__name", class = "mdl-textfield__input" },
+ label_attr = { class = "mdl-textfield__label", ["for"] = "lf-initiative__name" },
+ label = _"Title",
+ name = "name",
+ value = param.get("name")
+ }
+ end }
+ end
- slot.put("
")
- if config.attachments then
- local file_upload_session = param.get("file_upload_session") or multirand.string(
- 32,
- '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'
- )
- file_upload_session = string.gsub(file_upload_session, "[^A-Za-z0-9]", "")
- ui.field.hidden{ name = "file_upload_session", value = file_upload_session }
+ if config.initiative_abstract then
+ ui.container { content = _"Enter abstract:" }
+ ui.container{ attr = { class = "mdl-textfield mdl-js-textfield mdl-textfield--expandable mdl-textfield__fullwidth" }, content = function()
+ ui.field.text{
+ name = "abstract",
+ multiline = true,
+ attr = { id = "abstract", style = "height: 20ex; width: 100%;" },
+ value = param.get("abstract")
+ }
+ end }
+ end
+
+ ui.container { content = _"Enter your proposal and/or reasons:" }
+ ui.field.wysihtml{
+ name = "content",
+ multiline = true,
+ attr = { id = "draft", style = "height: 50ex; width: 100%;" },
+ value = param.get("content")
+ }
+ if not issue or issue.state == "admission" or issue.state == "discussion" then
+ ui.container { content = _"You can change your text again anytime during admission and discussion phase" }
+ else
+ ui.container { content = _"You cannot change your text again later, because this issue is already in verfication phase!" }
+ end
+
+ slot.put("
")
+ if config.attachments then
+ local file_upload_session = param.get("file_upload_session") or multirand.string(
+ 32,
+ '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'
+ )
+ file_upload_session = string.gsub(file_upload_session, "[^A-Za-z0-9]", "")
+ ui.field.hidden{ name = "file_upload_session", value = file_upload_session }
+ if initiative then
local files = File:new_selector()
:left_join("draft_attachment", nil, "draft_attachment.file_id = file.id")
:add_where{ "draft_attachment.draft_id = ?", initiative.current_draft.id }
@@ -195,7 +329,9 @@
content = function()
for i, file in ipairs(files) do
ui.image{ module = "file", view = "show.jpg", id = file.id, params = { preview = true } }
- ui.container{ content = file.title or "" }
+ ui.container{ content = function()
+ ui.tag{ tag = "strong", content = file.title or "" }
+ end }
ui.container{ content = file.description or "" }
ui.field.boolean{ label = _"delete", name = "file_delete_" .. file.id, value = param.get("file_delete_" .. file.id) and true or false }
slot.put("
")
@@ -203,61 +339,63 @@
end
}
end
-
- local filename = encode.file_path(WEBMCP_BASE_PATH, 'tmp', "file_upload-" .. file_upload_session .. ".json")
- local fh = io.open(filename, "r")
- if fh then
- local file_uploads = json.import(fh:read("*a"))
- for i, file_upload in ipairs(file_uploads) do
- ui.image{ module = "draft", view = "show_file_upload", params = {
- file_upload_session = file_upload_session, file_id = file_upload.id, preview = true
- } }
- ui.container{ content = file_upload.title or "" }
- ui.container{ content = file_upload.description or "" }
- ui.field.boolean{ label = _"delete", name = "file_upload_delete_" .. file_upload.id }
- slot.put("
")
- end
+ end
+ local filename = encode.file_path(WEBMCP_BASE_PATH, 'tmp', "file_upload-" .. file_upload_session .. ".json")
+ local fh = io.open(filename, "r")
+ if fh then
+ local file_uploads = json.import(fh:read("*a"))
+ for i, file_upload in ipairs(file_uploads) do
+ ui.image{ module = "draft", view = "show_file_upload", params = {
+ file_upload_session = file_upload_session, file_id = file_upload.id, preview = true
+ } }
+ ui.container{ content = function()
+ ui.tag{ tag = "strong", content = file_upload.title or "" }
+ end }
+ ui.container{ content = file_upload.description or "" }
+ ui.field.boolean{ label = _"delete", name = "file_upload_delete_" .. file_upload.id }
+ slot.put("
")
end
- ui.container{ attr = { id = "file_upload_template", style = "display: none;" }, content = function()
- ui.field.text{ label = _"Title", name = "__ID_title__" }
- ui.field.text{ label = _"Description", name = "__ID_description__" }
- ui.field.image{ field_name = "__ID_file__" }
- end }
- ui.container{ attr = { id = "file_upload" }, content = function()
- end }
- ui.field.hidden{ attr = { id = "file_upload_last_id" }, name = "file_upload_last_id" }
- ui.script{ script = [[ var file_upload_id = 1; ]] }
- ui.tag{ tag = "a", content = _"Attach image", attr = {
- href = "#",
- onclick = "var html = document.getElementById('file_upload_template').innerHTML; html = html.replace('__ID_file__', 'file_' + file_upload_id); html = html.replace('__ID_title__', 'title_' + file_upload_id); html = html.replace('__ID_description__', 'description_' + file_upload_id); var el = document.createElement('div'); el.innerHTML = html; document.getElementById('file_upload').appendChild(el); document.getElementById('file_upload_last_id').value = file_upload_id; file_upload_id++; return false;"
- } }
- slot.put("
")
-
- slot.put("
")
+ end
+ ui.container{ attr = { id = "file_upload_template", style = "display: none;" }, content = function()
+ ui.field.text{ label = _"Title", name = "__ID_title__" }
+ ui.field.text{ label = _"Description", name = "__ID_description__" }
+ ui.field.image{ field_name = "__ID_file__" }
+ end }
+ ui.container{ attr = { id = "file_upload" }, content = function()
+ end }
+ ui.field.hidden{ attr = { id = "file_upload_last_id" }, name = "file_upload_last_id" }
+ ui.script{ script = [[ var file_upload_id = 1; ]] }
+ ui.tag{ tag = "a", content = _"Attach image", attr = {
+ href = "#",
+ onclick = "var html = document.getElementById('file_upload_template').innerHTML; html = html.replace('__ID_file__', 'file_' + file_upload_id); html = html.replace('__ID_title__', 'title_' + file_upload_id); html = html.replace('__ID_description__', 'description_' + file_upload_id); var el = document.createElement('div'); el.innerHTML = html; document.getElementById('file_upload').appendChild(el); document.getElementById('file_upload_last_id').value = file_upload_id; file_upload_id++; return false;"
+ } }
+ slot.put("
")
+
+ slot.put("
")
- end
+ end
- ui.tag{
- tag = "input",
- attr = {
- type = "submit",
- name = "preview",
- class = "mdl-button mdl-js-button mdl-button--raised mdl-js-ripple-effect mdl-button--colored",
- value = _'Preview'
- },
- content = ""
- }
- slot.put(" ")
-
- ui.link{
- content = _"Cancel",
- module = "initiative",
- view = "show",
- id = initiative.id,
- attr = { class = "mdl-button mdl-js-button mdl-button--raised mdl-js-ripple-effect" }
- }
-
- end )
+ ui.tag{
+ tag = "input",
+ attr = {
+ type = "submit",
+ name = "preview",
+ class = "mdl-button mdl-js-button mdl-button--raised mdl-js-ripple-effect mdl-button--colored",
+ value = _'Preview'
+ },
+ content = ""
+ }
+ slot.put(" ")
+
+ ui.link{
+ content = _"Cancel",
+ module = initiative and "initiative" or issue and "issue" or "index",
+ view = area and "index" or "show",
+ id = initiative_id or issue_id,
+ params = { area = area_id, unit = area and area.unit_id or nil },
+ attr = { class = "mdl-button mdl-js-button mdl-button--raised mdl-js-ripple-effect" }
+ }
+
end
end }
end }
diff -r 17e7082c377a -r ed3c40911ae1 app/main/index/_head.lua
--- a/app/main/index/_head.lua Mon Feb 10 21:10:49 2020 +0100
+++ b/app/main/index/_head.lua Tue Feb 11 15:24:36 2020 +0100
@@ -116,7 +116,7 @@
if not config.voting_only and app.session.member_id and app.session.member:has_initiative_right_for_unit_id ( area.unit_id ) then
ui.link {
attr = { class = "mdl-button mdl-js-button mdl-js-ripple-effect mdl-button--underlined" },
- module = "initiative", view = "new",
+ module = "draft", view = "new",
params = { area_id = area.id },
content = function()
ui.tag{ tag = "i", attr = { class = "material-icons" }, content = "add" }
diff -r 17e7082c377a -r ed3c40911ae1 app/main/initiative/_action/create.lua
--- a/app/main/initiative/_action/create.lua Mon Feb 10 21:10:49 2020 +0100
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,219 +0,0 @@
-local issue
-local area
-
-local issue_id = param.get("issue_id", atom.integer)
-if issue_id then
- issue = Issue:new_selector():add_where{"id=?",issue_id}:for_share():single_object_mode():exec()
- if issue.closed then
- slot.put_into("error", _"This issue is already closed.")
- return false
- elseif issue.fully_frozen then
- slot.put_into("error", _"Voting for this issue has already begun.")
- return false
- elseif issue.phase_finished then
- slot.put_into("error", _"Current phase is already closed.")
- return false
- end
- area = issue.area
-else
- local area_id = param.get("area_id", atom.integer)
- area = Area:new_selector():add_where{"id=?",area_id}:single_object_mode():exec()
- if not area.active then
- slot.put_into("error", "Invalid area.")
- return false
- end
-end
-
-if not app.session.member:has_voting_right_for_unit_id(area.unit_id) then
- return execute.view { module = "index", view = "403" }
-end
-
-local policy_id = param.get("policy_id", atom.integer)
-local policy
-if policy_id then
- policy = Policy:by_id(policy_id)
-end
-
-if not issue then
- if policy_id == -1 then
- slot.put_into("error", _"Please choose a policy")
- return false
- end
- if not policy.active then
- slot.put_into("error", "Invalid policy.")
- return false
- end
- if policy.polling and not app.session.member:has_polling_right_for_unit_id(area.unit_id) then
- return execute.view { module = "index", view = "403" }
- end
- if not area:get_reference_selector("allowed_policies")
- :add_where{ "policy.id = ?", policy_id }
- :optional_object_mode()
- :exec()
- then
- slot.put_into("error", "policy not allowed")
- return false
- end
-end
-
-local is_polling = (issue and param.get("polling", atom.boolean)) or (policy and policy.polling) or false
-
-local tmp = db:query({ "SELECT text_entries_left, initiatives_left FROM member_contingent_left WHERE member_id = ? AND polling = ?", app.session.member.id, is_polling }, "opt_object")
-if not tmp or tmp.initiatives_left < 1 then
- slot.put_into("error", _"Sorry, your contingent for creating initiatives has been used up. Please try again later.")
- return false
-end
-if tmp and tmp.text_entries_left < 1 then
- slot.put_into("error", _"Sorry, you have reached your personal flood limit. Please be slower...")
- return false
-end
-
-local name = param.get("name")
-
-local name = util.trim(name)
-
-if #name < 3 then
- slot.put_into("error", _"Please enter a meaningful title for your initiative!")
- return false
-end
-
-if #name > 140 then
- slot.put_into("error", _"This title is too long!")
- return false
-end
-
-local timing
-if not issue and policy.free_timeable then
- local free_timing_string = util.trim(param.get("free_timing"))
- if not free_timing_string or #free_timing_string < 1 then
- slot.put_into("error", _"Choose timing")
- return false
- end
- local available_timings
- if config.free_timing and config.free_timing.available_func then
- available_timings = config.free_timing.available_func(policy)
- if available_timings == false then
- slot.put_into("error", "error in free timing config")
- return false
- end
- end
- if available_timings then
- local timing_available = false
- for i, available_timing in ipairs(available_timings) do
- if available_timing.id == free_timing_string then
- timing_available = true
- end
- end
- if not timing_available then
- slot.put_into("error", _"Invalid timing")
- return false
- end
- end
- timing = config.free_timing.calculate_func(policy, free_timing_string)
- if not timing then
- slot.put_into("error", "error in free timing config")
- return false
- end
-end
-
-local draft_text = param.get("draft")
-
-if not draft_text then
- return false
-end
-
-local draft_text = util.wysihtml_preproc(draft_text)
-
-local valid_html, error_message = util.html_is_safe(draft_text)
-if not valid_html then
- slot.put_into("error", _("Draft contains invalid formatting or character sequence: #{error_message}", { error_message = error_message }) )
- return false
-end
-
-if config.initiative_abstract then
- local abstract = param.get("abstract")
- if not abstract then
- return false
- end
- abstract = encode.html(abstract)
- draft_text = abstract .. "" .. draft_text
-end
-
-local location = param.get("location")
-if location == "" then
- location = nil
-end
-
-if param.get("preview") or param.get("edit") then
- return
-end
-
-local initiative = Initiative:new()
-
-if not issue then
- issue = Issue:new()
- issue.area_id = area.id
- issue.policy_id = policy_id
-
- if policy.polling then
- issue.accepted = 'now'
- issue.state = 'discussion'
- initiative.polling = true
-
- if policy.free_timeable then
- issue.discussion_time = timing.discussion
- issue.verification_time = timing.verification
- issue.voting_time = timing.voting
- end
-
- end
-
- issue:save()
-
- if config.etherpad then
- local result = net.curl(
- config.etherpad.api_base
- .. "api/1/createGroupPad?apikey=" .. config.etherpad.api_key
- .. "&groupID=" .. config.etherpad.group_id
- .. "&padName=Issue" .. tostring(issue.id)
- .. "&text=" .. request.get_absolute_baseurl() .. "issue/show/" .. tostring(issue.id) .. ".html"
- )
- end
-end
-
-if param.get("polling", atom.boolean) and app.session.member:has_polling_right_for_unit_id(area.unit_id) then
- initiative.polling = true
-end
-initiative.issue_id = issue.id
-initiative.name = name
-initiative:save()
-
-local draft = Draft:new()
-draft.initiative_id = initiative.id
-draft.formatting_engine = formatting_engine
-draft.content = draft_text
-draft.location = location
-draft.author_id = app.session.member.id
-draft:save()
-
-local initiator = Initiator:new()
-initiator.initiative_id = initiative.id
-initiator.member_id = app.session.member.id
-initiator.accepted = true
-initiator:save()
-
-if not is_polling then
- local supporter = Supporter:new()
- supporter.initiative_id = initiative.id
- supporter.member_id = app.session.member.id
- supporter.draft_id = draft.id
- supporter:save()
-end
-
-slot.put_into("notice", _"Initiative successfully created")
-
-request.redirect{
- module = "initiative",
- view = "show",
- id = initiative.id
-}
diff -r 17e7082c377a -r ed3c40911ae1 app/main/initiative/new.lua
--- a/app/main/initiative/new.lua Mon Feb 10 21:10:49 2020 +0100
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,279 +0,0 @@
-local issue
-local area
-
-local issue_id = param.get("issue_id", atom.integer)
-if issue_id then
- issue = Issue:new_selector():add_where{"id=?",issue_id}:single_object_mode():exec()
- issue:load_everything_for_member_id(app.session.member_id)
- area = issue.area
-
-else
- local area_id = param.get("area_id", atom.integer)
- area = Area:new_selector():add_where{"id=?",area_id}:single_object_mode():exec()
- area:load_delegation_info_once_for_member_id(app.session.member_id)
-end
-
-local polling = param.get("polling", atom.boolean)
-
-local policy_id = param.get("policy_id", atom.integer)
-local policy
-
-local preview = param.get("preview")
-
-if #(slot.get_content("error")) > 0 then
- preview = false
-end
-
-if policy_id then
- policy = Policy:by_id(policy_id)
-end
-
-if issue_id then
- execute.view {
- module = "issue", view = "_head",
- params = { issue = issue, member = app.session.member }
- }
-else
- --[[
- execute.view {
- module = "area", view = "_head",
- params = { area = area, member = app.session.member }
- }
- --]]
- --[[
- execute.view {
- module = "initiative", view = "_sidebar_policies",
- params = {
- area = area,
- }
- }
- --]]
-end
-
-ui.form{
- module = "initiative",
- action = "create",
- params = {
- area_id = area.id,
- issue_id = issue and issue.id or nil
- },
- attr = { class = "vertical" },
- content = function()
- ui.grid{ content = function()
- ui.cell_main{ content = function()
- ui.container{ attr = { class = "mdl-card mdl-shadow--2dp mdl-card__fullwidth" }, content = function()
- ui.container{ attr = { class = "mdl-card__title mdl-card--border" }, content = function()
- if preview then
- ui.heading { attr = { class = "mdl-card__title-text" }, level = 2, content = _"Preview" }
- elseif issue_id then
- ui.heading { attr = { class = "mdl-card__title-text" }, level = 2, content = _"New competing initiative" }
- else
- ui.heading { attr = { class = "mdl-card__title-text" }, level = 2, content = _"Create a new issue" }
- end
- end }
-
- ui.container{ attr = { class = "mdl-card__content mdl-card--border" }, content = function()
-
-
- if preview then
-
- ui.section( function()
- ui.sectionHead( function()
- ui.heading{ level = 1, content = encode.html(param.get("name")) }
- if not issue then
- ui.container { content = policy.name }
- end
- if param.get("free_timing") then
- ui.container { content = param.get("free_timing") }
- end
- slot.put("
")
-
- local draft_text = param.get("draft")
- local draft_text = util.wysihtml_preproc(draft_text)
-
- ui.field.hidden{ name = "policy_id", value = param.get("policy_id") }
- ui.field.hidden{ name = "name", value = param.get("name") }
- if config.initiative_abstract then
- ui.field.hidden{ name = "abstract", value = param.get("abstract") }
- ui.container{
- attr = { class = "abstract" },
- content = param.get("abstract")
- }
- slot.put("
")
- end
- ui.field.hidden{ name = "draft", value = draft_text }
- ui.field.hidden{ name = "free_timing", value = param.get("free_timing") }
- ui.field.hidden{ name = "polling", value = param.get("polling", atom.boolean) }
- ui.field.hidden{ name = "location", value = param.get("location") }
- local formatting_engine
- if config.enforce_formatting_engine then
- formatting_engine = config.enforce_formatting_engine
- else
- formatting_engine = param.get("formatting_engine")
- end
- ui.container{
- attr = { class = "draft" },
- content = function()
- slot.put(draft_text)
- end
- }
- slot.put("
")
-
- ui.tag{
- tag = "input",
- attr = {
- type = "submit",
- class = "mdl-button mdl-js-button mdl-button--raised mdl-js-ripple-effect mdl-button--colored",
- value = _'Publish now'
- },
- content = ""
- }
- slot.put(" ")
- ui.tag{
- tag = "input",
- attr = {
- type = "submit",
- name = "edit",
- class = "mdl-button mdl-js-button mdl-button--raised mdl-js-ripple-effect",
- value = _'Edit again'
- },
- content = ""
- }
- slot.put(" ")
- local class = "mdl-button mdl-js-button mdl-button--raised mdl-js-ripple-effect"
- if issue then
- ui.link{ content = _"Cancel", module = "issue", view = "show", id = issue.id, attr = { class = class } }
- else
- ui.link{ content = _"Cancel", module = "index", view = "index", params = { unit = area.unit_id, area = area.id }, attr = { class = class } }
- end
- end )
- end )
- else
-
- ui.sectionRow( function()
- --[[
- if not preview and not issue_id then
- ui.container { attr = { class = "section" }, content = _"Before creating a new issue, please check any existant issues before, if the topic is already in discussion." }
- slot.put("
")
- end
- --]]
- if not issue_id then
- local tmp = { { id = -1, name = "" } }
- for i, allowed_policy in ipairs(area.allowed_policies) do
- if not allowed_policy.polling or app.session.member:has_polling_right_for_unit_id(area.unit_id) then
- tmp[#tmp+1] = allowed_policy
- end
- end
- ui.container{ content = _"Please choose a policy for the new issue:" }
- ui.field.select{
- name = "policy_id",
- foreign_records = tmp,
- foreign_id = "id",
- foreign_name = "name",
- value = param.get("policy_id", atom.integer) or area.default_policy and area.default_policy.id
- }
- if policy and policy.free_timeable then
- local available_timings
- if config.free_timing and config.free_timing.available_func then
- available_timings = config.free_timing.available_func(policy)
- if available_timings == false then
- slot.put_into("error", "error in free timing config")
- return false
- end
- end
- ui.heading{ level = 4, content = _"Free timing:" }
- if available_timings then
- ui.field.select{
- name = "free_timing",
- foreign_records = available_timings,
- foreign_id = "id",
- foreign_name = "name",
- value = param.get("free_timing")
- }
- else
- ui.field.text{
- name = "free_timing",
- value = param.get("free_timing")
- }
- end
- end
- end
-
- if issue and issue.policy.polling and app.session.member:has_polling_right_for_unit_id(area.unit_id) then
- slot.put("
")
- ui.field.boolean{ name = "polling", label = _"No admission needed", value = polling }
- end
-
- ui.container{ attr = { class = "mdl-textfield mdl-js-textfield mdl-textfield--floating-label mdl-card__fullwidth" }, content = function ()
- ui.field.text{
- attr = { id = "lf-initiative__name", class = "mdl-textfield__input" },
- label_attr = { class = "mdl-textfield__label", ["for"] = "lf-initiative__name" },
- label = _"Title",
- name = "name",
- value = param.get("name")
- }
- end }
-
- if config.initiative_abstract then
- ui.container { content = _"Enter abstract:" }
- ui.container{ attr = { class = "mdl-textfield mdl-js-textfield mdl-textfield--expandable mdl-textfield__fullwidth" }, content = function()
- ui.field.text{
- name = "abstract",
- multiline = true,
- attr = { id = "abstract", style = "height: 20ex; width: 100%;" },
- value = param.get("abstract")
- }
- end }
- end
-
- ui.container { content = _"Enter your proposal and/or reasons:" }
- ui.container{ attr = { class = "mdl-textfield mdl-js-textfield mdl-textfield--expandable mdl-textfield__fullwidth" }, content = function()
- ui.field.wysihtml{
- name = "draft",
- multiline = true,
- attr = { id = "draft", style = "height: 50ex; width: 100%;" },
- value = param.get("draft") or config.draft_template
- }
- end }
- if not issue or issue.state == "admission" or issue.state == "discussion" then
- ui.container { content = _"You can change your text again anytime during admission and discussion phase" }
- else
- ui.container { content = _"You cannot change your text again later, because this issue is already in verfication phase!" }
- end
- slot.put("
")
-
- slot.put("
")
- ui.tag{
- tag = "input",
- attr = {
- type = "submit",
- name = "preview",
- class = "mdl-button mdl-js-button mdl-button--raised mdl-js-ripple-effect mdl-button--colored",
- value = _'Preview'
- },
- content = ""
- }
- slot.put(" ")
-
- local class = "mdl-button mdl-js-button mdl-button--raised mdl-js-ripple-effect"
- if issue then
-
- ui.link{ content = _"Cancel", module = "issue", view = "show", id = issue.id, attr = { class = class } }
- else
- ui.link{ content = _"Cancel", module = "index", view = "index", params = { unit = area.unit_id, area = area.id }, attr = { class = class } }
- end
- end )
- end
- end }
- end }
- end }
- if config.map or config.firstlife then
- ui.cell_sidebar{ content = function()
- ui.container{ attr = { class = "mdl-special-card map mdl-shadow--2dp" }, content = function()
- ui.field.location{ name = "location", value = param.get("location") }
- end }
- end }
- end
- end }
- end
-}
diff -r 17e7082c377a -r ed3c40911ae1 app/main/initiative/show.lua
--- a/app/main/initiative/show.lua Mon Feb 10 21:10:49 2020 +0100
+++ b/app/main/initiative/show.lua Tue Feb 11 15:24:36 2020 +0100
@@ -155,7 +155,9 @@
ui.link{ module = "file", view = "show.jpg", id = file.id, content = function()
ui.image{ module = "file", view = "show.jpg", id = file.id, params = { preview = true } }
end }
- ui.container{ content = file.title or "" }
+ ui.container{ content = function()
+ ui.tag{ tag = "strong", content = file.title or "" }
+ end }
ui.container{ content = file.description or "" }
slot.put("
")
end
diff -r 17e7082c377a -r ed3c40911ae1 app/main/issue/_sidebar_issue.lua
--- a/app/main/issue/_sidebar_issue.lua Mon Feb 10 21:10:49 2020 +0100
+++ b/app/main/issue/_sidebar_issue.lua Tue Feb 11 15:24:36 2020 +0100
@@ -36,7 +36,7 @@
ui.container{ attr = { class = "mdl-card__actions mdl-card--border" }, content = function()
ui.link {
attr = { class = "mdl-button mdl-js-button" },
- module = "initiative", view = "new",
+ module = "draft", view = "new",
params = { issue_id = issue.id },
content = _"start a new competing initiative"
}