* Ignore IDEA files
* Publishing PageModels from the PageModelEditor


git-svn-id: https://svn.libreccm.org/ccm/ccm_ng@5535 8810af33-2d31-482b-a856-94f89814c4df
pull/2/head
jensp 2018-06-17 15:44:07 +00:00
parent 5c782ea87a
commit 0803a107e3
8 changed files with 330 additions and 177 deletions

View File

@ -62,7 +62,6 @@ import javax.xml.bind.annotation.XmlTransient;
* page.
*
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
*
* @see PageModelRepository
* @see PageModelManager
* @see PageRenderer
@ -74,38 +73,46 @@ import javax.xml.bind.annotation.XmlTransient;
@NamedQuery(
name = "PageModel.findAllDraftModels",
query = "SELECT p FROM PageModel p "
+ "WHERE p.version = org.libreccm.pagemodel.PageModelVersion.DRAFT")
+ "WHERE p.version = org.libreccm.pagemodel"
+ ".PageModelVersion.DRAFT")
,
@NamedQuery(
name = "PageModel.findAllLiveModels",
query = "SELECT p FROM PageModel p "
+ "WHERE p.version = org.libreccm.pagemodel.PageModelVersion.LIVE")
+ "WHERE p.version = org.libreccm.pagemodel"
+ ".PageModelVersion.LIVE")
,
@NamedQuery(
name = "PageModel.findDraftVersion",
query = "SELECT p FROM PageModel p "
+ "WHERE p.modelUuid = :uuid "
+ "AND p.version = org.libreccm.pagemodel.PageModelVersion.DRAFT")
+ "AND p.version = org.libreccm.pagemodel"
+ ".PageModelVersion.DRAFT")
,
@NamedQuery(
name = "PageModel.hasLiveVersion",
query = "SELECT (CASE WHEN COUNT(p) > 0 THEN true ELSE False END) "
query =
"SELECT (CASE WHEN COUNT(p) > 0 THEN true ELSE "
+ "False END) "
+ "FROM PageModel p "
+ "WHERE p.modelUuid = :uuid "
+ "AND p.version = org.libreccm.pagemodel.PageModelVersion.LIVE"
+ "AND p.version = org.libreccm.pagemodel"
+ ".PageModelVersion.LIVE"
)
,
@NamedQuery(
name = "PageModel.findLiveVersion",
query = "SELECT p FROM PageModel p "
+ "WHERE p.modelUuid = :uuid "
+ "AND p.version = org.libreccm.pagemodel.PageModelVersion.LIVE")
+ "AND p.version = org.libreccm.pagemodel"
+ ".PageModelVersion.LIVE")
,
@NamedQuery(
name = "PageModel.findDraftByApplication",
query = "SELECT p FROM PageModel p "
+ "WHERE p.application = :application "
+ "AND p.version = org.libreccm.pagemodel.PageModelVersion.DRAFT"
+ "AND p.version = org.libreccm.pagemodel"
+ ".PageModelVersion.DRAFT"
)
,
@NamedQuery(
@ -113,41 +120,48 @@ import javax.xml.bind.annotation.XmlTransient;
query = "SELECT p FROM PageModel p "
+ "WHERE p.application = :application "
+ "AND p.name = :name "
+ "AND p.version = org.libreccm.pagemodel.PageModelVersion.DRAFT"
+ "AND p.version = org.libreccm.pagemodel"
+ ".PageModelVersion.DRAFT"
)
,
@NamedQuery(
name = "PageModel.countDraftByApplicationAndName",
query = "SELECT COUNT(p) FROM PageModel p "
+ "WHERE p.application = :application "
+ "AND p.version = org.libreccm.pagemodel.PageModelVersion.DRAFT"
+ "WHERE p.name = :name "
+ "AND p.application = :application "
+ "AND p.version = org.libreccm.pagemodel"
+ ".PageModelVersion.DRAFT"
)
,
@NamedQuery(
name = "PageModel.countDraftByApplication",
query = "SELECT COUNT(p) FROM PageModel p "
+ "WHERE p.application = :application "
+ "AND p.version = org.libreccm.pagemodel.PageModelVersion.DRAFT"
+ "AND p.version = org.libreccm.pagemodel"
+ ".PageModelVersion.DRAFT"
)
,
@NamedQuery(
name = "PageModel.findLiveByApplication",
query = "SELECT p FROM PageModel p "
+ "WHERE p.application = :application "
+ "AND p.version = org.libreccm.pagemodel.PageModelVersion.LIVE")
+ "AND p.version = org.libreccm.pagemodel"
+ ".PageModelVersion.LIVE")
,
@NamedQuery(
name = "PageModel.countLiveByApplication",
query = "SELECT COUNT(p) FROM PageModel p "
+ "WHERE p.application = :application "
+ "AND p.version = org.libreccm.pagemodel.PageModelVersion.LIVE")
+ "AND p.version = org.libreccm.pagemodel"
+ ".PageModelVersion.LIVE")
,
@NamedQuery(
name = "PageModel.findLiveByApplicationAndName",
query = "SELECT p FROM PageModel p "
+ "WHERE p.name = :name "
+ "AND p.application = :application "
+ "AND p.version = org.libreccm.pagemodel.PageModelVersion.LIVE"
+ "AND p.version = org.libreccm.pagemodel"
+ ".PageModelVersion.LIVE"
)
,
@NamedQuery(
@ -155,7 +169,8 @@ import javax.xml.bind.annotation.XmlTransient;
query = "SELECT COUNT(p) FROM PageModel p "
+ "WHERE p.name = :name "
+ "AND p.application = :application "
+ "AND p.version = org.libreccm.pagemodel.PageModelVersion.LIVE"
+ "AND p.version = org.libreccm.pagemodel"
+ ".PageModelVersion.LIVE"
)
})
@XmlRootElement(name = "pagemodel")
@ -164,9 +179,7 @@ public class PageModel implements Serializable {
private static final long serialVersionUID = 7252512839926020978L;
/**
*
* The ID of the entity in the database.
*
*/
@Id
@Column(name = "PAGE_MODEL_ID")
@ -175,11 +188,9 @@ public class PageModel implements Serializable {
private long pageModelId;
/**
*
* The UUID of this {@code PageModel}. Please note that this UUID identifies
* the dataset not the model. Therefore the draft and the live version have
* different values for this field.
*
*/
@Column(name = "UUID", length = 255, nullable = false)
@NotNull
@ -257,115 +268,142 @@ public class PageModel implements Serializable {
private List<ContainerModel> containers;
public PageModel() {
title = new LocalizedString();
description = new LocalizedString();
containers = new ArrayList<>();
}
public long getPageModelId() {
return pageModelId;
}
protected void setPageModelId(final long pageModelId) {
this.pageModelId = pageModelId;
}
public String getUuid() {
return uuid;
}
protected void setUuid(final String uuid) {
this.uuid = uuid;
}
public String getModelUuid() {
return modelUuid;
}
protected void setModelUuid(final String modelUuid) {
this.modelUuid = modelUuid;
}
public String getName() {
return name;
}
public void setName(final String name) {
this.name = name;
}
public PageModelVersion getVersion() {
return version;
}
protected void setVersion(final PageModelVersion version) {
this.version = version;
}
public Date getLastModified() {
return lastModified;
}
protected void setLastModified(final Date lastModified) {
this.lastModified = new Date(lastModified.getTime());
}
public LocalizedString getTitle() {
return title;
}
protected void setTitle(final LocalizedString title) {
Objects.requireNonNull(title);
this.title = title;
}
public LocalizedString getDescription() {
return description;
}
protected void setDescription(final LocalizedString description) {
Objects.requireNonNull(description);
this.description = description;
}
public CcmApplication getApplication() {
return application;
}
public void setApplication(final CcmApplication application) {
this.application = application;
}
public String getType() {
return type;
}
public void setType(final String type) {
this.type = type;
}
public List<ContainerModel> getContainers() {
return Collections.unmodifiableList(containers);
}
protected void setContainers(final List<ContainerModel> containers) {
this.containers = new ArrayList<>(containers);
}
protected void addContainer(final ContainerModel container) {
containers.add(container);
}
protected void removeContainer(final ContainerModel container) {
containers.remove(container);
}
protected void clearContainers() {
containers.clear();
}
@Override
public int hashCode() {
int hash = 7;
hash = 71 * hash + (int) (pageModelId ^ (pageModelId >>> 32));
hash = 71 * hash + Objects.hashCode(uuid);
@ -378,6 +416,7 @@ public class PageModel implements Serializable {
@Override
public boolean equals(final Object obj) {
if (this == obj) {
return true;
}
@ -410,6 +449,7 @@ public class PageModel implements Serializable {
}
public boolean canEqual(final Object obj) {
return obj instanceof PageModel;
}

View File

@ -89,11 +89,12 @@ public class PageModelManager {
/**
* Called by CDI after an instance of this class is created. Initialises the
* {@link #components} by retrieving the data about all available
* {@link ComponentModel}s.
* {@link #components} by retrieving the data about all available {@link
* ComponentModel}s.
*/
@PostConstruct
private void init() {
LOGGER.debug("Initalising {}...", PageModelManager.class.getName());
final ServiceLoader<CcmModule> modules = ServiceLoader.load(
@ -127,11 +128,11 @@ public class PageModelManager {
/**
* Creates a new {@link PageModel} for the provided application. The method
* tries to retrieve the appropriate application by using
* {@link PageModelRepository#findLiveByApplicationAndName(org.libreccm.web.CcmApplication, java.lang.String)}.
* Please note that this method will always return the
* <strong>draft</strong>
* version of the page model.
* tries to retrieve the appropriate application by using {@link
* PageModelRepository#findLiveByApplicationAndName(org.libreccm.web
* .CcmApplication,
* java.lang.String)}. Please note that this method will always return the
* <strong>draft</strong> version of the page model.
*
* @param name The name of the new page model. Must be unique for the
* application.
@ -149,7 +150,8 @@ public class PageModelManager {
final String type) {
Objects.requireNonNull(application,
"Can't create a page model for application null");
"Can't create a page model for application "
+ "null");
Objects.requireNonNull(name, "Then name of a Pagemodel can't be null.");
if (name.isEmpty()
|| name.matches("\\s*")) {
@ -158,7 +160,8 @@ public class PageModelManager {
}
LOGGER.debug(
"Creating new PageModel with name \"{}\" for application \"{}\" and type \"{}\".",
"Creating new PageModel with name \"{}\" for application \"{}\" "
+ "and type \"{}\".",
name,
application.getPrimaryUrl(),
type);
@ -191,8 +194,8 @@ public class PageModelManager {
/**
* Retrieves the draft version of a {@link PageModel}. To invoke this method
* the current user needs a permission granting the
* {@link CoreConstants#PRIVILEGE_ADMIN} privilege.
* the current user needs a permission granting the {@link
* CoreConstants#PRIVILEGE_ADMIN} privilege.
*
* @param pageModel The {@link PageModel} for which the draft version is
* retrieved.
@ -222,11 +225,12 @@ public class PageModelManager {
*
* @param pageModel The {@link PageModel} to check for a live version.
*
* @return {@code true} if there is a live version for the provided
* {@link PageModel}, {@code false} otherwise.
* @return {@code true} if there is a live version for the provided {@link
* PageModel}, {@code false} otherwise.
*/
@Transactional(Transactional.TxType.REQUIRED)
public boolean isLive(final PageModel pageModel) {
final TypedQuery<Boolean> query = entityManager.createNamedQuery(
"PageModel.hasLiveVersion", Boolean.class);
query.setParameter("uuid", pageModel.getModelUuid());
@ -280,10 +284,13 @@ public class PageModelManager {
final PageModel draftModel = getDraftVersion(pageModel);
final PageModel liveModel;
final boolean isLive;
if (isLive(pageModel)) {
isLive = true;
liveModel = getLiveVersion(draftModel).get();
} else {
liveModel = new PageModel();
isLive = false;
}
liveModel.setName(draftModel.getName());
@ -312,11 +319,17 @@ public class PageModelManager {
.getContainers()
.stream()
.map(this::publishContainerModel)
.forEach(liveContainerModel -> addContainerModel(pageModel,
.forEach(liveContainerModel -> addContainerModel(liveModel,
liveContainerModel));
liveModel.setLastModified(new Date());
pageModelRepo.save(liveModel);
//if (isLive) {
// entityManager.merge(liveModel);
//} else {
// entityManager.persist(liveModel);
//}
LOGGER.debug("Successfully published PageModel \"{}\".",
liveModel.getName());
return liveModel;
@ -332,6 +345,7 @@ public class PageModelManager {
liveModel.setContainerUuid(draftModel.getContainerUuid());
final Styles draftStyles = draftModel.getStyles();
if (draftStyles != null) {
final Styles liveStyles = new Styles();
liveStyles.setStyleName(draftStyles.getStyleName());
liveStyles.setRules(draftStyles
@ -344,6 +358,7 @@ public class PageModelManager {
.stream()
.map(this::publishMediaRule)
.collect(Collectors.toList()));
}
draftModel
.getComponents()
@ -414,9 +429,11 @@ public class PageModelManager {
* @return The live version of the {@link ComponentModel}.
*/
@SuppressWarnings("unchecked")
private ComponentModel publishComponentModel(final ComponentModel draftModel) {
private ComponentModel publishComponentModel(final ComponentModel
draftModel) {
Objects.requireNonNull(draftModel, "Can't publish ComponentModel null.");
Objects.requireNonNull(draftModel,
"Can't publish ComponentModel null.");
LOGGER.debug("Publishing ComponentModel \"{}\"...",
draftModel.getKey());
@ -481,7 +498,8 @@ public class PageModelManager {
final Map<Object, Object> target;
try {
source = (Map<Object, Object>) readMethod.invoke(draftModel);
source
= (Map<Object, Object>) readMethod.invoke(draftModel);
target = (Map<Object, Object>) readMethod.invoke(liveModel);
} catch (IllegalAccessException
| IllegalArgumentException
@ -537,6 +555,7 @@ public class PageModelManager {
* process, {@link false} if not.
*/
private boolean propertyIsExcluded(final String name) {
final String[] excluded = new String[]{
"class",
"uuid",

View File

@ -205,7 +205,7 @@ public class PageModelRepository extends AbstractEntityRepository<Long, PageMode
"The name of a page model can't be null or empty.");
}
final long count = countLiveByApplicationAndName(application, name);
final long count = countDraftByApplicationAndName(application, name);
if (count == 0) {
return Optional.empty();
}

View File

@ -38,8 +38,10 @@ import javax.json.JsonObject;
import javax.transaction.Transactional;
import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
import javax.ws.rs.FormParam;
import javax.ws.rs.GET;
import javax.ws.rs.NotFoundException;
import javax.ws.rs.POST;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
@ -151,6 +153,29 @@ public class PageModels {
return mapPageModelToJson(pageModel);
}
@POST
@Path(PageModelsApp.PAGE_MODEL_PATH)
@Produces("application/json; charset=utf-8")
@Transactional(Transactional.TxType.REQUIRED)
@AuthorizationRequired
@RequiresPrivilege(CoreConstants.PRIVILEGE_ADMIN)
public JsonObject publishPageModel(
@PathParam(PageModelsApp.APP_NAME) final String appPath,
@PathParam(PageModelsApp.PAGE_MODEL_NAME) final String pageModelName,
@FormParam("action") String action) {
if ("publish".equals(action)) {
final CcmApplication app = controller
.findCcmApplication(String.format("/%s/", appPath));
final PageModel pageModel = controller.findPageModel(app,
pageModelName);
pageModelManager.publish(pageModel);
}
return getPageModel(appPath, pageModelName);
}
/**
* Creates or updates a {@link PageModel}.
*
@ -259,6 +284,12 @@ public class PageModels {
} else {
lastPublished = 0;
}
final long lastModified;
if (pageModel.getLastModified() == null) {
lastModified = 0;
} else {
lastModified = pageModel.getLastModified().getTime();
}
return Json
.createObjectBuilder()
@ -276,6 +307,7 @@ public class PageModels {
.add("version", pageModel.getVersion().toString())
.add("publicationStatus",
getPublicationStatus(pageModel).toString())
.add("lastModified", lastModified)
.add("lastPublished", lastPublished)
.build();
}
@ -302,10 +334,9 @@ public class PageModels {
|| liveModel.get().getLastModified() == null) {
return PublicationStatus.NEEDS_UPDATE;
} else if (liveModel
.get()
} else if (draftModel
.getLastModified()
.before(draftModel.getLastModified())) {
.before(liveModel.get().getLastModified())) {
publicationStatus = PublicationStatus.PUBLISHED;
} else {

View File

@ -0,0 +1,2 @@
alter table CCM_CORE.PAGE_MODELS
add column LAST_MODIFIED TIMESTAMP;

View File

@ -0,0 +1,2 @@
alter table CCM_CORE.PAGE_MODELS
add column LAST_MODIFIED TIMESTAMP;

View File

@ -274,14 +274,12 @@ class PageModelComponent
<dd>{this.props.pageModel.version.toString()}</dd>
<dt>Description</dt>
<dd>{this.props.pageModel.description}</dd>
<dt>Last modified</dt>
<dd>{this.getLastModifiedDate()}</dd>
<dt>Last published</dt>
<dd>{this.getLastPublishedDate()}</dd>
<dt>PublicationStatus</dt>
<dd>{this.props.pageModel.publicationStatus}</dd>
<dt>Publish</dt>
<dd>{this.props.pageModel.publicationStatus === PublicationStatus.NOT_PUBLISHED}</dd>
<dt>Republish</dt>
<dd>{this.props.pageModel.publicationStatus === PublicationStatus.NEEDS_UPDATE}</dd>
</dl>
<button onClick={(event) => {
@ -292,11 +290,11 @@ class PageModelComponent
});
}}>Edit
</button>
{this.props.pageModel.publicationStatus === PublicationStatus.NOT_PUBLISHED
&& <button>Publish</button>
{this.props.pageModel.publicationStatus === PublicationStatus.NOT_PUBLISHED.toString()
&& <button onClick={(event) => this.publishPageModel(event)}>Publish</button>
}
{this.props.pageModel.publicationStatus === PublicationStatus.NEEDS_UPDATE
&& <button>Republish</button>
{this.props.pageModel.publicationStatus === PublicationStatus.NEEDS_UPDATE.toString()
&& <button onClick={(event) => this.publishPageModel(event)}>Republish</button>
}
</div>;
}
@ -317,6 +315,18 @@ class PageModelComponent
});
}
private getLastModifiedDate():string {
if (this.props.pageModel.lastPublished === 0) {
return "";
} else {
const lastModified: Date = new Date();
lastModified.setTime(this.props.pageModel.lastModified);
return lastModified.toISOString();
}
}
private getLastPublishedDate(): string {
if (this.props.pageModel.lastPublished === 0) {
@ -426,6 +436,53 @@ class PageModelComponent
});
}
private publishPageModel(event: React.MouseEvent<HTMLButtonElement>): void {
event.preventDefault();
const headers: Headers = new Headers();
//headers.append("Content-Type", "application/json");
headers.append("Content-Type", "application/x-www-form-urlencoded");
//const formData: FormData = new FormData();
//formData.set("action", "publish");
//const data: URLSearchParams = new URLSearchParams();
//data.append("action", "publish");
const init: RequestInit = {
body: "action=publish",
credentials: "same-origin",
headers,
method: "POST",
}
const url: string = `${this.props.dispatcherPrefix}`
+ `/page-models/${this.props.ccmApplication}/`
+ `${this.props.pageModel.name}`
fetch(url, init)
.then((response: Response) => {
if (response.ok) {
this.props.reload();
} else {
this.setState({
...this.state,
errorMsg: `Failed to publish PageModel: `
+ ` ${response.status} ${response.statusText}`,
});
}
})
.catch((error) => {
this.setState({
...this.state,
errorMsg: `Failed to publish PageModel: ${error.message}`,
})
});
}
}
// interface PageModelEditorProps {
@ -551,11 +608,12 @@ class PageModelEditor
...this.state,
selectedPageModel: {
description: "",
lastModified: 0,
lastPublished: 0,
modelUuid: "",
name: "",
pageModelId: 0,
publicationStatus: PublicationStatus.NOT_PUBLISHED,
publicationStatus: PublicationStatus.NOT_PUBLISHED.toString(),
title: "",
type: "",
uuid: "",

View File

@ -10,7 +10,8 @@ interface PageModel {
type: string;
uuid: string;
version: PageModelVersion;
publicationStatus: PublicationStatus;
publicationStatus: string;
lastModified: number;
lastPublished: number;
}
@ -22,7 +23,7 @@ enum PageModelVersion {
enum PublicationStatus {
NOT_PUBLISHED,
PUBLISHED,
NEEDS_UPDATE,
NOT_PUBLISHED = "NOT_PUBLISHED",
PUBLISHED = "PUBLISHED",
NEEDS_UPDATE = "NEEDS_UPDATE",
}