revision 8281. Merge from trunk.
This commit is contained in:
commit
d83cc5f1c9
10 changed files with 193 additions and 101 deletions
|
@ -3,6 +3,7 @@
|
||||||
package edu.cornell.mannlib.vitro.webapp.auth.identifier.common;
|
package edu.cornell.mannlib.vitro.webapp.auth.identifier.common;
|
||||||
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
import java.util.Collections;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
|
@ -14,8 +15,16 @@ import edu.cornell.mannlib.vitro.webapp.auth.identifier.IdentifierBundle;
|
||||||
* CommonIdentifierBundleFactory.
|
* CommonIdentifierBundleFactory.
|
||||||
*/
|
*/
|
||||||
public abstract class AbstractCommonIdentifier {
|
public abstract class AbstractCommonIdentifier {
|
||||||
protected static <T> Collection<T> getIdentifiersForClass(
|
|
||||||
|
/**
|
||||||
|
* Get all of the instances of this class of Identifier from this bundle.
|
||||||
|
*/
|
||||||
|
protected static <T extends Identifier> Collection<T> getIdentifiersForClass(
|
||||||
IdentifierBundle ids, Class<T> clazz) {
|
IdentifierBundle ids, Class<T> clazz) {
|
||||||
|
if ((ids == null) || (clazz == null)) {
|
||||||
|
return Collections.emptySet();
|
||||||
|
}
|
||||||
|
|
||||||
Set<T> set = new HashSet<T>();
|
Set<T> set = new HashSet<T>();
|
||||||
for (Identifier id : ids) {
|
for (Identifier id : ids) {
|
||||||
if (clazz.isAssignableFrom(id.getClass())) {
|
if (clazz.isAssignableFrom(id.getClass())) {
|
||||||
|
|
|
@ -11,7 +11,6 @@ import org.apache.commons.logging.LogFactory;
|
||||||
|
|
||||||
import edu.cornell.mannlib.vitro.webapp.auth.identifier.IdentifierBundle;
|
import edu.cornell.mannlib.vitro.webapp.auth.identifier.IdentifierBundle;
|
||||||
import edu.cornell.mannlib.vitro.webapp.auth.identifier.common.HasAssociatedIndividual;
|
import edu.cornell.mannlib.vitro.webapp.auth.identifier.common.HasAssociatedIndividual;
|
||||||
import edu.cornell.mannlib.vitro.webapp.auth.identifier.common.HasRoleLevel;
|
|
||||||
import edu.cornell.mannlib.vitro.webapp.auth.policy.bean.PropertyRestrictionPolicyHelper;
|
import edu.cornell.mannlib.vitro.webapp.auth.policy.bean.PropertyRestrictionPolicyHelper;
|
||||||
import edu.cornell.mannlib.vitro.webapp.auth.policy.ifaces.Authorization;
|
import edu.cornell.mannlib.vitro.webapp.auth.policy.ifaces.Authorization;
|
||||||
import edu.cornell.mannlib.vitro.webapp.auth.policy.ifaces.PolicyDecision;
|
import edu.cornell.mannlib.vitro.webapp.auth.policy.ifaces.PolicyDecision;
|
||||||
|
@ -57,11 +56,6 @@ public class DisplayRestrictedDataToSelfPolicy implements PolicyIface {
|
||||||
return defaultDecision("whatToAuth was null");
|
return defaultDecision("whatToAuth was null");
|
||||||
}
|
}
|
||||||
|
|
||||||
RoleLevel userRole = HasRoleLevel.getUsersRoleLevel(whoToAuth);
|
|
||||||
if (userRole != RoleLevel.SELF) {
|
|
||||||
return defaultDecision("not a self-editor");
|
|
||||||
}
|
|
||||||
|
|
||||||
Collection<String> associated = HasAssociatedIndividual
|
Collection<String> associated = HasAssociatedIndividual
|
||||||
.getIndividualUris(whoToAuth);
|
.getIndividualUris(whoToAuth);
|
||||||
if (associated.isEmpty()) {
|
if (associated.isEmpty()) {
|
||||||
|
|
|
@ -1,18 +0,0 @@
|
||||||
/* $This file is distributed under the terms of the license in /doc/license.txt$ */
|
|
||||||
|
|
||||||
package edu.cornell.mannlib.vitro.webapp.auth.policy;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import com.hp.hpl.jena.query.QuerySolutionMap;
|
|
||||||
|
|
||||||
import edu.cornell.mannlib.vitro.webapp.auth.identifier.IdentifierBundle;
|
|
||||||
import edu.cornell.mannlib.vitro.webapp.auth.requestedAction.ifaces.RequestedAction;
|
|
||||||
|
|
||||||
public interface Ids2QueryBindings {
|
|
||||||
/**
|
|
||||||
* Returns null if no binding can be made. In some implementations this
|
|
||||||
* might be different than an empty QuerySolutionMap. Must be thread safe.
|
|
||||||
*/
|
|
||||||
public List<QuerySolutionMap> makeScopeBinding(IdentifierBundle ids, RequestedAction action );
|
|
||||||
}
|
|
|
@ -76,6 +76,8 @@ public class SimpleReasoner extends StatementListener {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* This constructor is used for the unit tests only
|
||||||
|
*
|
||||||
* @param tboxModel - input. This model contains both asserted and inferred TBox axioms
|
* @param tboxModel - input. This model contains both asserted and inferred TBox axioms
|
||||||
* @param aboxModel - input. This model contains asserted ABox statements
|
* @param aboxModel - input. This model contains asserted ABox statements
|
||||||
* @param inferenceModel - output. This is the model in which inferred (materialized) ABox statements are maintained (added or retracted).
|
* @param inferenceModel - output. This is the model in which inferred (materialized) ABox statements are maintained (added or retracted).
|
||||||
|
@ -158,8 +160,27 @@ public class SimpleReasoner extends StatementListener {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ( stmt.getObject().isResource() && (stmt.getObject().asResource()).getURI() == null ) {
|
||||||
|
log.warn("The object of this assertion has a null URI: " + stmtString(stmt));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( stmt.getSubject().getURI() == null ) {
|
||||||
|
log.warn("The subject of this assertion has a null URI: " + stmtString(stmt));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
OntClass subject = tboxModel.getOntClass((stmt.getSubject()).getURI());
|
OntClass subject = tboxModel.getOntClass((stmt.getSubject()).getURI());
|
||||||
|
if (subject == null) {
|
||||||
|
log.debug("didn't find subject class in the tbox: " + (stmt.getSubject()).getURI());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
OntClass object = tboxModel.getOntClass(((Resource)stmt.getObject()).getURI());
|
OntClass object = tboxModel.getOntClass(((Resource)stmt.getObject()).getURI());
|
||||||
|
if (object == null) {
|
||||||
|
log.debug("didn't find object class in the tbox: " + ((Resource)stmt.getObject()).getURI());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (stmt.getPredicate().equals(RDFS.subClassOf)) {
|
if (stmt.getPredicate().equals(RDFS.subClassOf)) {
|
||||||
addedSubClass(subject,object,inferenceModel);
|
addedSubClass(subject,object,inferenceModel);
|
||||||
|
@ -208,8 +229,27 @@ public class SimpleReasoner extends StatementListener {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ( stmt.getObject().isResource() && (stmt.getObject().asResource()).getURI() == null ) {
|
||||||
|
log.warn("The object of this assertion has a null URI: " + stmtString(stmt));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( stmt.getSubject().getURI() == null ) {
|
||||||
|
log.warn("The subject of this assertion has a null URI: " + stmtString(stmt));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
OntClass subject = tboxModel.getOntClass((stmt.getSubject()).getURI());
|
OntClass subject = tboxModel.getOntClass((stmt.getSubject()).getURI());
|
||||||
|
if (subject == null) {
|
||||||
|
log.debug("didn't find subject class in the tbox: " + (stmt.getSubject()).getURI());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
OntClass object = tboxModel.getOntClass(((Resource)stmt.getObject()).getURI());
|
OntClass object = tboxModel.getOntClass(((Resource)stmt.getObject()).getURI());
|
||||||
|
if (object == null) {
|
||||||
|
log.debug("didn't find object class in the tbox: " + ((Resource)stmt.getObject()).getURI());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (stmt.getPredicate().equals(RDFS.subClassOf)) {
|
if (stmt.getPredicate().equals(RDFS.subClassOf)) {
|
||||||
removedSubClass(subject,object,inferenceModel);
|
removedSubClass(subject,object,inferenceModel);
|
||||||
|
@ -253,7 +293,11 @@ public class SimpleReasoner extends StatementListener {
|
||||||
tboxModel.enterCriticalSection(Lock.READ);
|
tboxModel.enterCriticalSection(Lock.READ);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
OntClass cls = tboxModel.getOntClass(((Resource)stmt.getObject()).getURI());
|
|
||||||
|
OntClass cls = null;
|
||||||
|
|
||||||
|
if ( (stmt.getObject().asResource()).getURI() != null ) {
|
||||||
|
cls = tboxModel.getOntClass(stmt.getObject().asResource().getURI());
|
||||||
|
|
||||||
if (cls != null) {
|
if (cls != null) {
|
||||||
|
|
||||||
|
@ -284,6 +328,10 @@ public class SimpleReasoner extends StatementListener {
|
||||||
} else {
|
} else {
|
||||||
log.debug("Didn't find target class (the object of the added rdf:type statement) in the TBox: " + ((Resource)stmt.getObject()).getURI());
|
log.debug("Didn't find target class (the object of the added rdf:type statement) in the TBox: " + ((Resource)stmt.getObject()).getURI());
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
log.warn("The object of this rdf:type assertion has a null URI: " + stmtString(stmt));
|
||||||
|
return;
|
||||||
|
}
|
||||||
} finally {
|
} finally {
|
||||||
tboxModel.leaveCriticalSection();
|
tboxModel.leaveCriticalSection();
|
||||||
}
|
}
|
||||||
|
@ -340,7 +388,7 @@ public class SimpleReasoner extends StatementListener {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
log.warn("Didn't find target property (the predicate of the added statement) in the TBox: " + stmt.getPredicate().getURI());
|
log.debug("Didn't find target property (the predicate of the added statement) in the TBox: " + stmt.getPredicate().getURI());
|
||||||
}
|
}
|
||||||
} finally {
|
} finally {
|
||||||
tboxModel.leaveCriticalSection();
|
tboxModel.leaveCriticalSection();
|
||||||
|
@ -359,8 +407,15 @@ public class SimpleReasoner extends StatementListener {
|
||||||
|
|
||||||
tboxModel.enterCriticalSection(Lock.READ);
|
tboxModel.enterCriticalSection(Lock.READ);
|
||||||
|
|
||||||
|
// convert this method to use generic resources - not get ontclass, not cls.listSuperClasses...
|
||||||
|
// use model contains if want to log warning about type owl class
|
||||||
|
|
||||||
try {
|
try {
|
||||||
OntClass cls = tboxModel.getOntClass(((Resource)stmt.getObject()).getURI());
|
|
||||||
|
OntClass cls = null;
|
||||||
|
|
||||||
|
if ( (stmt.getObject().asResource()).getURI() != null ) {
|
||||||
|
cls = tboxModel.getOntClass(stmt.getObject().asResource().getURI());
|
||||||
|
|
||||||
if (cls != null) {
|
if (cls != null) {
|
||||||
|
|
||||||
|
@ -396,6 +451,9 @@ public class SimpleReasoner extends StatementListener {
|
||||||
} else {
|
} else {
|
||||||
log.debug("Didn't find target class (the object of the removed rdf:type statement) in the TBox: " + ((Resource)stmt.getObject()).getURI());
|
log.debug("Didn't find target class (the object of the removed rdf:type statement) in the TBox: " + ((Resource)stmt.getObject()).getURI());
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
log.warn("The object of this rdf:type assertion has a null URI: " + stmtString(stmt));
|
||||||
|
}
|
||||||
} finally {
|
} finally {
|
||||||
tboxModel.leaveCriticalSection();
|
tboxModel.leaveCriticalSection();
|
||||||
}
|
}
|
||||||
|
@ -700,10 +758,17 @@ public class SimpleReasoner extends StatementListener {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
OntClass ontClass = tboxModel.getOntClass(stmt.getObject().asResource().getURI());
|
OntClass ontClass = null;
|
||||||
|
|
||||||
|
if ( (stmt.getObject().asResource()).getURI() != null ) {
|
||||||
|
ontClass = tboxModel.getOntClass(stmt.getObject().asResource().getURI());
|
||||||
|
} else {
|
||||||
|
log.warn("The object of this rdf:type assertion has a null URI: " + stmtString(stmt));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if (ontClass == null) {
|
if (ontClass == null) {
|
||||||
log.warn("Didn't find target class (the object of the added rdf:type statement) in the TBox: " + (stmt.getObject().asResource()).getURI());
|
log.debug("Didn't find target class (the object of the added rdf:type statement) in the TBox: " + (stmt.getObject().asResource()).getURI());
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -17,8 +17,12 @@ presents some admirably clear rules for capitalizing titles:
|
||||||
(1) a, an, and the,
|
(1) a, an, and the,
|
||||||
(2) two and three letter conjunctions (and, or, nor, for, but, so, yet),
|
(2) two and three letter conjunctions (and, or, nor, for, but, so, yet),
|
||||||
(3) prepositions.
|
(3) prepositions.
|
||||||
Exceptions: The first and last words are always capitalized even
|
Exceptions: The first word is always capitalized even
|
||||||
if they are among the above three groups.
|
if it is among the above three groups. For the last word, we can specify the
|
||||||
|
option to always capitalize it or to treat it like a medial word. The original
|
||||||
|
method always capitalized the final word, so to support the old method calls
|
||||||
|
we have defined another method to provide this as default behavior.
|
||||||
|
|
||||||
|
|
||||||
But consider the case:
|
But consider the case:
|
||||||
"It Waits Underneath the Sea"
|
"It Waits Underneath the Sea"
|
||||||
|
@ -34,7 +38,7 @@ The default entries on the exception list are:
|
||||||
to of by at for but in with has
|
to of by at for but in with has
|
||||||
de von
|
de von
|
||||||
The observant may note that the last row is not composed of English words. The honorary
|
The observant may note that the last row is not composed of English words. The honorary
|
||||||
"de" has been included in honor of "Honoré de Balzac". And "von" was added for the sake
|
"de" has been included in honor of "Honore' de Balzac". And "von" was added for the sake
|
||||||
of equal time.
|
of equal time.
|
||||||
*/
|
*/
|
||||||
public class TitleCase {
|
public class TitleCase {
|
||||||
|
@ -42,6 +46,11 @@ public class TitleCase {
|
||||||
"to","of","by","at","for","but","in","with","has","de","von"};
|
"to","of","by","at","for","but","in","with","has","de","von"};
|
||||||
|
|
||||||
public static String toTitleCase(String in) {
|
public static String toTitleCase(String in) {
|
||||||
|
// Support old behavior without modifying method calls
|
||||||
|
return toTitleCase(in, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String toTitleCase(String in, boolean alwaysCapitalizeLast){
|
||||||
if( in == null || in.length() ==0 )
|
if( in == null || in.length() ==0 )
|
||||||
return in;
|
return in;
|
||||||
|
|
||||||
|
@ -55,9 +64,12 @@ public class TitleCase {
|
||||||
while(st.hasMoreTokens()){
|
while(st.hasMoreTokens()){
|
||||||
String token = st.nextToken();
|
String token = st.nextToken();
|
||||||
|
|
||||||
//always capatize first and last
|
// always capitalize first
|
||||||
if( count == 1 || count == last ){
|
if ( count == 1 ||
|
||||||
|
// always capitalize last, unless we've asked not to
|
||||||
|
( alwaysCapitalizeLast && count == last ) ) {
|
||||||
out.append(capitalizeWord(token));
|
out.append(capitalizeWord(token));
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
//check if on ignored list
|
//check if on ignored list
|
||||||
|
|
|
@ -2,21 +2,44 @@
|
||||||
|
|
||||||
package edu.cornell.mannlib.vitro.webapp.web.templatemodels;
|
package edu.cornell.mannlib.vitro.webapp.web.templatemodels;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
|
|
||||||
import edu.cornell.mannlib.vedit.beans.LoginStatusBean;
|
import edu.cornell.mannlib.vedit.beans.LoginStatusBean;
|
||||||
|
import edu.cornell.mannlib.vitro.webapp.auth.identifier.IdentifierBundle;
|
||||||
|
import edu.cornell.mannlib.vitro.webapp.auth.identifier.RequestIdentifiers;
|
||||||
|
import edu.cornell.mannlib.vitro.webapp.auth.identifier.common.HasAssociatedIndividual;
|
||||||
import edu.cornell.mannlib.vitro.webapp.auth.policy.PolicyHelper;
|
import edu.cornell.mannlib.vitro.webapp.auth.policy.PolicyHelper;
|
||||||
import edu.cornell.mannlib.vitro.webapp.beans.UserAccount;
|
import edu.cornell.mannlib.vitro.webapp.beans.UserAccount;
|
||||||
import edu.cornell.mannlib.vitro.webapp.controller.VitroRequest;
|
import edu.cornell.mannlib.vitro.webapp.controller.VitroRequest;
|
||||||
import edu.cornell.mannlib.vitro.webapp.controller.freemarker.RevisionInfoController;
|
import edu.cornell.mannlib.vitro.webapp.controller.freemarker.RevisionInfoController;
|
||||||
import edu.cornell.mannlib.vitro.webapp.controller.freemarker.SiteAdminController;
|
import edu.cornell.mannlib.vitro.webapp.controller.freemarker.SiteAdminController;
|
||||||
|
import edu.cornell.mannlib.vitro.webapp.controller.freemarker.UrlBuilder;
|
||||||
|
|
||||||
public class User extends BaseTemplateModel {
|
public class User extends BaseTemplateModel {
|
||||||
private final VitroRequest vreq;
|
private final VitroRequest vreq;
|
||||||
|
|
||||||
private final UserAccount currentUser;
|
private final UserAccount currentUser;
|
||||||
|
private final String profileUrl;
|
||||||
|
|
||||||
public User(VitroRequest vreq) {
|
public User(VitroRequest vreq) {
|
||||||
this.vreq = vreq;
|
this.vreq = vreq;
|
||||||
this.currentUser = LoginStatusBean.getCurrentUser(vreq);
|
this.currentUser = LoginStatusBean.getCurrentUser(vreq);
|
||||||
|
this.profileUrl = figureAssociatedProfileUrl();
|
||||||
|
}
|
||||||
|
|
||||||
|
private String figureAssociatedProfileUrl() {
|
||||||
|
IdentifierBundle ids = RequestIdentifiers.getIdBundleForRequest(vreq);
|
||||||
|
Collection<String> uris = HasAssociatedIndividual.getIndividualUris(ids);
|
||||||
|
if (uris.isEmpty()) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
String uri = uris.iterator().next();
|
||||||
|
String url = UrlBuilder.getIndividualProfileUrl(uri, vreq);
|
||||||
|
if (url == null) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
return url;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isLoggedIn() {
|
public boolean isLoggedIn() {
|
||||||
|
@ -63,4 +86,11 @@ public class User extends BaseTemplateModel {
|
||||||
return PolicyHelper.isAuthorizedForActions(vreq, RevisionInfoController.REQUIRED_ACTIONS);
|
return PolicyHelper.isAuthorizedForActions(vreq, RevisionInfoController.REQUIRED_ACTIONS);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean getHasProfile() {
|
||||||
|
return !profileUrl.isEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getProfileUrl() {
|
||||||
|
return profileUrl;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,7 +4,6 @@
|
||||||
#admin {
|
#admin {
|
||||||
font-size: .8em;
|
font-size: .8em;
|
||||||
padding-top: 0;
|
padding-top: 0;
|
||||||
padding-right: 40px;
|
|
||||||
}
|
}
|
||||||
#admin h3 {
|
#admin h3 {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
|
@ -210,7 +209,7 @@ h1.fn .preferred-title {
|
||||||
}
|
}
|
||||||
/* <------ INDIVIDUAL VISUALIZATION */
|
/* <------ INDIVIDUAL VISUALIZATION */
|
||||||
#visualization {
|
#visualization {
|
||||||
padding: 0 0 20px 30px;
|
padding: 0 0 20px 20px;
|
||||||
padding-top: 0;
|
padding-top: 0;
|
||||||
float: right;
|
float: right;
|
||||||
background-color: #fff;
|
background-color: #fff;
|
||||||
|
|
|
@ -22,6 +22,9 @@
|
||||||
margin-top: 13px;
|
margin-top: 13px;
|
||||||
margin-left: 20px;
|
margin-left: 20px;
|
||||||
}
|
}
|
||||||
|
#newPassword {
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
#login-form .label-remember-me {
|
#login-form .label-remember-me {
|
||||||
display: block;
|
display: block;
|
||||||
float: left;
|
float: left;
|
||||||
|
@ -71,10 +74,9 @@ h3.internal-auth {
|
||||||
p.password-note {
|
p.password-note {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
margin-top: -8px;
|
|
||||||
font-size: 0.8em;
|
font-size: 0.8em;
|
||||||
color: #615e5e;
|
color: #615e5e;
|
||||||
padding-top: 15px;
|
padding-top: 3px;
|
||||||
}
|
}
|
||||||
.or {
|
.or {
|
||||||
display: inline;
|
display: inline;
|
||||||
|
|
Binary file not shown.
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 1.2 KiB |
|
@ -52,9 +52,8 @@
|
||||||
</#if>
|
</#if>
|
||||||
|
|
||||||
<#if confirmMessage?has_content>
|
<#if confirmMessage?has_content>
|
||||||
<section id="error-alert" role="alert">
|
<section class="account-feedback" role="alert">
|
||||||
<img src="${urls.images}/iconConfirmation.png" width="24" height="24" alert="Confirmation icon"/>
|
<p><img class="middle" src="${urls.images}/iconConfirmation.png" alert="Confirmation icon"/> ${confirmMessage}</p>
|
||||||
<p>${confirmMessage}</p>
|
|
||||||
</section>
|
</section>
|
||||||
</#if>
|
</#if>
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue