Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Vocabulary search list Twig-templates #1470

Merged
merged 15 commits into from
Sep 28, 2023
24 changes: 21 additions & 3 deletions resource/css/skosmos.css
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,11 @@
--feedback-form-text: var(--dark-color);
--feedback-form-input: var(--light-color);
--feedback-form-button-bg: var(--dark-color);
--sidebar-search-bg: var(--dark-color);
--sidebar-search-text: var(--white-color);
--vocab-bg: var(--white-color);
--vocab-table-border: var(--medium-color);
--vocab-link: var(--secondary-dark-color);

/* Font definitions */
--font-size: 14px;
Expand Down Expand Up @@ -84,6 +89,7 @@ body {
color: var(--vocab-text);
font-size: 16px;
width: 20px;
text-align: center;
}

#main-container.searchpage .fa-copy, #main-container.searchpage-multi-vocab .fa-copy {
Expand Down Expand Up @@ -275,7 +281,7 @@ body {
font-weight: bold;
}

/***** Main container frontpage & frontpage one vacab *****/
/***** Main container frontpage & frontpage one vocab *****/
#background.frontpage, #background.frontpage-one-vocab {
background-color: var(--main-bg-1);
background-image: var(--frontpage-stripes-1);
Expand Down Expand Up @@ -362,7 +368,6 @@ body {
/***** Main container vocabpage & termpage & searchpage & searchpage multi vocab *****/
#main-container.vocabpage, #main-container.termpage, #main-container.searchpage, #main-container.searchpage-multi-vocab {
background-color: var(--main-bg-2);
padding: 1rem 0;
}

#main-container.vocabpage a, #main-container.termpage a, #main-container.searchpage a, #main-container.searchpage-multi-vocab a {
Expand All @@ -373,6 +378,7 @@ body {

#sidebar, #main-content {
background-color: var(--vocab-bg);
margin-left: 1rem;
}

