CCM Admin UI Settings Editor: Resetting to default value

ccm-docs
Jens Pelzetter 2020-11-07 18:56:07 +01:00
parent 0650e1a073
commit 16cc7aedcb
5 changed files with 189 additions and 30 deletions

View File

@ -39,6 +39,7 @@ import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;
/**
@ -112,10 +113,10 @@ public class SettingManager {
/**
* Create a {@link SettingInfo} instance for a setting.
*
* @param configuration The configuration class to which the settings
* belongs.
* @param name The name of the setting for which the
* {@link SettingInfo} is generated.
* @param configurationClass The configuration class to which the settings
* belongs.
* @param name The name of the setting for which the
* {@link SettingInfo} is generated.
*
* @return The {@link SettingInfo} for the provided configuration class.
*/
@ -123,28 +124,29 @@ public class SettingManager {
"PMD.CyclomaticComplexity",
"PMD.StandardCyclomaticComplexity"})
public SettingInfo getSettingInfo(
final Class<?> configuration,
final String name) {
if (configuration == null) {
final Class<?> configurationClass,
final String name
) {
if (configurationClass == null) {
throw new IllegalArgumentException("Configuration can't be null");
}
if (configuration.getAnnotation(Configuration.class) == null) {
if (configurationClass.getAnnotation(Configuration.class) == null) {
throw new IllegalArgumentException(String.format(
"The class \"%s\" of the provided object is not annotated "
+ "with \"%s\".",
configuration.getClass().getName(),
configurationClass.getClass().getName(),
Configuration.class.getName()));
}
final Field field;
try {
field = configuration.getDeclaredField(name);
field = configurationClass.getDeclaredField(name);
} catch (SecurityException | NoSuchFieldException ex) {
LOGGER.warn(String.format(
"Failed to generate SettingInfo for field \"%s\" of "
+ "configuration \"%s\". Ignoring field.",
configuration.getClass().getName(),
configurationClass.getClass().getName(),
name),
ex);
return null;
@ -169,11 +171,19 @@ public class SettingManager {
settingInfo.setValueType(field.getType().getName());
try {
final Constructor<?> constructor = configuration.getConstructor();
final Object conf = constructor.newInstance();
final Object defaultValueObj = field.get(conf);
final Constructor<?> constructor = configurationClass
.getConstructor();
final Object configuration = constructor.newInstance();
final Object defaultValueObj = field.get(configuration);
final String defaultValue;
if (defaultValueObj instanceof LocalizedString) {
if (defaultValueObj instanceof List) {
@SuppressWarnings("unchecked")
final List<String> defaultValueList
= (List<String>) defaultValueObj;
defaultValue = defaultValueList
.stream()
.collect(Collectors.joining("\n"));
} else if (defaultValueObj instanceof LocalizedString) {
final LocalizedString defaultValueLstr
= (LocalizedString) defaultValueObj;
defaultValue = defaultValueLstr
@ -186,24 +196,30 @@ public class SettingManager {
entry.getKey().toString(), entry.getValue()
)
)
.collect(Collectors.joining(", "));
.collect(Collectors.joining("\n"));
} else if (defaultValueObj instanceof Set) {
@SuppressWarnings("unchecked")
final Set<String> defaultValueSet
= (Set<String>) defaultValueObj;
defaultValue = defaultValueSet
.stream()
.collect(Collectors.joining("\n"));
} else {
defaultValue = Objects.toString(defaultValueObj);
}
settingInfo.setDefaultValue(defaultValue);
} catch (NoSuchMethodException
| InstantiationException
| InvocationTargetException
| IllegalAccessException ex) {
LOGGER.warn(String.format("Failed to create instance of \"%s\" to "
+ "get default values.",
configuration.getName()),
configurationClass.getName()),
ex);
}
settingInfo.setConfClass(configuration.getName());
settingInfo.setDescBundle(getDescBundle(configuration));
settingInfo.setConfClass(configurationClass.getName());
settingInfo.setDescBundle(getDescBundle(configurationClass));
if (Strings.isBlank(settingAnnotation.labelKey())) {
settingInfo.setLabelKey(String.join(".", field.getName(),
@ -257,6 +273,61 @@ public class SettingManager {
}
}
public Object getDefaultValue(
final Class<?> configurationClass,
final String settingName
) {
if (configurationClass == null) {
throw new IllegalArgumentException("Configuration can't be null");
}
if (configurationClass.getAnnotation(Configuration.class) == null) {
throw new IllegalArgumentException(String.format(
"The class \"%s\" of the provided object is not annotated "
+ "with \"%s\".",
configurationClass.getClass().getName(),
Configuration.class.getName()));
}
final Field field;
try {
field = configurationClass.getDeclaredField(settingName);
} catch (SecurityException | NoSuchFieldException ex) {
LOGGER.warn(String.format(
"Failed to generate SettingInfo for field \"%s\" of "
+ "configuration \"%s\". Ignoring field.",
configurationClass.getClass().getName(),
settingName),
ex);
return null;
}
//Make the field accessible even if it has a private modifier
field.setAccessible(true);
if (field.getAnnotation(Setting.class) == null) {
return null;
}
try {
final Constructor<?> constructor = configurationClass
.getConstructor();
final Object configuration = constructor.newInstance();
final Object defaultValueObj = field.get(configuration);
return defaultValueObj;
} catch (NoSuchMethodException
| IllegalAccessException
| InstantiationException
| InvocationTargetException ex) {
LOGGER.warn(String.format("Failed to create instance of \"%s\" to "
+ "get default values.",
configurationClass.getName()),
ex);
return null;
}
}
/**
* Low level method of saving a setting.
*

View File

@ -323,6 +323,42 @@ public class SettingsController {
}
}
@POST
@Path("/{settingName}/reset")
@Transactional(Transactional.TxType.REQUIRED)
@AuthorizationRequired
@RequiresPrivilege(CoreConstants.PRIVILEGE_ADMIN)
public String resetSettingValue(
@PathParam("configurationClass")
final String configurationClassName,
@PathParam("settingName")
final String settingName,
@FormParam("confirmed")
final String confirmed
) {
if ("true".equals(confirmed)) {
final Class<?> configurationClass;
try {
configurationClass = Class.forName(
configurationClassName
);
} catch (ClassNotFoundException ex) {
models.put("configurationClass", configurationClassName);
return "org/libreccm/ui/admin/configuration/configuration-class-not-found.xhtml";
}
final SettingInfo settingInfo = settingManager.getSettingInfo(
configurationClass, settingName
);
return updateSettingValue(
configurationClassName,
settingName,
settingInfo.getDefaultValue()
);
} else {
return buildRedirectAfterUpdateSettingTarget(configurationClassName);
}
}
private String updateBigDecimalSetting(
final String configurationClassName,
final Class<?> configurationClass,
@ -481,7 +517,7 @@ public class SettingsController {
);
}
private String updateStringSetSetting(
private String updateStringSetSetting(
final String configurationClassName,
final Class<?> configurationClass,
final Object configuration,

View File

@ -53,16 +53,16 @@
<td>
<c:choose>
<c:when test="#{setting.value == null}">
<span class="text-muted">#{setting.defaultValue}</span>
<pre class="text-muted">#{setting.defaultValue}</pre>
</c:when>
<c:otherwise>
<strong>
<pre>#{setting.value}</pre>
</strong>
<pre>#{setting.value}</pre>
</c:otherwise>
</c:choose>
</td>
<td>#{setting.defaultValue}</td>
<td>
<pre>#{setting.defaultValue}</pre>
</td>
<td>
<c:if test="#{setting.description.length() > 0}">
<button class="btn btn-info"
@ -137,7 +137,7 @@
method="post">
<div class="modal-header">
<h2 class="model-title"
id="setting-#{setting.name}-edit-dialog">
id="setting-#{setting.name}-edit-dialog-title">
#{AdminMessages.getMessage('configuration.settings.setting.dialog.title', [setting.label])}
</h2>
<button aria-label="#{AdminMessages['configuration.settings.setting.dialog.close']}"
@ -336,7 +336,9 @@
</td>
<td>
<button class="btn btn-danger"
title="#{AdminMessages.getMessage('configuration.settings.table.actions.reset.help', [setting.label])}"
data-toggle="modal"
data-target="#setting-#{setting.name}-reset-dialog"
title="#{AdminMessages.getMessage('configuration.settings.table.actions.reset.help', [setting.label, setting.defaultValue])}"
type="button">
<svg class="bi"
width="1em"
@ -346,6 +348,48 @@
</svg>
#{AdminMessages['configuration.settings.table.actions.reset']}
</button>
<div aria-hidden="true"
aria-labelledby="setting-#{setting.name}-reset-dialog-title"
class="modal fade"
data-backdrop="static"
id="setting-#{setting.name}-reset-dialog"
tabindex="-1">
<div class="modal-dialog">
<form action="#{mvc.uri('SettingsController#resetSettingValue', {'configurationClass': configurationClass, 'settingName': setting.name })}"
class="modal-content"
method="post">
<div class="modal-header">
<h2 class="modal-title"
id="setting-#{setting.name}-reset-dialog-title">
#{AdminMessages.getMessage('configuration.settings.setting.reset.title', [setting.label])}
</h2>
<button aria-label="#{AdminMessages['configuration.settings.setting.reset.close']}"
class="close"
data-dismiss="modal"
type="button"><span aria-hidden="true">&times;</span></button>
</div>
<div class="modal-body">
<p>
#{AdminMessages.getMessage('configuration.settings.setting.reset.confirm', [configuration.name, setting.label, setting.defaultValue])}
</p>
<input name="confirmed"
type="hidden"
value="true" />
</div>
<div class="modal-footer">
<button class="btn btn-danger"
data-dismiss="modal"
type="button">
#{AdminMessages['configuration.settings.setting.reset.close']}
</button>
<button class="btn btn-success"
type="submit">
#{AdminMessages['configuration.settings.setting.reset.submit']}
</button>
</div>
</form>
</div>
</div>
</td>
</tr>
</c:forEach>

View File

@ -236,3 +236,7 @@ configuration.setting.not_found.message=Setting {1} of type {2} not found in con
configuration.settings.setting.dialog.value.label=Value
configuration.setting.failed_to_update.title=Failed to update setting
configuration.setting.failed_to_update.message=Failed to update setting {1} of configuration {0}.
configuration.settings.setting.reset.title=Reset setting {0}
configuration.settings.setting.reset.close=Cancel
configuration.settings.setting.reset.confirm=Are you sure to set reset setting {1} of configuration {0} to its default value {2}?
configuration.settings.setting.reset.submit=Reset to default value

View File

@ -236,3 +236,7 @@ configuration.setting.not_found.message=Keine Einstellung {1} vom Typ {2} in Kon
configuration.settings.setting.dialog.value.label=Wert
configuration.setting.failed_to_update.title=Aktualisieren der Einstellung fehlgeschlagen
configuration.setting.failed_to_update.message=Aktualisieren der Einstellung {1} in Konfiguration {0} fehlgeschlagen.
configuration.settings.setting.reset.title=Einstellung {0} zur\u00fccksetzen
configuration.settings.setting.reset.close=Abbrechen
configuration.settings.setting.reset.confirm=Sind Sie sicher, dass die die Einstellung {1} in Konfiguration {0} auf ihren Standardwert {2} zur\u00fccksetzen wollen?
configuration.settings.setting.reset.submit=Auf Standardwert zur\u00fccksetzen