diff --git a/avBooth/booth-directive/booth-directive.less b/avBooth/booth-directive/booth-directive.less index 0a1ff40a..1aa04498 100644 --- a/avBooth/booth-directive/booth-directive.less +++ b/avBooth/booth-directive/booth-directive.less @@ -197,10 +197,7 @@ gap: 8px; border-radius: 4px; line-height: 19px; - } - - .glyphicon-warning-sign { - margin-top: 3px; + align-items: center; } } diff --git a/avBooth/search-filter-service.js b/avBooth/search-filter-service.js new file mode 100644 index 00000000..c8db1a4f --- /dev/null +++ b/avBooth/search-filter-service.js @@ -0,0 +1,75 @@ +/** + * This file is part of voting-booth. + * Copyright (C) 2023 Sequent Tech Inc + + * voting-booth is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License. + + * voting-booth is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + + * You should have received a copy of the GNU Affero General Public License + * along with voting-booth. If not, see . +**/ + +angular.module('avBooth') + .factory('SearchFilter', function($filter) { + var service = {}; + + service.isStringContained = function (searchTerm, text) { + // convert to lower case to make comparison case-insensitive + searchTerm = searchTerm.toLocaleLowerCase('en-US'); + text = text.toLocaleLowerCase('en-US'); + // transform accented letters into their decomposed form + searchTerm = searchTerm.normalize("NFD").replace(/[\u0300-\u036f]/g, ""); + // match and remove all accents + text = text.normalize("NFD").replace(/[\u0300-\u036f]/g, ""); + + // split the search by '*' + var searchParts = searchTerm.split("*"); + // remove empty strings from multiple * in a row or initial/end * + searchParts = searchParts.filter(function (part) { return part.length > 0; }); + + // Loop through each part + var lastIdx = 0; + for (var part of searchParts) { + // Find the part in the text, starting from the last index found + var idx = text.indexOf(part, lastIdx); + + // If the part is not found, or if it's found before the last part, return false + if (idx < 0) { + return false; + } + + // Update the last index found to after the current part + lastIdx = idx + part.length; + } + + // If we get through the loop without returning false, then the search term is contained in the text + return true; + }; + + service.isSelectedAnswer = function (searchText, answer) { + var filter = searchText.trim().toLowerCase(); + + // doesn't apply if there's no filter + if (0 === filter.length) { + return true; + } + + var inputs = [ + ($filter('customI18n')(answer, 'text') || "").toLowerCase(), + ($filter('customI18n')(answer, 'details') || "").toLowerCase(), + ($filter('customI18n')(answer, 'category') || "").toLowerCase() + ]; + return inputs.map(function (text) { + return service.isStringContained(filter, text); + }).some(function (val) { return val; }); + + }; + + return service; + }); \ No newline at end of file diff --git a/avBooth/simultaneous-questions-category-v2-directive/simultaneous-questions-category-v2-directive.html b/avBooth/simultaneous-questions-category-v2-directive/simultaneous-questions-category-v2-directive.html index 6deae60e..cd7049c1 100644 --- a/avBooth/simultaneous-questions-category-v2-directive/simultaneous-questions-category-v2-directive.html +++ b/avBooth/simultaneous-questions-category-v2-directive/simultaneous-questions-category-v2-directive.html @@ -22,14 +22,14 @@

class="question-answers text-left" >

+ +
+
+ + + +
+
+
+
+ + +
+
@@ -92,13 +127,13 @@

+ diff --git a/locales/ca.json b/locales/ca.json index 33bffd1d..0aca5d52 100644 --- a/locales/ca.json +++ b/locales/ca.json @@ -338,7 +338,9 @@ "header": "Informació: Pantalla de votació", "body": "Aquesta pantalla mostra la votació en la quals ets elegible per votar. Pots seleccionar la teva secció activant la casella de la dreta Candidat/Resposta. Per a restablir les teves seleccions, fes clic al botó 'Esborrar selecció', per passar al següent pas, fes clic al botó 'Següent'.", "confirm": "D'acord" - } + }, + "searchWarn": "Els candidats de la pregunta han estat filtrats. Per veure tots els candidats en aquesta pregunta, si us plau desactiva el filtre.", + "filterOptionsPlaceholder": "Cerca un Candidat" }, "pairwiseBeta": { diff --git a/locales/en.json b/locales/en.json index b7103c2f..cd5f3083 100644 --- a/locales/en.json +++ b/locales/en.json @@ -389,7 +389,9 @@ "header": "Information: Ballot screen", "body": "This screen shows the contest you are elegible to vote. You can make your section by activate the checkbox on the Candidate/Answer right. To reset your selections, click “Clear selection” button, to move to next step, click “Next” button bellow.", "confirm": "OK" - } + }, + "searchWarn": "Ballot candidates have been filtered. To view all candidates on this ballot, please disable the filter.", + "filterOptionsPlaceholder": "Search a Candidate" }, "pairwiseBeta": { diff --git a/locales/es.json b/locales/es.json index 908198f3..74cf376e 100644 --- a/locales/es.json +++ b/locales/es.json @@ -368,7 +368,9 @@ "header": "Información: Pantalla de votación", "body": "Esta pantalla muestra la votación en la que usted es elegible para votar. Puede seleccionar su sección activando la casilla de la derecha Candidato/Respuesta. Para restablecer sus selecciones, haga clic en el botón “Borrar selección”, para pasar al siguiente paso, haga clic en el botón “Siguiente”.", "confirm": "OK" - } + }, + "searchWarn": "Los candidatos de la pregunta han sido filtrados. Para ver a todos los candidatos en esta pregunta, por favor desactiva el filtro.", + "filterOptionsPlaceholder": "Busca un Candidato" }, "pairwiseBeta": { diff --git a/locales/fr.json b/locales/fr.json index 3e479c13..faf39541 100644 --- a/locales/fr.json +++ b/locales/fr.json @@ -290,7 +290,9 @@ "header": "Voulez-vous sauter cette ou ces questions ?", "body": "Veuillez confirmer que vous voulez sauter cette (ces) question(s). Vous pouvez voter pour la ou les questions ignor\u00e9es en vous connectant \u00e0 nouveau.", "confirm": "Confirmer et SAUTER cette(ces) question(s)" - } + }, + "searchWarn": "Les candidats de la question ont été filtrés. Pour voir tous les candidats de cette question, veuillez désactiver le filtre.", + "filterOptionsPlaceholder": "Cherchez un Candidat" }, "pairwiseBeta": { "web": "Web",