zeronet/plugins/UiConfig/media/js/UiConfig.coffee
2018-07-10 03:30:47 +02:00

223 lines
6.8 KiB
CoffeeScript

window.h = maquette.h
class UiConfig extends ZeroFrame
init: ->
@save_visible = true
@config = null # Setting currently set on the server
@values = null # Entered values on the page
window.onbeforeunload = =>
if @getValuesChanged().length > 0
return true
else
return null
onOpenWebsocket: =>
@cmd("wrapperSetTitle", "Config - ZeroNet")
@updateConfig()
updateConfig: (cb) =>
@cmd "configList", [], (res) =>
@config = res
@values = {}
@config_storage = new ConfigStorage(@config)
for key, item of res
@values[key] = @config_storage.formatValue(item.value)
@projector.scheduleRender()
cb?()
createProjector: =>
@projector = maquette.createProjector()
@projector.replace($("#content"), @render)
@projector.replace($("#bottom-save"), @renderBottomSave)
@projector.replace($("#bottom-restart"), @renderBottomRestart)
getValuesChanged: =>
values_changed = []
for key, value of @values
if @config_storage.formatValue(value) != @config_storage.formatValue(@config[key].value)
values_changed.push({key: key, value: value})
return values_changed
getValuesPending: =>
values_pending = []
for key, item of @config
if item.pending
values_pending.push(key)
return values_pending
saveValues: (cb) =>
changed_values = @getValuesChanged()
for item, i in changed_values
last = i == changed_values.length - 1
value = @config_storage.deformatValue(item.value, typeof(@config[item.key].default))
value_same_as_default = JSON.stringify(@config[item.key].default) == JSON.stringify(value)
if value_same_as_default
value = null
@saveValue(item.key, value, if last then cb else null)
saveValue: (key, value, cb) =>
if key == "open_browser"
if value
value = "default_browser"
else
value = "False"
Page.cmd "configSet", [key, value], (res) =>
if res != "ok"
Page.cmd "wrapperNotification", ["error", res.error]
cb?()
renderSection: (section) =>
h("div.section", {key: section.title}, [
h("h2", section.title),
h("div.config-items", section.items.map @renderSectionItem)
])
handleResetClick: (e) =>
node = e.currentTarget
config_key = node.attributes.config_key.value
default_value = node.attributes.default_value?.value
Page.cmd "wrapperConfirm", ["Reset #{config_key} value?", "Reset to default"], (res) =>
if (res)
@values[config_key] = default_value
Page.projector.scheduleRender()
renderSectionItem: (item) =>
value_pos = item.value_pos
if item.type == "textarea"
value_pos ?= "fullwidth"
else
value_pos ?= "right"
value_changed = @config_storage.formatValue(@values[item.key]) != item.value
value_default = @config_storage.formatValue(@values[item.key]) == item.default
if item.key in ["open_browser", "fileserver_port"] # Value default for some settings makes no sense
value_default = true
marker_title = "Changed from default value: #{item.default} -> #{@values[item.key]}"
if item.pending
marker_title += " (change pending until client restart)"
h("div.config-item", [
h("div.title", [
h("h3", item.title),
h("div.description", item.description)
])
h("div.value.value-#{value_pos}",
if item.type == "select"
@renderValueSelect(item)
else if item.type == "checkbox"
@renderValueCheckbox(item)
else if item.type == "textarea"
@renderValueTextarea(item)
else
@renderValueText(item)
h("a.marker", {
href: "#Reset", title: marker_title,
onclick: @handleResetClick, config_key: item.key, default_value: item.default,
classes: {default: value_default, changed: value_changed, visible: not value_default or value_changed or item.pending, pending: item.pending}
}, "\u2022")
)
])
# Values
handleInputChange: (e) =>
node = e.target
config_key = node.attributes.config_key.value
@values[config_key] = node.value
Page.projector.scheduleRender()
handleCheckboxChange: (e) =>
node = e.currentTarget
config_key = node.attributes.config_key.value
value = not node.classList.contains("checked")
@values[config_key] = value
Page.projector.scheduleRender()
renderValueText: (item) =>
value = @values[item.key]
if not value
value = ""
h("input.input-#{item.type}", {type: item.type, config_key: item.key, value: value, placeholder: item.placeholder, oninput: @handleInputChange})
autosizeTextarea: (e) =>
@log "autosize", arguments
if e.currentTarget
# @handleInputChange(e)
node = e.currentTarget
else
node = e
height_before = node.style.height
if height_before
node.style.height = "0px"
h = node.offsetHeight
scrollh = node.scrollHeight + 20
if scrollh > h
node.style.height = scrollh + "px"
else
node.style.height = height_before
renderValueTextarea: (item) =>
value = @values[item.key]
if not value
value = ""
h("textarea.input-#{item.type}.input-text",{
type: item.type, config_key: item.key, oninput: @handleInputChange, afterCreate: @autosizeTextarea, updateAnimation: @autosizeTextarea, value: value
})
renderValueCheckbox: (item) =>
if @values[item.key] and @values[item.key] != "False"
checked = true
else
checked = false
h("div.checkbox", {onclick: @handleCheckboxChange, config_key: item.key, classes: {checked: checked}}, h("div.checkbox-skin"))
renderValueSelect: (item) =>
h("select.input-select", {config_key: item.key, oninput: @handleInputChange},
item.options.map (option) =>
h("option", {selected: option.value == @values[item.key], value: option.value}, option.title)
)
render: =>
if not @config
return h("div.content")
h("div.content", [
@config_storage.items.map @renderSection
])
handleSaveClick: =>
@save_loading = true
@logStart "Save"
@saveValues =>
@save_loading = false
@logEnd "Save"
@updateConfig()
Page.projector.scheduleRender()
return false
renderBottomSave: =>
values_changed = @getValuesChanged()
h("div.bottom.bottom-save", {classes: {visible: values_changed.length}}, h("div.bottom-content", [
h("div.title", "#{values_changed.length} configuration item value changed"),
h("a.button.button-submit.button-save", {href: "#Save", classes: {loading: @save_loading}, onclick: @handleSaveClick}, "Save settings")
]))
handleRestartClick: =>
@restart_loading = true
Page.cmd("serverShutdown", {restart: true})
Page.projector.scheduleRender()
return false
renderBottomRestart: =>
values_pending = @getValuesPending()
values_changed = @getValuesChanged()
h("div.bottom.bottom-restart", {classes: {visible: values_pending.length and not values_changed.length}}, h("div.bottom-content", [
h("div.title", "Some changes settings requires restart"),
h("a.button.button-submit.button-restart", {href: "#Restart", classes: {loading: @restart_loading}, onclick: @handleRestartClick}, "Restart ZeroNet client")
]))
window.Page = new UiConfig()
window.Page.createProjector()