cluster_search_ui/commit
Added old cluster_search config available file.
author | Chris Dijkshoorn |
---|---|
Sat Dec 13 13:22:50 2014 +0100 | |
committer | Chris Dijkshoorn |
Sat Dec 13 13:22:50 2014 +0100 | |
commit | 2308f004c307511b678d5c31a3fb3eabbc29871b |
tree | 6a7c1d205570de0b81f7e2fc15ee4dbc80a32dd1 |
parent | ec2012f112c4daa4a1b3ba02ddaae0b4e9dd4e08 |
Diff style: patch stat
diff --git a/config-available/cluster_search_ui.pl b/config-available/cluster_search_ui.pl index 908828d..38203e5 100644 --- a/config-available/cluster_search_ui.pl +++ b/config-available/cluster_search_ui.pl @@ -1,5 +1,15 @@ -:- module(conf_cluster_search_ui, []). +:- module(conf_cluster_search, []). -/** <module> Frontend for cluster search +/** <module> search based on clustering paths in the graph */ +:- use_module(library('semweb/rdf_db')). +:- use_module(library('semweb/rdf_library')). + +:- rdf_attach_library(cluster_search(rdf)). +:- rdf_load_library('cluster-search-ui-schema'). +:- rdf_load_library('cluster-search-schema'). +:- rdf_load_library('rijksmuseum-search-ui'). +:- rdf_load_library('bird-search-ui'). + +:- use_module(api(cluster_search)). diff --git a/lib/cluster_search_ui/settings.pl b/lib/cluster_search_ui/settings.pl new file mode 100644 index 0000000..c1c12f5 --- /dev/null +++ b/lib/cluster_search_ui/settings.pl @@ -0,0 +1,48 @@ +:- module(cluster_search_settings, []). + +:- use_module(library(settings)). + +/*************************************************** +* Cluster search settings +***************************************************/ + +:- setting(search:basic_search_target, uri, 'http://www.europeana.eu/schemas/edm/ProvidedCHO', + 'Default Target for search'). +:- setting(search:threshold, float, 0.05, + 'Graph-search threshold'). +:- setting(search:literal_threshold, float, 0.05, + 'Literal-search threshold'). +:- setting(search:literal_score, boolean, true, + 'Use score of string match in threshold of graph search'). +:- setting(search:steps, nonneg, 1000, + 'Maximum number of steps in the graph search (0 is unbound)'). +:- setting(search:edge_limit, nonneg, 0, + 'Limit extension of Node with a maximum number of edges \c + (0 is unbound)'). +:- setting(search:max, nonneg, 100, + 'Maximum number of results shown in the output'). +:- setting(search:cluster, oneof([concept, path, spath, role]), spath, + 'Create clusters by graph path or schema path'). +:- setting(search:search_path, oneof([best, breadth]), best, + 'Create clusters on best or shortest path'). +:- setting(search:sort, oneof([score, path_length, false]), score, + 'Sort the results by'). +:- setting(search:prune, boolean, true, + 'Prune the search Graph'). +:- setting(search:search_type, oneof([literal,concept,backward]), backward, + 'Method to traverse the graph'). +% frontend settings +:- setting(search:strategy, atom, cluster, + 'The strategy used for searching.'). +:- setting(search:image_filter, atom, only_images, + 'Filter used for presenting the results.'). +:- setting(search:enrichment, atom, thumbnails, + 'Setting indicating the level of enrichment of results.'). +:- setting(search:ui, uri, rui:rijksmuseumUI, + 'Default URI defining the UI for search'). +:- setting(search:graphSearchCache, boolean, false, + 'Cache graph search results'). +:- setting(search:graphSearchCacheSize, nonneg, 50, + 'Maximum searches kept in cache (0 is unbound)'). +:- setting(search:annotate, boolean, false, + 'Indicate the possibility of annotating search result.'). diff --git a/lib/cluster_search_ui/web_ui.pl b/lib/cluster_search_ui/web_ui.pl new file mode 100644 index 0000000..973476c --- /dev/null +++ b/lib/cluster_search_ui/web_ui.pl @@ -0,0 +1,671 @@ +:- module(web_ui, [ + web/1, + results/1, + about/1, + result/1, + analytics/1 + ]). +/** <module> Generation of web ui for cluster search + +This module is used for generating HTML elements for the ui for cluster +search. It is able to generate 4 different types of pages: + + * front - frontpage with a carousel of search examples + * results - results page depicting the search results + * result - one result and its metadata + * about - information about the system + +The ui variables are retrieved from rdf (e.g. rdf/rijksmuseum_ui.ttl). +*/ + +:- use_module(library(http/html_write)). +:- use_module(library(http/html_head)). +:- use_module(library(http/http_path)). +:- use_module(library(http/http_parameters)). +:- 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)). +:- use_module(library(cluster_search/settings)). +:- use_module(cliopatria(components/label)). +:- use_module(library(cluster_search/search_statistics)). +:- use_module(applications(annotation)). + +:- set_setting_default(thumbnail:thumbnail_size, size(350,300)). +:- set_setting_default(thumbnail:medium_size, size(1280,1024)). +:- set_setting_default(search:image_filter, all). + +%% web(+Request) is det. +% +% If query is given, generate results page, fron page otherwise. +web(_Request) :- + reply_page(front, _Options). + +%% results(+Request) is det. +% +% Generate results page. +results(Request) :- + get_parameters(Request, Options), + reply_page(results, Options). + +%% restult(+Request) is det. +% +% Generate a page showing a result with its metadata. +result(Request) :- + get_parameters(Request, Options), + reply_page(result, Options). + +%% about(+Request) is det. +% +% Generate about page. +about(Request) :- + get_parameters(Request, Options), + reply_page(about, Options). + +%% analytics(+Request) is det. +% +% Generate analytics page. +analytics(Request) :- + get_parameters(Request, Options), + reply_page(analytics, Options). + + +%% get_parameters(+Request, -Options) +% +% Retrieves an option list of parameters from the url. +get_parameters(Request, Options) :- + http_parameters(Request, + [query(Query, [description('Entered Query'), optional(true)]), + uri(URI, [description('URI of the item'), optional(true)]) + ]), + Options = [query(Query), uri(URI)]. + +%% reply_page(+Page, +Options) +% +% Replies the html page corresponding to the type of page and +% Request. +reply_page(Page, Options) :- + setting(search:ui, UI), + rdf(UI, ui:iconLocation, literal(IconName)), + http_absolute_location(icons(IconName), Icon, []), + html_resource(css('search.css'), [requires([css('bootstrap.min.css')])]), + reply_html_page( + [ + \title(Page, Options), + link([href(Icon),rel('shortcut icon')]), + meta([name('viewport'),content('width=device-width, initial-scale=1.0')]) + ], + [\html_requires(css('search.css')), + \navigation_bar(Page), + \scripts(Page), + \content(Page, Options) + ]). + +%% 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(search:annotate, Annotate), + (Annotate + -> get_annotation_options(Uri, AnnotationOrImage) + ; get_image_options(Uri, AnnotationOrImage) + ), + findall([Predicate, Object], rdf(Uri, Predicate, Object), Metadata) + }, + html([\result_page_body(Annotate, AnnotationOrImage), + div([class('row'), id('metadata')],div([class('well well-sm')],dl(class('dl-horizontal'), + \metadata(Metadata)))) + ]). + +content(about, _) --> + {current_prolog_flag(version, Version), + setting(search:ui, UI), + rdf(UI, dcterms:title, literal(lang(en, Title))) + }, + html({|html(Title, Version)|| + <div class="row"> + <div class="col-md-10 col-md-offset-1"> + <h3>About <span>Title</span></h3> + + <p>This website is used to demo semantic search strategies, developed at the <a href="http://wm.cs.vu.nl/">Web and Media group </a>of the VU University Amsterdam. The images originate from the <a href="https://www.rijksmuseum.nl/">Rijksmuseum Amsterdam</a>. This work is done in the context of the <a href="http://sealincmedia.wordpress.com/">SEALINCMedia</a> project. For more information contact <a href="http://www.few.vu.nl/~cdn370/">Chris Dijkshoorn</a>. + </p> + + <p><span>Title</span> is running on <a href="http://cliopatria.swi-prolog.org/">Cliopatria</a> powered by <a href="http://www.swi-prolog.org/">Prolog</a> version <span>Version</span>. The code is available on <a href="https://github.com/rasvaan/cluster_search/">Github</a>, you are welcome to report bugs or file feature requests. + </p> + </div> + </div> + |}). + +content(analytics, _) --> + {debug(analytics, 'Querying for statistics.', []), + get_dataset_statistics_minimal(DatasetStatistics), + %DatasetStatistics = [dataset_statistics(rma, 'Rijksmuseum Collection', [['stub', 36]])], + %http_absolute_location(analysis('analysis_results.csv'), AnalysisCSV, []), + %concat('areaChart("', AnalysisCSV, FunctionArea0), + %concat(FunctionArea0, '");', FunctionArea), + %concat('barChart("', AnalysisCSV, FunctionBar0), + %concat(FunctionBar0, '");', FunctionBar), + debug(analytics, 'The statistics: ~p', [DatasetStatistics]) + }, + html([div(class('container-fluid'), + div(class('row'), + [div(class('col-sm-3 col-md-2 sidebar'), + \navigation_analytics), + div(['data-spy'('scroll'), 'data-target'('.sidebar'), class('col-sm-9 col-sm-offset-3 col-md-10 col-md-offset-2 col-md-8 col-md-offset-2')], + [div([h1('Statistics'), + p(class('lead'),'Get (some) insight in the loaded collection.')]), + %div(id('query-overview'), + % [a([class('anchor'), id('query-overview-anchor')],''), + % h2('Query Overview')]), + %div(id('query-matches'), + % [a([class('anchor'), id('query-matches-anchor')],''), + % h2('Query Matches')]), + %div(id('analytics-test'), + % [a([class('anchor'), id('analytics-test-anchor')],''), + % h2('Analytics Test'), + % \analytics_html]), + div(id('dataset-statistics'), + [a([class('anchor'), id('dataset-statistics-anchor')],''), + h2('Dataset Statistics'), + \dataset_statistics(DatasetStatistics)]) + ]) + ])), + %script(src('https://apis.google.com/js/client.js?onload=handleClientLoad'), ''), + \load_javascript(analytics)]). + %script(FunctionArea), + %script(FunctionBar)]). + %html([div(id('results'),''),script('analytics();')]). + +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). +%analytics_html --> +% html({|html|| +% <!-- The 2 Buttons for the user to interact with --> +% <button id="authorize-button" style="visibility: +% hidden">Authorize</button><br/> +% <button id="make-api-call-button" style="visibility: hidden">Get Visits</button> |}). +% + + +%% get_carousel_items(-CarouselItems) +% +% Retrieve items for the carousel from the RDF store. +get_carousel_items(CarouselItems) :- + findall(item(LocationAbsolute, Action, Title), + ( rdf(Item, rdf:type, ui:carouselItem), + 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. +% If not present, but a isShownBy is present in database, remove +% isShownBy triple. If not present in cache, database and at RMA, +% send image stub. +image_url(Uri, ImageUrl) :- + cliopatria:image_url(Uri, ImageUrl). + +image_url(Uri, ImageUrl) :- + rdf(Aggregation, edm:aggregatedCHO, Uri), + rdf(Aggregation, edm:isShownBy, Image), + url_cached(Image, file(_)), + !, + concat('cache/original?uri=', Image, RequestUrl), + http_absolute_location(root(RequestUrl), ImageUrl, []). + +image_url(Uri, ImageUrl) :- + rdf(Aggregation, edm:aggregatedCHO, Uri), + rdf(Aggregation, edm:isShownBy, Image), + https_header_response(Image, Status), + Status == 200, + !, + concat('cache/original?uri=', Image, RequestUrl), + http_absolute_location(root(RequestUrl), ImageUrl, []). + +image_url(Uri, Stub) :- + rdf(Aggregation, edm:aggregatedCHO, Uri), + rdf(Aggregation, edm:isShownBy, Image), + !, + rdf_retractall(Uri, edm:isShownBy, Image), + http_absolute_location(icons('stub.png'), Stub, []). + +image_url(_, Stub) :- http_absolute_location(icons('stub.png'), Stub, []). + +%% 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(search:ui, UI), + rdf(UI, dcterms:title, literal(lang(en, Title)))}, + html(title(Title)). +title(about, _) --> + {setting(search: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(search: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)). + +%% scripts(+Page) +% +% Replies the scripts needed for the indicated page. +scripts(front) --> + html([\load_javascript(jquery), + \load_javascript(bootstrap), + \load_javascript(type_ahead), + \load_javascript(search), + \load_javascript(google_analytics)]). + +scripts(results) --> + html([\load_javascript(jquery), + \load_javascript(bootstrap), + \load_javascript(type_ahead), + \load_javascript(search), + \load_javascript(pagination), + \load_javascript(thumbnail), + \load_javascript(google_analytics)]). + +scripts(result) --> + html([\load_javascript(jquery), + \load_javascript(bootstrap), + \load_javascript(type_ahead), + \load_javascript(search), + \load_javascript(google_analytics)]). + +scripts(about) --> + html([\load_javascript(jquery), + \load_javascript(bootstrap), + \load_javascript(type_ahead), + \load_javascript(search), + \load_javascript(google_analytics)]). + +scripts(analytics) --> + html([\load_javascript(jquery), + \load_javascript(bootstrap), + \load_javascript(d3js), + \load_javascript(type_ahead), + \load_javascript(search), + \load_javascript(google_analytics)]). + +%% 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(d3js) --> + html(script(src('http://d3js.org/d3.v3.js'),'')). +load_javascript(type_ahead) --> + {http_absolute_location(js('typeahead.min.js'), JavaScriptTypeahead, [])}, + html(script(src(JavaScriptTypeahead),'')). +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(google_analytics) --> + {http_absolute_location(js('google_analytics.js'), JavaScriptGoogleAnalytics, [])}, + html(script(src(JavaScriptGoogleAnalytics),'')). +load_javascript(analytics) --> + {http_absolute_location(js('analytics.js'), JavaScriptAnalytics, [])}, + html(script(src(JavaScriptAnalytics),'')). + +%% navigation_bar(+Page) +% +% Generates the navigation bar for the given page. +navigation_bar(front) --> + {http_location_by_id(web, HttpWeb), + http_location_by_id(results, HttpSearch), + http_location_by_id(about, HttpAbout), + http_location_by_id(analytics, HttpAnalytics), + setting(search:ui, UI), + rdf(UI, dcterms:title, literal(lang(en, Title))) + }, + html({|html(HttpWeb, HttpSearch, HttpAbout, HttpAnalytics, Title)|| + <nav class="navbar navbar-fixed-top navbar-inverse" role="navigation"> + <div class="navbar-header"> + <button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-sign-collapse"> + <span class="icon-bar"></span> + </button> + <a class="navbar-brand" href="HttpWeb">Title</a> + </div> + + <div class="collapse navbar-collapse navbar-sign-collapse"> + <ul class="nav navbar-nav navbar-right"> + <li><a href="HttpAnalytics">Statistics</a></li> + <li><a href="HttpAbout">About</a></li> + </ul> + <form class="navbar-form" action="HttpSearch" autocomplete="off"> + <div class="input-group search-form"> + <input type="search" class="form-control typeahead" name="query"> + <span class="input-group-btn"> + <button type="submit" class="btn btn-default">Search</button> + </span> + </div><!-- /input-group --> + </form> + </div> + </nav> + |}). + +navigation_bar(about) --> + {http_location_by_id(web, HttpWeb), + http_location_by_id(results, HttpSearch), + http_location_by_id(about, HttpAbout), + http_location_by_id(analytics, HttpAnalytics), + setting(search:ui, UI), + rdf(UI, dcterms:title, literal(lang(en, Title))) + }, + html({|html(HttpWeb, HttpSearch, HttpAbout, HttpAnalytics, Title)|| + <nav class="navbar navbar-fixed-top navbar-inverse" role="navigation"> + <div class="navbar-header"> + <button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-sign-collapse"> + <span class="icon-bar"></span> + </button> + <a class="navbar-brand" href="HttpWeb">Title</a> + </div> + + <div class="collapse navbar-collapse navbar-sign-collapse"> + <ul class="nav navbar-nav navbar-right"> + <li><a href="HttpAnalytics">Statistics</a></li> + <li class="active"><a href="HttpAbout">About</a></li> + </ul> + <form class="navbar-form" action="HttpSearch" autocomplete="off"> + <div class="input-group search-form"> + <input type="search" class="form-control typeahead" name="query"> + <span class="input-group-btn"> + <button type="submit" class="btn btn-default">Search</button> + </span> + </div><!-- /input-group --> + </form> + </div> + </nav> + |}). + +navigation_bar(analytics) --> + {http_location_by_id(web, HttpWeb), + http_location_by_id(results, HttpSearch), + http_location_by_id(about, HttpAbout), + http_location_by_id(analytics, HttpAnalytics), + setting(search:ui, UI), + rdf(UI, dcterms:title, literal(lang(en, Title))) + }, + html({|html(HttpWeb, HttpSearch, HttpAbout, HttpAnalytics, Title)|| + <nav class="navbar navbar-fixed-top navbar-inverse" role="navigation"> + <div class="navbar-header"> + <button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-sign-collapse"> + <span class="icon-bar"></span> + </button> + <a class="navbar-brand" href="HttpWeb">Title</a> + </div> + + <div class="collapse navbar-collapse navbar-sign-collapse"> + <ul class="nav navbar-nav navbar-right"> + <li class="active"><a href="HttpAnalytics">Statistics</a></li> + <li><a href="HttpAbout">About</a></li> + </ul> + <form class="navbar-form" action="HttpSearch" autocomplete="off"> + <div class="input-group search-form"> + <input type="search" class="form-control typeahead" name="query"> + <span class="input-group-btn"> + <button type="submit" class="btn btn-default">Search</button> + </span> + </div><!-- /input-group --> + </form> + </div> + </nav> + |}). + + +navigation_bar(results) --> navigation_bar(front). +navigation_bar(result) --> navigation_bar(front). + +navigation_analytics --> + html({|html|| + <ul class="nav nav-sidebar"> + <!--<li class="active"><a href="#query-overview-anchor">Query Overview</a></li>--> + <!--<li><a href="#query-matches-anchor">Query Matches</a></li>--> + <li><a href="#dataset-statistics-anchor">Dataset</a></li> + </ul> + |}). + +%% metadata(+ListOfPredicateObjectPairs) +% +% Loops through the list of metadata fields +metadata([]) --> []. +metadata([[Predicate,Object]|T]) --> + html(\format_metadata(Predicate, Object)), + metadata(T). + +%% format_metadata(+Predicate, +Object) +% +% Formats the metadata field into table rows. +format_metadata(Predicate, Object) --> + html( + [dt(\rdf_link(Predicate, [resource_format(nslabel)])), + dd(\rdf_link(Object, [resource_format(nslabel)])) + ]). + +%% dataset_statistics(+Statistics) +% +% Loops through the list of dataset statistics +dataset_statistics(Statistics) --> + html([ul(class('nav nav-tabs'),\navigation_tabs(Statistics)), + div(class('tab-content'),\tab_tables(Statistics))]). + +%% navigation_tabs(+Statistics) +% +% Loops through the list of dataset statistics +navigation_tabs([First|More]) --> + html([\first_tab(First), + \more_tabs(More)]). + +first_tab(dataset_statistics(ID, Name, _Statistics)) --> + {concat('#', ID, IDRef)}, + html(li(class('active'), a([href(IDRef), 'data-toggle'('tab')], Name))). + +more_tabs([]) --> []. +more_tabs([dataset_statistics(ID, Name, _Statistics)|T]) --> + {concat('#', ID, IDRef)}, + html(li(a([href(IDRef), 'data-toggle'('tab')], Name))), + more_tabs(T). + +%% tab_tables(+Statistics) +% +% Loops through the list of dataset statistics to create the +% contents, which are tables. +tab_tables([First|More]) --> + html([\first_tab_pane(First), + \more_tab_panes(More)]). + + +first_tab_pane(dataset_statistics(ID, _Name, Statistics)) --> + html(div([class('tab-pane fade in active'),id(ID)], + table(class('table table-striped'),\dataset_rows(Statistics)))). + +more_tab_panes([]) --> []. +more_tab_panes([Dataset|T]) --> + html(\tab_pane(Dataset)), + more_tab_panes(T). + +tab_pane(dataset_statistics(ID, _Name, Statistics)) --> + html(div([class('tab-pane fade data-table'),id(ID)], + table(class('table table-striped'), + \dataset_rows(Statistics)))). + +%% dataset_rowd(+Statistics) +% +% Loops through the list of dataset statistics +dataset_rows([]) --> []. +dataset_rows([[Property, Value]|T]) --> + html([tr([td(Property), td(Value)])]), + dataset_rows(T). + +%% 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'),'')) + ] + ).