Added file upload dialog

This commit is contained in:
G. Gibson 2022-04-14 11:50:59 -07:00
parent 20dad4ac76
commit d09194635d
3 changed files with 213 additions and 104 deletions

View file

@ -170,6 +170,68 @@ module GxG
true true
end end
# #
def post(form_data="", options={}, &handler)
# Uses POST method, with data payload
if @active
if form_data.is_a?(::GxG::Gui::Form)
action = form_data.get_attribute("action").to_s
if action.size > 0
if @relative_url.to_s.size > 0
the_url = "#{@host_prefix}#{@relative_url.to_s}#{action.to_s}?display=#{@display_path.to_s}"
else
the_url = "#{@host_prefix}#{action.to_s}?display=#{@display_path.to_s}"
end
else
if @relative_url.to_s.size > 0
the_url = "#{@host_prefix}#{@relative_url.to_s}?display=#{@display_path.to_s}"
else
the_url = "#{@host_prefix}?display=#{@display_path.to_s}"
end
end
the_xhr = `new XMLHttpRequest`
`#{the_xhr}.open('POST',#{the_url},true)`
`#{the_xhr}.timeout = #{(options[:timeout] || 5000)}`
`#{the_xhr}.setRequestHeader('X-Requested-With','XMLHttpRequest')`
`#{the_xhr}.setRequestHeader('Accept','application/json')`
`#{the_xhr}.setRequestHeader('X-CSRF-Token', #{@csrf})`
`#{the_xhr}.setRequestHeader('Content-Type', 'multipart/form-data')`
failed = Proc.new do |reason={:error => "unknown"}|
log_error(reason)
end
succeeded = Proc.new do
response_code = (`#{the_xhr}.status`).to_i
if response_code < 300
begin
the_response = (::JSON.parse(`#{the_xhr}.response`,{:symbolize_names => true}))
log_info(the_response.inspect)
if handler.respond_to?(:call)
handler.call(the_response)
end
rescue Exception => the_error
log_error({:error => the_error, :parameters => `#{the_xhr}.response`})
end
else
begin
failed.call(::JSON.parse(`#{the_xhr}.response`,{:symbolize_names => true}))
rescue Exception => the_error
log_error({:error => the_error, :parameters => `#{the_xhr}.response`})
end
end
end
`#{the_xhr}.addEventListener('load', #{succeeded})`
`#{the_xhr}.addEventListener('error', #{failed})`
`#{the_xhr}.addEventListener('timeout', #{failed})`
`#{the_xhr}.addEventListener('abort', #{failed})`
`#{the_xhr}.send(#{form_data.element})`
#
true
else
false
end
end
#
end
#
def push(the_message=nil, options={}) def push(the_message=nil, options={})
if @active if @active
# Uses PUT method, with data payload # Uses PUT method, with data payload
@ -643,7 +705,7 @@ module GxG
end end
end end
# Service Call Event Support: # Service Call Event Support:
def call_event(service=:core, op_frame={:noop => nil}, error_handler=nil, &the_handler) def call_event(service=:core, op_frame={:interface => true}, error_handler=nil, &the_handler)
if self.open? if self.open?
if op_frame.is_a?(::Hash) && the_handler if op_frame.is_a?(::Hash) && the_handler
self.pull_data({:call_event => {:service => service.to_s, :op_frame => op_frame}},error_handler) do |data| self.pull_data({:call_event => {:service => service.to_s, :op_frame => op_frame}},error_handler) do |data|

View file

@ -2127,4 +2127,26 @@ module GxG
::GxG::Gui::register_component_class(:"org.gxg.gui.topbar.right", ::GxG::Gui::TopbarRight) ::GxG::Gui::register_component_class(:"org.gxg.gui.topbar.right", ::GxG::Gui::TopbarRight)
# #
end end
end
#
class Object
private
def new_component(the_format_moniker=nil)
result = nil
if the_format_moniker
if ::GxG::Gui::component_registered?(the_format_moniker.to_s.to_sym)
result = ::GxG::Database::DetachedHash.new
result[:component] = the_format_moniker.to_s
result[:settings] = {}
result[:options] = {}
result[:script] = ""
result[:content] = []
else
log_error("Component #{the_format_moniker.inspect} not registered.")
end
else
log_error("You MUST specify a registered component moniker.")
end
result
end
end end

