liquid_feedback_frontend

changeset 1495:17e7082c377a

Added image attachments for initiatives
author bsw
date Mon Feb 10 21:10:49 2020 +0100 (2020-02-10)
parents 3e9b0f1adec3
children ed3c40911ae1
files app/main/_filter/21_auth.lua app/main/draft/_action/add.lua app/main/draft/new.lua app/main/draft/show.lua app/main/draft/show_file_upload.lua app/main/file/show.jpg.lua app/main/initiative/show.lua model/draft.lua model/draft_attachment.lua model/file.lua
line diff
     1.1 --- a/app/main/_filter/21_auth.lua	Mon Dec 09 15:54:57 2019 +0100
     1.2 +++ b/app/main/_filter/21_auth.lua	Mon Feb 10 21:10:49 2020 +0100
     1.3 @@ -71,6 +71,7 @@
     1.4      or module == "suggestion" and view == "show"
     1.5      or module == "draft" and view == "diff"
     1.6      or module == "draft" and view == "show"
     1.7 +    or module == "file" and view == "show.jpg"
     1.8      or module == "index" and view == "search"
     1.9      or module == "index" and view == "usage_terms"
    1.10      or module == "help" and view == "introduction"
     2.1 --- a/app/main/draft/_action/add.lua	Mon Dec 09 15:54:57 2019 +0100
     2.2 +++ b/app/main/draft/_action/add.lua	Mon Feb 10 21:10:49 2020 +0100
     2.3 @@ -21,7 +21,68 @@
     2.4    draft_text = abstract .. "<!--END_OF_ABSTRACT-->" .. draft_text
     2.5  end
     2.6  
     2.7 -return Draft:update_content(
     2.8 +if config.attachments then
     2.9 +  local file_upload_session = param.get("file_upload_session")
    2.10 +  file_upload_session = string.gsub(file_upload_session, "[^A-Za-z0-9]", "")
    2.11 +  local file_uploads = json.array()
    2.12 +  local filename = encode.file_path(WEBMCP_BASE_PATH, 'tmp', "file_upload-" .. file_upload_session .. ".json")
    2.13 +  local fh = io.open(filename, "r")
    2.14 +  if fh then
    2.15 +    file_uploads = json.import(fh:read("*a"))
    2.16 +  end
    2.17 +  for i, file_upload in ipairs(file_uploads) do
    2.18 +    if param.get("file_upload_delete_" .. file_upload.id, atom.boolean) then
    2.19 +      for j = i, #file_uploads - 1 do
    2.20 +        file_uploads[j] = file_uploads[j+1]
    2.21 +      end
    2.22 +      file_uploads[#file_uploads] = nil
    2.23 +    end
    2.24 +  end
    2.25 +  local convert_func = config.attachments.convert_func
    2.26 +  local last_id = param.get("file_upload_last_id", atom.number)
    2.27 +  if last_id and last_id > 0 then
    2.28 +    if last_id > 1024 then
    2.29 +      last_id = 1024
    2.30 +    end
    2.31 +    for i = 1, last_id do
    2.32 +      local file = param.get("file_" .. i)
    2.33 +      if file and #file > 0 then
    2.34 +        local id = multirand.string(
    2.35 +          32,
    2.36 +          '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'
    2.37 +        )
    2.38 +        local data, err, status = convert_func(file)
    2.39 +        if status ~= 0 or data == nil then
    2.40 +          slot.put_into("error", _"Error while converting image. Please note, that only JPG files are supported!")
    2.41 +          return false
    2.42 +        end
    2.43 +        local filename = encode.file_path(WEBMCP_BASE_PATH, 'tmp', "file_upload-" .. file_upload_session .. "-" .. id .. ".jpg")
    2.44 +        local fh = assert(io.open(filename, "w"))
    2.45 +        fh:write(file)
    2.46 +        fh:write("\n")
    2.47 +        fh:close()
    2.48 +        local filename = encode.file_path(WEBMCP_BASE_PATH, 'tmp', "file_upload-" .. file_upload_session .. "-" .. id .. ".preview.jpg")
    2.49 +        local fh = assert(io.open(filename, "w"))
    2.50 +        fh:write(data)
    2.51 +        fh:write("\n")
    2.52 +        fh:close()
    2.53 +        table.insert(file_uploads, json.object{
    2.54 +          id = id,
    2.55 +          filename = filename,
    2.56 +          title = param.get("title_" .. i),
    2.57 +          description = param.get("description_" .. i)
    2.58 +        })
    2.59 +      end
    2.60 +    end
    2.61 +  end
    2.62 +  local filename = encode.file_path(WEBMCP_BASE_PATH, 'tmp', "file_upload-" .. file_upload_session .. ".json")
    2.63 +  local fh = assert(io.open(filename, "w"))
    2.64 +  fh:write(json.export(file_uploads))
    2.65 +  fh:write("\n")
    2.66 +  fh:close()
    2.67 +end
    2.68 +
    2.69 +local draft_id = Draft:update_content(
    2.70    app.session.member.id, 
    2.71    param.get("initiative_id", atom.integer),
    2.72    param.get("formatting_engine"),
    2.73 @@ -29,3 +90,66 @@
    2.74    nil,
    2.75    param.get("preview") or param.get("edit")
    2.76  )
    2.77 +
    2.78 +if draft_id and config.attachments then
    2.79 +  local file_upload_session = param.get("file_upload_session")
    2.80 +  file_upload_session = string.gsub(file_upload_session, "[^A-Za-z0-9]", "")
    2.81 +
    2.82 +  local draft_attachments = DraftAttachment:new_selector()
    2.83 +    :add_where{ "draft_attachment.draft_id = ?", draft_id }
    2.84 +    :exec()
    2.85 +
    2.86 +  for i, draft_attachment in ipairs(draft_attachments) do
    2.87 +    if param.get("file_delete_" .. draft_attachment.file_id, atom.boolean) then
    2.88 +      draft_attachment:destroy()
    2.89 +    end
    2.90 +  end
    2.91 +
    2.92 +  local file_uploads = json.array()
    2.93 +  local filename = encode.file_path(WEBMCP_BASE_PATH, 'tmp', "file_upload-" .. file_upload_session .. ".json")
    2.94 +  local fh = io.open(filename, "r")
    2.95 +  if fh then
    2.96 +    file_uploads = json.import(fh:read("*a"))
    2.97 +  end
    2.98 +  for i, file_upload in ipairs(file_uploads) do
    2.99 +    local filename = encode.file_path(WEBMCP_BASE_PATH, 'tmp', "file_upload-" .. file_upload_session .. "-" .. file_upload.id .. ".jpg")
   2.100 +    local data
   2.101 +    local fh = io.open(filename, "r")
   2.102 +    if fh then
   2.103 +      data = fh:read("*a")
   2.104 +    end
   2.105 +    local filename = encode.file_path(WEBMCP_BASE_PATH, 'tmp', "file_upload-" .. file_upload_session .. "-" .. file_upload.id .. ".preview.jpg")
   2.106 +    local data_preview
   2.107 +    local fh = io.open(filename, "r")
   2.108 +    if fh then
   2.109 +      data_preview = fh:read("*a")
   2.110 +    end
   2.111 +
   2.112 +    local hash = moonhash.sha3_512(data)
   2.113 +
   2.114 +    local file = File:new_selector()
   2.115 +      :add_where{ "hash = ?", hash }
   2.116 +      :add_where{ "content_type = ?", "image/jpeg" }
   2.117 +      :optional_object_mode()
   2.118 +      :exec()
   2.119 +
   2.120 +    if not file then
   2.121 +      file = File:new()
   2.122 +      file.content_type = "image/jpeg"
   2.123 +      file.hash = hash
   2.124 +      file.data = data
   2.125 +      file.preview_content_type = "image/jpeg"
   2.126 +      file.preview_data = data_preview
   2.127 +      file:save()
   2.128 +    end
   2.129 +
   2.130 +    local draft_attachment = DraftAttachment:new()
   2.131 +    draft_attachment.draft_id = draft_id
   2.132 +    draft_attachment.file_id = file.id
   2.133 +    draft_attachment.title = file_upload.title
   2.134 +    draft_attachment.description = file_upload.description
   2.135 +    draft_attachment:save()
   2.136 +  end
   2.137 +end
   2.138 +
   2.139 +return draft_id and true or false
     3.1 --- a/app/main/draft/new.lua	Mon Dec 09 15:54:57 2019 +0100
     3.2 +++ b/app/main/draft/new.lua	Mon Feb 10 21:10:49 2020 +0100
     3.3 @@ -23,7 +23,7 @@
     3.4  
     3.5  ui.form{
     3.6    record = draft,
     3.7 -  attr = { class = "vertical section" },
     3.8 +  attr = { class = "vertical section", enctype = 'multipart/form-data' },
     3.9    module = "draft",
    3.10    action = "add",
    3.11    params = { initiative_id = initiative.id },
    3.12 @@ -65,6 +65,54 @@
    3.13                  }
    3.14                  slot.put("<br />")
    3.15  
    3.16 +                if config.attachments then
    3.17 +                  local file_upload_session = param.get("file_upload_session") or multirand.string(
    3.18 +                    32,
    3.19 +                    '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'
    3.20 +                  )
    3.21 +                  file_upload_session = string.gsub(file_upload_session, "[^A-Za-z0-9]", "")
    3.22 +                  ui.field.hidden{ name = "file_upload_session", value = file_upload_session }
    3.23 +                   local files = File:new_selector()
    3.24 +                    :left_join("draft_attachment", nil, "draft_attachment.file_id = file.id")
    3.25 +                    :add_where{ "draft_attachment.draft_id = ?", initiative.current_draft.id }
    3.26 +                    :reset_fields()
    3.27 +                    :add_field("file.id")
    3.28 +                    :add_field("draft_attachment.title")
    3.29 +                    :add_field("draft_attachment.description")
    3.30 +                    :add_order_by("draft_attachment.id")
    3.31 +                    :exec()
    3.32 +
    3.33 +                  if #files > 0 then
    3.34 +                    ui.container {
    3.35 +                      content = function()
    3.36 +                        for i, file in ipairs(files) do
    3.37 +                          if param.get("file_delete_" .. file.id, atom.boolean) then
    3.38 +                            ui.field.hidden{ name = "file_delete_" .. file.id, value = "1" }
    3.39 +                          else
    3.40 +                            ui.image{ module = "file", view = "show.jpg", id = file.id, params = { preview = true } }
    3.41 +                            ui.container{ content = file.title or "" }
    3.42 +                            ui.container{ content = file.description or "" }
    3.43 +                            slot.put("<br /><br />")
    3.44 +                          end
    3.45 +                        end
    3.46 +                      end
    3.47 +                    }
    3.48 +                  end
    3.49 +                  local filename = encode.file_path(WEBMCP_BASE_PATH, 'tmp', "file_upload-" .. file_upload_session .. ".json")
    3.50 +                  local fh = io.open(filename, "r")
    3.51 +                  if fh then
    3.52 +                    local file_uploads = json.import(fh:read("*a"))
    3.53 +                    for i, file_upload in ipairs(file_uploads) do
    3.54 +                      ui.image{ module = "draft", view = "show_file_upload", params = {
    3.55 +                        file_upload_session = file_upload_session, file_id = file_upload.id, preview = true
    3.56 +                      } }
    3.57 +                      ui.container{ content = file_upload.title or "" }
    3.58 +                      ui.container{ content = file_upload.description or "" }
    3.59 +                      slot.put("<br />")
    3.60 +                    end
    3.61 +                  end
    3.62 +                end
    3.63 +
    3.64                  ui.tag{
    3.65                    tag = "input",
    3.66                    attr = {
    3.67 @@ -123,7 +171,71 @@
    3.68                  else
    3.69                    ui.container { content = _"You cannot change your text again later, because this issue is already in verfication phase!" }
    3.70                  end
    3.71 +
    3.72                  slot.put("<br />")
    3.73 +                if config.attachments then
    3.74 +                  local file_upload_session = param.get("file_upload_session") or multirand.string(
    3.75 +                    32,
    3.76 +                    '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'
    3.77 +                  )
    3.78 +                  file_upload_session = string.gsub(file_upload_session, "[^A-Za-z0-9]", "")
    3.79 +                  ui.field.hidden{ name = "file_upload_session", value = file_upload_session }
    3.80 +                  local files = File:new_selector()
    3.81 +                    :left_join("draft_attachment", nil, "draft_attachment.file_id = file.id")
    3.82 +                    :add_where{ "draft_attachment.draft_id = ?", initiative.current_draft.id }
    3.83 +                    :reset_fields()
    3.84 +                    :add_field("file.id")
    3.85 +                    :add_field("draft_attachment.title")
    3.86 +                    :add_field("draft_attachment.description")
    3.87 +                    :add_order_by("draft_attachment.id")
    3.88 +                    :exec()
    3.89 +
    3.90 +                  if #files > 0 then
    3.91 +                    ui.container {
    3.92 +                      content = function()
    3.93 +                        for i, file in ipairs(files) do
    3.94 +                          ui.image{ module = "file", view = "show.jpg", id = file.id, params = { preview = true } }
    3.95 +                          ui.container{ content = file.title or "" }
    3.96 +                          ui.container{ content = file.description or "" }
    3.97 +                          ui.field.boolean{ label = _"delete", name = "file_delete_" .. file.id, value = param.get("file_delete_" .. file.id) and true or false }
    3.98 +                          slot.put("<br /><br />")
    3.99 +                        end
   3.100 +                      end
   3.101 +                    }
   3.102 +                  end
   3.103 +
   3.104 +                  local filename = encode.file_path(WEBMCP_BASE_PATH, 'tmp', "file_upload-" .. file_upload_session .. ".json")
   3.105 +                  local fh = io.open(filename, "r")
   3.106 +                  if fh then
   3.107 +                    local file_uploads = json.import(fh:read("*a"))
   3.108 +                    for i, file_upload in ipairs(file_uploads) do
   3.109 +                      ui.image{ module = "draft", view = "show_file_upload", params = {
   3.110 +                        file_upload_session = file_upload_session, file_id = file_upload.id, preview = true
   3.111 +                      } }
   3.112 +                      ui.container{ content = file_upload.title or "" }
   3.113 +                      ui.container{ content = file_upload.description or "" }
   3.114 +                      ui.field.boolean{ label = _"delete", name = "file_upload_delete_" .. file_upload.id }
   3.115 +                      slot.put("<br />")
   3.116 +                    end
   3.117 +                  end
   3.118 +                  ui.container{ attr = { id = "file_upload_template", style = "display: none;" }, content = function()
   3.119 +                    ui.field.text{ label = _"Title", name = "__ID_title__" }
   3.120 +                    ui.field.text{ label = _"Description", name = "__ID_description__" }
   3.121 +                    ui.field.image{ field_name = "__ID_file__" }
   3.122 +                  end }
   3.123 +                  ui.container{ attr = { id = "file_upload" }, content = function()
   3.124 +                  end }
   3.125 +                  ui.field.hidden{ attr = { id = "file_upload_last_id" }, name = "file_upload_last_id" }
   3.126 +                  ui.script{ script = [[ var file_upload_id = 1; ]] }
   3.127 +                  ui.tag{ tag = "a", content = _"Attach image", attr = { 
   3.128 +                    href = "#",
   3.129 +                    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;"
   3.130 +                  } }
   3.131 +                  slot.put("<br />")
   3.132 +                  
   3.133 +                  slot.put("<br />")
   3.134 +
   3.135 +                end
   3.136  
   3.137                  ui.tag{
   3.138                    tag = "input",
     4.1 --- a/app/main/draft/show.lua	Mon Dec 09 15:54:57 2019 +0100
     4.2 +++ b/app/main/draft/show.lua	Mon Feb 10 21:10:49 2020 +0100
     4.3 @@ -6,61 +6,122 @@
     4.4    return
     4.5  end
     4.6  
     4.7 +local member = app.session.member
     4.8 +
     4.9 +if member then
    4.10 +  draft.initiative:load_everything_for_member_id(member.id)
    4.11 +  draft.initiative.issue:load_everything_for_member_id(member.id)
    4.12 +end
    4.13  
    4.14  local source = param.get("source", atom.boolean)
    4.15  
    4.16 -execute.view{
    4.17 -  module = "issue",
    4.18 -  view = "_head",
    4.19 -  params = { issue = draft.initiative.issue }
    4.20 -}
    4.21 +execute.view{ module = "issue", view = "_head", params = { issue = draft.initiative.issue, link_issue = true } }
    4.22 +
    4.23 +ui.grid{ content = function()
    4.24  
    4.25 -ui.section( function()
    4.26 -  
    4.27 -  ui.sectionHead( function()
    4.28 -    ui.link{
    4.29 -      module = "initiative", view = "show", id = draft.initiative.id,
    4.30 -      content = function ()
    4.31 +  ui.cell_main{ content = function()
    4.32 +
    4.33 +    ui.container{ attr = { class = "mdl-card mdl-card__fullwidth mdl-shadow--2dp" }, content = function()
    4.34 +
    4.35 +      ui.container{ attr = { class = "mdl-card__title mdl-card--has-fab mdl-card--border" }, content = function ()
    4.36 +
    4.37          ui.heading { 
    4.38 -          level = 1,
    4.39 -          content = draft.initiative.display_name
    4.40 +          attr = { class = "mdl-card__title-text" },
    4.41 +          level = 2,
    4.42 +          content = function()
    4.43 +            ui.link{
    4.44 +              module = "initiative", view = "show", id = draft.initiative.id,
    4.45 +              content = draft.initiative.display_name
    4.46 +            }
    4.47 +            ui.container{ content = _("Draft revision #{id}", { id = draft.id } ) }
    4.48 +          end 
    4.49          }
    4.50 -      end
    4.51 -    }
    4.52 -    ui.container { attr = { class = "right" }, content = function()
    4.53 -      if source then
    4.54 -        ui.link{
    4.55 -          content = _"Rendered",
    4.56 +      end }
    4.57 +
    4.58 +      ui.container{ attr = { class = "draft mdl-card__title mdl-card--border" }, content = function()
    4.59 +        if config.render_external_reference and config.render_external_reference.draft then
    4.60 +          config.render_external_reference.draft(draft, function (callback)
    4.61 +            ui.sectionRow(callback)
    4.62 +          end)
    4.63 +        end
    4.64 +        
    4.65 +        execute.view{
    4.66            module = "draft",
    4.67 -          view = "show",
    4.68 -          id = param.get_id(),
    4.69 -          params = { source = false }
    4.70 +          view = "_show",
    4.71 +          params = { draft = draft, source = source }
    4.72          }
    4.73 -      else
    4.74 -        ui.link{
    4.75 -          content = _"Source",
    4.76 -          module = "draft",
    4.77 -          view = "show",
    4.78 -          id = param.get_id(),
    4.79 -          params = { source = true }
    4.80 -        }
    4.81 +
    4.82 +
    4.83 +
    4.84 +      end }      
    4.85 +
    4.86 +      if config.attachments then
    4.87 +
    4.88 +        local files = File:new_selector()
    4.89 +          :left_join("draft_attachment", nil, "draft_attachment.file_id = file.id")
    4.90 +          :add_where{ "draft_attachment.draft_id = ?", draft.id }
    4.91 +          :reset_fields()
    4.92 +          :add_field("file.id")
    4.93 +          :add_field("draft_attachment.title")
    4.94 +          :add_field("draft_attachment.description")
    4.95 +          :add_order_by("draft_attachment.id")
    4.96 +          :exec()
    4.97 +
    4.98 +        if #files > 0 then
    4.99 +          ui.container {
   4.100 +            attr = { class = "mdl-card__content mdl-card--border" },
   4.101 +            content = function()
   4.102 +              for i, file in ipairs(files) do
   4.103 +                ui.link{ module = "file", view = "show.jpg", id = file.id, content = function()
   4.104 +                  ui.image{ module = "file", view = "show.jpg", id = file.id, params = { preview = true } }
   4.105 +                end }
   4.106 +                ui.container{ content = file.title or "" }
   4.107 +                ui.container{ content = file.description or "" }
   4.108 +                slot.put("<br /><br />")
   4.109 +              end
   4.110 +            end
   4.111 +          }
   4.112 +        end
   4.113        end
   4.114 +
   4.115 +      ui.container{ attr = { class = "mdl-card__actions" }, content = function()
   4.116 +        if source then
   4.117 +          ui.link{
   4.118 +            attr = { class = "mdl-button mdl-js-button" },
   4.119 +            content = _"Rendered",
   4.120 +            module = "draft",
   4.121 +            view = "show",
   4.122 +            id = param.get_id(),
   4.123 +            params = { source = false }
   4.124 +          }
   4.125 +        else
   4.126 +          ui.link{
   4.127 +            attr = { class = "mdl-button mdl-js-button" },
   4.128 +            content = _"Source",
   4.129 +            module = "draft",
   4.130 +            view = "show",
   4.131 +            id = param.get_id(),
   4.132 +            params = { source = true }
   4.133 +          }
   4.134 +        end
   4.135 +        
   4.136 +      end }
   4.137      end }
   4.138 -    ui.heading { level = 2, content = _("Draft revision #{id}", { id = draft.id } ) }
   4.139 -  end)
   4.140 -  
   4.141 -  if config.render_external_reference and config.render_external_reference.draft then
   4.142 -    config.render_external_reference.draft(draft, function (callback)
   4.143 -      ui.sectionRow(callback)
   4.144 -    end)
   4.145 -  end
   4.146 -  
   4.147 -  ui.sectionRow( function()
   4.148 -  
   4.149 -    execute.view{
   4.150 -      module = "draft",
   4.151 -      view = "_show",
   4.152 -      params = { draft = draft, source = source }
   4.153 +
   4.154 +  end }
   4.155 +
   4.156 +  ui.cell_sidebar{ content = function()
   4.157 +    if config.logo then
   4.158 +      config.logo()
   4.159 +    end
   4.160 +    execute.view {
   4.161 +      module = "issue", view = "_sidebar", 
   4.162 +      params = {
   4.163 +        issue = draft.initiative.issue,
   4.164 +        initiative = draft.initiative,
   4.165 +        member = app.session.member
   4.166 +      }
   4.167      }
   4.168 -  end)
   4.169 -end)
   4.170 +  end }
   4.171 +
   4.172 +end }
     5.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     5.2 +++ b/app/main/draft/show_file_upload.lua	Mon Feb 10 21:10:49 2020 +0100
     5.3 @@ -0,0 +1,22 @@
     5.4 +local file_upload_session = param.get("file_upload_session")
     5.5 +file_upload_session = string.gsub(file_upload_session, "[^A-Za-z0-9]", "")
     5.6 +
     5.7 +local file_id = param.get("file_id")
     5.8 +file_id = string.gsub(file_id, "[^A-Za-z0-9]", "")
     5.9 +
    5.10 +local filename = encode.file_path(WEBMCP_BASE_PATH, 'tmp', "file_upload-" .. file_upload_session .. "-" .. file_id .. ".jpg")
    5.11 +
    5.12 +if param.get("preview", atom.boolean) then
    5.13 +  filename = encode.file_path(WEBMCP_BASE_PATH, 'tmp', "file_upload-" .. file_upload_session .. "-" .. file_id .. ".preview.jpg")
    5.14 +end
    5.15 +
    5.16 +local data
    5.17 +
    5.18 +local fh = io.open(filename, "r")
    5.19 +if fh then
    5.20 +  data = fh:read("*a")
    5.21 +end
    5.22 +
    5.23 +
    5.24 +slot.set_layout(nil, content_type)
    5.25 +slot.put_into("data", data)
     6.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     6.2 +++ b/app/main/file/show.jpg.lua	Mon Feb 10 21:10:49 2020 +0100
     6.3 @@ -0,0 +1,12 @@
     6.4 +local id = param.get_id()
     6.5 +
     6.6 +local file = File:by_id(id)
     6.7 +
     6.8 +local output = file.data
     6.9 +
    6.10 +if param.get("preview", atom.boolean) then
    6.11 +  output = file.preview_data
    6.12 +end
    6.13 +
    6.14 +slot.set_layout(nil, file.content_type)
    6.15 +slot.put_into("data", output)
     7.1 --- a/app/main/initiative/show.lua	Mon Dec 09 15:54:57 2019 +0100
     7.2 +++ b/app/main/initiative/show.lua	Mon Feb 10 21:10:49 2020 +0100
     7.3 @@ -135,6 +135,35 @@
     7.4          end
     7.5        }
     7.6        
     7.7 +      if config.attachments then
     7.8 +
     7.9 +        local files = File:new_selector()
    7.10 +          :left_join("draft_attachment", nil, "draft_attachment.file_id = file.id")
    7.11 +          :add_where{ "draft_attachment.draft_id = ?", initiative.current_draft.id }
    7.12 +          :reset_fields()
    7.13 +          :add_field("file.id")
    7.14 +          :add_field("draft_attachment.title")
    7.15 +          :add_field("draft_attachment.description")
    7.16 +          :add_order_by("draft_attachment.id")
    7.17 +          :exec()
    7.18 +
    7.19 +        if #files > 0 then
    7.20 +          ui.container {
    7.21 +            attr = { class = "mdl-card__content mdl-card--border" },
    7.22 +            content = function()
    7.23 +              for i, file in ipairs(files) do
    7.24 +                ui.link{ module = "file", view = "show.jpg", id = file.id, content = function()
    7.25 +                  ui.image{ module = "file", view = "show.jpg", id = file.id, params = { preview = true } }
    7.26 +                end }
    7.27 +                ui.container{ content = file.title or "" }
    7.28 +                ui.container{ content = file.description or "" }
    7.29 +                slot.put("<br /><br />")
    7.30 +              end
    7.31 +            end
    7.32 +          }
    7.33 +        end
    7.34 +      end
    7.35 +
    7.36        local drafts_count = initiative:get_reference_selector("drafts"):count()
    7.37        
    7.38        if not config.voting_only then
     8.1 --- a/model/draft.lua	Mon Dec 09 15:54:57 2019 +0100
     8.2 +++ b/model/draft.lua	Mon Feb 10 21:10:49 2020 +0100
     8.3 @@ -97,5 +97,19 @@
     8.4  
     8.5    draft:render_content()
     8.6  
     8.7 +  local draft_attachments = DraftAttachment:new_selector()
     8.8 +    :add_where{ "draft_id = ?", old_draft.id }
     8.9 +    :exec()
    8.10 +
    8.11 +  for i, draft_attachment in ipairs(draft_attachments) do
    8.12 +    local new_draft_attachment = DraftAttachment:new()
    8.13 +    new_draft_attachment.draft_id = draft.id
    8.14 +    new_draft_attachment.file_id = draft_attachment.file_id
    8.15 +    new_draft_attachment.title = draft_attachment.title
    8.16 +    new_draft_attachment.description = draft_attachment.description
    8.17 +    new_draft_attachment:save()
    8.18 +  end
    8.19 +
    8.20    slot.put_into("notice", _"The initiative text has been updated")
    8.21 +  return draft.id
    8.22  end
     9.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     9.2 +++ b/model/draft_attachment.lua	Mon Feb 10 21:10:49 2020 +0100
     9.3 @@ -0,0 +1,5 @@
     9.4 +DraftAttachment = mondelefant.new_class()
     9.5 +DraftAttachment.table = "draft_attachment"
     9.6 +DraftAttachment.primary_key = "id"
     9.7 +
     9.8 +
    10.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    10.2 +++ b/model/file.lua	Mon Feb 10 21:10:49 2020 +0100
    10.3 @@ -0,0 +1,8 @@
    10.4 +File = mondelefant.new_class()
    10.5 +File.table = "file"
    10.6 +File.primary_key = "id"
    10.7 +
    10.8 +File.binary_columns = { 
    10.9 +  data = true,
   10.10 +  preview_data = true
   10.11 +}

Impressum / About Us