Added branding feature.
This commit is contained in:
parent
ca42df1ef6
commit
ac43efc60f
8 changed files with 267 additions and 60 deletions
|
@ -5,15 +5,30 @@ class App.SettingsArea extends App.Controller
|
||||||
# check authentication
|
# check authentication
|
||||||
return if !@authenticate()
|
return if !@authenticate()
|
||||||
|
|
||||||
App.Setting.bind 'refresh change', @render
|
@load()
|
||||||
App.Setting.fetch()
|
|
||||||
|
load: ->
|
||||||
|
@ajax(
|
||||||
|
id: "setting_area_#{@area}"
|
||||||
|
type: 'GET'
|
||||||
|
url: "#{@apiPath}/settings/area/#{@area}"
|
||||||
|
processData: true
|
||||||
|
success: (data, status, xhr) =>
|
||||||
|
App.Collection.load( localStorage: false, type: 'Setting', data: data )
|
||||||
|
@render()
|
||||||
|
)
|
||||||
|
|
||||||
render: =>
|
render: =>
|
||||||
settings = App.Setting.all()
|
settings = App.Setting.search(
|
||||||
|
filter:
|
||||||
|
area: @area
|
||||||
|
)
|
||||||
|
|
||||||
html = $('<div></div>')
|
html = $('<div></div>')
|
||||||
for setting in settings
|
for setting in settings
|
||||||
if setting.area is @area
|
if setting.name is 'product_logo'
|
||||||
|
item = new App.SettingsAreaLogo( setting: setting )
|
||||||
|
else
|
||||||
item = new App.SettingsAreaItem( setting: setting )
|
item = new App.SettingsAreaItem( setting: setting )
|
||||||
html.append( item.el )
|
html.append( item.el )
|
||||||
|
|
||||||
|
@ -55,6 +70,7 @@ class App.SettingsAreaItem extends App.Controller
|
||||||
|
|
||||||
update: (e) =>
|
update: (e) =>
|
||||||
e.preventDefault()
|
e.preventDefault()
|
||||||
|
@formDisable(e)
|
||||||
params = @formParam(e.target)
|
params = @formParam(e.target)
|
||||||
|
|
||||||
directValue = 0
|
directValue = 0
|
||||||
|
@ -78,6 +94,7 @@ class App.SettingsAreaItem extends App.Controller
|
||||||
ui = @
|
ui = @
|
||||||
@setting.save(
|
@setting.save(
|
||||||
done: =>
|
done: =>
|
||||||
|
ui.formEnable(e)
|
||||||
|
|
||||||
App.Event.trigger 'notify', {
|
App.Event.trigger 'notify', {
|
||||||
type: 'success'
|
type: 'success'
|
||||||
|
@ -90,4 +107,95 @@ class App.SettingsAreaItem extends App.Controller
|
||||||
|
|
||||||
# login check
|
# login check
|
||||||
App.Auth.loginCheck()
|
App.Auth.loginCheck()
|
||||||
|
fail: =>
|
||||||
|
ui.formEnable(e)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
class App.SettingsAreaLogo extends App.Controller
|
||||||
|
elements:
|
||||||
|
'.logo-preview': 'logoPreview'
|
||||||
|
|
||||||
|
events:
|
||||||
|
'submit form': 'submit'
|
||||||
|
'change .js-upload': 'onLogoPick'
|
||||||
|
|
||||||
|
constructor: ->
|
||||||
|
super
|
||||||
|
@render()
|
||||||
|
|
||||||
|
render: ->
|
||||||
|
logoFile = App.Config.get('product_logo')
|
||||||
|
logoUrl = App.Config.get('image_path') + "/#{logoFile}"
|
||||||
|
@html App.view('settings/logo')(
|
||||||
|
setting: @setting
|
||||||
|
logoUrl: logoUrl
|
||||||
|
)
|
||||||
|
|
||||||
|
onLogoPick: (event) =>
|
||||||
|
reader = new FileReader()
|
||||||
|
|
||||||
|
reader.onload = (e) =>
|
||||||
|
@logoPreview.attr('src', e.target.result)
|
||||||
|
|
||||||
|
file = event.target.files[0]
|
||||||
|
|
||||||
|
# if no file is given, about in file upload was used
|
||||||
|
if !file
|
||||||
|
return
|
||||||
|
|
||||||
|
maxSiteInMb = 8
|
||||||
|
if file.size && file.size > 1024 * 1024 * maxSiteInMb
|
||||||
|
#@showAlert( 'logo', App.i18n.translateInline( 'File too big, max. %s MB allowed.', maxSiteInMb ) )
|
||||||
|
@logoPreview.attr( 'src', '' )
|
||||||
|
return
|
||||||
|
|
||||||
|
reader.readAsDataURL(file)
|
||||||
|
|
||||||
|
submit: (e) =>
|
||||||
|
e.preventDefault()
|
||||||
|
@formDisable(e)
|
||||||
|
|
||||||
|
# get params
|
||||||
|
@params = @formParam(e.target)
|
||||||
|
|
||||||
|
# add logo
|
||||||
|
@params.logo = @logoPreview.attr('src')
|
||||||
|
|
||||||
|
store = (logoResizeDataUrl) =>
|
||||||
|
|
||||||
|
# store image
|
||||||
|
@params.logo_resize = logoResizeDataUrl
|
||||||
|
@ajax(
|
||||||
|
id: "setting_image_#{@setting.id}"
|
||||||
|
type: 'PUT'
|
||||||
|
url: "#{@apiPath}/settings/image/#{@setting.id}"
|
||||||
|
data: JSON.stringify(@params)
|
||||||
|
processData: true
|
||||||
|
success: (data, status, xhr) =>
|
||||||
|
@formEnable(e)
|
||||||
|
if data.result is 'ok'
|
||||||
|
@formEnable(e)
|
||||||
|
|
||||||
|
App.Event.trigger 'notify', {
|
||||||
|
type: 'success'
|
||||||
|
msg: App.i18n.translateContent('Update successful!')
|
||||||
|
timeout: 2000
|
||||||
|
}
|
||||||
|
@render()
|
||||||
|
|
||||||
|
App.Event.trigger( 'ui:rerender' )
|
||||||
|
for key, value of data.settings
|
||||||
|
App.Config.set( key, value )
|
||||||
|
else
|
||||||
|
App.Event.trigger 'notify', {
|
||||||
|
type: 'error'
|
||||||
|
msg: App.i18n.translateContent(data.message)
|
||||||
|
timeout: 2000
|
||||||
|
}
|
||||||
|
|
||||||
|
fail: =>
|
||||||
|
@formEnable(e)
|
||||||
|
)
|
||||||
|
|
||||||
|
# add resized image
|
||||||
|
App.ImageService.resizeForAvatar( @params.logo, @logoPreview.width(), @logoPreview.height(), store )
|
||||||
|
|
|
@ -1,31 +1,31 @@
|
||||||
|
class Branding extends App.ControllerTabs
|
||||||
|
constructor: ->
|
||||||
|
super
|
||||||
|
return if !@authenticate()
|
||||||
|
@title 'Branding', true
|
||||||
|
@tabs = [
|
||||||
|
{ name: 'Base', 'target': 'base', controller: App.SettingsArea, params: { area: 'System::Branding' } },
|
||||||
|
]
|
||||||
|
@render()
|
||||||
|
|
||||||
class System extends App.ControllerTabs
|
class System extends App.ControllerTabs
|
||||||
constructor: ->
|
constructor: ->
|
||||||
super
|
super
|
||||||
|
|
||||||
return if !@authenticate()
|
return if !@authenticate()
|
||||||
|
|
||||||
@title 'System', true
|
@title 'System', true
|
||||||
|
|
||||||
@tabs = [
|
@tabs = [
|
||||||
{ name: 'Base', 'target': 'base', controller: App.SettingsArea, params: { area: 'System::Base' } },
|
{ name: 'Base', 'target': 'base', controller: App.SettingsArea, params: { area: 'System::Base' } },
|
||||||
# { name: 'Language', 'target': 'language', controller: App.SettingsSystem, params: { area: 'System::Language' } },
|
|
||||||
# { name: 'Log', 'target': 'log', controller: App.SettingsSystem, params: { area: 'System::Log' } },
|
|
||||||
{ name: 'Storage', 'target': 'storage', controller: App.SettingsArea, params: { area: 'System::Storage' } },
|
{ name: 'Storage', 'target': 'storage', controller: App.SettingsArea, params: { area: 'System::Storage' } },
|
||||||
{ name: 'Geo Services', 'target': 'geo', controller: App.SettingsArea, params: { area: 'System::Geo' } },
|
{ name: 'Geo Services', 'target': 'geo', controller: App.SettingsArea, params: { area: 'System::Geo' } },
|
||||||
{ name: 'Frontend', 'target': 'ui', controller: App.SettingsArea, params: { area: 'System::UI' } },
|
{ name: 'Frontend', 'target': 'ui', controller: App.SettingsArea, params: { area: 'System::UI' } },
|
||||||
]
|
]
|
||||||
|
|
||||||
# render page
|
|
||||||
@render()
|
@render()
|
||||||
|
|
||||||
class Security extends App.ControllerTabs
|
class Security extends App.ControllerTabs
|
||||||
constructor: ->
|
constructor: ->
|
||||||
super
|
super
|
||||||
|
|
||||||
return if !@authenticate()
|
return if !@authenticate()
|
||||||
|
|
||||||
@title 'Security', true
|
@title 'Security', true
|
||||||
|
|
||||||
@tabs = [
|
@tabs = [
|
||||||
{ name: 'Base', 'target': 'base', controller: App.SettingsArea, params: { area: 'Security::Base' } },
|
{ name: 'Base', 'target': 'base', controller: App.SettingsArea, params: { area: 'Security::Base' } },
|
||||||
# { name: 'Authentication', 'target': 'auth', controller: App.SettingsArea, params: { area: 'Security::Authentication' } },
|
# { name: 'Authentication', 'target': 'auth', controller: App.SettingsArea, params: { area: 'Security::Authentication' } },
|
||||||
|
@ -33,42 +33,32 @@ class Security extends App.ControllerTabs
|
||||||
{ name: 'Third-Party Applications', 'target': 'third_party_auth', controller: App.SettingsArea, params: { area: 'Security::ThirdPartyAuthentication' } },
|
{ name: 'Third-Party Applications', 'target': 'third_party_auth', controller: App.SettingsArea, params: { area: 'Security::ThirdPartyAuthentication' } },
|
||||||
# { name: 'Session', 'target': 'session', controller: '' },
|
# { name: 'Session', 'target': 'session', controller: '' },
|
||||||
]
|
]
|
||||||
|
|
||||||
@render()
|
@render()
|
||||||
|
|
||||||
class Import extends App.ControllerTabs
|
class Import extends App.ControllerTabs
|
||||||
constructor: ->
|
constructor: ->
|
||||||
super
|
super
|
||||||
|
|
||||||
return if !@authenticate()
|
return if !@authenticate()
|
||||||
|
|
||||||
@title 'Import', true
|
@title 'Import', true
|
||||||
|
|
||||||
# import
|
|
||||||
@tabs = [
|
@tabs = [
|
||||||
{ name: 'Base', 'target': 'base', controller: App.SettingsArea, params: { area: 'Import::Base' } },
|
{ name: 'Base', 'target': 'base', controller: App.SettingsArea, params: { area: 'Import::Base' } },
|
||||||
{ name: 'OTRS', 'target': 'otrs', controller: App.SettingsArea, params: { area: 'Import::OTRS' } },
|
{ name: 'OTRS', 'target': 'otrs', controller: App.SettingsArea, params: { area: 'Import::OTRS' } },
|
||||||
]
|
]
|
||||||
|
|
||||||
@render()
|
@render()
|
||||||
|
|
||||||
class Ticket extends App.ControllerTabs
|
class Ticket extends App.ControllerTabs
|
||||||
constructor: ->
|
constructor: ->
|
||||||
super
|
super
|
||||||
|
|
||||||
return if !@authenticate()
|
return if !@authenticate()
|
||||||
|
|
||||||
@title 'Ticket', true
|
@title 'Ticket', true
|
||||||
|
|
||||||
# ticket
|
|
||||||
@tabs = [
|
@tabs = [
|
||||||
{ name: 'Base', 'target': 'base', controller: App.SettingsArea, params: { area: 'Ticket::Base' } },
|
{ name: 'Base', 'target': 'base', controller: App.SettingsArea, params: { area: 'Ticket::Base' } },
|
||||||
{ name: 'Number', 'target': 'number', controller: App.SettingsArea, params: { area: 'Ticket::Number' } },
|
{ name: 'Number', 'target': 'number', controller: App.SettingsArea, params: { area: 'Ticket::Number' } },
|
||||||
# { name: 'Sender Format', 'target': 'sender-format', controller: App.SettingsArea, params: { area: 'Ticket::SenderFormat' } },
|
# { name: 'Sender Format', 'target': 'sender-format', controller: App.SettingsArea, params: { area: 'Ticket::SenderFormat' } },
|
||||||
]
|
]
|
||||||
|
|
||||||
@render()
|
@render()
|
||||||
|
|
||||||
|
App.Config.set( 'SettingBranding', { prio: 1200, parent: '#settings', name: 'Branding', target: '#settings/branding', controller: Branding, role: ['Admin'] }, 'NavBarAdmin' )
|
||||||
App.Config.set( 'SettingSystem', { prio: 1400, parent: '#settings', name: 'System', target: '#settings/system', controller: System, role: ['Admin'] }, 'NavBarAdmin' )
|
App.Config.set( 'SettingSystem', { prio: 1400, parent: '#settings', name: 'System', target: '#settings/system', controller: System, role: ['Admin'] }, 'NavBarAdmin' )
|
||||||
App.Config.set( 'SettingSecurity', { prio: 1500, parent: '#settings', name: 'Security', target: '#settings/security', controller: Security, role: ['Admin'] }, 'NavBarAdmin' )
|
App.Config.set( 'SettingSecurity', { prio: 1500, parent: '#settings', name: 'Security', target: '#settings/security', controller: Security, role: ['Admin'] }, 'NavBarAdmin' )
|
||||||
App.Config.set( 'SettingImport', { prio: 1550, parent: '#settings', name: 'Import', target: '#settings/import', controller: Import, role: ['Admin'] }, 'NavBarAdmin' )
|
App.Config.set( 'SettingImport', { prio: 1550, parent: '#settings', name: 'Import', target: '#settings/import', controller: Import, role: ['Admin'] }, 'NavBarAdmin' )
|
||||||
|
|
36
app/assets/javascripts/app/views/settings/logo.jst.eco
Normal file
36
app/assets/javascripts/app/views/settings/logo.jst.eco
Normal file
|
@ -0,0 +1,36 @@
|
||||||
|
<form class="settings-entry" id="<%= @setting.name %>">
|
||||||
|
<h2><%- @T( @setting.title ) %></h2>
|
||||||
|
<p><%- @T( @setting.description ) %></p>
|
||||||
|
|
||||||
|
<div class="login branding centered darkBackground">
|
||||||
|
<div class="hero-unit">
|
||||||
|
<img class="logo-preview" src="<%= @logoUrl %>">
|
||||||
|
<div class="logo-preview-placeholder"><%- @T('Your Logo') %></div>
|
||||||
|
<div class="centered">
|
||||||
|
<div class="btn btn--success fileUpload"><%- @T('Change') %><input type="file" class="js-upload" name="logo" accept="image/*"></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="username"><%- @Ti( 'Username / email' ) %></label>
|
||||||
|
<input id="username" name="username" type="text" class="form-control" value="<%= @S('login') %>" autocapitalize="off" disabled="disabled"/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="password"><%- @Ti( 'Password' ) %></label>
|
||||||
|
<input id="password" name="password" type="password" class="form-control" value="some_pass" disabled="disabled"/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-group">
|
||||||
|
<label><input name="remember_me" value="1" type="checkbox" disabled="disabled"/> <%- @T( 'Remember me' ) %></label>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-controls">
|
||||||
|
<button class="btn btn--primary" type="submit" disabled="disabled"><%- @T( 'Sign in' ) %></button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="horizontal end">
|
||||||
|
<button type="submit" class="btn btn--primary"><%- @T( 'Submit' ) %></button>
|
||||||
|
</div>
|
||||||
|
</form>
|
|
@ -4811,7 +4811,7 @@ label + .wizard-buttonList {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.setup.wizard .logo-preview {
|
.setup.wizard .logo-preview, .branding .logo-preview {
|
||||||
display: block;
|
display: block;
|
||||||
height: 0;
|
height: 0;
|
||||||
max-width: 200px;
|
max-width: 200px;
|
||||||
|
@ -4832,7 +4832,7 @@ label + .wizard-buttonList {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.setup.wizard .logo-preview:not([src=""]) {
|
.setup.wizard .logo-preview:not([src=""]), .branding .logo-preview:not([src=""]) {
|
||||||
margin: 0 auto 15px;
|
margin: 0 auto 15px;
|
||||||
height: auto;
|
height: auto;
|
||||||
|
|
||||||
|
@ -4845,6 +4845,10 @@ label + .wizard-buttonList {
|
||||||
margin-top: 15px;
|
margin-top: 15px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.branding.login {
|
||||||
|
padding: 24px 24px 0px;
|
||||||
|
}
|
||||||
|
|
||||||
.import.wizard .wizard-slide {
|
.import.wizard .wizard-slide {
|
||||||
height: 300px;
|
height: 300px;
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,6 +6,14 @@ class SettingsController < ApplicationController
|
||||||
# GET /settings
|
# GET /settings
|
||||||
def index
|
def index
|
||||||
return if deny_if_not_role(Z_ROLENAME_ADMIN)
|
return if deny_if_not_role(Z_ROLENAME_ADMIN)
|
||||||
|
|
||||||
|
# only serve requested items
|
||||||
|
if params[:area]
|
||||||
|
model_index_render_result( Setting.where(area: params[:area]) )
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
# serve all items
|
||||||
model_index_render(Setting, params)
|
model_index_render(Setting, params)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -27,6 +35,57 @@ class SettingsController < ApplicationController
|
||||||
model_update_render(Setting, params)
|
model_update_render(Setting, params)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# PUT /settings/image/:id
|
||||||
|
def update_image
|
||||||
|
|
||||||
|
if !params[:logo]
|
||||||
|
render json: {
|
||||||
|
result: 'invalid',
|
||||||
|
message: 'Need logo param',
|
||||||
|
}
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
# validate image
|
||||||
|
if params[:logo] !~ /^data:image/i
|
||||||
|
render json: {
|
||||||
|
result: 'invalid',
|
||||||
|
message: 'Invalid payload, need data:image in logo param',
|
||||||
|
}
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
# process image
|
||||||
|
file = StaticAssets.data_url_attributes(params[:logo])
|
||||||
|
if !file[:content] || !file[:mime_type]
|
||||||
|
render json: {
|
||||||
|
result: 'invalid',
|
||||||
|
message: 'Unable to process image upload.',
|
||||||
|
}
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
# store image 1:1
|
||||||
|
StaticAssets.store_raw(file[:content], file[:mime_type])
|
||||||
|
|
||||||
|
# store resized image 1:1
|
||||||
|
setting = Setting.find_by(name: 'product_logo')
|
||||||
|
if params[:logo_resize] && params[:logo_resize] =~ /^data:image/i
|
||||||
|
|
||||||
|
# data:image/png;base64
|
||||||
|
file = StaticAssets.data_url_attributes( params[:logo_resize] )
|
||||||
|
|
||||||
|
# store image 1:1
|
||||||
|
setting.state = StaticAssets.store( file[:content], file[:mime_type] )
|
||||||
|
setting.save
|
||||||
|
end
|
||||||
|
|
||||||
|
render json: {
|
||||||
|
result: 'ok',
|
||||||
|
settings: [setting],
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
# DELETE /settings/1
|
# DELETE /settings/1
|
||||||
def destroy
|
def destroy
|
||||||
return if deny_if_not_role(Z_ROLENAME_ADMIN)
|
return if deny_if_not_role(Z_ROLENAME_ADMIN)
|
||||||
|
|
|
@ -3,8 +3,10 @@ Zammad::Application.routes.draw do
|
||||||
|
|
||||||
# base objects
|
# base objects
|
||||||
match api_path + '/settings', to: 'settings#index', via: :get
|
match api_path + '/settings', to: 'settings#index', via: :get
|
||||||
|
match api_path + '/settings/area/:area', to: 'settings#index', via: :get
|
||||||
match api_path + '/settings/:id', to: 'settings#show', via: :get
|
match api_path + '/settings/:id', to: 'settings#show', via: :get
|
||||||
match api_path + '/settings', to: 'settings#create', via: :post
|
match api_path + '/settings', to: 'settings#create', via: :post
|
||||||
|
match api_path + '/settings/image/:id', to: 'settings#update_image', via: :put
|
||||||
match api_path + '/settings/:id', to: 'settings#update', via: :put
|
match api_path + '/settings/:id', to: 'settings#update', via: :put
|
||||||
match api_path + '/settings/:id', to: 'settings#destroy', via: :delete
|
match api_path + '/settings/:id', to: 'settings#destroy', via: :delete
|
||||||
|
|
||||||
|
|
9
db/migrate/20150712000001_update_setting.rb
Normal file
9
db/migrate/20150712000001_update_setting.rb
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
class UpdateSetting < ActiveRecord::Migration
|
||||||
|
def up
|
||||||
|
%w(product_name product_logo organization).each {|setting_name|
|
||||||
|
setting = Setting.find_by(name: setting_name)
|
||||||
|
setting.area = 'System::Branding'
|
||||||
|
setting.save
|
||||||
|
}
|
||||||
|
end
|
||||||
|
end
|
41
db/seeds.rb
41
db/seeds.rb
|
@ -36,7 +36,7 @@ Setting.create_if_not_exists(
|
||||||
Setting.create_if_not_exists(
|
Setting.create_if_not_exists(
|
||||||
title: 'Product Name',
|
title: 'Product Name',
|
||||||
name: 'product_name',
|
name: 'product_name',
|
||||||
area: 'System::Base',
|
area: 'System::Branding',
|
||||||
description: 'Defines the name of the application, shown in the web interface, tabs and title bar of the web browser.',
|
description: 'Defines the name of the application, shown in the web interface, tabs and title bar of the web browser.',
|
||||||
options: {
|
options: {
|
||||||
form: [
|
form: [
|
||||||
|
@ -51,29 +51,10 @@ Setting.create_if_not_exists(
|
||||||
state: 'Zammad',
|
state: 'Zammad',
|
||||||
frontend: true
|
frontend: true
|
||||||
)
|
)
|
||||||
Setting.create_if_not_exists(
|
|
||||||
title: 'Logo',
|
|
||||||
name: 'product_logo',
|
|
||||||
area: 'System::CI',
|
|
||||||
description: 'Defines the logo of the application, shown in the web interface.',
|
|
||||||
options: {
|
|
||||||
form: [
|
|
||||||
{
|
|
||||||
display: '',
|
|
||||||
null: false,
|
|
||||||
name: 'product_logo',
|
|
||||||
tag: 'input',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
state: 'logo.svg',
|
|
||||||
frontend: true
|
|
||||||
)
|
|
||||||
|
|
||||||
Setting.create_if_not_exists(
|
Setting.create_if_not_exists(
|
||||||
title: 'Organization',
|
title: 'Organization',
|
||||||
name: 'organization',
|
name: 'organization',
|
||||||
area: 'System::Base',
|
area: 'System::Branding',
|
||||||
description: 'Will also be included in emails as an X-Header.',
|
description: 'Will also be included in emails as an X-Header.',
|
||||||
options: {
|
options: {
|
||||||
form: [
|
form: [
|
||||||
|
@ -88,6 +69,24 @@ Setting.create_if_not_exists(
|
||||||
state: '',
|
state: '',
|
||||||
frontend: true
|
frontend: true
|
||||||
)
|
)
|
||||||
|
Setting.create_if_not_exists(
|
||||||
|
title: 'Logo',
|
||||||
|
name: 'product_logo',
|
||||||
|
area: 'System::Branding',
|
||||||
|
description: 'Defines the logo of the application, shown in the web interface.',
|
||||||
|
options: {
|
||||||
|
form: [
|
||||||
|
{
|
||||||
|
display: '',
|
||||||
|
null: false,
|
||||||
|
name: 'product_logo',
|
||||||
|
tag: 'input',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
state: 'logo.svg',
|
||||||
|
frontend: true
|
||||||
|
)
|
||||||
|
|
||||||
Setting.create_if_not_exists(
|
Setting.create_if_not_exists(
|
||||||
title: 'SystemID',
|
title: 'SystemID',
|
||||||
|
|
Loading…
Reference in a new issue