Commit 31bf50b4 authored by Jean Pommier's avatar Jean Pommier
Browse files

[template-editor] most of the interface works

Except ajax parts, apparently (see AbstractTemplateFormPanel)
parent aa7e15d4
......@@ -95,6 +95,7 @@
<descriptor>release/ext-qos.xml</descriptor>
<descriptor>release/ext-web-resource.xml</descriptor>
<descriptor>release/ext-s3-geotiff.xml</descriptor>
<descriptor>release/ext-template-editor.xml</descriptor>
</descriptors>
</configuration>
</plugin>
......@@ -593,5 +594,11 @@
<module>monitor-hibernate</module>
</modules>
</profile>
<profile>
<id>template-editor</id>
<modules>
<module>template-editor</module>
</modules>
</profile>
</profiles>
</project>
<assembly>
<id>template-editor-plugin</id>
<formats>
<format>zip</format>
</formats>
<includeBaseDirectory>false</includeBaseDirectory>
<fileSets>
<fileSet>
<directory>release/target/dependency</directory>
<outputDirectory/>
<includes>
<include>gs-template-editor*.jar</include>
</includes>
</fileSet>
</fileSets>
</assembly>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd ">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.geoserver</groupId>
<artifactId>community</artifactId>
<version>2.15-SNAPSHOT</version> <!-- change this to the proper GeoServer version -->
</parent>
<groupId>org.geoserver.community</groupId>
<artifactId>gs-template-editor</artifactId>
<packaging>jar</packaging>
<name>Geoserver template editor</name>
<dependencies>
<dependency>
<groupId>org.geoserver</groupId>
<artifactId>gs-main</artifactId>
<version>2.15-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.geoserver.web</groupId>
<artifactId>gs-web-core</artifactId>
<version>2.15-SNAPSHOT</version> <!-- change this to the proper GeoServer version -->
</dependency>
<dependency>
<groupId>org.geoserver.web</groupId>
<artifactId>gs-web-wms</artifactId>
<version>2.15-SNAPSHOT</version> <!-- change this to the proper GeoServer version -->
</dependency>
<dependency>
<groupId>org.geoserver.web</groupId>
<artifactId>gs-web-rest</artifactId>
<version>2.15-SNAPSHOT</version> <!-- change this to the proper GeoServer version -->
</dependency>
</dependencies>
</project>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<!--
Copyright (C) 2015 - 2016 - Open Source Geospatial Foundation. All rights reserved.
This code is licensed under the GPL 2.0 license, available at the root
application directory.
-->
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">
<beans >
<bean id="TemplateEditorPage" class="org.geoserver.web.MenuPageInfo">
<property name="id" value="TemplateEditorPage"/>
<property name="titleKey" value="TemplateEditorPage.page.title"/>
<property name="descriptionKey" value="TemplateEditorPage.page.description"/>
<property name="componentClass" value="org.geoserver.template.editor.TemplateEditorPage"/>
</bean>
<bean id="templateMenuPage" class="org.geoserver.web.MenuPageInfo">
<property name="id" value="templates" />
<property name="titleKey" value="TemplatePage.title" />
<property name="descriptionKey" value="TemplatePage.description" />
<property name="componentClass" value="org.geoserver.template.editor.web.TemplatePage" />
<property name="category" ref="dataCategory" />
<property name="icon" value="../img/icons/template.png" />
<property name="order" value="60" />
<property name="authorizer" ref="workspaceAdminAuthorizer"/>
</bean>
<bean id="AbstractTemplateEditorPage" class="org.geoserver.template.editor.web.TemplateEditorPageInfo">
<property name="id" value="AbstractTemplateEditorPage" />
<property name="titleKey" value="AbstractTemplateEditorPage.title" />
<property name="descriptionKey" value="AbstractTemplateEditorPage.description" />
<property name="componentClass" value="org.geoserver.template.editor.web.AbstractTemplateEditorPage" />
</bean>
</beans>
\ No newline at end of file
<html>
<body>
<wicket:extend>
<div wicket:id="label"></div>
</wicket:extend>
</body>
</html>
\ No newline at end of file
package org.geoserver.template.editor;
import org.apache.wicket.markup.html.basic.Label;
import org.geoserver.web.GeoServerBasePage;
public class TemplateEditorPage extends GeoServerBasePage {
public TemplateEditorPage() {
add(new Label("label", "Hello World!"));
}
}
/* (c) 2014 Open Source Geospatial Foundation - all rights reserved
* This code is licensed under the GPL 2.0 license, available at the root
* application directory.
*/
package org.geoserver.template.editor.constants;
public class GeoServerConstants {
public static final String WORKSPACES = "workspaces";
}
textarea {
width : 90%;
}
#templates_editor td {
vertical-align : top;
}
#templates_editor td {
background-color : #F9F9F9;
}
#templates_editor #template_header textarea{
height : 200px;
}
#templates_editor #template_content textarea{
}
#templates_editor #template_footer textarea{
height : 100px;
}
#templates_editor .path span.active,
#templates_editor p.path span.active+span {
font-weight : bold;
color : black;
}
#templates_editor .path span{
font-weight : normal;
color : grey;
}
#templates_editor p.srcpath {
margin-bottom : 0;
}
#templates_editor h3 {
margin-bottom : 0.5em;
}
#templates_editor .align-left {
float : left;
}
#templates_editor .align-right {
float : right;
}
#templates_editor ul {
list-style-type: none;
}
#templates_editor .attributes ul {
list-style-type: circle;
}
#templates_editor li {
clear : both;
}
#templates_editor button[disabled] {
opacity:.5;
}
$(document).ready(function() {
String.prototype.endsWith = function(pattern) {
var d = this.length - pattern.length;
return d >= 0 && this.lastIndexOf(pattern) === d;
};
var watch = function(tag) {
$(tag+' textarea').bind('input propertychange', function() {
$(tag+' .srcpath span').removeClass( "active" );
$(tag+' .destpath span').addClass( "active" );
var text = $(tag+' .destpath span').text();
if (text.substr(-1) !== "*") { //equiv to endswith "*"
text += '*';
$(tag+' .destpath span').text( text );
}
});
};
watch('#template_header');
watch('#template_content');
watch('#template_footer');
});
<html xmlns:wicket="http://wicket.apache.org/">
<body>
<wicket:head>
<wicket:link>
<link rel="stylesheet" type="text/css" href="../css/TemplateEditorStyle.css"/>
<!--<script type="text/javascript" src="../js/fmte.js" />-->
</wicket:link>
</wicket:head>
<wicket:extend>
<h2>
<span wicket:id="name"></span> (<span wicket:id="type"></span>)
</h2>
<table id="templates_editor">
<tr>
<td id="templates_cell">
<ul>
<li id="template_header">
<h3 class="name"><wicket:message key="tpl_header_name">Header: </wicket:message></h3>
<div wicket:id="headerTplPanel">
</div>
</li>
<li id="template_content">
<h3 class="name"><wicket:message key="tpl_content_name">Content: </wicket:message></h3>
<div wicket:id="contentTplPanel">
</div>
</li>
<li id="template_footer">
<h3 class="name"><wicket:message key="tpl_footer_name">Footer: </wicket:message></h3>
<div wicket:id="footerTplPanel">
</div>
</li>
</ul>
</td>
<td class="attributes">
<wicket:child/>
</td>
</tr>
</table>
</wicket:extend>
</body>
</html>
\ No newline at end of file
/* (c) 2014 Open Source Geospatial Foundation - all rights reserved
* This code is licensed under the GPL 2.0 license, available at the root
* application directory.
*/
package org.geoserver.template.editor.web;
import java.io.IOException;
import java.util.List;
import java.util.logging.Logger;
import org.apache.wicket.request.mapper.parameter.PageParameters;
import org.apache.wicket.markup.html.basic.Label;
import org.apache.wicket.model.CompoundPropertyModel;
import org.apache.wicket.model.Model;
import org.geoserver.platform.GeoServerResourceLoader;
import org.geoserver.web.ComponentAuthorizer;
import org.geoserver.web.GeoServerSecuredPage;
import org.geotools.util.logging.Logging;
/**
* Base page for creating/editing templates
*/
@SuppressWarnings("serial")
public abstract class AbstractTemplateEditorPage extends GeoServerSecuredPage {
protected static final Logger LOGGER = Logging.getLogger(AbstractTemplateEditorPage.class);
protected String msg_pathNotSet = "Error, resource path is undefined";
private String fullname = "";
protected String path;
protected List<String> resourcePaths;
protected String resourceType = "abstract";
protected TemplateResourceObject tpl_header, tpl_content, tpl_footer;
protected AbstractTemplateFormPanel headerFormPanel, contentFormPanel, footerFormPanel;
public AbstractTemplateEditorPage() {
}
public AbstractTemplateEditorPage(PageParameters parameters) {
this.resourcePaths = this.getResourcePaths(parameters);
LOGGER.info("Resource path is " + path);
this.fullname = this.buildResourceFullName();
LOGGER.info("Resource full name is " + fullname);
this.loadData();
this.initComponents();
/*
* ResourceInfo resource = getResource(name, workspaceName); this.initComponents(resource);
*/
}
private void loadData() {
try {
readTemplates();
} catch (IOException e) {
e.printStackTrace();
LOGGER.info("Oops, error retrieving template files");
}
}
private void readTemplates() throws IOException {
if (this.resourcePaths == null) {
LOGGER.severe(msg_pathNotSet);
return;
}
GeoServerResourceLoader loader = this.getCatalog().getResourceLoader();
tpl_header = TemplateManager.readTemplate("header.ftl", resourcePaths, loader,
getCharset());
tpl_content = TemplateManager.readTemplate("content.ftl", resourcePaths, loader,
getCharset());
tpl_footer = TemplateManager.readTemplate("footer.ftl", resourcePaths, loader,
getCharset());
}
/**
* Builds a list of available paths where to look for templates
*
* @param parameters URL parameters used to identify the resource and build the paths
* @return List<String> List of paths (as Strings)
*/
protected abstract List<String> getResourcePaths(PageParameters parameters);
protected abstract String buildResourceFullName();
protected void initComponents() {
add(new Label("name", Model.of(fullname)));
add(new Label("type", Model.of(resourceType)));
headerFormPanel = new AbstractTemplateFormPanel("headerTplPanel",
new CompoundPropertyModel(tpl_header));
headerFormPanel.setParent(this);
add(headerFormPanel);
contentFormPanel = new AbstractTemplateFormPanel("contentTplPanel",
new CompoundPropertyModel(tpl_content));
contentFormPanel.setParent(this);
add(contentFormPanel);
footerFormPanel = new AbstractTemplateFormPanel("footerTplPanel",
new CompoundPropertyModel(tpl_footer));
footerFormPanel.setParent(this);
add(footerFormPanel);
}
protected void saveTemplate(TemplateResourceObject tpl) {
GeoServerResourceLoader loader = getCatalog().getResourceLoader();
String outcome = TemplateManager.saveTemplate(tpl, loader);
LOGGER.fine(outcome);
}
protected void deleteTemplate(TemplateResourceObject tpl) {
GeoServerResourceLoader loader = getCatalog().getResourceLoader();
String outcome = "";
try {
outcome = TemplateManager.deleteTemplate(tpl, loader, getCharset());
} catch (IOException e) {
LOGGER.severe("Could not delete template file");
LOGGER.severe(e.getMessage());
}
LOGGER.fine(outcome);
}
public String getCharset() {
return this.getGeoServer().getSettings().getCharset();
}
@Override
protected ComponentAuthorizer getPageAuthorizer() {
return ComponentAuthorizer.WORKSPACE_ADMIN;
}
}
<wicket:panel>
<textarea wicket:id="content"></textarea>
<div class="align-left">
<p class="path srcpath">
<wicket:message key="srcpath">Source: </wicket:message>
<span wicket:id="srcpath" class="active"></span>/<span wicket:id="filename"></span>
</p>
<p class="path destpath">
<wicket:message key="destpath">Destination path: </wicket:message>
<span wicket:id="destpath"></span>/<span wicket:id="filename"></span>
<span wicket:id="dirty"></span>
</p>
</div>
<div class="button-group align-right">
<button wicket:id="delete_btn"> <wicket:message key="delete">Delete</wicket:message></button>
<button wicket:id="reload_btn"> <wicket:message key="reload">Reset</wicket:message></button>
<button wicket:id="save_btn"> <wicket:message key="save">Save</wicket:message></button>
</div>
<wicket:child/>
</wicket:panel>
\ No newline at end of file
/* (c) 2014 Open Source Geospatial Foundation - all rights reserved
* This code is licensed under the GPL 2.0 license, available at the root
* application directory.
*/
package org.geoserver.template.editor.web;
import java.util.logging.Logger;
import org.apache.wicket.ajax.AjaxRequestTarget;
import org.apache.wicket.ajax.form.OnChangeAjaxBehavior;
import org.apache.wicket.ajax.markup.html.AjaxLink;
import org.apache.wicket.AttributeModifier;
import org.apache.wicket.markup.html.basic.Label;
import org.apache.wicket.markup.html.form.TextArea;
import org.apache.wicket.markup.html.panel.Panel;
import org.apache.wicket.model.IModel;
import org.apache.wicket.model.Model;
import org.geotools.util.logging.Logging;
public class AbstractTemplateFormPanel extends Panel {
private static final Logger LOGGER = Logging.getLogger(AbstractTemplateFormPanel.class);
/** serialVersionUID */
private static final long serialVersionUID = 1L;
private Label srcpath_label, destpath_label, destpath_label_dirty, filename_label,
destfilename_label;
private TextArea<String> tpl;
private AjaxLink save_btn, reload_btn, delete_btn;
private AbstractTemplateEditorPage templateEditorPage;
private IModel<TemplateResourceObject> templateModel;
public AbstractTemplateFormPanel(String id, final IModel<TemplateResourceObject> model) {
super(id, model);
this.templateModel = model;
srcpath_label = new Label("srcpath");
srcpath_label.setOutputMarkupId(true);
add(srcpath_label);
filename_label = new Label("filename");
filename_label.setOutputMarkupId(true);
add(filename_label);
destpath_label = new Label("destpath");
destpath_label.setOutputMarkupId(true);
add(destpath_label);
destpath_label_dirty = new Label("dirty");
destpath_label_dirty.setOutputMarkupId(true);
add(destpath_label_dirty);
tpl = new TextArea<String>("content");
tpl.setOutputMarkupId(true);
add(tpl);
tpl.add(new OnChangeAjaxBehavior() {
/** serialVersionUID */
private static final long serialVersionUID = 1L;
@Override
protected void onUpdate(AjaxRequestTarget target) {
ajaxSetDirty(target);
}
});
save_btn = new AjaxLink("save_btn", Model.of("Save")) {
@Override
public void onClick(AjaxRequestTarget target) {
if (templateEditorPage != null) {
templateEditorPage.saveTemplate(model.getObject());
ajaxReload(target);
}
}
};
save_btn.setEnabled(false);
save_btn.setOutputMarkupId(true);
add(save_btn);
reload_btn = new AjaxLink("reload_btn", Model.of("Reload")) {
@Override
public void onClick(AjaxRequestTarget target) {
ajaxReload(target);
}
};
add(reload_btn);
delete_btn = new AjaxLink("delete_btn", Model.of("Delete this template file")) {
@Override
public void onClick(AjaxRequestTarget target) {
if (templateEditorPage != null) {
templateEditorPage.deleteTemplate(model.getObject());
ajaxReload(target);
}
}
};
add(delete_btn);
}
private void ajaxSetDirty(AjaxRequestTarget target) {
templateModel.getObject().setDirty("*");
srcpath_label.add(AttributeModifier.replace("class", ""));
destpath_label.add(AttributeModifier.replace("class", "active"));
destpath_label_dirty.add(AttributeModifier.replace("class", "active"));
// TODO rewrite this
//target.addComponent(srcpath_label);
//target.addComponent(destpath_label);
//target.addComponent(destpath_label_dirty);
}
private void ajaxReload(AjaxRequestTarget target) {
templateModel.getObject().resetContent();