:- module(web_ui_dcg, [
content/4,
title/4,
scripts/3,
navigation_bar/3
]).
:- use_module(library(cluster_search_ui/settings)).
:- use_module(applications(annotation)).
:- use_module(library(http/html_write)).
:- use_module(library(http/http_path)).
:- use_module(library(http/url_cache)).
:- use_module(library(http/http_open)).
:- use_module(library(http/http_dispatch)).
:- use_module(library(semweb/rdf_db)).
:- rdf_register_prefix(edm, 'http://www.europeana.eu/schemas/edm/').
%% content(+Type, +Options)
%
% Returns the content according to the type of page. Four
% different types are possible: front, results, result and about.
content(front, _) -->
{get_carousel_items(CarouselItems)},
carousel(CarouselItems).
content(results, Options) -->
results_page(cluster, Options).
content(result, Options) -->
{option(uri(Uri), Options),
setting(cluster_search_ui:annotate, Annotate),
atomic_list_concat(['showResult(\'',Uri, '\');'], FunctionCall),
(Annotate
-> get_annotation_options(Uri, AnnotationOrImage)
; get_image_options(Uri, AnnotationOrImage)
)
},
html([\result_page_body(Annotate, AnnotationOrImage),
div([class('row'), id('metadata')],''),
script(FunctionCall)
]).
content(about, _) -->
{current_prolog_flag(version, Version),
setting(cluster_search_ui:ui, UI),
rdf(UI, dcterms:title, literal(lang(en, Title)))
},
html({|html(Title, Version)||
About Title
This website is used to demo semantic search strategies, developed at the Web and Media group of the VU University Amsterdam. The images originate from the Rijksmuseum Amsterdam . This work is done in the context of the SEALINCMedia project. For more information contact Chris Dijkshoorn .
Title is running on Cliopatria powered by Prolog version Version . The code is available on Github , you are welcome to report bugs or file feature requests.
|}).
content(results, Options) -->
results_page(cluster, Options).
get_annotation_options(Uri, AnnotationOptions) :-
AnnotationUI = 'http://semanticweb.cs.vu.nl/annotate/nicheAccuratorBirdDemoUi',
AnnotationFields = [
'http://semanticweb.cs.vu.nl/annotate/example#IOCCommonNameAnnotation',
'http://semanticweb.cs.vu.nl/annotate/example#IOCScientificNameAnnotation'],
get_metafields(AnnotationUI, [], MetadataFields),
query_title(Uri, Title),
AnnotationOptions = [
target(Uri),
ui(AnnotationUI),
title(Title),
user('http://invenit.user.nl/'),
annotation_fields(AnnotationFields),
metadata_fields(MetadataFields)
].
get_image_options(Uri, ImageUrl) :-
image_url(Uri, ImageUrl).
%% get_carousel_items(-CarouselItems)
%
% Retrieve items for the carousel from the RDF store.
get_carousel_items(CarouselItems) :-
setting(cluster_search_ui:ui, UI),
findall(item(LocationAbsolute, Action, Title),
( rdf(Item, rdf:type, ui:carouselItem),
rdf(Item, ui:elementOf, UI),
rdf(Item, ui:imageLocation, literal(LocationRelative)),
http_absolute_location(img(LocationRelative), LocationAbsolute, []),
rdf(Item, ui:action, literal(Action)),
rdf(Item, dcterms:title, literal(lang(en, Title)))
),
CarouselItems).
:- multifile cliopatria:image_url/2.
%% image_url(+Uri, -ImageUrl) is det.
%
% * Check if image is present, if so, return request url.
% * If the image is not present, check if present at url.
% isShownBy triple.
% * If not present in cache, database and at
% server, send image stub.
image_url(Uri, ImageUrl) :-
check_cache_shown(Uri, Image), !,
image_link(Image, ImageUrl).
image_url(Uri, ImageUrl) :-
check_server_shown(Uri, Image), !,
image_link(Image, ImageUrl).
image_url(Uri, ImageUrl) :-
check_cache_view(Uri, Image), !,
image_link(Image, ImageUrl).
image_url(Uri, ImageUrl) :-
check_server_view(Uri, Image), !,
image_link(Image, ImageUrl).
image_url(_, Stub) :- http_absolute_location(img('stub_vertical.png'), Stub, []).
check_cache_shown(Uri, Image) :-
rdf(Aggregation, edm:aggregatedCHO, Uri),
rdf(Aggregation, edm:isShownBy, Image),
url_cached(Image, file(_)).
check_cache_view(Uri, Image) :-
rdf(Aggregation, edm:aggregatedCHO, Uri),
rdf(Aggregation, edm:hasView, Image0),
check_if_local(Image0, Image),
url_cached(Image, file(_)).
check_server_shown(Uri, Image) :-
rdf(Aggregation, edm:aggregatedCHO, Uri),
rdf(Aggregation, edm:isShownBy, Image),
https_header_response(Image, Status),
Status == 200.
check_server_view(Uri, Image) :-
rdf(Aggregation, edm:aggregatedCHO, Uri),
rdf(Aggregation, edm:hasView, Image0),
check_if_local(Image0, Image),
https_header_response(Image, Status),
Status == 200.
image_link(Image, ThumbUrl) :-
concat('cache/original?uri=', Image, RequestUrl),
http_absolute_location(root(RequestUrl), ThumbUrl, []).
check_if_local(Image, ImageUrl) :-
not(concat('http', _, Image)),
http_absolute_uri(img(Image), ImageUrl).
check_if_local(ImageUrl, ImageUrl).
%% https_header_response(+URL, -Status)
%
% Return the response header of input URL
https_header_response(URL, Status) :-
http_open(URL, In,
[method(head),
status_code(Status),
cert_verify_hook(ssl_verify)
]),
close(In).
:- public ssl_verify/5.
%% ssl_verify(+SSL, +ProblemCert, +AllCerts, +FirstCert, +Error)
%
% Currently we accept all certificates.
ssl_verify(_SSL, _ProblemCertificate, _AllCertificates, _FirstCertificate, _Error).
/***************************************************
* web page elements dcg
***************************************************/
%% title(+Page)
%
% Replies the title for the given page.
title(front, _) -->
{setting(cluster_search_ui:ui, UI),
rdf(UI, dcterms:title, literal(lang(en, Title)))},
html(title(Title)).
title(about, _) -->
{setting(cluster_search_ui:ui, UI),
rdf(UI, dcterms:title, literal(lang(en, Title))),
concat('About ', Title, TitleAbout)
},
html(title(TitleAbout)).
title(results, _) --> html(title('Results')).
title(result, Options) -->
{option(uri(Uri), Options),
query_title(Uri, Title)
},
html(title(Title)).
title(analytics, _) -->
{setting(cluster_search_ui:ui, UI),
rdf(UI, dcterms:title, literal(lang(en, Title))),
concat(Title, ' Statistics', TitleStatistics)},
html(title(TitleStatistics)).
result_page_body(true, AnnotationOptions) -->
annotation_page_body(AnnotationOptions).
result_page_body(false, ImageUrl) -->
html(img([src(ImageUrl), class('img-responsive'), alt('Image')])).
%% query_title(+Uri, -Title)
%
% Retrieve the tile of a uri, ignoring the language tag.
query_title(Uri, Title) :-
rdf(Uri, dc:title, literal(lang(_,Title))), !.
query_title(Uri, Title) :-
rdf(Uri, dc:title, literal(Title)).
query_title(Uri, Uri).
%% scripts(+Page)
%
% Replies the scripts needed for the indicated page.
scripts(front) -->
html([\load_javascript(jquery),
\load_javascript(bootstrap),
\load_javascript(search)]).
scripts(results) -->
html([\load_javascript(jquery),
\load_javascript(bootstrap),
\load_javascript(laconic),
\load_javascript(pengines),
\load_javascript(search),
\load_javascript(pagination),
\load_javascript(thumbnail)]).
scripts(result) -->
html([\load_javascript(jquery),
\load_javascript(bootstrap),
\load_javascript(pengines),
\load_javascript(laconic),
\load_javascript(result),
\load_javascript(search)]).
scripts(about) -->
html([\load_javascript(jquery),
\load_javascript(bootstrap),
\load_javascript(search)]).
%% load_javascript(+Script)
%
% Generates the html to load the indicated script.
load_javascript(jquery) -->
html(script(src('http://code.jquery.com/jquery.js'),'')).
load_javascript(bootstrap) -->
{http_absolute_location(js('bootstrap.min.js'), JavaScriptBootstrap, [])},
html(script(src(JavaScriptBootstrap),'')).
load_javascript(laconic) -->
{http_absolute_location(js('laconic.js'), JavaScriptLaconic, [])},
html(script(src(JavaScriptLaconic),'')).
load_javascript(pengines) -->
{http_absolute_location(js('pengines.js'), JavaScriptPengine, [])},
html(script(src(JavaScriptPengine),'')).
load_javascript(search) -->
{http_absolute_location(js('search.js'), JavaScriptSearch, [])},
html(script(src(JavaScriptSearch),'')).
load_javascript(pagination) -->
{http_absolute_location(js('pagination.js'), JavaScriptPagination, [])},
html(script(src(JavaScriptPagination),'')).
load_javascript(thumbnail) -->
{http_absolute_location(js('thumbnail.js'), JavaScriptThumbnail, [])},
html(script(src(JavaScriptThumbnail),'')).
load_javascript(result) -->
{http_absolute_location(js('result.js'), JavaScriptResult, [])},
html(script(src(JavaScriptResult),'')).
%% navigation_bar(+Page)
%
% Generates the navigation bar for the given page.
navigation_bar(front) -->
{http_location_by_id(cluster_search, HttpWeb),
http_location_by_id(results, HttpSearch),
http_location_by_id(about, HttpAbout),
setting(cluster_search_ui:ui, UI),
rdf(UI, dcterms:title, literal(lang(en, Title)))
},
html({|html(HttpWeb, HttpSearch, HttpAbout, Title)||
|}).
navigation_bar(about) -->
{http_location_by_id(cluster_search, HttpWeb),
http_location_by_id(results, HttpSearch),
http_location_by_id(about, HttpAbout),
setting(cluster_search_ui:ui, UI),
rdf(UI, dcterms:title, literal(lang(en, Title)))
},
html({|html(HttpWeb, HttpSearch, HttpAbout, Title)||
|}).
navigation_bar(results) --> navigation_bar(front).
navigation_bar(result) --> navigation_bar(front).
%% results_page(+TypeResults, +Results, +NumberOfResults)
%
% Generates a div were the results are shown.
results_page(cluster, Options) -->
{option(query(Query), Options),
concat('search(\'', Query, FunctionCall0),
concat(FunctionCall0, '\');', FunctionCall),
debug(functioncall, 'FunctionCall: ~p', [FunctionCall])
},
html([div(id('results'),''),script(FunctionCall)]).
%% carousel(+Items)
%
% Generates a carousel of the image urls and descriptions in
% Items.
carousel(Items) -->
html(div([class('carousel slide'),id('exampleCarousel'),'data-interval'('false')],
[\carousel_indicators(Items),
\carousel_items(Items),
\carousel_navigation
])).
carousel_indicators([First|Items]) -->
html(ol(class('carousel-indicators'),
[\first_carousel_indicator(First),
\more_carousel_indicators(Items,0)]
)
).
first_carousel_indicator(_) -->
html(
li(['data-target'('#exampleCarousel'), 'data-slide-to'('0'), class('active')],'')
).
more_carousel_indicators([],_) --> [].
more_carousel_indicators([_Indicator|Indicators],N) -->
{NextN is N+1},
indicator(NextN),
more_carousel_indicators(Indicators, NextN).
indicator(N) -->
html(li(['data-target'('#exampleCarousel'),'data-slide-to'(N)],''
)
).
carousel_items([First|Items]) -->
html(div(class('carousel-inner'),
[\first_carousel_item(First),
\more_carousel_items(Items)]
)
).
first_carousel_item(item(Image, Link, Text)) -->
html(
div(class('active item'),
[a(href(Link),img([src(Image),alt('Example'),id('example_image')])),
a(href(Link),div(class('carousel-caption'),h2(Text)))
]
)
).
more_carousel_items([]) --> [].
more_carousel_items([Item|Items]) -->
carousel_item(Item),
more_carousel_items(Items).
carousel_item(item(Image, Link, Text)) -->
html(
div(class('item'),
[a(href(Link),img([src(Image),alt('Example'),id('example_image')])),
a(href(Link),div(class('carousel-caption'),h2(Text)))
]
)
).
carousel_navigation -->
html(
[a([class('left carousel-control'), href('#exampleCarousel'), 'data-slide'('prev')],
span(class('icon-prev'),'')),
a([class('right carousel-control'), href('#exampleCarousel'), 'data-slide'('next')],
span(class('icon-next'),''))
]
).