Skip to content

Commit

Permalink
New webclient feature: Permalinks (#106).
Browse files Browse the repository at this point in the history
Individual topicmaps/topics can be addressed via webclient URLs.

To jump into a particular topicmap:
http://localhost:8080/topicmap/2204

To jump into a particular topicmap and display a particular topic of that map:
http://localhost:8080/topicmap/2204/topic/2512

Browser compatibility: the permalinks work in all browsers. However, to see the address bar's location change *while you navigate* (and for functional back and forward browser buttons) Firefox 4, Safari 5, or Chrome is required.

Note: the "topicmap" URL query parameter is not supported anymore. Use the new URL format instead.

Close ticket 106.
  • Loading branch information
jri committed Oct 16, 2011
1 parent b2e4bcc commit 9fb9617
Show file tree
Hide file tree
Showing 5 changed files with 96 additions and 98 deletions.
Expand Up @@ -4,7 +4,6 @@
import de.deepamehta.plugins.topicmaps.service.TopicmapsService;

import de.deepamehta.core.Association;
import de.deepamehta.core.Topic;
import de.deepamehta.core.model.AssociationModel;
import de.deepamehta.core.model.AssociationRoleModel;
import de.deepamehta.core.model.CompositeValue;
Expand All @@ -16,13 +15,12 @@
import javax.ws.rs.POST;
import javax.ws.rs.DELETE;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.Consumes;
import javax.ws.rs.CookieParam;
import javax.ws.rs.HeaderParam;
import javax.ws.rs.PathParam;
import javax.ws.rs.QueryParam;
import javax.ws.rs.WebApplicationException;

import java.io.InputStream;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
Expand All @@ -43,45 +41,6 @@ public class TopicmapsPlugin extends Plugin implements TopicmapsService {



// **************************************************
// *** Core Hooks (called from DeepaMehta 4 Core) ***
// **************************************************



/* ### @Override
public void postDeleteRelationHook(long relationId) {
// remove the relation from all topicmaps
List<Topic> refTopics = dms.getTopics("de/deepamehta/core/property/RelationID", relationId);
logger.info("### Removing relation " + relationId + " from " + refTopics.size() + " topicmaps");
for (Topic refTopic : refTopics) {
removeAssociationFromTopicmap(refTopic.id);
}
} */

// ---

/* ### @Override
public void providePropertiesHook(Topic topic) {
if (topic.typeUri.equals("de/deepamehta/core/topictype/TopicmapRelationRef")) {
PropValue relation_id = dms.getTopicProperty(topic.id, "de/deepamehta/core/property/RelationID");
topic.setProperty("de/deepamehta/core/property/RelationID", relation_id);
}
} */

/* ### @Override
public void providePropertiesHook(Relation relation) {
if (relation.typeId.equals("TOPICMAP_TOPIC")) {
// transfer all relation properties
Properties properties = dms.getRelation(relation.id).getProperties();
for (String key : properties.keySet()) {
relation.setProperty(key, properties.get(key));
}
}
} */



// **********************
// *** Plugin Service ***
// **********************
Expand Down Expand Up @@ -131,6 +90,26 @@ public void removeAssociationFromTopicmap(@PathParam("id") long topicmapId,
removeAssociationFromTopicmap(refId);
}

// ---

// Note: not part of topicmaps service
@GET
@Path("/{id}")
@Produces("text/html")
public InputStream getTopicmapInWebclient() {
// Note: the template parameter is evaluated at client-side
return invokeWebclient();
}

// Note: not part of topicmaps service
@GET
@Path("/{id}/topic/{topic_id}")
@Produces("text/html")
public InputStream getTopicmapAndTopicInWebclient() {
// Note: the template parameters are evaluated at client-side
return invokeWebclient();
}



// ------------------------------------------------------------------------------------------------- Private Methods
Expand All @@ -141,4 +120,14 @@ public void removeAssociationFromTopicmap(@PathParam("id") long topicmapId,
private void removeAssociationFromTopicmap(long refId) {
dms.deleteAssociation(refId, null); // clientContext=null
}

// ---

private InputStream invokeWebclient() {
try {
return dms.getPlugin("de.deepamehta.webclient").getResourceAsStream("web/index.html");
} catch (Exception e) {
throw new WebApplicationException(e);
}
}
}
Expand Up @@ -79,16 +79,24 @@ function topicmaps_plugin() {
}

function select_initial_topicmap() {
if (location.search.match(/topicmap=(\d+)/)) {
var topicmap_id = RegExp.$1
var groups = location.pathname.match(/\/topicmap\/(\d+)(\/topic\/(\d+))?/)
if (groups) {
var topicmap_id = groups[1]
var topic_id = groups[3]
var no_history_update = false // ### FIXME: rethink about history
select_menu_item(topicmap_id)
} else {
var topicmap_id = get_topicmap_id_from_menu()
var no_history_update = false // ### FIXME: rethink about history
}
// update model
select_topicmap(topicmap_id)
// update view
display_topicmap()
display_topicmap(no_history_update)
//
if (topic_id) {
dm4c.do_select_topic(topic_id, no_history_update)
}
}
}

Expand Down
46 changes: 23 additions & 23 deletions deepamehta-webclient/src/main/resources/web/index.html
Expand Up @@ -3,31 +3,31 @@
<head>
<title>DeepaMehta ${project.version}</title>
<!-- jQuery -->
<link rel="stylesheet" href="script/vendor/jquery/css/smoothness/jquery-ui-1.8.2.custom.css" type="text/css">
<script src="script/vendor/jquery/jquery-1.4.2.min.js"></script>
<script src="script/vendor/jquery/jquery-ui-1.8.2.custom.min.js"></script>
<link rel="stylesheet" href="/script/vendor/jquery/css/smoothness/jquery-ui-1.8.2.custom.css" type="text/css">
<script src="/script/vendor/jquery/jquery-1.4.2.min.js"></script>
<script src="/script/vendor/jquery/jquery-ui-1.8.2.custom.min.js"></script>
<!-- TinyMCE -->
<script src="script/vendor/tiny_mce/tiny_mce.js"></script>
<script src="/script/vendor/tiny_mce/tiny_mce.js"></script>
<!-- DeepaMehta 4 -->
<link rel="icon" href="images/deepamehta-favicon.png" type="image/png">
<link rel="stylesheet" href="style/webclient.css" type="text/css">
<link rel="stylesheet" href="style/jquery-ui-overrides.css" type="text/css">
<script src="script/util/js_utils.js"></script>
<script src="script/util/rest_client.js"></script>
<script src="script/util/gui_toolkit.js"></script>
<script src="script/util/render_helper.js"></script>
<script src="script/util/type_cache.js"></script>
<script src="script/model/topic.js"></script>
<script src="script/model/association.js"></script>
<script src="script/model/topic_type.js"></script>
<script src="script/model/association_type.js"></script>
<script src="script/interfaces/topicmap_renderer.js"></script>
<script src="script/interfaces/page_renderer.js"></script>
<script src="script/topicmap_renderers/canvas.js"></script>
<script src="script/gui/toolbar_panel.js"></script>
<script src="script/gui/page_panel.js"></script>
<script src="script/gui/upload_dialog.js"></script>
<script src="script/webclient.js"></script>
<link rel="icon" href="/images/deepamehta-favicon.png" type="image/png">
<link rel="stylesheet" href="/style/webclient.css" type="text/css">
<link rel="stylesheet" href="/style/jquery-ui-overrides.css" type="text/css">
<script src="/script/util/js_utils.js"></script>
<script src="/script/util/rest_client.js"></script>
<script src="/script/util/gui_toolkit.js"></script>
<script src="/script/util/render_helper.js"></script>
<script src="/script/util/type_cache.js"></script>
<script src="/script/model/topic.js"></script>
<script src="/script/model/association.js"></script>
<script src="/script/model/topic_type.js"></script>
<script src="/script/model/association_type.js"></script>
<script src="/script/interfaces/topicmap_renderer.js"></script>
<script src="/script/interfaces/page_renderer.js"></script>
<script src="/script/topicmap_renderers/canvas.js"></script>
<script src="/script/gui/toolbar_panel.js"></script>
<script src="/script/gui/page_panel.js"></script>
<script src="/script/gui/upload_dialog.js"></script>
<script src="/script/webclient.js"></script>
</head>
<body>
</body>
Expand Down
Expand Up @@ -2,7 +2,7 @@ function HTMLFieldRenderer(topic, field, rel_topics) {

tinymce_options = {
theme: "advanced",
content_css: "style/tinymce.css",
content_css: "/style/tinymce.css",
plugins: "autoresize",
width: "98%",
extended_valid_elements: "iframe[align<bottom?left?middle?right?top|class|frameborder|height|id|" +
Expand Down
55 changes: 28 additions & 27 deletions deepamehta-webclient/src/main/resources/web/script/webclient.js
Expand Up @@ -598,7 +598,7 @@ var dm4c = new function() {
* Loads a Javascript file dynamically. Synchronous and asynchronous loading is supported.
*
* @param script_url The URL (absolute or relative) of the Javascript file to load.
* @param callback The function to invoke when asynchronous loading is complete.
* @param callback Optional: the function to invoke when asynchronous loading is complete.
* If not given loading is performed synchronously.
*/
this.javascript_source = function(script_url, callback) {
Expand Down Expand Up @@ -1114,22 +1114,22 @@ var dm4c = new function() {

// --- register default modules ---
//
this.register_page_renderer("script/page_renderers/topic_renderer.js")
this.register_page_renderer("script/page_renderers/association_renderer.js")
this.register_page_renderer("/script/page_renderers/topic_renderer.js")
this.register_page_renderer("/script/page_renderers/association_renderer.js")
//
this.register_field_renderer("script/field_renderers/text_field_renderer.js")
this.register_field_renderer("script/field_renderers/number_field_renderer.js")
this.register_field_renderer("script/field_renderers/boolean_field_renderer.js")
this.register_field_renderer("script/field_renderers/html_field_renderer.js")
// ### this.register_field_renderer("script/field_renderers/date_field_renderer.js")
// ### this.register_field_renderer("script/field_renderers/reference_field_renderer.js")
this.register_field_renderer("script/field_renderers/title_renderer.js")
this.register_field_renderer("script/field_renderers/body_text_renderer.js")
this.register_field_renderer("script/field_renderers/search_result_renderer.js")
this.register_field_renderer("/script/field_renderers/text_field_renderer.js")
this.register_field_renderer("/script/field_renderers/number_field_renderer.js")
this.register_field_renderer("/script/field_renderers/boolean_field_renderer.js")
this.register_field_renderer("/script/field_renderers/html_field_renderer.js")
// ### this.register_field_renderer("/script/field_renderers/date_field_renderer.js")
// ### this.register_field_renderer("/script/field_renderers/reference_field_renderer.js")
this.register_field_renderer("/script/field_renderers/title_renderer.js")
this.register_field_renderer("/script/field_renderers/body_text_renderer.js")
this.register_field_renderer("/script/field_renderers/search_result_renderer.js")
//
register_plugin("script/internal_plugins/default_plugin.js")
register_plugin("script/internal_plugins/fulltext_plugin.js")
register_plugin("script/internal_plugins/tinymce_plugin.js")
register_plugin("/script/internal_plugins/default_plugin.js")
register_plugin("/script/internal_plugins/fulltext_plugin.js")
register_plugin("/script/internal_plugins/tinymce_plugin.js")

var default_topic_icon = this.create_image(this.DEFAULT_TOPIC_ICON)

Expand Down Expand Up @@ -1206,9 +1206,6 @@ var dm4c = new function() {
// Note: in order to let a plugin provide a custom canvas renderer (the dm4-freifunk-geomap plugin does!)
// the canvas is created *after* loading the plugins.
dm4c.canvas = dm4c.trigger_plugin_hook("get_canvas_renderer")[0] || new Canvas()
// Note: in order to let a plugin provide the initial canvas rendering (the deepamehta-topicmaps plugin
// does!) the "init" hook is triggered *after* creating the canvas.
dm4c.trigger_plugin_hook("init")
//
// setup create widget
dm4c.refresh_create_menu()
Expand All @@ -1220,6 +1217,11 @@ var dm4c = new function() {
$("#page-content").height($("#canvas").height())
//
$(window).resize(window_resized)
// Note: in order to let a plugin provide the initial canvas rendering (the deepamehta-topicmaps plugin
// does!) the "init" hook is triggered *after* creating the canvas.
// Note: for displaying an initial topic (the deepamehta-topicmaps plugin does!) the "init" hook must
// be triggered *after* the GUI setup is complete.
dm4c.trigger_plugin_hook("init")
}

function load_page_renderers() {
Expand All @@ -1231,22 +1233,21 @@ var dm4c = new function() {

function load_page_renderer(page_renderer_src) {
if (LOG_PLUGIN_LOADING) dm4c.log("..... " + page_renderer_src)
// load page renderer asynchronously
dm4c.javascript_source(page_renderer_src, function() {
// instantiate
var page_renderer_class = js.to_camel_case(js.basename(page_renderer_src))
if (LOG_PLUGIN_LOADING) dm4c.log(".......... instantiating \"" + page_renderer_class + "\"")
page_renderers[page_renderer_class] = js.instantiate(PageRenderer, page_renderer_class)
})
// load page renderer synchronously (Note: synchronous is required for displaying initial topic)
dm4c.javascript_source(page_renderer_src)
// instantiate
var page_renderer_class = js.to_camel_case(js.basename(page_renderer_src))
if (LOG_PLUGIN_LOADING) dm4c.log(".......... instantiating \"" + page_renderer_class + "\"")
page_renderers[page_renderer_class] = js.instantiate(PageRenderer, page_renderer_class)
}
}

function load_field_renderers() {
if (LOG_PLUGIN_LOADING) dm4c.log("Loading " + field_renderer_sources.length + " data field renderers:")
for (var i = 0, field_renderer_source; field_renderer_source = field_renderer_sources[i]; i++) {
if (LOG_PLUGIN_LOADING) dm4c.log("..... " + field_renderer_source)
// load field renderer asynchronously
dm4c.javascript_source(field_renderer_source, function() {})
// load field renderer synchronously (Note: synchronous is required for displaying initial topic)
dm4c.javascript_source(field_renderer_source)
}
}

Expand Down

0 comments on commit 9fb9617

Please sign in to comment.