1<#-- Variables -->
2<#assign specificationName = 'ics' />
3<#assign paramNameSpecificationName = cpSpecificationOptionsSearchFacetDisplayContext.getParameterName() />
4<#assign isDebug = false />
5<#assign showAllSpecificationsName = false />
6<#assign staticHost = getCXConfig("ecom-static-files") />
7
8<#-- ========================= -->
9<#-- Functions freemaker -->
10<#-- ========================= -->
11<#function getCXConfig clientExtensionName field="webApiUrl">
12 <#if !clientExtensionName?has_content><#return "" /></#if>
13 <#local encoded = urlCodec.encodeURL(clientExtensionName) />
14 <#local items = restClient.get("/c/customconfigs/?fields=clientExtensionConfig&filter=clientExtensionName eq '" + encoded + "'").items![] />
15 <#return items?has_content?then(items[0].clientExtensionConfig?eval[field]!"", "") />
16</#function>
17
18<#if paramNameSpecificationName == specificationName || showAllSpecificationsName>
19
20 <#-- ========================= -->
21 <#-- Mapa de organismos -->
22 <#-- ========================= -->
23 <#assign taxonomyResponse = restClient.get("/headless-admin-taxonomy/v1.0/taxonomy-vocabularies/39789900/taxonomy-categories?pageSize=50")!{} />
24 <#assign organismoMap = {} />
25 <#list taxonomyResponse.items![] as cat>
26 <#assign categoryKey = "39789900-" + cat.id />
27 <#assign organismoMap = organismoMap + {categoryKey: cat.name} />
28 </#list>
29
30 <#-- ========================= -->
31 <#-- Agregacion spec-Organismos-->
32 <#-- ========================= -->
33 <#assign sharedSearchResponse = renderRequest.getAttribute("LIFERAY_SHARED_PortletSharedSearchResponse") />
34 <#assign searchResponse = sharedSearchResponse.get() />
35 <#assign esResponse = searchResponse.getSearchResponse() />
36 <#assign aggName = paramNameSpecificationName + "_with_organismos" />
37 <#assign specOrgAggResult = esResponse.getAggregationResult(aggName) />
38
39 <#-- Construir mapa spec -> lista de organismos -->
40 <#assign specOrganismosMap = {} />
41 <#if specOrgAggResult?has_content>
42 <#list specOrgAggResult.getBuckets() as specBucket>
43 <#assign specKey = specBucket.getKey() />
44 <#assign organismoAgg = specBucket.getChildAggregationResult("organismos") />
45 <#assign orgNames = [] />
46 <#list organismoAgg.getBuckets() as orgBucket>
47 <#assign orgName = organismoMap[orgBucket.getKey()]!"?" />
48 <#assign orgNames = orgNames + [orgName] />
49 </#list>
50 <#assign specOrganismosMap = specOrganismosMap + {specKey: orgNames} />
51 </#list>
52 </#if>
53
54 <#-- ========================= -->
55 <#-- Debug -->
56 <#-- ========================= -->
57 <#if isDebug>
58 <div style="background:#f0f0f0;padding:8px;margin-bottom:8px;font-size:11px;border:1px solid #ccc;">
59 <p><strong>aggName:</strong> ${aggName}</p>
60 <p><strong>organismoMap size:</strong> ${organismoMap?size}</p>
61 <p><strong>specOrganismosMap size:</strong> ${specOrganismosMap?size}</p>
62 <#list specOrganismosMap?keys as spec>
63 <p>${spec}: ${specOrganismosMap[spec]?join(", ")}</p>
64 </#list>
65 </div>
66 </#if>
67
68 <#-- Variables -->
69 <#assign facetId = "facet-" + paramNameSpecificationName + "-" + renderResponse.getNamespace() />
70 <#assign facetClass = "facet-" + paramNameSpecificationName + "-combo-search-wrapper" />
71
72 <#-- ========================= -->
73 <#-- TOM SELECT framework -->
74 <#-- ========================= -->
75 <@liferay_util["html-top"] outputKey="tom-select">
76 <link href="${staticHost}/scripts/vendor/tom-select/tom-select.css" rel="stylesheet">
77 <script src="${staticHost}/scripts/vendor/tom-select/tom-select.complete.min.js"></script>
78 </@>
79
80 <#-- ========================= -->
81 <#-- CSS -->
82 <#-- ========================= -->
83 <style>
84 #${facetId} {
85 --facet-font-family: Inter;
86 --facet-font-size: 14px;
87 --facet-font-weight: 400;
88 --facet-line-height: 18px;
89 --facet-letter-spacing: 0.5px;
90 --facet-color: #66757f;
91 }
92 #${facetId}-select {
93 appearance: none;
94 -webkit-appearance: none;
95 visibility: hidden;
96 position: absolute;
97 }
98 #${facetId} .ts-wrapper {
99 width: 100%;
100 margin-bottom: 16px;
101 opacity: 0;
102 transition: opacity 0.1s ease;
103 }
104 #${facetId} .ts-wrapper .ts-control {
105 padding: 15.5px 16px;
106 font-family: var(--facet-font-family);
107 font-size: var(--facet-font-size);
108 font-weight: var(--facet-font-weight);
109 line-height: var(--facet-line-height);
110 letter-spacing: var(--facet-letter-spacing);
111 color: var(--facet-color);
112 text-align: left;
113 height: 55px;
114 width: 100%;
115 border-radius: 4px;
116 border: none;
117 background-color: #F5F5F5;
118 background-image: url(/documents/d/global/ico-chevron-down-2);
119 background-repeat: no-repeat;
120 background-position: right 1rem center;
121 background-size: 18px 10px;
122 box-shadow: none;
123 cursor: pointer;
124 box-sizing: border-box;
125 }
126 #${facetId} .ts-wrapper .ts-control:focus,
127 #${facetId} .ts-wrapper .ts-control:focus-visible {
128 background-image: url(/documents/d/global/ico-chevron-down-2);
129 background-position: right 1rem center;
130 background-size: 18px 10px;
131 outline: none;
132 box-shadow: none;
133 }
134 #${facetId} .ts-wrapper .ts-control .item {
135 padding-right: 0.75rem;
136 overflow: hidden;
137 text-overflow: ellipsis;
138 max-width: calc(100% - 0.75rem);
139 }
140 #${facetId} .ts-wrapper.single .ts-control::after {
141 display: none;
142 }
143 #${facetId} .ts-dropdown .dropdown-input-wrap .dropdown-input {
144 font-family: var(--facet-font-family);
145 font-size: var(--facet-font-size);
146 font-weight: var(--facet-font-weight);
147 line-height: var(--facet-line-height);
148 letter-spacing: var(--facet-letter-spacing);
149 color: var(--facet-color);
150 padding: 8px 16px;
151 border: none;
152 border-bottom: 1px solid #d9d9d9;
153 background-color: #fff;
154 width: 100%;
155 box-sizing: border-box;
156 }
157 #${facetId} .ts-dropdown .dropdown-input-wrap .dropdown-input:focus {
158 outline: none;
159 box-shadow: none;
160 }
161 #${facetId} .ts-dropdown .ts-dropdown-content .option {
162 font-family: var(--facet-font-family);
163 font-size: var(--facet-font-size);
164 font-weight: var(--facet-font-weight);
165 line-height: var(--facet-line-height);
166 letter-spacing: var(--facet-letter-spacing);
167 color: var(--facet-color);
168 padding: 8px 16px;
169 }
170 #${facetId} .ts-dropdown .ts-dropdown-content .option:hover,
171 #${facetId} .ts-dropdown .ts-dropdown-content .option.active {
172 background-color: #6a9bd3;
173 color: #fff;
174 }
175 #${facetId} .ts-dropdown .ts-dropdown-content .option:hover .badge,
176 #${facetId} .ts-dropdown .ts-dropdown-content .option.active .badge {
177 background-color: #fff;
178 color: #3a6a9b;
179 }
180 </style>
181
182 <div class="checks-container ${facetClass}" id="${facetId}">
183 <div class="d-flex flex-column w-100">
184 <label class="panel-title mb-2" for="${facetId}-select">
185 ${languageUtil.get(locale, "norma." + paramNameSpecificationName)}
186 <#if isDebug>
187 <p style="font-size:11px;color:#999;font-weight:normal;">
188 (total options: ${entries?size})
189 </p>
190 <p style="font-size:11px;color:#999;font-weight:normal;">
191 (facetId: ${facetId})
192 </p>
193 </#if>
194 </label>
195
196 <#-- ========================= -->
197 <#-- SELECT UI -->
198 <#-- ========================= -->
199 <select id="${facetId}-select" data-parameter-name="${paramNameSpecificationName}">
200 <option value="">${languageUtil.get(locale, "search.cualquiera")}</option>
201 <#list entries?sort_by("displayName") as entry>
202 <#assign specName = entry.getDisplayName() />
203 <#assign orgNames = specOrganismosMap[specName]![] />
204 <option value="${htmlUtil.escape(specName)}"
205 <#if entry.isSelected()>selected</#if>
206 data-organismos="${htmlUtil.escape(orgNames?join(","))}">
207 ${htmlUtil.escape(specName)} (${entry.getFrequency()})
208 </option>
209 </#list>
210 </select>
211 </div>
212 </div>
213
214 <#-- ========================= -->
215 <#-- SCRIPT -->
216 <#-- ========================= -->
217 <script>
218 (function () {
219 var FACET_ID = '${facetId}';
220 var PARAM_NAME = '${paramNameSpecificationName}';
221
222 function applyUrlFilter(value) {
223 var url = new URL(window.location.href);
224 if (value) {
225 url.searchParams.set(PARAM_NAME, value);
226 } else {
227 url.searchParams.delete(PARAM_NAME);
228 }
229 window.location.href = url.toString();
230 }
231
232 function initFacet() {
233 var select = document.getElementById(FACET_ID + '-select');
234 if (!select) return;
235 if (select.tomselect) select.tomselect.destroy();
236 if (select.dataset.bound === 'true') return;
237 select.dataset.bound = 'true';
238
239 new TomSelect(select, {
240 allowEmptyOption: true,
241 maxItems: 1,
242 create: false,
243 render: {
244 option: function(data, escape) {
245 var organismos = data.$option ? data.$option.getAttribute('data-organismos') : '';
246 var badges = '';
247 if (organismos) {
248 organismos.split(',').forEach(function(org) {
249 badges += '<span class="badge badge-secondary mr-1">' + escape(org.trim()) + '</span>';
250 });
251 }
252 return '<div class="option py-1">' + escape(data.text) + '<div class="mt-1">' + badges + '</div></div>';
253 },
254 no_results: function(data, escape) {
255 return '<div class="no-results">${languageUtil.get(locale, "occurrence-not-found")}</div>';
256 }
257 },
258 plugins: {
259 dropdown_input: {}
260 },
261 onDelete: function(value) {
262 this.isDelete = true;
263 },
264 onChange: function(value) {
265 if (value) {
266 this.lastValidValue = value;
267 applyUrlFilter(value);
268 return;
269 }
270 this.lastValidValue = '';
271 applyUrlFilter('');
272 },
273 onInitialize: function() {
274 this.lastValidValue = this.getValue() || '';
275 this.isDelete = false;
276 var wrapper = document.querySelector('#' + FACET_ID + ' .ts-wrapper');
277 if (wrapper) wrapper.style.opacity = '1';
278 }
279 });
280 }
281
282 if (document.readyState === 'loading') {
283 document.addEventListener('DOMContentLoaded', initFacet);
284 } else {
285 initFacet();
286 }
287 })();
288 </script>
289
290</#if>