/*** Sidebar termpage & vocabpage ***/
Expand Down Expand Up @@ -549,10 +555,12 @@ body {
/***** Main content searchpage & searchpage multi vocab *****/
.search-result {
border-top: 1px solid var(--vocab-table-border);
margin-top: 2.5rem;
}

.search-result-term a {
font-family: var(--font-family-heading);
font-size: 1.5rem;
text-decoration: none;
}

Expand All @@ -564,7 +572,17 @@ body {
.uri-icon {
display: inline-block;
width: 20px;
font-size: 10px;
font-size: 0.75rem;
text-align: center;
}

.prefLabel.proplabel {
font-weight: bold;
color: var(--secondary-dark-color);
}

.altLabel.proplabel {
font-style: italic;
}

/***** Main container infopage & feedbackpage *****/
Expand Down
7 changes: 5 additions & 2 deletions src/view/base-template.twig
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,17 @@
<link href="node_modules/bootstrap/dist/css/bootstrap.min.css" media="screen, print" rel="stylesheet" type="text/css">
<link href="resource/css/fonts.css" media="screen, print" rel="stylesheet" type="text/css">
<link href="resource/css/skosmos.css" media="screen, print" rel="stylesheet" type="text/css">
<link href="resource/fontawesome/css/fontawesome.css" rel="stylesheet">
<link href="resource/fontawesome/css/solid.css" rel="stylesheet">
<link href="resource/fontawesome/css/regular.css" rel="stylesheet">
{% if ServiceCustomCss %}
<link href="{{ ServiceCustomCss }}" media="screen, print" rel="stylesheet" type="text/css">
{% endif %}
{% for plugin, files in request.plugins.pluginsCSS %}{% for file in files %}<link href="{{ file }}" media="screen, print" rel="stylesheet" type="text/css">{% endfor %}{% endfor %}

<title>{{ ServiceName }}{% block title %}{% endblock %}</title>
</head>
<body{% if request.vocabid == '' and request.page != 'feedback' and request.page != 'about' %} class="bg-light frontpage-logo"{% else %} class="bg-medium vocab-{{ request.vocabid }}"{% endif %}>
<body{% if request.vocabid == '' and request.page != 'feedback' and request.page != 'about' and request.page != 'search' %} class="bg-light frontpage-logo"{% else %} class="bg-medium vocab-{{ request.vocabid }}"{% endif %}>
<noscript>
<strong>We're sorry but Skosmos doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
</noscript>
Expand Down Expand Up @@ -62,7 +65,7 @@
{% endif %}
</div>
</header>
<main id="main-container" class="py-5{% if request.vocabid == '' or global_search %} frontpage{% elseif concept_uri != '' %} termpage{% elseif request.vocab != '' %} vocabpage{% if list_style %} {{ list_style }}{% endif %}{% endif %}">
<main id="main-container" class="{% if request.vocabid == '' or global_search %} frontpage{% elseif concept_uri != '' %} termpage{% elseif request.vocab != '' %} vocabpage{% if list_style %} {{ list_style }}{% endif %}{% endif %}">
<div class="container">
<div class="row" tabindex="-1">
{% block content %}
Expand Down
Empty file removed src/view/global-search.twig
Empty file.
7 changes: 7 additions & 0 deletions src/view/search-results-filter.inc
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{% block content %}
<div class="col-md-4 pe-3">
<div class="p-4" id="sidebar">
<h4 class="fw-bold mb-5">{{ "Search options" | trans }}</h4>
</div>
</div>
{% endblock %}
113 changes: 113 additions & 0 deletions src/view/search-results.inc
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
{% block content %}
{%~ if search_results is not null and search_results|length == 0 ~%}
<p class="no-results">{{ "The search provided no results." | trans }}</p>
{%~ endif ~%}

{%~ for concept in search_results ~%} {# loop through the hits #}

<div class="search-result pt-1">
<div class="search-result-term">
{%- if vocab == '' and concept.vocab.id is defined %}<span class="fw-bold" data-title="{{ concept.vocabTitle }}">{{ concept.shortName }}: </span>{% endif -%}
{%- if concept.foundBy %} {# hit has been found through an alt/hidden/another language label #}
{%~ if concept.foundByType != 'lang' and concept.foundByType != 'hidden' ~%}
<span class="fst-italic">{{ concept.foundBy }}{%~ if explicit_langcodes or request.queryparam('anylang') and concept.contentLang != '' ~%} ({{ concept.contentLang }}){%~ endif ~%}</span>
&nbsp;<i class="fa-solid fa-arrow-right"></i>&nbsp;
{%~ if concept.notation ~%}<span>{{ concept.notation }}&nbsp;</span>{%~ endif ~%}
<a class="fw-bold" href="{%~ if 'isothes:ConceptGroup' in concept.type ~%}{{ concept.uri | link_url(concept.vocab,request.lang,'page',concept.contentLang) }}{%~ else ~%}{{ concept.uri | link_url(concept.vocab,request.lang,'page',concept.contentLang) }}{%~ endif ~%}">{{ concept.label(request.contentLang) }}</a>
{%~ if explicit_langcodes or request.queryparam('anylang') ~%}<span> ({{ concept.label.lang }})</span>{%~ endif ~%}
{%~ else ~%}
{%~ if concept.notation ~%}<span>{{ concept.notation }}&nbsp;</span>{%~ endif ~%}
<a href="{%~ if "isothes:ConceptGroup" in concept.type ~%}{{ concept.uri | link_url(concept.vocab,request.lang,'page',concept.contentLang) }}{%~ else ~%}{{ concept.uri | link_url(concept.vocab,request.lang,'page',concept.contentLang) }}{%~ endif ~%}">{{ concept.label(request.contentLang) }}</a>
{%~ if explicit_langcodes or request.queryparam('anylang') ~%}<span> ({{ concept.contentLang }})</span>{%~ endif ~%}
{%~ endif ~%}
{%~ else ~%}
{%~ if concept.notation %}<span class="notation">{{ concept.notation }}&nbsp;</span>{% endif ~%}
<a class="prefLabel conceptlabel" href="{%~ if "isothes:ConceptGroup" in concept.type ~%}{{ concept.uri | link_url(concept.vocab, request.lang, 'page') }}{%~ elseif concept.exvocab is defined%}{{ concept.uri | link_url(concept.exvocab,concept.contentLang) }}{%~ else ~%}{{ concept.uri | link_url(concept.vocab,request.lang,'page',concept.contentLang) }}{%~ endif ~%}">{{ concept.label(request.contentLang) }}</a>{%~ if explicit_langcodes or request.queryparam('anylang') ~%} ({{ concept.contentLang }}){%~ endif ~%}
{% endif -%}
</div>
<ul class="list-group">
{% set conceptProperties = concept.properties %}
{%~ for property in conceptProperties ~%} {# loop through ConceptProperty objects #}
{%~ if property.type in PreferredProperties or property.type in concept.vocab.config.additionalSearchProperties or property.type in concept.vocab.config.hierarchyProperty ~%}
<li class="list-group-item px-0 py-1">
<span class="skosmos-tooltip" data-title="{{ property.description }}">
{%- if property.type == 'skos:broader' -%}<i class="property-hover fa-solid fa-arrow-turn-up fa-rotate-270"></i>
{%- elseif property.type == 'skos:narrower' -%}<i class="property-hover fa-solid fa-arrow-turn-up fa-rotate-90"></i>
{%- elseif property.type == 'skos:altLabel' -%}<i class="property-hover fa-solid fa-ban"></i>
{%- elseif property.type == 'skos:related' -%}<i class="property-hover fa-solid fa-cloud"></i>
{%- elseif property.type == 'skosmos:memberOf' -%}<i class="property-hover fa-solid fa-layer-group"></i>
{%- elseif property.type == 'skos:note' -%}<i class="property-hover fa-solid fa-note-sticky"></i>
{%- else -%}<i class="property-hover fa-solid fa-globe"></i>
{%- endif -%}
</span>
{%- for propval in property.values -%} {# loop through ConceptPropertyValue objects #}
{%~ set outerLast = loop.last ~%}
{%- if propval.uri ~%} {# resources with URI #}
{%- if propval.label ~%}
{%- if propval.exvocab and propval.exvocab != propval.vocab ~%}{# if the property is located in a another vocabulary #}{{ propval.label }}
{% else %}
{{ propval.label(request.contentLang) }}
{%- endif -%}
{%- if propval.lang and (propval.lang != request.lang) or explicit_langcodes %} ({{ propval.lang }}){%~ endif -%}{%- if not loop.last ~%}, {%~ endif ~%}
{%~ endif -%}
{%~ else ~%} {# Literals (no URI), eg. alternative labels as properties #}
<span class="{%~ if propval.type == 'skos:altLabel' %}altLabel proplabel{% endif ~%}">{{ propval.label }}{%- if not loop.last -%}, {% endif %}</span>
{%~ endif %}
{%- endfor %}
</li>
{%~ endif ~%}
{%~ endfor ~%}
{%~ set foreignLabels = concept.foreignLabels ~%}
{%~ if foreignLabels ~%}
<li class="list-group-item px-0 py-1">
<span class="skosmos-tooltip" data-title="foreign prefLabel help"><i class="property-hover fa-solid fa-globe"></i></span>
{%- for langstring, labels in foreignLabels ~%}
{%~ for label in labels.prefLabel|default([])|merge(labels.altLabel|default([])) ~%}
<span class="{% if label.type == 'skos:prefLabel' %}prefLabel{% elseif label.type == 'skos:altLabel' %}altLabel{% endif %} proplabel">{{ label }}</span>{%~ if label.lang %} ({{ label.lang }}){% endif ~%}{%- if loop.last == false %}, {% endif -%}
{%~ endfor ~%}
{%- if loop.last == false -%}, {%- endif -%}
{%~ endfor ~%}
</li>
{% endif ~%}

{%~ if concept.vocab.config.additionalSearchProperties ~%}
{%~ set mappingProperties = concept.mappingProperties(concept.vocab.config.additionalSearchProperties) ~%}
{%~ if mappingProperties ~%}
{%~ for property in mappingProperties ~%} {# loop through ConceptProperty objects #}
{%~ if property.type in concept.vocab.config.additionalSearchProperties ~%}
<li class="list-group-item px-0 py-1">
<span class="skosmos-tooltip" data-title="{{ property.type }}">
<i class="property-hover fa-solid fa-globe"></i>
</span>
{%- for propval in property.values -%} {# loop through ConceptMappingPropertyValue objects #}
{%- if propval.exVocab -%}<span class="redirected-vocab-id prefLabel">{{ propval.exVocab.shortName }}: </span>{%- endif -%}{{ propval.label(request.contentLang) }}
{%- if propval.label(request.contentLang).lang != request.contentLang -%} ({{ propval.label(request.contentLang).lang }}){%- endif -%}{%- if loop.last == false -%}, {% endif %}
{% endfor %}
</li>
{%~ endif ~%}
{%~ endfor ~%}
{%~ endif ~%}
{%~ endif -%}
{%- for property in conceptProperties ~%} {# loop through ConceptProperty objects #}
{%- if property.type == 'rdf:type' ~%}
<li class="list-group-item px-0 py-1">
<span class="skosmos-tooltip" data-title="concept_types">
<i class="property-hover fa-solid fa-arrows-to-circle"></i>
</span>
{%- for propval in property.values %}{{ propval.label | trans }}{% if loop.last == false %}, {% endif %}{% endfor %}

</li>
{%~ endif -%}
{%~ endfor -%}
{%~ if concept.uri ~%}
<li class="list-group-item px-0 py-1">
<span class="uri-icon">URI</span>
<span class="search-result-uri">{{ concept.uri }}</span>
<i class="fa-regular fa-copy"></i> <!-- no copy to clipboard functionality yet -->
</li>
{%~ endif ~%}
</ul>

</div>
{%~ endfor ~%}
{% endblock %}
22 changes: 22 additions & 0 deletions src/view/vocab-search.twig
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
{% extends "base-template.twig" %}
{% block title %}: {{ vocab.shortName(request.contentLang) }} '{{ term }}'{% endblock %}
{% block content %}
<main class="searchpage py-5" id="main-container" >
<div class="container">
<div class="row">
{% include "search-results-filter.inc" %}

<div class="col-md-7 ps-3" id="main-content">
<div class="p-4 pt-4">
<div class="search-count">
<p class="py-2">
<span class="fw-bold">{{ "%search_count% results for '%term%'" | trans({'%search_count%': search_count, '%term%' : term}) }}</span>
</p>
</div>
{% include "search-results.inc" %}
</div>
</div>
</div>
</div>
</main>
{% endblock %}
32 changes: 31 additions & 1 deletion tests/cypress/template/vocab-search.cy.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,33 @@
describe('Vocabulary search page', () => {
it('no-op test', () => {})
const vocab = 'test';
const term = 'bass';
it('Contains correct amount of search results ', () => {
const count = 1;
const searchCountTitle = `${count} results for \'${term}\'`;
cy.visit(`/${vocab}/en/search?clang=en&q=${term}`)

//Check that the search count is correct
cy.get('.search-count > p > span').invoke('text').should('contain', searchCountTitle);

//Check that search count matces the number of results
cy.get('div.search-result').should('have.length', count)

})
it('Search results contains correct info', () => {
cy.visit(`/${vocab}/en/search?clang=en&q=${term}`)

//Check that there is a search result that contains a type icon
cy.get('div.search-result > ul > li > span > i.property-hover.fa-solid.fa-arrows-to-circle')

//Check that there is correct amount of different properties for the search result
cy.get('div.search-result > ul > li').should('have.length', 3)

//Check the order of search result properties
cy.get('div.search-result > ul').within(() => {
cy.get('li').eq(0).invoke('text').should('contain', 'Fish')
cy.get('li').eq(1).invoke('text').should('contain', 'Test class')
cy.get('li').eq(2).invoke('text').should('contain', 'http://www.skosmos.skos/test/ta116')
})

})
})