View file

@ -568,6 +568,107 @@ module GxG
# Page extensions # Page extensions
module Vdom module Vdom
class Page class Page
# File Upload Dialog
def upload_dialog(the_application=nil, details=nil, &block)
self.layout_refresh()
# Determine Dialog Details:
window_title = (details || {:title => "Choose a file:"})[:title].to_s
banner_text = (details || {:banner => "Choose a file to upload"})[:banner].to_s
destination_path = (details || {:destination => nil})[:destination].to_s
# Define bounds: (in px)
total_width = (self.layout_content_area()[:page_width].to_f * 0.25).to_i
form_padding = 20
form_margin = 5
inner_width = (total_width - ((form_padding + form_margin) * 2))
total_height = ((form_padding + form_margin) * 2)
#
banner_font_size = 16
if banner_text.to_s.size > 40
banner_height = ((banner_text.size.to_f / 40.0) * banner_font_size.to_f).round.to_i
else
banner_height = banner_font_size
end
input_font_size = 16
#
if destination_path.size > 0
# Main Build:
form = new_component(:"org.gxg.gui.form")
form[:options][:action] = "/file_upload"
form[:options][:method] = "POST"
form[:options][:enctype] = "multipart/form-data"
form[:options][:style] = {:"background-color" => "#f2f2f2", :padding => "20px", :margin => "5px", :width => "100%"}
#
total_height = 330
#
file_input = new_component(:"org.gxg.gui.input.file")
file_input.title = "file"
file_input[:options][:name] = "file"
form[:content] << file_input
#
destination = new_component(:"org.gxg.gui.input.hidden")
destination.title = "destination"
destination[:options][:name] = "destination"
destination[:options][:value] = destination_path
form[:content] << destination
#
grid_container = new_component(:"org.gxg.gui.grid.container")
cancel_frame = new_component(:"org.gxg.gui.grid.x")
submit_frame = new_component(:"org.gxg.gui.grid.x")
cancel_button = new_component(:"org.gxg.gui.input.button")
submit_button = new_component(:"org.gxg.gui.input.button.submit")
cancel_frame[:content] << cancel_button
submit_frame[:content] << submit_button
grid_container[:content] << cancel_frame
grid_container[:content] << submit_frame
form[:content] << grid_container
#
cancel_button[:script] = "
on(:mouseup) do |event|
the_window = self.find_parent_type(::GxG::Gui::DialogBox)
form = self.find_parent_type(::GxG::Gui::Form)
if the_window && form
the_window.respond({:action => :cancel})
end
end
"
#
submit_button[:script] = "
on(:mouseup) do |event|
the_window = self.find_parent_type(::GxG::Gui::DialogBox)
form = self.find_parent_type(::GxG::Gui::Form)
if the_window && form
page.set_busy true
::GxG::CONNECTION.post(form) do |response|
page.set_busy false
the_window.respond({:action => :upload, :destination => form.form_data[:destination].to_s})
end
end
end
"
#
viewport = new_component(:"org.gxg.gui.application.viewport")
viewport.title = "gxg_selection_viewport"
viewport[:options][:style] = {:overflow => "hidden", :width => "100%", :height => "100%"}
viewport[:content] << form
#
dialog_source = new_component(:"org.gxg.gui.window.dialog")
dialog_source.title = window_title
dialog_source[:options] = {:window_title => window_title, :states => {:hidden => true}, :width => 350, :height => total_height}
dialog_source[:content] << viewport
#
begin
self.dialog_open(dialog_source, the_application, details, &block)
true
rescue Exception => the_error
log_error({:error => the_error, :parameters => details})
false
end
#
else
log_error("You MUST provide a destination path")
false
end
end
# Choice Dialog # Choice Dialog
def choice_dialog(the_application=nil, details=nil, &block) def choice_dialog(the_application=nil, details=nil, &block)
# details: {:type => :choose, :title => "Some Title", :banner => "Some Text Here"} # details: {:type => :choose, :title => "Some Title", :banner => "Some Text Here"}
@ -812,27 +913,18 @@ module GxG
end end
" "
# #
menu_bar = ::GxG::Database::DetachedHash.new
menu_bar = new_component(:"org.gxg.gui.menu.bar")
menu_bar.title = "gxg_path_menu_bar" menu_bar.title = "gxg_path_menu_bar"
menu_bar[:component] = "org.gxg.gui.menu.bar"
menu_bar[:settings] = {:path => (details[:path] || "/")} menu_bar[:settings] = {:path => (details[:path] || "/")}
menu_bar[:options] = {}
menu_bar[:script] = ""
menu_bar[:content] = []
# #
menu_header = ::GxG::Database::DetachedHash.new menu_header = new_component(:"org.gxg.gui.menu.item")
menu_header.title = "gxg_path_menu_header" menu_header.title = "gxg_path_menu_header"
menu_header[:component] = "org.gxg.gui.menu.item"
menu_header[:settings] = {:label => File.basename(menu_bar[:settings][:path]), :data => nil} menu_header[:settings] = {:label => File.basename(menu_bar[:settings][:path]), :data => nil}
menu_header[:options] = {}
menu_header[:script] = ""
menu_header[:content] = []
# #
menu = ::GxG::Database::DetachedHash.new menu = new_component(:"org.gxg.gui.menu")
menu.title = "gxg_path_menu" menu.title = "gxg_path_menu"
menu[:component] = "org.gxg.gui.menu"
menu[:settings] = {:item_script => menu_item_script} menu[:settings] = {:item_script => menu_item_script}
menu[:options] = {}
menu[:script] = " menu[:script] = "
def update_menu(the_path=nil) def update_menu(the_path=nil)
if the_path.is_a?(::String) if the_path.is_a?(::String)
@ -862,30 +954,23 @@ module GxG
end end
end end
" "
menu[:content] = []
# #
menu_manifest = [] menu_manifest = []
(0..(menu_bar[:settings][:path].split("/").size - 1)).each do |the_index| (0..(menu_bar[:settings][:path].split("/").size - 1)).each do |the_index|
menu_manifest << (menu_bar[:settings][:path].split("/")[0..(the_index)].join("/")) menu_manifest << (menu_bar[:settings][:path].split("/")[0..(the_index)].join("/"))
end end
menu_manifest.reverse[1..-1].each do |the_path| menu_manifest.reverse[1..-1].each do |the_path|
the_item = ::GxG::Database::DetachedHash.new the_item = new_component(:"org.gxg.gui.menu.item")
the_item[:component] = "org.gxg.gui.menu.item"
the_item[:settings] = {:label => File.basename(the_path), :data => the_path} the_item[:settings] = {:label => File.basename(the_path), :data => the_path}
the_item[:options] = {}
the_item[:script] = menu_item_script the_item[:script] = menu_item_script
the_item[:content] = []
menu[:content] << the_item menu[:content] << the_item
end end
# #
menu_header[:content] << menu menu_header[:content] << menu
menu_bar[:content] << menu_header menu_bar[:content] << menu_header
# #
menu_bar_cell = ::GxG::Database::DetachedHash.new menu_bar_cell = new_component(:"org.gxg.gui.block.table.cell")
menu_bar_cell[:component] = "org.gxg.gui.block.table.cell"
menu_bar_cell[:settings] = {}
menu_bar_cell[:options] = {:style => {:border => "1px solid #c2c2c2", :padding => "0px", :margin => "0px", :width => "100%"}} menu_bar_cell[:options] = {:style => {:border => "1px solid #c2c2c2", :padding => "0px", :margin => "0px", :width => "100%"}}
menu_bar_cell[:script] = ""
menu_bar_cell[:content] = [(menu_bar)] menu_bar_cell[:content] = [(menu_bar)]
# SubItem List: # SubItem List:
list_item_script = " list_item_script = "
@ -911,9 +996,8 @@ module GxG
self.select() self.select()
end end
" "
subitems = ::GxG::Database::DetachedHash.new subitems = new_component(:"org.gxg.gui.list")
subitems.title = "gxg_path_subitems" subitems.title = "gxg_path_subitems"
subitems[:component] = "org.gxg.gui.list"
subitems[:settings] = {:list_item_script => list_item_script} subitems[:settings] = {:list_item_script => list_item_script}
subitems[:options] = {:style => {:clear => "both", :"list-style" => "none", :padding => "0px", :margin => "0px"}} subitems[:options] = {:style => {:clear => "both", :"list-style" => "none", :padding => "0px", :margin => "0px"}}
subitems[:script] = " subitems[:script] = "
@ -1006,8 +1090,7 @@ module GxG
end end
end end
" "
subitems[:content] = [] #
# xxx
case dialog_type case dialog_type
when :save when :save
subitems[:script] = (subitems[:script] + "\n" + " subitems[:script] = (subitems[:script] + "\n" + "
@ -1095,39 +1178,24 @@ module GxG
") ")
end end
# #
subitems_container = ::GxG::Database::DetachedHash.new subitems_container = new_component(:"org.gxg.gui.block")
subitems_container[:component] = "org.gxg.gui.block"
subitems_container[:settings] = {}
subitems_container[:options] = {:style => {:width => "100%", :height => "192px", :"overflow-y" => "scroll"}} subitems_container[:options] = {:style => {:width => "100%", :height => "192px", :"overflow-y" => "scroll"}}
subitems_container[:script] = ""
subitems_container[:content] = [(subitems)] subitems_container[:content] = [(subitems)]
# #
subitems_cell = ::GxG::Database::DetachedHash.new subitems_cell = new_component(:"org.gxg.gui.block.table.cell")
subitems_cell[:component] = "org.gxg.gui.block.table.cell"
subitems_cell[:settings] = {}
subitems_cell[:options] = {:style => {:border => "1px solid #c2c2c2", :padding => "0px", :margin => "0px", :width => "100%"}} subitems_cell[:options] = {:style => {:border => "1px solid #c2c2c2", :padding => "0px", :margin => "0px", :width => "100%"}}
subitems_cell[:script] = ""
subitems_cell[:content] = [(subitems_container)] subitems_cell[:content] = [(subitems_container)]
# Save As ... Field # Save As ... Field
save_name = ::GxG::Database::DetachedHash.new save_name = new_component(:"org.gxg.gui.input.text")
save_name.title = "gxg_save_name" save_name.title = "gxg_save_name"
save_name[:component] = "org.gxg.gui.input.text"
save_name[:settings] = {}
save_name[:options] = {:style => {:"background-color" => "#f2f2f2", :"font-size" => "16px", :width => "100%"}} save_name[:options] = {:style => {:"background-color" => "#f2f2f2", :"font-size" => "16px", :width => "100%"}}
save_name[:script] = ""
save_name[:content] = []
# #
save_name_cell = ::GxG::Database::DetachedHash.new save_name_cell = new_component(:"org.gxg.gui.block.table.cell")
save_name_cell[:component] = "org.gxg.gui.block.table.cell"
save_name_cell[:settings] = {}
save_name_cell[:options] = {:style => {:padding => "0px", :margin => "0px", :width => "100%"}} save_name_cell[:options] = {:style => {:padding => "0px", :margin => "0px", :width => "100%"}}
save_name_cell[:script] = ""
save_name_cell[:content] = [(save_name)] save_name_cell[:content] = [(save_name)]
# Buttons: # Buttons:
action_btn = ::GxG::Database::DetachedHash.new action_btn = new_component(:"org.gxg.gui.input.button.submit")
action_btn.title = "gxg_action_button" action_btn.title = "gxg_action_button"
action_btn[:component] = "org.gxg.gui.input.button.submit"
action_btn[:settings] = {}
action_btn[:options] = {:content => action_title, :style => {:padding => "0px", :width => "80px", :height => "32px"}} action_btn[:options] = {:content => action_title, :style => {:padding => "0px", :width => "80px", :height => "32px"}}
action_btn[:script] = " action_btn[:script] = "
on(:mouseup) do |event| on(:mouseup) do |event|
@ -1143,19 +1211,13 @@ module GxG
end end
end end
" "
action_btn[:content] = []
# #
action_cell = ::GxG::Database::DetachedHash.new action_cell = new_component(:"org.gxg.gui.block.table.cell")
action_cell[:component] = "org.gxg.gui.block.table.cell"
action_cell[:settings] = {}
action_cell[:options] = {:style => {:padding => "10px 0px 0px 35px", :margin => "0px", :width => "50%"}} action_cell[:options] = {:style => {:padding => "10px 0px 0px 35px", :margin => "0px", :width => "50%"}}
action_cell[:script] = ""
action_cell[:content] = [(action_btn)] action_cell[:content] = [(action_btn)]
# #
cancel_btn = ::GxG::Database::DetachedHash.new cancel_btn = new_component(:"org.gxg.gui.input.button.submit")
cancel_btn.title = "gxg_cancel_button" cancel_btn.title = "gxg_cancel_button"
cancel_btn[:component] = "org.gxg.gui.input.button.submit"
cancel_btn[:settings] = {}
cancel_btn[:options] = {:content => "Cancel", :style => {:padding => "2px", :width => "80px", :height => "32px"}} cancel_btn[:options] = {:content => "Cancel", :style => {:padding => "2px", :width => "80px", :height => "32px"}}
cancel_btn[:script] = " cancel_btn[:script] = "
on(:mouseup) do |event| on(:mouseup) do |event|
@ -1165,79 +1227,48 @@ module GxG
end end
end end
" "
cancel_btn[:content] = []
# #
cancel_cell = ::GxG::Database::DetachedHash.new cancel_cell = new_component(:"org.gxg.gui.block.table.cell")
cancel_cell[:component] = "org.gxg.gui.block.table.cell"
cancel_cell[:settings] = {}
cancel_cell[:options] = {:style => {:padding => "10px 0px 0px 35px", :margin => "0px", :width => "50%"}} cancel_cell[:options] = {:style => {:padding => "10px 0px 0px 35px", :margin => "0px", :width => "50%"}}
cancel_cell[:script] = ""
cancel_cell[:content] = [(cancel_btn)] cancel_cell[:content] = [(cancel_btn)]
# #
# Rows: # Rows:
row_one = ::GxG::Database::DetachedHash.new row_one = new_component(:"org.gxg.gui.block.table.row")
row_one[:component] = "org.gxg.gui.block.table.row"
row_one[:settings] = {}
row_one[:options] = {:style => {:padding => "0px", :margin => "0px", :width => "100%"}} row_one[:options] = {:style => {:padding => "0px", :margin => "0px", :width => "100%"}}
row_one[:script] = ""
row_one[:content] = [(menu_bar_cell)] row_one[:content] = [(menu_bar_cell)]
# #
row_two = ::GxG::Database::DetachedHash.new row_two = new_component(:"org.gxg.gui.block.table.row")
row_two[:component] = "org.gxg.gui.block.table.row"
row_two[:settings] = {}
row_two[:options] = {:style => {:padding => "0px", :margin => "0px", :width => "100%"}} row_two[:options] = {:style => {:padding => "0px", :margin => "0px", :width => "100%"}}
row_two[:script] = ""
row_two[:content] = [(subitems_cell)] row_two[:content] = [(subitems_cell)]
# #
row_three = ::GxG::Database::DetachedHash.new row_three = new_component(:"org.gxg.gui.block.table.row")
row_three[:component] = "org.gxg.gui.block.table.row"
row_three[:settings] = {}
row_three[:options] = {:style => {:padding => "0px", :margin => "0px", :width => "100%"}} row_three[:options] = {:style => {:padding => "0px", :margin => "0px", :width => "100%"}}
row_three[:script] = ""
row_three[:content] = [(save_name_cell)] row_three[:content] = [(save_name_cell)]
# #
row_four = ::GxG::Database::DetachedHash.new row_four = new_component(:"org.gxg.gui.block.table.row")
row_four[:component] = "org.gxg.gui.block.table.row"
row_four[:settings] = {}
row_four[:options] = {:style => {:padding => "0px", :margin => "0px", :width => "100%"}} row_four[:options] = {:style => {:padding => "0px", :margin => "0px", :width => "100%"}}
row_four[:script] = ""
row_four[:content] = [(cancel_cell),(action_cell)] row_four[:content] = [(cancel_cell),(action_cell)]
# #
# Tables: # Tables:
table_one = ::GxG::Database::DetachedHash.new table_one = new_component(:"org.gxg.gui.block.table")
table_one[:component] = "org.gxg.gui.block.table"
table_one[:settings] = {}
table_one[:options] = {:style => {:padding => "0px", :margin => "0px", :width => "300px", :height => "32px"}} table_one[:options] = {:style => {:padding => "0px", :margin => "0px", :width => "300px", :height => "32px"}}
table_one[:script] = ""
table_one[:content] = [(row_one)] table_one[:content] = [(row_one)]
# #
table_two = ::GxG::Database::DetachedHash.new table_two = new_component(:"org.gxg.gui.block.table")
table_two[:component] = "org.gxg.gui.block.table"
table_two[:settings] = {}
table_two[:options] = {:style => {:padding => "0px", :margin => "0px", :width => "300px", :height => "192px"}} table_two[:options] = {:style => {:padding => "0px", :margin => "0px", :width => "300px", :height => "192px"}}
table_two[:script] = ""
table_two[:content] = [(row_two)] table_two[:content] = [(row_two)]
# #
table_three = ::GxG::Database::DetachedHash.new table_three = new_component(:"org.gxg.gui.block.table")
table_three[:component] = "org.gxg.gui.block.table"
table_three[:settings] = {}
table_three[:options] = {:style => {:padding => "0px", :margin => "0px", :width => "300px", :height => "32px"}} table_three[:options] = {:style => {:padding => "0px", :margin => "0px", :width => "300px", :height => "32px"}}
table_three[:script] = ""
table_three[:content] = [(row_three)] table_three[:content] = [(row_three)]
# #
table_four = ::GxG::Database::DetachedHash.new table_four = new_component(:"org.gxg.gui.block.table")
table_four[:component] = "org.gxg.gui.block.table"
table_four[:settings] = {}
table_four[:options] = {:style => {:padding => "0px", :margin => "0px", :width => "300px", :height => "32px"}} table_four[:options] = {:style => {:padding => "0px", :margin => "0px", :width => "300px", :height => "32px"}}
table_four[:script] = ""
table_four[:content] = [(row_four)] table_four[:content] = [(row_four)]
# #
# Main Build: # Main Build:
form = ::GxG::Database::DetachedHash.new form = new_component(:"org.gxg.gui.form")
form[:component] = "org.gxg.gui.form"
form[:settings] = {}
form[:options] = {:style => {:"background-color" => "#f2f2f2", :padding => "20px", :margin => "5px", :width => "100%"}} form[:options] = {:style => {:"background-color" => "#f2f2f2", :padding => "20px", :margin => "5px", :width => "100%"}}
form[:script] = ""
form[:content] = [] form[:content] = []
# #
total_height = 330 total_height = 330
@ -1249,20 +1280,14 @@ module GxG
end end
form[:content] << table_four form[:content] << table_four
# #
viewport = ::GxG::Database::DetachedHash.new viewport = new_component(:"org.gxg.gui.application.viewport")
viewport.title = "gxg_selection_viewport" viewport.title = "gxg_selection_viewport"
viewport[:component] = "org.gxg.gui.application.viewport"
viewport[:settings] = {}
viewport[:options] = {:style => {:overflow => "hidden", :width => "100%", :height => "100%"}} viewport[:options] = {:style => {:overflow => "hidden", :width => "100%", :height => "100%"}}
viewport[:script] = ""
viewport[:content] = [(form)] viewport[:content] = [(form)]
# #
dialog_source = ::GxG::Database::DetachedHash.new dialog_source = new_component(:"org.gxg.gui.window.dialog")
dialog_source.title = window_title dialog_source.title = window_title
dialog_source[:component] = "org.gxg.gui.window.dialog"
dialog_source[:settings] = {}
dialog_source[:options] = {:window_title => window_title, :states => {:hidden => true}, :width => 350, :height => total_height} dialog_source[:options] = {:window_title => window_title, :states => {:hidden => true}, :width => 350, :height => total_height}
dialog_source[:script] = ""
dialog_source[:content] = [(viewport)] dialog_source[:content] = [(viewport)]
# #
begin begin