chg: [instance:settings] Improved support of checkboxes

pull/70/head
mokaddem 2021-07-22 15:51:06 +02:00
parent 362a42787a
commit 7c4b45a6e0
4 changed files with 68 additions and 25 deletions

View File

@ -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',
],
],
],
],

View File

@ -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')

View File

@ -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%);

View File

@ -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