forked from ScoDoc/ScoDoc
multiselect.py + fix bug event + changement icône + unfixed height
This commit is contained in:
parent
00eb37e8ac
commit
5b68adaf87
118
app/forms/multiselect.py
Normal file
118
app/forms/multiselect.py
Normal file
@ -0,0 +1,118 @@
|
||||
"""
|
||||
Simplification des multiselect HTML/JS
|
||||
"""
|
||||
|
||||
|
||||
class MultiSelect:
|
||||
"""
|
||||
Classe pour faciliter l'utilisation du multi-select HTML/JS
|
||||
|
||||
Les values sont représentées en dict {
|
||||
value: "...",
|
||||
label:"...",
|
||||
selected: True/False (default to False),
|
||||
single: True/False (default to False)
|
||||
}
|
||||
|
||||
Args:
|
||||
values (dict[str, list[dict]]): Dictionnaire des valeurs
|
||||
génère des <optgroup> pour chaque clef du dictionnaire
|
||||
génère des <option> pour chaque valeur du dictionnaire
|
||||
name (str, optional): Nom du multi-select. Defaults to "multi-select".
|
||||
html_id (str, optional): Id HTML du multi-select. Defaults to "multi-select".
|
||||
classname (str, optional): Classe CSS du multi-select. Defaults to "".
|
||||
label (str, optional): Label du multi-select. Defaults to "".
|
||||
export (str, optional): Format du multi-select (HTML/JS). Defaults to "js".
|
||||
HTML : group_ids="val1"&group_ids="val2"...
|
||||
JS : ["val1","val2", ...]
|
||||
|
||||
**kwargs: Arguments supplémentaires (appliqué au multiselect en HTML <multi-select key="value" ...>)
|
||||
"""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
values: dict[str, list[dict]],
|
||||
name="multi-select",
|
||||
html_id="multi-select",
|
||||
label="",
|
||||
classname="",
|
||||
**kwargs,
|
||||
) -> None:
|
||||
self.values: dict[str, list[dict]] = values
|
||||
self._on = ""
|
||||
|
||||
self.name: str = name
|
||||
self.html_id: str = html_id
|
||||
self.classname: str = classname
|
||||
self.label: str = label or name
|
||||
|
||||
self.args: dict = kwargs
|
||||
self.js: str = ""
|
||||
self.export: str = "return values"
|
||||
|
||||
def html(self) -> str:
|
||||
"""
|
||||
Génère l'HTML correspondant au multi-select
|
||||
"""
|
||||
opts: list[str] = []
|
||||
|
||||
for key, values in self.values.items():
|
||||
optgroup = f"<optgroup label='{key}'>"
|
||||
for value in values:
|
||||
selected = "selected" if value.get("selected", False) else ""
|
||||
single = "single" if value.get("single", False) else ""
|
||||
opt = f"<option value='{value.get('value')}' {selected} {single} >{value.get('label')}</option>"
|
||||
optgroup += opt
|
||||
optgroup += "</optgroup>"
|
||||
opts.append(optgroup)
|
||||
|
||||
args: list[str] = [f'{key}="{value}"' for key, value in self.args.items()]
|
||||
js: str = "{" + self.js + "}"
|
||||
export: str = "{" + self.export + "}"
|
||||
return f"""
|
||||
<multi-select
|
||||
label="{self.label}"
|
||||
id="{self.html_id}"
|
||||
name="{self.name}"
|
||||
class="{self.classname}"
|
||||
{" ".join(args)}
|
||||
>
|
||||
{"".join(opts)}
|
||||
</multi-select>
|
||||
<script>
|
||||
window.addEventListener('load', () => {{document.getElementById("{self.html_id}").on((values)=>{js});
|
||||
document.getElementById("{self.html_id}").format((values)=>{export});}} );
|
||||
</script>
|
||||
"""
|
||||
|
||||
def change_event(self, js: str) -> None:
|
||||
"""
|
||||
Ajoute un évènement de changement au multi-select
|
||||
|
||||
CallBack JS : (event) => {/*actions à effectuer*/}
|
||||
|
||||
Sera retranscrit dans l'HTML comme :
|
||||
|
||||
document.getElementById(%self.id%).on((event)=>{%self.js%})
|
||||
|
||||
Exemple d'utilisation :
|
||||
|
||||
js : "console.log(event.target.value)"
|
||||
"""
|
||||
self.js: str = js
|
||||
|
||||
def export_format(self, js: str) -> None:
|
||||
"""
|
||||
Met à jour le format de retour de valeur du multi-select
|
||||
|
||||
CallBack JS : (values) => {/*actions à effectuer*/}
|
||||
|
||||
Sera retranscrit dans l'HTML comme :
|
||||
|
||||
document.getElementById(%self.id%).format((values)=>{%self.js%})
|
||||
|
||||
Exemple d'utilisation :
|
||||
|
||||
js : "return values.map(v=> 'val:'+v)"
|
||||
"""
|
||||
self.export: str = js
|
@ -750,7 +750,7 @@ def groups_table(
|
||||
name="options",
|
||||
html_id="group_list_options",
|
||||
)
|
||||
multi_select.change_event("change_list_options(values)")
|
||||
multi_select.change_event("change_list_options(event.target.value);")
|
||||
H.extend(
|
||||
# ;
|
||||
[
|
||||
|
@ -63,6 +63,8 @@ from werkzeug.http import HTTP_STATUS_CODES
|
||||
from config import Config
|
||||
from app import log, ScoDocJSONEncoder
|
||||
|
||||
from app.forms.multiselect import MultiSelect
|
||||
|
||||
from app.scodoc.codes_cursus import NOTES_TOLERANCE, CODES_EXPL
|
||||
from app.scodoc.sco_exceptions import ScoValueError
|
||||
from app.scodoc import sco_xml
|
||||
@ -445,121 +447,6 @@ def translate_assiduites_metric(metric, inverse=True, short=True) -> str:
|
||||
return None
|
||||
|
||||
|
||||
class MultiSelect:
|
||||
"""
|
||||
Classe pour faciliter l'utilisation du multi-select HTML/JS
|
||||
|
||||
Les values sont représentées en dict {
|
||||
value: "...",
|
||||
label:"...",
|
||||
selected: True/False (default to False),
|
||||
single: True/False (default to False)
|
||||
}
|
||||
|
||||
Args:
|
||||
values (dict[str, list[dict]]): Dictionnaire des valeurs
|
||||
génère des <optgroup> pour chaque clef du dictionnaire
|
||||
génère des <option> pour chaque valeur du dictionnaire
|
||||
name (str, optional): Nom du multi-select. Defaults to "multi-select".
|
||||
html_id (str, optional): Id HTML du multi-select. Defaults to "multi-select".
|
||||
classname (str, optional): Classe CSS du multi-select. Defaults to "".
|
||||
label (str, optional): Label du multi-select. Defaults to "".
|
||||
export (str, optional): Format du multi-select (HTML/JS). Defaults to "js".
|
||||
HTML : group_ids="val1"&group_ids="val2"...
|
||||
JS : ["val1","val2", ...]
|
||||
|
||||
**kwargs: Arguments supplémentaires (appliqué au multiselect en HTML <multi-select key="value" ...>)
|
||||
"""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
values: dict[str, list[dict]],
|
||||
name="multi-select",
|
||||
html_id="multi-select",
|
||||
label="",
|
||||
classname="",
|
||||
**kwargs,
|
||||
) -> None:
|
||||
self.values: dict[str, list[dict]] = values
|
||||
self._on = ""
|
||||
|
||||
self.name: str = name
|
||||
self.html_id: str = html_id
|
||||
self.classname: str = classname
|
||||
self.label: str = label or name
|
||||
|
||||
self.args: dict = kwargs
|
||||
self.js: str = ""
|
||||
self.export: str = "return values"
|
||||
|
||||
def html(self) -> str:
|
||||
"""
|
||||
Génère l'HTML correspondant au multi-select
|
||||
"""
|
||||
opts: list[str] = []
|
||||
|
||||
for key, values in self.values.items():
|
||||
optgroup = f"<optgroup label='{key}'>"
|
||||
for value in values:
|
||||
selected = "selected" if value.get("selected", False) else ""
|
||||
single = "single" if value.get("single", False) else ""
|
||||
opt = f"<option value='{value.get('value')}' {selected} {single} >{value.get('label')}</option>"
|
||||
optgroup += opt
|
||||
optgroup += "</optgroup>"
|
||||
opts.append(optgroup)
|
||||
|
||||
args: list[str] = [f'{key}="{value}"' for key, value in self.args.items()]
|
||||
js: str = "{" + self.js + "}"
|
||||
export: str = "{" + self.export + "}"
|
||||
return f"""
|
||||
<multi-select
|
||||
label="{self.label}"
|
||||
id="{self.html_id}"
|
||||
name="{self.name}"
|
||||
class="{self.classname}"
|
||||
{" ".join(args)}
|
||||
>
|
||||
{"".join(opts)}
|
||||
</multi-select>
|
||||
<script>
|
||||
window.addEventListener('load', () => {{document.getElementById("{self.html_id}").on((values)=>{js});
|
||||
document.getElementById("{self.html_id}").format((values)=>{export});}} );
|
||||
</script>
|
||||
"""
|
||||
|
||||
def change_event(self, js: str) -> None:
|
||||
"""
|
||||
Met à jour l'évènement de changement de valeur du multi-select
|
||||
|
||||
CallBack JS : (values) => {/*actions à effectuer*/}
|
||||
|
||||
Sera retranscrit dans l'HTML comme :
|
||||
|
||||
document.getElementById(%self.id%).on((values)=>{%self.js%})
|
||||
|
||||
Exemple d'utilisation :
|
||||
|
||||
js : "console.log(values)"
|
||||
"""
|
||||
self.js: str = js
|
||||
|
||||
def export_format(self, js: str) -> None:
|
||||
"""
|
||||
Met à jour le format de retour de valeur du multi-select
|
||||
|
||||
CallBack JS : (values) => {/*actions à effectuer*/}
|
||||
|
||||
Sera retranscrit dans l'HTML comme :
|
||||
|
||||
document.getElementById(%self.id%).format((values)=>{%self.js%})
|
||||
|
||||
Exemple d'utilisation :
|
||||
|
||||
js : "return values.map(v=> 'val:'+v)"
|
||||
"""
|
||||
self.export: str = js
|
||||
|
||||
|
||||
# Types de modules
|
||||
class ModuleType(IntEnum):
|
||||
"""Code des types de module."""
|
||||
|
@ -76,18 +76,28 @@ class MultiSelect extends HTMLElement {
|
||||
position: absolute;
|
||||
background-color: #fff;
|
||||
min-width: 200px;
|
||||
max-height: 200px;
|
||||
overflow-y: auto;
|
||||
box-shadow: 0px 8px 16px 0px rgba(0,0,0,0.2);
|
||||
z-index: 1;
|
||||
}
|
||||
.dropdown-content .optgroup {
|
||||
padding: 10px;
|
||||
padding: 4px 8px;
|
||||
width: 100%;
|
||||
}
|
||||
.dropdown-content .optgroup div {
|
||||
font-weight: bold;
|
||||
}
|
||||
.dropdown-button::after{
|
||||
content: "";
|
||||
display: inline-block;
|
||||
width: 0;
|
||||
height: 0;
|
||||
margin-left: 4px;
|
||||
vertical-align: middle;
|
||||
border-top: 4px dashed;
|
||||
border-right: 4px solid transparent;
|
||||
border-left: 4px solid transparent;
|
||||
}
|
||||
|
||||
.dropdown-content .option {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
@ -252,11 +262,6 @@ class MultiSelect extends HTMLElement {
|
||||
} else {
|
||||
btn.textContent = `${checkedBoxes.length} sélections`;
|
||||
}
|
||||
|
||||
btn.textContent += " ⮛";
|
||||
|
||||
this._values(values);
|
||||
|
||||
this.dispatchEvent(new Event("change"));
|
||||
}
|
||||
|
||||
@ -280,6 +285,7 @@ class MultiSelect extends HTMLElement {
|
||||
});
|
||||
|
||||
this._internals.setFormValue(this._values());
|
||||
this._updateSelect();
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user