chg: [instance:settings] Improved support of checkboxes
parent
362a42787a
commit
7c4b45a6e0
|
@ -248,12 +248,15 @@ class SettingsProviderTable extends AppTable
|
|||
],
|
||||
'UI' => [
|
||||
'General' => [
|
||||
],
|
||||
'app.ui.dark' => [
|
||||
'description' => __('Enable the dark theme of the application'),
|
||||
'default' => false,
|
||||
'name' => __('Dark theme'),
|
||||
'type' => 'boolean',
|
||||
'app.ui.dark' => [
|
||||
'description' => __('Enable the dark theme of the application'),
|
||||
'default' => false,
|
||||
'name' => __('Dark theme'),
|
||||
'test' => function() {
|
||||
return 'Fake error';
|
||||
},
|
||||
'type' => 'boolean',
|
||||
],
|
||||
],
|
||||
],
|
||||
],
|
||||
|
|
|
@ -129,7 +129,7 @@ function genLevel1($level1Setting, $appView)
|
|||
}
|
||||
$contentHtml = implode('', $content1);
|
||||
$scrollspyNav = genScrollspyNav($nav1);
|
||||
$mainPanelHeight = 'calc(100vh - 8px - 42px - 1rem - 56px - 38px - 1rem)';
|
||||
$mainPanelHeight = 'calc(100vh - 42px - 1rem - 56px - 38px - 1rem)';
|
||||
$container = '<div class="d-flex">';
|
||||
$container .= "<div class=\"\" style=\"flex: 0 0 10em;\">{$scrollspyNav}</div>";
|
||||
$container .= "<div data-spy=\"scroll\" data-target=\"#navbar-scrollspy-setting\" data-offset=\"25\" style=\"height: {$mainPanelHeight}\" class=\"p-3 overflow-auto position-relative flex-grow-1\">{$contentHtml}</div>";
|
||||
|
@ -285,11 +285,13 @@ function genInputCheckbox($settingName, $setting, $appView)
|
|||
$settingId = str_replace('.', '_', $settingName);
|
||||
$switch = $appView->Bootstrap->genNode('input', [
|
||||
'class' => [
|
||||
'custom-control-input'
|
||||
'custom-control-input',
|
||||
(!empty($setting['error']) ? 'is-invalid' : ''),
|
||||
(!empty($setting['error']) && $setting['severity'] == 'warning' ? 'warning' : ''),
|
||||
],
|
||||
'type' => 'checkbox',
|
||||
'value' => !empty($setting['value']) ? 1 : 0,
|
||||
'checked' => !empty($setting['value']) ? 'checked' : '',
|
||||
(!empty($setting['value']) ? 'checked' : '') => !empty($setting['value']) ? 'checked' : '',
|
||||
'id' => $settingId,
|
||||
'data-setting-name' => $settingName,
|
||||
]);
|
||||
|
@ -421,26 +423,22 @@ function isLeaf($setting)
|
|||
})
|
||||
|
||||
$('.tab-content input').on('input', function() {
|
||||
handleSettingValueChange($(this))
|
||||
if ($(this).attr('type') == 'checkbox') {
|
||||
const $input = $(this)
|
||||
const $inputGroup = $(this).closest('.form-group')
|
||||
const settingName = $(this).data('setting-name')
|
||||
const settingValue = $(this).is(':checked')
|
||||
saveSetting($inputGroup[0], $input, settingName, settingValue)
|
||||
} else {
|
||||
handleSettingValueChange($(this))
|
||||
}
|
||||
})
|
||||
|
||||
$('.tab-content .input-group-actions .btn-save-setting').click(function() {
|
||||
const $input = $(this).closest('.input-group').find('input')
|
||||
const settingName = $input.data('setting-name')
|
||||
const settingValue = $input.val()
|
||||
const url = '/instance/saveSetting/'
|
||||
const data = {
|
||||
name: settingName,
|
||||
value: settingValue,
|
||||
}
|
||||
const APIOptions = {
|
||||
statusNode: this
|
||||
}
|
||||
AJAXApi.quickFetchAndPostForm(url, data, APIOptions).then((result) => {
|
||||
settingsFlattened[settingName] = result.data
|
||||
$input.val(result.data.value)
|
||||
handleSettingValueChange($input)
|
||||
})
|
||||
saveSetting(this, $input, settingName, settingValue)
|
||||
})
|
||||
$('.tab-content .input-group-actions .btn-reset-setting').click(function() {
|
||||
const $btn = $(this)
|
||||
|
@ -451,6 +449,26 @@ function isLeaf($setting)
|
|||
})
|
||||
})
|
||||
|
||||
function saveSetting(statusNode, $input, settingName, settingValue) {
|
||||
const url = '/instance/saveSetting/'
|
||||
const data = {
|
||||
name: settingName,
|
||||
value: settingValue,
|
||||
}
|
||||
const APIOptions = {
|
||||
statusNode: statusNode,
|
||||
}
|
||||
AJAXApi.quickFetchAndPostForm(url, data, APIOptions).then((result) => {
|
||||
settingsFlattened[settingName] = result.data
|
||||
if ($input.attr('type') == 'checkbox') {
|
||||
$input.prop('checked', result.data.value)
|
||||
} else {
|
||||
$input.val(result.data.value)
|
||||
}
|
||||
handleSettingValueChange($input)
|
||||
})
|
||||
}
|
||||
|
||||
function settingMatcher(params, data) {
|
||||
if (params.term == null || params.term.trim() === '') {
|
||||
return data;
|
||||
|
@ -504,7 +522,8 @@ function isLeaf($setting)
|
|||
|
||||
function handleSettingValueChange($input) {
|
||||
const oldValue = settingsFlattened[$input.data('setting-name')].value
|
||||
if ($input.val() == oldValue) {
|
||||
const newValue = ($input.attr('type') == 'checkbox' ? $input.is(':checked') : $input.val())
|
||||
if (newValue == oldValue) {
|
||||
restoreWarnings($input)
|
||||
} else {
|
||||
removeWarnings($input)
|
||||
|
@ -532,6 +551,8 @@ function isLeaf($setting)
|
|||
$input.addClass('warning')
|
||||
}
|
||||
$inputGroup.parent().find('.invalid-feedback').addClass('d-block').text(setting.errorMessage)
|
||||
} else {
|
||||
removeWarnings($input)
|
||||
}
|
||||
const $callout = $input.closest('.settings-group')
|
||||
updateCalloutColors($callout)
|
||||
|
@ -539,6 +560,9 @@ function isLeaf($setting)
|
|||
}
|
||||
|
||||
function updateCalloutColors($callout) {
|
||||
if ($callout.length == 0) {
|
||||
return
|
||||
}
|
||||
const $settings = $callout.find('input')
|
||||
const settingNames = Array.from($settings).map((i) => {
|
||||
return $(i).data('setting-name')
|
||||
|
|
|
@ -142,6 +142,22 @@ div.progress-timeline .progress-line.progress-inactive {
|
|||
background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' fill='none' stroke='%23ffc107' viewBox='0 0 12 12'%3e%3ccircle cx='6' cy='6' r='4.5'/%3e%3cpath stroke-linejoin='round' d='M5.8 3.6h.4L6 6.5z'/%3e%3ccircle cx='6' cy='8.2' r='.6' fill='%23ffc107' stroke='none'/%3e%3c/svg%3e")
|
||||
}
|
||||
|
||||
.custom-control-input.is-invalid.warning ~ .custom-control-label {
|
||||
color: unset;
|
||||
}
|
||||
.custom-control-input.is-invalid.warning ~ .custom-control-label::before {
|
||||
border-color: #ffc107;
|
||||
}
|
||||
.custom-control-input.is-invalid.warning:checked ~ .custom-control-label::before {
|
||||
background-color: #ffc107;
|
||||
}
|
||||
.custom-control-input.is-invalid.warning:focus:not(:checked) ~ .custom-control-label::before {
|
||||
border-color: #ffc107;
|
||||
}
|
||||
.custom-control-input.is-invalid.warning:focus ~ .custom-control-label::before {
|
||||
box-shadow: 0 0 0 0.2rem #ffc10740;
|
||||
}
|
||||
|
||||
.p-abs-center-y {
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
|
|
|
@ -833,7 +833,7 @@ class OverlayFactory {
|
|||
* @property {string=('primary'|'secondary'|'success'|'danger'|'warning'|'info'|'light'|'dark'|'white'|'transparent')} variant - The variant of the overlay
|
||||
* @property {number} opacity - The opacity of the overlay
|
||||
* @property {boolean} rounded - If the overlay should be rounded
|
||||
* @property {number} auto - Whether overlay and spinner options should be adapted automatically based on the node
|
||||
* @property {boolean} auto - Whether overlay and spinner options should be adapted automatically based on the node
|
||||
* @property {string=('primary'|'secondary'|'success'|'danger'|'warning'|'info'|'light'|'dark'|'white'|'transparent')} spinnerVariant - The variant of the spinner
|
||||
* @property {boolean} spinnerSmall - If the spinner inside the overlay should be small
|
||||
* @property {string=('border'|'grow')} spinnerSmall - If the spinner inside the overlay should be small
|
||||
|
|
Loading…
Reference in New Issue