diff --git a/AUTHORS b/AUTHORS
index 9f72f04689895b1cf28eaa87f342c7a7a5292d77..951dadbbfcabcec5bf829dc6dd8513b98ee19e14 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -52,6 +52,7 @@
- Damien DASSIEU
- Benjamin BOISSE
- Pacôme GASNIER
+- Wassim BOUALI
# TRANSLATORS:
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 4e1a81efb6086862f77ca9837b40173166348d2e..8bee72b0608e1f6cd1c5ab69757db8355238a3c2 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -41,6 +41,7 @@ that explain the infaisability by the solver of a set of constraints
- Modification proposal: id for modification bunch, modification
applicability, email notification
- Room preferences: user interface improvement, room exclusion
+- Interface allowing user to manage differents constraints
## [0.3.0] - 2019-11-07
### Added
diff --git a/FlOpEDT/FlOpEDT/settings/local.py b/FlOpEDT/FlOpEDT/settings/local.py
index 21b040b6ae83758e05cdcdc7efb3e66400127e55..b3c244858059ac8742843619924a2b7e37cd4e55 100644
--- a/FlOpEDT/FlOpEDT/settings/local.py
+++ b/FlOpEDT/FlOpEDT/settings/local.py
@@ -102,3 +102,4 @@ DEBUG_TOOLBAR_CONFIG = {
}
INTERNAL_IPS = ['127.0.0.1']
+
diff --git a/FlOpEDT/api/TTapp/serializers.py b/FlOpEDT/api/TTapp/serializers.py
index 13779386a78ad58a0d66a22f61ddee659320d3ca..a03a8497c5e5de866fbcffaf90b937a30c42f721 100644
--- a/FlOpEDT/api/TTapp/serializers.py
+++ b/FlOpEDT/api/TTapp/serializers.py
@@ -153,8 +153,10 @@ class TTConstraintSerializer(serializers.ModelSerializer):
else :
#Récupère le modele en relation avec un ManyToManyField ou un ForeignKey
mod = field.related_model
- typenamesplit= str(mod)[8:-2].split(".")
- typename = typenamesplit[0]+"."+typenamesplit[2]
+
+ typenamesplit = str(mod)[8:-2].split(".")
+ typename = typenamesplit[0] + "." + typenamesplit[2]
+
acceptablelist = mod.objects.values("id")
#Filtre les ID dans acceptable list en fonction du department
diff --git a/FlOpEDT/base/core/period_weeks.py b/FlOpEDT/base/core/period_weeks.py
index 2be6a56854d4a71403e59bf811943cba73392a51..08e6fd182f990d35afd2e4e0addea16b4cbb8e62 100644
--- a/FlOpEDT/base/core/period_weeks.py
+++ b/FlOpEDT/base/core/period_weeks.py
@@ -91,7 +91,7 @@ class PeriodWeeks():
"""
return Course.objects \
.filter(
- year=year,
+ week__year=year,
week__in=list(range(start, end + 1)),
module__train_prog__department=department) \
.distinct() \
diff --git a/FlOpEDT/base/static/base/img/LasuppressiondesIRP.png b/FlOpEDT/base/static/base/img/LasuppressiondesIRP.png
new file mode 100644
index 0000000000000000000000000000000000000000..768f6008c8a8f6eb2f73b6f8a249bab0c1bcb314
Binary files /dev/null and b/FlOpEDT/base/static/base/img/LasuppressiondesIRP.png differ
diff --git a/FlOpEDT/base/static/base/img/ajout.png b/FlOpEDT/base/static/base/img/ajout.png
new file mode 100644
index 0000000000000000000000000000000000000000..6226473ef32e63eab9c45c927b205b83230dbc9f
Binary files /dev/null and b/FlOpEDT/base/static/base/img/ajout.png differ
diff --git a/FlOpEDT/base/static/base/img/copier-coller-1.png b/FlOpEDT/base/static/base/img/copier-coller-1.png
new file mode 100644
index 0000000000000000000000000000000000000000..2d51532069ccb72c7368a469aba031af14f8bc0a
Binary files /dev/null and b/FlOpEDT/base/static/base/img/copier-coller-1.png differ
diff --git a/FlOpEDT/base/static/base/img/suppression.jpg b/FlOpEDT/base/static/base/img/suppression.jpg
new file mode 100644
index 0000000000000000000000000000000000000000..165921f4c4be5ff3400dfa2902e31de631fb1397
Binary files /dev/null and b/FlOpEDT/base/static/base/img/suppression.jpg differ
diff --git a/FlOpEDT/base/static/base/img/suppression.png b/FlOpEDT/base/static/base/img/suppression.png
new file mode 100644
index 0000000000000000000000000000000000000000..67c616269cac4d525145b6736457eb6eb7614a81
Binary files /dev/null and b/FlOpEDT/base/static/base/img/suppression.png differ
diff --git a/FlOpEDT/base/static/base/img/valider.png b/FlOpEDT/base/static/base/img/valider.png
new file mode 100644
index 0000000000000000000000000000000000000000..7b05b73c8dbfb45845c02bd55f6f0ec7cf290326
Binary files /dev/null and b/FlOpEDT/base/static/base/img/valider.png differ
diff --git a/FlOpEDT/base/static/base/variables.js b/FlOpEDT/base/static/base/variables.js
index b3a227123840c4b8ded898d1d710bd265aa2f9ad..3abd79303645b6fa177ec3c106f89d870081635c 100644
--- a/FlOpEDT/base/static/base/variables.js
+++ b/FlOpEDT/base/static/base/variables.js
@@ -126,11 +126,14 @@ var file_fetch =
function main(name, data) {
file_fetch[name].data = data;
file_fetch[name].done = true;
- if (file_fetch.groups.done && file_fetch.constraints.done
- && file_fetch.rooms.done) {
- file_fetch.constraints.callback();
- file_fetch.rooms.callback();
- file_fetch.groups.callback();
+
+ // callback all when all received
+ if (!Object.keys(file_fetch).some(function(att){
+ return !file_fetch[att].done ;
+ })) {
+ Object.keys(file_fetch).forEach(function(att){
+ file_fetch[att].callback() ;
+ });
}
}
diff --git a/FlOpEDT/solve_board/static/solve_board/easySelect.js b/FlOpEDT/solve_board/static/solve_board/easySelect.js
new file mode 100644
index 0000000000000000000000000000000000000000..4fc083f29973834c7555b07e12c011bfa2bb2d18
--- /dev/null
+++ b/FlOpEDT/solve_board/static/solve_board/easySelect.js
@@ -0,0 +1,308 @@
+//The options are on the bottom
+
+(function ($) {
+ $.fn.easySelect = function (options) {
+ return this.each(function () {
+ var settings = $.extend({
+ search: true,
+ buttons: false,
+ placeholder: 'Select item',
+ selectColor: '#414c52',
+ placeholderColor: '#838383',
+ itemTitle: 'Selected items',
+ showEachItem: false,
+ width: '100%',
+ dropdownMaxHeight: 'auto'
+ }, options);
+
+ var $this = $(this),
+
+ numberOfOptions = $(this).children('option').length;
+
+ $this.addClass('s-hidden');
+
+ $this.wrap('
');
+ var $main = $this.closest('.easySelect').css('width', settings.width);
+
+ $this.after('');
+
+ var $styledSelect = $this.next('div.styledSelect');
+
+ $styledSelect.text(settings.placeholder).css('color', settings.placeholderColor);
+
+ var MaxAllowed = $this.data("max");
+
+ var clear = $('',{
+ 'class': 'clearSelectfromDiv',
+ html: '×',
+ 'style': 'display: none',
+ }).prependTo($main);
+
+ var $list = $('', {
+ 'class': 'options'
+ }).insertAfter($styledSelect);
+
+ var $divSearch = $(' ', {
+ 'class': 'divSearcheasySelect',
+ }).appendTo($list)
+ if(settings.search == false){
+ $divSearch.hide();
+ }
+
+
+ var $divoptions = $(' ', {
+ 'class': 'divOptionsesySelect',
+ }).appendTo($divSearch);
+ if(settings.buttons == false ){
+ $divoptions.hide();
+ }
+
+ var $clearSpan = $('', {
+ 'class': 'optionRow ',
+ text: 'Clear all',
+ 'id': 'clearAlleasySelect',
+ }).appendTo($divoptions);
+
+ var $clear = $('', {
+ 'class': 'alleasySelect',
+ html: '×'
+ }).appendTo($clearSpan);
+
+ var $selectAllspan = $('', {
+ 'class': 'optionRow',
+ 'id': 'selectAlleasySelect',
+ text: 'Select all'
+ }).appendTo($divoptions);
+
+ var $selectAll = $('', {
+ 'class': 'alleasySelect',
+ html: '✓'
+ }).appendTo($selectAllspan);
+
+ var $message = $('', {
+ 'class': 'messageMaxallowedSelections',
+ style: 'display:none',
+ text: 'You can select max ' + MaxAllowed + ' items '
+ }).appendTo($divoptions);
+
+ var $searchInput = $(' ', {
+ 'type': 'text',
+ 'class': 'searchInputeasySelect',
+ 'placeholder': 'Search',
+ }).appendTo($divSearch)
+
+ var $maindiv = $(' ', {
+ 'class': 'scrolableDiv',
+ }).appendTo($list);
+ $maindiv.css('max-height', settings.dropdownMaxHeight);
+
+ var $hiddenli = $(' ', {
+ text: 'You can select only ' + MaxAllowed + ' items',
+ 'class': 'hiddenLieasySelect',
+ style: 'display: none'
+ }).appendTo($list);
+
+
+ for (var i = 0; i < numberOfOptions; i++) {
+ var $li = $(' ').appendTo($maindiv);
+
+ var $label = $(' ', {
+ 'class': 'container-item',
+ text: $this.children('option').eq(i).text(),
+ }).appendTo($li)
+
+ var $checkbox = $(' ', {
+ 'class': 'mulpitply_checkbox_style',
+ 'type': 'checkbox',
+ value: $this.children('option').eq(i).val(),
+ }).appendTo($label)
+
+ $(' ', {
+ 'class': 'checkmark',
+ }).appendTo($label)
+ }
+
+ var $listItems = $list.find('li');
+ var checkItem = $list.find('.mulpitply_checkbox_style');
+
+ $styledSelect.click(function (e) {
+ e.stopPropagation();
+ $('div.styledSelect.active').each(function () {
+ $(this).removeClass('active').next('ul.options').hide();
+ });
+ $(this).toggleClass('active').next('ul.options').toggle();
+ });
+
+ function eachItem() {
+ arrText = [];
+ $.each($list.find('.mulpitply_checkbox_style:checked'), function () {
+ arrText.push($(this).parent().text());
+ });
+ }
+
+ function eachItemoutput() {
+
+ if (settings.showEachItem == true) {
+ $styledSelect.text(arrText.join(", ")).removeClass('active').css('color', settings.selectColor);
+
+ } else {
+ var $checked_items = checkItem.filter(":checked").length;
+ $styledSelect.text($checked_items + ' ' + settings.itemTitle).removeClass('active').css('color', settings.selectColor);
+
+ }
+ }
+
+
+ $listItems.click(function (e) {
+ e.stopPropagation();
+ $styledSelect.text($(this).text()).removeClass('active');
+ $this.val($(this).attr('val'));
+ clear.show();
+
+ val = [];
+ $('.mulpitply_checkbox_style:checked').each(function () {
+ val.push($(this).val());
+ })
+ $this.closest('select').val(val);
+
+ $($this.closest('select').children('option:selected')).each(function () {
+ $(this).attr('selected', 'selected');
+ });
+
+ arrVal = [];
+ var getVal = $.each($('.mulpitply_checkbox_style:checked'), function () {
+ arrVal.push($(this).val());
+ });
+ /*--===============================*/
+ eachItem();
+ eachItemoutput();
+
+ var $checked_items = checkItem.filter(":checked").length;
+ if ($checked_items == 0) {
+ $styledSelect.text(settings.placeholder).removeClass('active').css('color', settings.placeholderColor);
+ clear.hide();
+ }
+
+ var MaxAllowed = $this.data("max");
+ if ($checked_items >= MaxAllowed && MaxAllowed !== "") {
+ checkItem.not(":checked").attr("disabled", "disabled");
+ // $maindiv.hide();
+ $divSearch.hide();
+ $hiddenli.show();
+ } else {
+ // Enable the inputs again when he unchecks one
+ checkItem.removeAttr("disabled");
+ }
+ });
+
+ var $optionRow = $list.find('.optionRow');
+
+ $optionRow.click(function (e) {
+ e.stopPropagation();
+ });
+ var $clearAll = $list.find('#clearAlleasySelect');
+ var $selectAll = $list.find('#selectAlleasySelect');
+
+/*--================================*/
+ function unselectAll() {
+ checkItem.prop('checked', false);
+ $styledSelect.text(settings.placeholder).removeClass('active').css('color', settings.placeholderColor);
+ $this.closest('select').val('');
+ $maindiv.show();
+ $hiddenli.hide();
+ }
+ $clearAll.click(function () {
+ clear.hide();
+ unselectAll()
+ })
+ clear.click(function () {
+ $(this).hide();
+
+ unselectAll()
+ })
+/*--================================*/
+ allValue = [];
+ $selectAll.click(function () {
+ if (MaxAllowed == "" || typeof MaxAllowed == typeof undefined) {
+ checkItem.prop('checked', true);
+ $('.mulpitply_checkbox_style:checked').each(function () {
+ allValue.push($(this).val());
+ })
+ $this.closest('select').val(allValue);
+ clear.show();
+ eachItem();
+ eachItemoutput();
+ } else {
+ $message.css('display', 'inline-block');
+ setTimeout(function () {
+ $message.hide()
+ }, 2000);
+ }
+ })
+
+ $(document).on('click', function () {
+ $styledSelect.removeClass('active');
+ $list.hide();
+ });
+
+ var $block = $(' ', {
+ 'class': 'no_results',
+ text: 'No results found..',
+ }).appendTo($list)
+ $block.hide();
+ var $input = $divSearch.find('input[type="text"]');
+ $input.on('click',function (e) {
+ e.stopPropagation();
+ });
+ $input.on('keyuo', function () {
+ var val = $(this).val();
+ var isMatch = false;
+ $listItems.find('.container-item').each(function (i) {
+ var content = $(this).html();
+ if (content.toLowerCase().indexOf(val) == -1) {
+ $(this).hide();
+ } else {
+ isMatch = true;
+ $(this).show();
+ }
+ });
+ $block.toggle(!isMatch);
+ });
+ });
+ }
+}(jQuery));
+
+ $("#demo").easySelect({
+ buttons: false,
+ search: false,
+ placeholder: 'Choose Country',
+ placeholderColor: '#524781',
+ selectColor: '#524781',
+ itemTitle: 'Countrys selected',
+ showEachItem: true,
+ width: '100%',
+ dropdownMaxHeight: '450px',
+ })
+ $("#demo1").easySelect({
+ buttons: false,
+ search: true,
+ placeholder: 'Choose color',
+ placeholderColor: 'violet',
+ selectColor: 'lila',
+ itemTitle: 'Color selected',
+ showEachItem: true,
+ width: '100%',
+ dropdownMaxHeight: '450px',
+ })
+
+ $("#demo3").easySelect({
+ buttons: true, //
+ search: true,
+ placeholder: 'Pick Car',
+ placeholderColor: 'green',
+ selectColor: '#524781',
+ itemTitle: 'Car selected',
+ showEachItem: true,
+ width: '100%',
+ dropdownMaxHeight: '450px',
+ })
diff --git a/FlOpEDT/solve_board/static/solve_board/easySelectStyle.css b/FlOpEDT/solve_board/static/solve_board/easySelectStyle.css
new file mode 100644
index 0000000000000000000000000000000000000000..0613b9e38df7fc770828f8e6330bf5099f9f602d
--- /dev/null
+++ b/FlOpEDT/solve_board/static/solve_board/easySelectStyle.css
@@ -0,0 +1,705 @@
+.s-hidden {
+ visibility: hidden;
+ padding-right: 10px;
+}
+
+
+.easySelect {
+ font-size: 0.8rem !important;
+ cursor: default;
+ display: block;
+ /*make dropdown width */
+ position: relative;
+ font-family: Arial, Helvetica, sans-serif;
+ color: #414c52;
+ border: 1px solid #cbcbcb !important;
+ border-radius: 3px;
+ height: 25px;
+}
+
+.styledSelect {
+ border-radius: 0.2rem;
+ position: absolute;
+ top: 0;
+ right: 0;
+ bottom: 0;
+ left: 0;
+ background-color: white;
+ padding-left: 8px;
+ padding-top: 5px;
+ font-weight: 400 !important;
+ color: #414c52;
+ text-overflow: ellipsis;
+ white-space: nowrap;
+ overflow: hidden;
+ padding-right: 15%
+}
+
+.clearSelectfromDiv {
+ float: right;
+ margin-right: 35px;
+ font-size: 22px;
+ cursor: pointer;
+ position: relative;
+ top: -2px;
+ z-index: 4;
+ color: #414c52;
+}
+
+.clearSelectfromDiv:hover {
+ color: rgba(65, 76, 82, 0.76);
+}
+
+.styledSelect:after {
+ content: "";
+ width: 0;
+ height: 0;
+ border: 5px solid transparent;
+ border-color: #414c52 transparent transparent transparent;
+ position: absolute;
+ top: 15px;
+ right: 8px;
+}
+
+.styledSelect:active,
+.styledSelect.active {
+ background-color: #fafafa;
+}
+
+.options {
+ display: none;
+ position: absolute;
+ top: 100%;
+ right: 0;
+ left: 0;
+ z-index: 999;
+ margin: 3px 0;
+ padding: 3px 0 0 0px;
+ list-style: none;
+ border: 1px solid #cbcbcb !important;
+ background-color: white;
+ border-radius: 0.2rem;
+ -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.2);
+ -moz-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.2);
+ box-shadow: 0 1px 2px rgba(0, 0, 0, 0.2);
+ width: 100%
+}
+
+.scrolableDiv {
+ overflow: auto
+}
+
+.divSearcheasySelect {
+ border-bottom: 1px solid #cbcbcb !important;
+}
+
+.options li {
+ margin: auto;
+ max-width: 100% !important;
+ font-size: 0.6rem !important;
+ font-family: Arial, Helvetica, sans-serif;
+ font-weight: 500;
+ overflow: hidden
+}
+
+.options li:hover {
+ background-color: #f1f1fc;
+}
+
+.container-item {
+ display: flex;
+ align-items: center;
+ position: relative;
+ margin: 0px;
+ width: auto !important;
+ cursor: pointer;
+ font-size: 0.8rem;
+ padding: 0.25rem 0px 0.25rem 33px !important;
+ -webkit-user-select: none;
+ -moz-user-select: none;
+ -ms-user-select: none;
+}
+
+.container-item>input {
+ position: absolute;
+ opacity: 0;
+ cursor: pointer;
+ height: 0;
+ width: 0;
+}
+
+.checkmark {
+ position: absolute;
+ margin-left: 3px;
+ left: 5px;
+ width: 1rem;
+ height: 1rem;
+ background-color: white;
+ border-radius: 3px;
+ border: #adb5bd solid 1px;
+}
+
+.container input:checked~.checkmark {
+ background-color: white;
+ border-color: #3490dc;
+}
+
+
+.checkmark:after {
+ content: "";
+ position: absolute;
+ display: none;
+
+}
+
+.container-item input:checked~.checkmark:after {
+ display: block;
+
+}
+
+.container-item .checkmark:after {
+ left: 5px;
+ top: 1px;
+ width: 4.5px;
+ height: 10px;
+ border: 2px solid #1720ff;
+ border-width: 0 2px 2px 0;
+ -webkit-transform: rotate(45deg);
+ -ms-transform: rotate(45deg);
+ transform: rotate(45deg);
+
+}
+
+.divSearcheasySelect {
+ padding-right: 12px;
+ padding-left: 7px;
+ padding-top: 4px;
+ padding-bottom: 7px;
+ overflow: hidden;
+}
+
+.optionRow {
+ margin: -4px 0px 8px 0px;
+ border-radius: 3px;
+ font-size: 11.5px;
+ text-align: left;
+ font-weight: 600;
+ color: #414c52;
+ display: block ruby;
+}
+
+#clearAlleasySelect {
+ margin-right: 20px
+}
+
+#selectAlleasySelect {
+ margin-right: 20px
+}
+
+.optionRow:hover {
+ color: rgba(65, 76, 82, 0.81);
+}
+
+.optionRow .alleasySelect {
+ font-size: 13px;
+ margin: 2px auto auto 4px;
+}
+
+.divSearcheasySelect .searchInputeasySelect {
+ width: 100%;
+ margin-right: auto;
+
+ border: 1px solid #ced4da;
+ height: 30px;
+ background-color: white !important;
+
+ text-indent: 8px;
+ border-radius: 0.2rem;
+}
+
+.divSearcheasySelect .searchInputeasySelect::-ms-input-placeholder {
+ color: #6c757d !important;
+}
+
+.divSearcheasySelect .searchInputeasySelect::-moz-placeholder {
+ color: #6c757d !important;
+}
+
+.divSearcheasySelect .searchInputeasySelect::placeholder {
+ color: #6c757d !important;
+}
+
+.divSearcheasySelect .searchInputeasySelect:focus {
+ color: #495057;
+ background-color: #fff;
+ border-color: var(--info) !important;
+ outline: 0;
+ box-shadow: 0px 0px 3px 0px rgba(0, 0, 0, 0.16);
+ -moz-box-shadow: 0px 0px 3px 0px rgba(0, 0, 0, 0.16);
+ -webkit-box-shadow: 0px 0px 3px 0px rgba(0, 0, 0, 0.16);
+}
+
+.divOptionsesySelect>p {
+ display: inline-block
+}
+
+.messageMaxallowedSelections {
+ padding: 0px !important;
+ font-size: 12px;
+ font-weight: bold;
+ margin: auto;
+ color: #838383
+}
+
+.hiddenLieasySelect {
+ text-align: center;
+ padding: 4px 4px 6px 0px;
+ background-color: #f3f6f9;
+}
+
+li.hiddenLieasySelect {
+ font-size: 12px !important;
+ font-weight: 600
+}
+
+.options>.hiddenLieasySelect:hover {
+ background: none !important;
+ cursor: context-menu;
+}
+
+li.no_results {
+ padding: 6px;
+ font-size: 12px !important;
+ font-weight: 600
+}
+
+.range-slider{
+ width: 100%; /* Width of the outside container */
+}
+
+/* The slider itself */
+.range-slider__range {
+ -webkit-appearance: none; /* Override default CSS styles */
+ appearance: none;
+
+ height: 25px; /* Specified height */
+ background: #a9a9a9; /* Grey background */
+ outline: none; /* Remove outline */
+ -webkit-transition: .2s; /* 0.2 seconds transition on hover */
+}
+
+/* Mouse-over effects */
+.range-slider__range:hover {
+ opacity: 1; /* Fully shown on mouse-over */
+}
+
+/* The slider handle (use -webkit- (Chrome, Opera, Safari, Edge) and -moz- (Firefox) to override default look) */
+.range-slider__range::-webkit-slider-thumb {
+ -webkit-appearance: none; /* Override default look */
+ appearance: none;
+ width: 25px; /* Set a specific slider handle width */
+ height: 25px; /* Slider handle height */
+ background: #04AA6D; /* Green background */
+ cursor: pointer; /* Cursor on hover */
+}
+
+.range-slider__range::-moz-range-thumb {
+ width: 25px; /* Set a specific slider handle width */
+ height: 25px; /* Slider handle height */
+ background: #04AA6D; /* Green background */
+ cursor: pointer; /* Cursor on hover */
+}
+
+ #conteneurGeneral
+ {
+ display: flex;
+ width: 1460px;
+ flex-wrap: wrap;
+
+ margin-left: 270px;
+ margin-right: 90px;
+
+ position: -webkit-sticky;
+ position: sticky;
+ top: 0px;
+ background: grey;
+ }
+
+ .elementGeneral
+ {
+ padding-top: 10px;
+ padding-bottom: 10px;
+ }
+
+ .elementGeneral:nth-child(1)
+ {
+ width:242px;
+ text-align: right;
+
+ padding-right: 5%;
+ border-right: 1px black solid;
+ }
+
+ .elementGeneral:nth-child(2)
+ {
+ width: 744px;
+ text-align: center;
+
+ border-right: 1px black solid;
+ }
+
+ .elementGeneral:nth-child(3)
+ {
+ width: 76px;
+ text-align: center;
+
+ border-right: 1px black solid;
+ }
+
+ .elementGeneral:nth-child(4)
+ {
+ width: 130px;
+ padding-left: 5%;
+ border-right: 1px black solid;
+ }
+
+ .elementGeneral:nth-child(5)
+ {
+ width: 50px;
+ padding-left: 2%;
+ text-align: center;
+ }
+
+ #conteneurCategorie
+ {
+ display: flex;
+ flex-wrap: wrap;
+ width: 81%;
+
+ margin-left: 15%;
+ }
+
+ .elementCategorie:nth-child(1)
+ {
+ text-align: right;
+ padding-right: 1%;
+ padding-top: 1%;
+ width: 2%;
+ border-bottom: 2px grey solid;
+ }
+
+ .elementCategorie:nth-child(2)
+ {
+ width: 97%;
+ border-bottom: 2px grey solid;
+ }
+
+ .elementCategorie:nth-child(3)
+ {
+ text-align: right;
+ padding-right: 1%;
+ padding-top: 1%;
+ width: 4%;
+ border-bottom: 2px grey solid;
+ }
+
+ .elementCategorie:nth-child(4)
+ {
+ width: 95%;
+ border-bottom: 2px grey solid;
+ }
+
+
+
+
+
+table {
+ margin-left: 270px;
+ margin-right: 90px;
+ width: 1460px;
+}
+
+
+tr:hover
+ {
+ background-color: cornflowerblue;
+ }
+
+
+.tr{
+ display: flex;
+ flex-wrap: wrap;
+ border-bottom: 1px grey solid;
+}
+
+
+.selec_contrainte {
+ height: 5px;
+ width: 25px;
+ padding-top: 1.5%;
+ padding-right: 1%;
+ text-align: right;
+ background-color: DodgerBlue;
+}
+
+
+
+.nom_contrainte {
+ width: 285px;
+ padding-top: 0.6%;
+ padding-left: 1%;
+ padding-right: 1%;
+ background-color: DeepSkyBlue;
+}
+
+
+.para_contrainte {
+
+ overflow: auto;
+ padding-left: 1%;
+ padding-right: 1%;
+ padding-bottom: 0.5%;
+ display: flex;
+ flex-wrap: wrap;
+ background-color: cornflowerblue;
+
+}
+
+.case_param_required
+ {
+ margin-top: 3px;
+ margin-left: 3px;
+ padding-left: 1%;
+ padding-right: 1%;
+ text-align: center;
+ background-color: indianred;
+ border: 1px solid black;
+ }
+
+.commentaire
+ {
+ margin-bottom: 10px;
+ margin-top: 3px;
+ margin-left: 3px;
+ padding-left: 1%;
+ padding-right: 1%;
+ text-align: center;
+ background-color: indianred;
+ border: 1px solid black;
+ }
+
+.case_param_second
+ {
+ margin-top: 3px;
+ margin-left: 3px;
+ overflow: auto;
+ flex-wrap: wrap;
+ padding-left: 1%;
+ padding-right: 1%;
+ text-align: center;
+ background-color: seagreen;
+ border: 1px solid black;
+ }
+
+.ajout_param{
+ background-color: green;
+ margin-top: 5%;
+ margin-bottom: 6%;
+ width: 45px;
+}
+
+#btn_possibl{
+ background-color: white;
+ margin-bottom: 5px;
+
+}
+
+#btn_possibl:disabled{
+ color:black;
+ border-color: #a0a0a0;
+ background-color: white;
+
+}
+
+.zone_Possib{
+ display: none;
+ margin-bottom: 10px;
+ text-align: center;
+ overflow: auto;
+ flex-wrap: wrap;
+ padding-left: 1%;
+ padding-right: 1%;
+ background-color: white;
+ max-width: 140px;
+}
+
+.Menu{
+ display: none;
+}
+
+#image_Add{
+ padding-left: 10px;
+ padding-right: 10px;
+
+}
+
+
+
+#image_Delete{
+ padding-left: 10px;
+ padding-right: 10px;
+
+}
+
+.activ_contrainte{
+ width: 5.2%;
+ text-align: center;
+ background-color: SkyBlue;
+}
+
+.poid_contrainte{
+ width: 14%;
+ padding-left: 1%;
+ background-color: LightSkyBlue;
+}
+
+.duplic_contrainte{
+ width: 8%;
+ text-align: center;
+ background-color: LightSteelBlue;
+
+}
+
+#image_Validate{
+ padding-left: 10px;
+
+}
+
+ #conteneurOptions
+ {
+ position: fixed;
+ width: 13.5%;
+ }
+
+
+
+ #tableauOptions
+ {
+ background-color: grey;
+ flex-wrap: wrap;
+ border: 2px black solid;
+ }
+
+ .elementTableauOptions:nth-child(1)
+ {
+ text-align: center;
+ border-bottom: 1px black solid;
+ }
+
+ .elementTableauOptions:nth-child(2)
+ {
+ text-align: center;
+ border-bottom: 1px black solid;
+ padding-top: 5%;
+ padding-bottom: 5%;
+ }
+
+ .elementTableauOptions:nth-child(3)
+ {
+ text-align: center;
+ border-bottom: 1px black solid;
+ padding-top: 5%;
+ padding-bottom: 5%;
+ }
+
+ .elementTableauOptions:nth-child(4)
+ {
+ text-align: center;
+ border-bottom: 1px black solid;
+ padding-top: 3%;
+ padding-bottom: 5%;
+ }
+
+
+ #boutonSupprimer
+ {
+ background-color: red;
+ }
+
+ #boutonValiderPoidsOption
+ {
+ background-color: lime;
+ }
+
+
+ #conteneurAjoutLigne
+ {
+ display: flex;
+ width: 80.5%;
+ flex-wrap: wrap;
+ margin-left: 15%;
+ top: 51px;
+ border: 5px lime solid;
+ background-color: #c3c3c3;
+ }
+
+ .elementAjoutLigne:nth-child(1)
+ {
+ width: 18.5%;
+ text-align: right;
+
+ padding-top: 2%;
+ padding-right: 5%;
+ }
+
+ .elementAjoutLigne:nth-child(2)
+ {
+ width: 46%;
+ overflow: auto;
+
+ padding-left: 1%;
+ padding-right: 1%;
+ display: flex;
+ flex-wrap: wrap;
+ }
+
+ .elementAjoutLigne:nth-child(3)
+ {
+ width: 5.2%;
+ text-align: center;
+
+ padding-top: 2%;
+ }
+
+ .elementAjoutLigne:nth-child(4)
+ {
+ width: 14%;
+ padding-top: 1.5%;
+ padding-left: 1%;
+ }
+
+ .elementAjoutLigne:nth-child(5)
+ {
+ width: 8%;
+ text-align: center;
+
+ padding-top: 2%;
+ }
+
+ #boutonAjoutEnregistrement
+ {
+ background-color: lime;
+ }
+
+ #caseBoutonEnregistrerGeneral
+ {
+ text-align: center;
+ padding-top: 15%;
+ padding-bottom: 10%;
+ }
+
+ #boutonEnregistrerGeneral
+ {
+ background-color: lime;
+ font-size: 20px;
+ }
\ No newline at end of file
diff --git a/FlOpEDT/solve_board/static/solve_board/kiffDegree.js b/FlOpEDT/solve_board/static/solve_board/kiffDegree.js
new file mode 100644
index 0000000000000000000000000000000000000000..5d9b345d914efffda74cb52955bf8c3ec44fadd8
--- /dev/null
+++ b/FlOpEDT/solve_board/static/solve_board/kiffDegree.js
@@ -0,0 +1,83 @@
+ let circles=[{id:1, color:"#009000", coordx:10,value:8},
+{id:2, color:"#40A400" , coordx:30,value:7},
+{id:3, color:"#80B800" , coordx:50,value:6},
+{id:4, color:"#BFCC00" , coordx:70,value:5},
+{id:5, color:"#FFA500" , coordx:90,value:4},
+{id:6, color:"#FF7C00" , coordx:110,value:3},
+{id:7, color:"#FF5300" , coordx:130,value:2},
+{id:8, color:"#FF3000", coordx:150,value:1},
+{id:9, color:"#FF0000", coordx:170,value:0}]
+
+
+function addCircles(idCircle,idBar){
+ let newCircles="";
+ for(let c of circles){
+ let coordx=c.id*6+50;
+ let newCircle= ` `;
+ newCircles=newCircles+newCircle
+ // //sens interdit pour le cercle 9
+ // if(c.id===9){
+
+ // d3.select("#"+idCircle+"circleContent9")
+ // .append("rect")
+ // .attr("x",163)
+ // .attr("y",9)
+ // .attr("width",14)
+ // .attr("height",2.5)
+ // .attr("fill","white");
+ // }
+ }
+ newCircles=newCircles+"";
+ return newCircles
+}
+
+
+
+
+//allCircles récupère tous les cercles de kiff
+//let allcircles=document.getElementsByClassName("circleKiff")
+
+/*####################################Fonctionnel####################################*/
+
+//Quand on click sur un cercle, il prend l'attribut check=True et les autres cercles de sa ligne prennent l'attribut check=False
+for(let elmt of allcircles){
+ elmt.addEventListener("click",otherCircleInCheckFalse);
+ elmt.addEventListener("click", circleInCheckTrue);
+}
+//Quand on click sur cercle, il prend l'attribut check=True
+function circleInCheckTrue(event){
+ let circleId=event.originalTarget.id;
+ d3.select("#"+circleId).attr("check","True");
+}
+//Quand on click sur un cercle, les autres prennent l'attribut check=False
+function otherCircleInCheckFalse(event){
+ console.log(event);
+ let idLine=event.target.parentNode.parentNode.id;
+ d3.select("#"+idLine).selectAll("circle").attr("check","False");
+}
+
+/*####################################Animation####################################*/
+//Animation quand on clique sur l'un des cercles
+
+for(let elmt of allcircles){
+ elmt.addEventListener("click",animNull);
+ elmt.addEventListener("click", animBorderBlack);
+}
+
+//fonction qui ajoute un contour noir sur un cercle sélectionné et qui l'enlève si déjà sélectionné
+function animBorderBlack(event){
+ let circleId=event.originalTarget.id;
+ d3.select("#"+circleId).attr("stroke","black").attr("stroke-width",5).attr("r",8);
+ let value=event.explicitOriginalTarget.attributes.value.nodeValue;
+ if(value==="0"){
+ alert("Attention, choisir cette préférence indique un refus total!");
+ }
+}
+
+//quand on click sur un cercle, les autres sont démunis de leurs animation
+function animNull(event){
+ let idLine=event.explicitOriginalTarget.parentNode.parentNode.id;
+ d3.select("#"+idLine).selectAll("circle").attr("stroke-width",0).attr("r",10);
+}
+
+/*########################################################################*/
diff --git a/FlOpEDT/solve_board/static/solve_board/solve.css b/FlOpEDT/solve_board/static/solve_board/solve.css
index e4ed124197a7377c874ddbc5386329a22da65ba4..3aa91f072b1f945facbdaf99f6fa05ae37926980 100644
--- a/FlOpEDT/solve_board/static/solve_board/solve.css
+++ b/FlOpEDT/solve_board/static/solve_board/solve.css
@@ -24,7 +24,42 @@
section#content{
height: 80vh;
}
+.menu {
+ display: flex; /* Transformation en flexbox */
+ padding:0; /* Suppression des marges internes */
+ background-color: #ccc; /* Ajout de la couleur d'arrière-plan */
+ justify-content: space-around;/* Alignements des liens dans le menu */
+}
+.menu li {
+ list-style-type: none ; /* Suppression des puces */
+}
+.menu a {
+ display:block; /* Transformation en block */
+ min-width: 120px; /* Largeur minimale des liens */
+
+ margin: 0.5rem; /* Marges externes */
+ padding: 0.4rem 0; /* Marges internes */
+ text-align: center; /* Centrage du texte */
+ background-color: #1ABC9C; /* Arrière-plan */
+ color: #fff; /* Couleur du texte */
+ text-decoration: none; /* Suppression du soulignement */
+ border: 1px solid #fff; /* Ajout d'une bordure */
+ border-radius: 4px; /* Arrondis des bordures */
+
+ transition: all 1s ; /* Ajout des effets de transition */
+}
+.menu a.actif {
+ background-color: #000 ;
+ color: #1ABC9C ;
+ border-color: #1ABC9C ;
+}
+.menu a:hover,
+.menu a:hover.actif{
+ background-color: #ed2794;
+ color: #ffe843;
+ border-color: #ffe843;
+}
.solver{
display: flex;
flex-direction: row;
@@ -102,6 +137,7 @@
display: none;
}
+
input[type=checkbox] + label:before {
content: "\2714";
border: 0.1em solid #000;
diff --git a/FlOpEDT/solve_board/static/solve_board/solve_perso.js b/FlOpEDT/solve_board/static/solve_board/solve_perso.js
new file mode 100644
index 0000000000000000000000000000000000000000..69dd7389419be7ef2bb2055cb1bc7f50e6bb2de2
--- /dev/null
+++ b/FlOpEDT/solve_board/static/solve_board/solve_perso.js
@@ -0,0 +1,637 @@
+// This file is part of the FlOpEDT/FlOpScheduler project.
+// Copyright (c) 2017
+// Authors: Iulian Ober, Paul Renaud-Goud, Pablo Seban, et al.
+//
+// This program 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, or (at your option) any later version.
+//
+// This program 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 this program. If not, see
+// .
+//
+// You can be released from the requirements of the license by purchasing
+// a commercial license. Buying such a license is mandatory as soon as
+// you develop activities involving the FlOpEDT/FlOpScheduler software
+// without disclosing the source code of your own applications.
+
+
+
+
+
+
+/**
+ *
+ * The storage structure is below,
+ * It is made up of different attributes that you can
+ * understand thanks to the comments.Each constraint has a
+ * number of parameters stored in a list.
+ * constraints is a constraint list. Each constraint
+ * is an object.
+ *
+*/
+
+/*
+let constraints = [
+ {
+ id: 8, // id de la TTC
+ name: "Covoiturage", // nom du type de TTC
+ weight: 1, // poids de la TTC
+ is_active: true, // contrainte active ?
+ comment: "", // commentaire sur la TTC
+ last_modification: null, // date de création
+ weeks : [{nb: 14 , year: 2021},{nb: 33 , year: 2021}], // week a la forme : {nb: int , year: int}
+ parameters : [
+ {
+ name: "Prof", // nom du paramètre dans la TTC
+ type: 'people.Tutor', // nom du type des objets dans ce paramètre
+ required: true, // paramètre obligatoire ?
+ all_except: true, // tous sauf ?
+ multiple : true,
+ id_list: [2,6], // ids des objets pour le paramètre dans la TTC
+ acceptable: [1,2,3,4,5,6,7,8,9,10,11] // ids des objets acceptables comme valeur du paramètre
+ },
+ {
+ name: "bonjour", // nom du paramètre dans la TTC
+ type: 'people.Tutor', // nom du type des objets dans ce paramètre
+ required: false, // paramètre obligatoire ?
+ all_except: true, // tous sauf ?
+ multiple : true,
+ id_list: [1,8,5,6,7,8,9], // ids des objets pour le paramètre dans la TTC
+ acceptable: [1,2,3,4,5,6,7,8,9,10,11,12] // ids des objets acceptables comme valeur du paramètre
+ }]
+ }];
+
+*/
+
+
+/**
+ *
+ * The storage structure of the parameters is below,
+ * this allows you to retrieve the value associated with an id
+ * found in the id_list of the parameters of a constraint.
+ * It is composed of a parameters object storing another object
+ * which itself stores a list. For example in the first case
+ * below people and Tutor represents the type of the parameter.
+ *
+*/
+
+/*
+ let parameters = {
+ people:{
+ Tutor:[
+ {
+ "id": 1,
+ "name": "PSE"
+ },
+ {
+ "id": 2,
+ "name": "PRG"
+ }
+]
+ },
+ base:{
+ Module:[
+ {"id":1,"abbrev":"AMN"},
+ {"id":2,"abbrev":'AMN2'}
+ ]
+ }
+}
+*/
+
+
+/**
+ *
+ * The structure below is a list of categories,
+ * this is used to define to which category belongs
+ * each constraint. A category can contain some
+ * another.
+ *
+*/
+
+/*
+let categories = [
+ {id:1,
+ name: 'Tous',// nom de la catégorie
+ parent:null, // catégorie parent
+ constraints_list:[8,9,10], //nombre de contraintes comprises dans cette catégorie
+ hidden:false},
+ {id:2,
+ name: 'Categorie cool',
+ parent:1, // id de la categorie parent
+ constraints_list:[],
+ hidden:true}
+]
+*/
+
+
+
+
+// Function allowing to retrieve all the constraints from the API
+let constraints;
+function fetch_constraint(){
+
+ $.ajax({
+ type:"GET",
+ dataType: 'text',
+ url: build_url(url_ttconstraints),
+ async: false,
+ contentType: "application/json",
+ success: function(msg){
+ constraints = JSON.parse(msg);
+ },
+ error: function (msg){
+ console.log("error");
+ show_loader(false);
+ }
+ })
+ return constraints;
+};
+
+fetch_constraint() ;
+
+
+
+// Function allowing to retrieve all the parameters from the API
+let parameters;
+function fetch_parameters(){
+
+ $.ajax({
+ type:"GET",
+ dataType: 'text',
+ url: build_url(url_parameters),
+ async: false,
+ contentType: "application/json",
+ success: function(msg){
+ parameters = JSON.parse(msg);
+
+ },
+ error: function (msg){
+ console.log("error");
+ show_loader(false);
+ }
+ })
+ return parameters;
+};
+fetch_parameters();
+
+
+
+
+
+
+
+
+
+// Variables
+// The zone where we are going to create our HTML skeleton for the display of the constraints
+ let consZone = document.getElementById("Zone de contrainte");
+ consZone.setAttribute('id','consZone');
+
+// Function regenerating the lines of constraints
+function refresh_param() {
+
+// Table where we will add the rows for the constraints and the columns for these attributes
+ let tbl = document.createElement("table");
+ tbl.setAttribute('id','table');
+ let tblBody = document.createElement("tbody");
+ tblBody.setAttribute('id','tableBody');
+
+
+ // Loop traversing each constraint 1 by 1
+ for (let l = 0; l < constraints.length; l++) {
+
+ // Create a row
+ let row = document.createElement("tr");
+ row.setAttribute('class', 'ligne_contrainte');
+ row.setAttribute('id', 'ligne_contrainte');
+
+
+ // Selection button
+ let select = document.createElement("td");
+ select.setAttribute('class', 'selec_contrainte');
+
+ // Create a checkbox button to select the constraint
+ let selec = document.createElement('input');
+ selec.setAttribute('type', 'checkbox');
+ selec.setAttribute('id', 'selection');
+ selec.setAttribute('name', 'selection');
+ select.appendChild(selec);
+ row.appendChild(select);
+
+
+ // Name of the constraint
+ let div_nom = document.createElement("td");
+ div_nom.setAttribute('class', 'nom_contrainte');
+ nom = document.createTextNode(constraints[l].name);
+ div_nom.appendChild(nom);
+ row.appendChild(div_nom);
+
+
+
+ // Parameters of the constraint
+ // tag allowing the creation of a column corresponding to the parameters
+ let para = document.createElement("td");
+ para.setAttribute('class', 'para_contrainte');
+
+
+
+ // The various existing parameters of the constraint line
+ for (let k = 0; k < constraints[l].parameters.length; k++) {
+
+ if (constraints[l].parameters[k].type === "base.Department") {
+ continue;
+ }
+
+ let p_param = document.createElement("p");
+ p_param.setAttribute('id', 'param' + constraints[l].parameters[k].name);
+ // Parameter name in bold if it is required
+ let strong = document.createElement("strong");
+ // Parameter name in italics if it is not required
+ let em = document.createElement("em");
+
+ // Button used to add possibilities to a parameter
+ let btn_Possib = document.createElement('input');
+ btn_Possib.setAttribute('type', 'image');
+ btn_Possib.setAttribute('id', 'image_Add');
+ btn_Possib.setAttribute('src', '/static/base/img/ajout.png');
+ btn_Possib.setAttribute('width', '15px');
+ btn_Possib.setAttribute('height', '15px');
+
+
+ // Button allowing the display of the possibilities zone if there are more than 2
+ let btn_possibl = document.createElement('input');
+ btn_possibl.setAttribute('id', 'btn_possibl');
+ btn_possibl.setAttribute('type', 'button');
+ btn_possibl.setAttribute('width', '15px');
+ btn_possibl.setAttribute('height', '15px');
+ btn_possibl.setAttribute('onclick', 'hide(\'zone_Possib' + constraints[l].parameters[k].id_list + k + '\')');
+ btn_possibl.setAttribute('class', 'btn_possibl');
+
+ // Display area of all the possibilities of a parameter
+ let zone_Possib = document.createElement("div");
+ zone_Possib.setAttribute('class', 'zone_Possib');
+ zone_Possib.setAttribute('id', 'zone_Possib' + constraints[l].parameters[k].id_list + k);
+ //type du paramètre actuel sous form de string
+ let type = constraints[l].parameters[k].type;
+ // Concatenate the type + parameters and remove the quotes
+ let type_concat = stringGetter(type);
+
+ for (let m = 0; m < constraints[l].parameters[k].id_list.length; m++) {
+ let tab_username = [];
+ type_concat.find(function (n) {
+ if (n.id === constraints[l].parameters[k].id_list[m]) {
+ let list_values = Object.values(n);
+ tab_username.push(list_values[1]);
+ }
+ });
+ for (let h = 0; h < tab_username.length; h++) {
+ let possib = document.createTextNode(tab_username[h] + " ");
+ // if there is only one value in the id_list
+ if (constraints[l].parameters[k].id_list.length === 1) {
+ btn_possibl.value = tab_username[h];
+ btn_possibl.disabled = true;
+ } else {
+ type_concat.find(function (n) {
+ // if there is more than 1 values in the id_list
+ if (n.id === constraints[l].parameters[k].id_list[0]) {
+ let list_values = Object.values(n);
+ btn_possibl.value = list_values[1] + "...";
+ }
+ });
+ zone_Possib.appendChild(possib);
+
+ }
+ }
+ }
+
+ // Button for deleting a parameter
+ let btn_Suppr = document.createElement('input');
+ btn_Suppr.setAttribute('type', 'image');
+ btn_Suppr.setAttribute('id', 'image_Delete');
+ btn_Suppr.setAttribute('src', '/static/base/img/suppression.png');
+ btn_Suppr.addEventListener('click', () => suppr(constraints[l].parameters[k].id_list));
+ btn_Suppr.setAttribute('width', '15px');
+ btn_Suppr.setAttribute('height', '15px');
+
+
+ // If there are no possibilities found in parameters, then we display none
+ let btn_None = document.createElement('input');
+ btn_None.setAttribute('id', 'None');
+ btn_None.setAttribute('type', 'button');
+ btn_None.setAttribute('value', 'None');
+ btn_None.setAttribute('width', '15px');
+ btn_None.setAttribute('height', '15px');
+
+
+
+ // The name of the current parameter
+ let parametres_nom = document.createTextNode(" " + constraints[l].parameters[k].name + " ");
+
+ // Condition used to check if a parameter is required and if it is not empty
+ if (constraints[l].parameters[k].required === true && constraints[l].parameters[k].id_list.length !== 0) {
+ let case_param_required = document.createElement("div");
+ case_param_required.setAttribute('class', 'case_param_required');
+ strong.appendChild(parametres_nom);
+ p_param.appendChild(strong);
+ case_param_required.appendChild(p_param);
+ case_param_required.appendChild(btn_Possib);
+
+ // Condition if the btn is empty then display none otherwise display the button correctly
+ if (btn_possibl.value === "") {
+ case_param_required.appendChild(btn_None);
+ btn_None.disabled = true;
+ } else {
+ case_param_required.appendChild(btn_possibl);
+ }
+ case_param_required.appendChild(btn_Suppr);
+ case_param_required.appendChild(zone_Possib);
+ para.appendChild(case_param_required);
+
+ // Condition used to display the non-required parameters
+ } else if (constraints[l].parameters[k].id_list.length !== 0) {
+ let case_param_second = document.createElement("div");
+ case_param_second.setAttribute('class', 'case_param_second');
+ em.appendChild(parametres_nom);
+ p_param.appendChild(em);
+ case_param_second.appendChild(p_param);
+ case_param_second.appendChild(btn_Possib);
+
+ // Condition if the btn is empty then display none otherwise display the button correctly
+ if (btn_possibl.value === "") {
+ case_param_second.appendChild(btn_None);
+ btn_None.disabled = true;
+ } else {
+ case_param_second.appendChild(btn_possibl);
+ }
+ case_param_second.appendChild(btn_Suppr);
+ case_param_second.appendChild(zone_Possib);
+ para.appendChild(case_param_second);
+ }
+
+ }
+
+ row.appendChild(para);
+
+
+ // Adding a column for button insertion
+ let ajout_Param = document.createElement("td");
+ ajout_Param.setAttribute('class', 'ajout_param');
+
+ // Button used to display the drop-down menu
+ let btn = document.createElement('input');
+ btn.setAttribute('type', 'image');
+ btn.setAttribute('id', 'image_Add');
+ btn.setAttribute('src', '/static/base/img/ajout.png');
+ btn.setAttribute('width', '20px');
+ btn.setAttribute('height', '20px');
+ btn.setAttribute('onclick', 'hide(\'Menu' + l + '\')');
+ ajout_Param.appendChild(btn);
+
+ // Validate the selected parameters to add
+ let btn_valid_param = document.createElement('input');
+ btn_valid_param.setAttribute('type', 'button');
+ btn_valid_param.setAttribute('id', 'valider' + l);
+ btn_valid_param.setAttribute('value', 'Valider');
+ btn_valid_param.setAttribute('width', '20px');
+ btn_valid_param.setAttribute('height', '20px');
+ row.appendChild(ajout_Param);
+
+
+ // Add the zone allowing the display of the drop-down menu
+ let Menu = document.createElement("div");
+ Menu.setAttribute('id', 'Menu' + l);
+ Menu.setAttribute('class', 'Menu');
+ let Select = document.createElement("select");
+ Select.setAttribute('id', 'ChoixP' + l);
+ Select.setAttribute('data-max', '');
+ Select.setAttribute('multiple', 'multiple');
+ Select.setAttribute('style', '');
+ Menu.appendChild(Select);
+ Menu.appendChild(btn_valid_param);
+ ajout_Param.appendChild(Menu);
+ row.appendChild(ajout_Param);
+
+ // Activate a row
+ let activ = document.createElement("td");
+ activ.setAttribute('class', 'activ_contrainte');
+ let activate = document.createElement('input');
+ activate.setAttribute('type', 'checkbox');
+ activate.setAttribute('id', 'activation');
+ activate.setAttribute('name', 'activation');
+ activate.setAttribute('onclick', 'activate(this,constraints[' + l + '])');
+ activ.appendChild(activate);
+ row.appendChild(activ);
+
+
+ // If a constraint is active, then the button will be checked
+ if (constraints[l].is_active === true) {
+ activate.checked = true;
+ }
+
+
+ // Select the weight of a constraint
+ let range_td = document.createElement("td");
+ range_td.setAttribute('class', 'poid_contrainte');
+
+
+ // Button used to manage the weight of a constraint
+ let slide_btn = document.createElement('input');
+ slide_btn.setAttribute('type', 'range');
+ slide_btn.setAttribute('min', '1');
+ slide_btn.setAttribute('max', '8');
+ slide_btn.setAttribute('value', constraints[l].weight);
+ slide_btn.setAttribute('onclick', 'update_weight(this,constraints[' + l + '])');
+ slide_btn.setAttribute('class', 'range-slider__range');
+ slide_btn.setAttribute('id', 'Weight');
+ slide_btn.setAttribute('name', 'Weight');
+ range_td.appendChild(slide_btn);
+ row.appendChild(range_td);
+
+ // Duplicate a constraint line
+ let duplic = document.createElement("td");
+ duplic.setAttribute('class', 'duplic_contrainte');
+ let btn_duplicate = document.createElement('input');
+ btn_duplicate.setAttribute('type', 'image');
+ btn_duplicate.setAttribute('id', 'image_duplic');
+ btn_duplicate.setAttribute('src', '/static/base/img/copier-coller-1.png');
+ btn_duplicate.setAttribute('width', '25px');
+ btn_duplicate.setAttribute('height', '25px');
+ // Validating a row and sending to the API
+ let btn_Validate = document.createElement('input');
+ btn_Validate.setAttribute('type', 'image');
+ btn_Validate.setAttribute('id', 'image_Validate');
+ btn_Validate.setAttribute('src', '/static/base/img/valider.png');
+ btn_Validate.setAttribute('onclick', 'update_send(constraints,parameters)');
+ btn_Validate.setAttribute('width', '25px');
+ btn_Validate.setAttribute('height', '25px');
+ duplic.appendChild(btn_duplicate);
+ duplic.appendChild(btn_Validate);
+ //Deleting a constraint
+ let btn_delete = document.createElement('input');
+ btn_delete.setAttribute('type', 'image');
+ btn_delete.setAttribute('id', 'image_Validate');
+ btn_delete.setAttribute('src', '/static/base/img/LasuppressiondesIRP.png');
+ btn_delete.setAttribute('onclick', 'suppr_contstraint('+l+')');
+ btn_delete.setAttribute('width', '25px');
+ btn_delete.setAttribute('height', '25px');
+ duplic.appendChild(btn_delete);
+ row.appendChild(duplic);
+
+ // Adding the row to the table
+ tblBody.appendChild(row);
+ }
+// Adding the generate table in the HTML area
+ tbl.appendChild(tblBody);
+ consZone.appendChild(tbl);
+ }
+refresh_param();
+create_menu();
+
+//Function transforming a string into a path that can be used to browse a list and / or a JS object
+function stringGetter (getter) {
+ return getter
+ .split('.')
+ .reduce((o,i)=>o[i], parameters);
+ }
+
+
+/**
+ * Deleting a Parameter
+ * @param param
+ *
+ */
+function suppr(param){
+ param.length=0;
+ document.getElementById('tableBody').remove();
+ // Regeneration of the constraint lines
+ refresh_param();
+ // Create new drop-down menus
+ create_menu();
+}
+
+/**
+ * Deleting a Constraints
+ * @param param
+ *
+ */
+function suppr_contstraint(index,constraint_name){
+
+
+
+ if (confirm("Êtes-vous sûr de vouloir supprimer cette contrainte ?")) {
+ // Delete the constraints
+ if (index !== -1) constraints.splice(index, 1);
+ alert("La contrainte à été supprimée avec succés.");
+ } else {
+ // Do nothing!
+ alert("La contrainte n'a pas été supprimée.");
+ }
+
+ document.getElementById('tableBody').remove();
+ // Regeneration of the constraint lines
+ refresh_param();
+ // Create new drop-down menus
+ create_menu();
+}
+
+/**
+ * Activation / deactivation of a parameter
+ * @param param
+ *
+ */
+function activate(checkbox,param){
+ if (checkbox.checked) {
+ param.is_active = true;
+ }
+ else {
+ param.is_active = false;
+ }
+
+}
+
+/**
+ * Managing the weight of a constraint
+ * @param slider, param
+ *
+ *
+ */
+function update_weight(slider,param){
+ param.weight = slider.value;
+}
+
+/**
+ * Sending the modified constraint to the API
+ * @param constr,param
+ *
+ *
+ */
+function update_send(constr,param){
+ console.log(constr);
+ console.log(param);
+}
+
+
+/**
+ * Show/hide an élement
+ *
+ */
+ function hide(id) {
+ let x = document.getElementById(id);
+ if (x.style.display === "block") {
+ x.style.display = "none";
+ } else {
+ x.style.display = "block";
+ }
+ }
+
+
+// Function allowing the generation of the drop-down menu of options
+function create_menu() {
+ for (let cpt = 0; cpt < constraints.length; cpt++) {
+ var ldd = document.getElementById("ChoixP" + cpt);
+
+ //Creation of the option menu that is filled.
+ for (let j = 0; j < constraints[cpt].parameters.length; j++) {
+ if (constraints[cpt].parameters[j].id_list.length == 0) {
+ var opt = document.createElement('option');
+ opt.innerHTML = constraints[cpt].parameters[j].name;
+ ldd.appendChild(opt);
+ }
+ }
+
+ // javascript from the drop-down menu allowing selection
+ $("#ChoixP" + cpt).easySelect({
+ buttons: true,
+ search: true,
+ placeholder: 'Choisissez un paramètre',
+ placeholderColor: 'violet',
+ selectColor: 'lila',
+ itemTitle: 'Color selected',
+ showEachItem: true,
+ width: '100%',
+ dropdownMaxHeight: '450px',
+ })
+
+
+// Listener allowing to return the selected elements in the easyselect
+ $('#valider' + cpt).click(function () {
+ $('#ChoixP' + cpt + ' option:selected').each(function () {
+ str = $(this).text() + " ";
+ val = $(this).val();
+ })
+ });
+
+ }
+}
+
+
+
+
+
diff --git a/FlOpEDT/solve_board/templates/solve_board/main-board_perso.html b/FlOpEDT/solve_board/templates/solve_board/main-board_perso.html
new file mode 100644
index 0000000000000000000000000000000000000000..e113bc163ac15cd39dfdf649d24146103a0acf00
--- /dev/null
+++ b/FlOpEDT/solve_board/templates/solve_board/main-board_perso.html
@@ -0,0 +1,112 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+{% extends "base.html" %}
+{% csrf_token %}
+{% load i18n %}
+
+{% block title %} {% trans "Schedule Generation" %} {% endblock %}
+{% block content %}
+{% load static %}
+
+{% block jquery %}
+
+
+
+
+
+
+
+{% endblock %}
+
+
+
+
+
+
+
+
+
+
+
Gérer le poids
+
+
+
+
1--2--3--4--5--6--7--8--O
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
1--2--3--4--5--6--7--8--O
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Image + Nom de la catégorie
+
+
+
+
+
+
+
+
+
+
+
+
+
+{% endblock %}
+
+
diff --git a/FlOpEDT/solve_board/views.py b/FlOpEDT/solve_board/views.py
index 580164b821ab0473d791e12148cdf5abbe2ff166..69e6451557842e01eb50d15f1d828884325c8f26 100644
--- a/FlOpEDT/solve_board/views.py
+++ b/FlOpEDT/solve_board/views.py
@@ -172,7 +172,7 @@ def main_board(req, **kwargs):
# Get contextual datas (constraints, work_copies)
if len(week_list) > 0:
data_context = get_context(department, year=week_list[0][0], week=week_list[0][1])
- view_context.update({ k:json.dumps(v) for k, v in data_context.items()})
+ view_context.update({k: json.dumps(v) for k, v in data_context.items()})
- return TemplateResponse(req, 'solve_board/main-board.html', view_context)
+ return TemplateResponse(req, 'solve_board/main-board_perso.html', view_context)