mirror of
				https://github.com/ae-utbm/sith.git
				synced 2025-10-31 09:03:06 +00:00 
			
		
		
		
	improve pagination
This commit is contained in:
		
							
								
								
									
										30
									
								
								core/static/core/colors.scss
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										30
									
								
								core/static/core/colors.scss
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,30 @@ | ||||
| $first-color: hsl(220, 100%, 50%); | ||||
| $second-color: hsl(48, 100%, 67%); | ||||
| $primary-color: hsl(219.9, 53.7%, 50%); | ||||
| $secondary-color: hsl(204, 64%, 44%); | ||||
| $primary-color-text: hsl(0, 0%, 100%); | ||||
| $secondary-color-text: hsla(0, 0%, 0%, 0.87); | ||||
|  | ||||
| $primary-light-color: hsl(219.8, 46.4%, 64.9%); | ||||
| $primary-dark-color: hsl(203, 75%, 40%); | ||||
|  | ||||
| $secondary-light-color: hsl(40, 68%, 65%); | ||||
| $secondary-dark-color: hsl(40, 68%, 35%); | ||||
|  | ||||
| $primary-neutral-color: hsl(219.6, 20.8%, 50%); | ||||
| $primary-neutral-light-color: hsl(0, 0%, 94%); | ||||
| $primary-neutral-dark-color: hsl(210, 29%, 29%); | ||||
|  | ||||
| $secondary-neutral-color: hsl(204, 64%, 44%); | ||||
| $secondary-neutral-light-color: hsl(0, 0%, 91%); | ||||
| $secondary-neutral-dark-color: hsl(40, 57.6%, 17%); | ||||
|  | ||||
| $white-color: hsl(219.6, 20.8%, 98%); | ||||
| $black-color: hsl(0, 0%, 17%); | ||||
|  | ||||
| $faceblue: hsl(221, 44%, 41%); | ||||
| $twitblue: hsl(206, 82%, 63%); | ||||
|  | ||||
| $shadow-color: rgb(223, 223, 223); | ||||
|  | ||||
| $background-button-color: hsl(0, 0%, 95%); | ||||
| @@ -1,5 +1,7 @@ | ||||
| @import "colors"; | ||||
|  | ||||
| nav.navbar { | ||||
|   background-color: hsl(203, 75%, 40%); | ||||
|   background-color: $primary-dark-color; | ||||
|   margin: 1em; | ||||
|   color: white; | ||||
|   border-radius: 0.6em; | ||||
|   | ||||
							
								
								
									
										37
									
								
								core/static/core/pagination.scss
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										37
									
								
								core/static/core/pagination.scss
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,37 @@ | ||||
| @import "colors"; | ||||
|  | ||||
| .pagination { | ||||
|   text-align: center; | ||||
|   gap: 10px; | ||||
|  | ||||
|   button { | ||||
|     background-color: $secondary-neutral-light-color; | ||||
|     min-width: 37px; | ||||
|  | ||||
|     &:hover { | ||||
|       background-color: darken($secondary-neutral-light-color, 10%); | ||||
|     } | ||||
|  | ||||
|     &:disabled { | ||||
|       color: #fff; | ||||
|       background-color: darken($secondary-neutral-light-color, 5%); | ||||
|     } | ||||
|  | ||||
|     &.active, | ||||
|     &.active:hover { | ||||
|       background-color: $primary-neutral-color; | ||||
|       color: white; | ||||
|       border-radius: 50%; | ||||
|     } | ||||
|  | ||||
|     &:first-of-type, | ||||
|     &:last-of-type { | ||||
|       // previous and next buttons | ||||
|       &:disabled { | ||||
|         // Hide the arrows when they are disabled, without | ||||
|         // changing the layout of the navigation | ||||
|         opacity: 0; | ||||
|       } | ||||
|     } | ||||
|   } | ||||
| } | ||||
| @@ -1,39 +1,9 @@ | ||||
| $first-color: hsl(220, 100%, 50%); | ||||
| $second-color: hsl(48, 100%, 67%); | ||||
| $primary-color: hsl(219.9, 53.7%, 50%); | ||||
| $secondary-color: hsl(204, 64%, 44%); | ||||
| $primary-color-text: hsl(0, 0%, 100%); | ||||
| $secondary-color-text: hsla(0, 0%, 0%, 0.87); | ||||
|  | ||||
| $primary-light-color: hsl(219.8, 46.4%, 64.9%); | ||||
| $primary-dark-color: hsl(203, 75%, 40%); | ||||
|  | ||||
| $secondary-light-color: hsl(40, 68%, 65%); | ||||
| $secondary-dark-color: hsl(40, 68%, 35%); | ||||
|  | ||||
| $primary-neutral-color: hsl(219.6, 20.8%, 50%); | ||||
| $primary-neutral-light-color: hsl(0, 0%, 94%); | ||||
| $primary-neutral-dark-color: hsl(210, 29%, 29%); | ||||
|  | ||||
| $secondary-neutral-color: hsl(204, 64%, 44%); | ||||
| $secondary-neutral-light-color: hsl(0, 0%, 91%); | ||||
| $secondary-neutral-dark-color: hsl(40, 57.6%, 17%); | ||||
|  | ||||
| $white-color: hsl(219.6, 20.8%, 98%); | ||||
| $black-color: hsl(0, 0%, 17%); | ||||
|  | ||||
| $faceblue: hsl(221, 44%, 41%); | ||||
| $twitblue: hsl(206, 82%, 63%); | ||||
|  | ||||
| $shadow-color: rgb(223, 223, 223); | ||||
|  | ||||
| $background-button-color: hsl(0, 0%, 95%); | ||||
| @import "colors"; | ||||
|  | ||||
| /*--------------------------MEDIA QUERY HELPERS------------------------*/ | ||||
| $small-devices: 576px; | ||||
| $medium-devices: 768px; | ||||
| $large-devices: 992px; | ||||
| $extra-large-devices: 1200px; | ||||
|  | ||||
| /*--------------------------------GENERAL------------------------------*/ | ||||
|  | ||||
| @@ -43,17 +13,6 @@ body { | ||||
|   font-family: sans-serif; | ||||
| } | ||||
|  | ||||
| button:disabled, | ||||
| button:disabled:hover { | ||||
|   color: #fff; | ||||
|   background-color: #6c757d; | ||||
| } | ||||
|  | ||||
| button.active, | ||||
| button.active:hover { | ||||
|   color: #fff; | ||||
|   background-color: $secondary-color; | ||||
| } | ||||
|  | ||||
| a.button, | ||||
| button, | ||||
|   | ||||
							
								
								
									
										511
									
								
								pedagogy/static/pedagogy/css/pedagogy.scss
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										511
									
								
								pedagogy/static/pedagogy/css/pedagogy.scss
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,511 @@ | ||||
| @import "core/static/core/colors"; | ||||
|  | ||||
|  | ||||
| $pedagogy-blue: #1bb9ea; | ||||
| $pedagogy-orange: #ea7900; | ||||
| $pedagogy-hover-blue: #0e97ce; | ||||
| $pedagogy-light-blue: #caf0ff; | ||||
| $pedagogy-white-text: #f0f0f0; | ||||
|  | ||||
| $small-devices: 576px; | ||||
| $medium-devices: 768px; | ||||
| $large-devices: 992px; | ||||
|  | ||||
| .pedagogy { | ||||
|   &.star-not-checked { | ||||
|     color: #f7f7f7; | ||||
|     margin-bottom: 0; | ||||
|     margin-top: 0; | ||||
|   } | ||||
|   &.star-checked { | ||||
|     color: $pedagogy-orange; | ||||
|     margin-bottom: 0; | ||||
|     margin-top: 0; | ||||
|   } | ||||
|  | ||||
|   &.grade-without-star { | ||||
|     display: none; | ||||
|   } | ||||
|  | ||||
|   @media screen and (max-width: $large-devices) { | ||||
|     &.star-not-checked { | ||||
|       margin-left: 5px; | ||||
|       margin-right: 5px; | ||||
|     } | ||||
|     &.star-checked { | ||||
|       margin-left: 5px; | ||||
|       margin-right: 5px; | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   @media screen and (max-width: $small-devices) { | ||||
|     &.grade-without-star { | ||||
|       display: block; | ||||
|     } | ||||
|     &.grade-with-star { | ||||
|       display: none; | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   #dynamic_view { | ||||
|     font-size: 1.1em; | ||||
|  | ||||
|     overflow-wrap: break-word; | ||||
|  | ||||
|     td { | ||||
|       text-align: center; | ||||
|       border: none; | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   #search_form { | ||||
|     .search-form-container { | ||||
|       display: grid; | ||||
|       grid-template-columns: auto auto; | ||||
|       grid-template-rows: auto auto auto; | ||||
|       grid-template-areas: | ||||
|       "action-bar action-bar" | ||||
|       "search-bar search-bar" | ||||
|       "radio-department radio-department" | ||||
|       "radio-credit-type radio-semester"; | ||||
|     } | ||||
|  | ||||
|     .action-bar { | ||||
|       grid-area: action-bar; | ||||
|       margin-bottom: 10px; | ||||
|     } | ||||
|  | ||||
|     .search-bar { | ||||
|       grid-area: search-bar; | ||||
|       display: grid; | ||||
|       grid-template-columns: auto 200px; | ||||
|       grid-template-rows: auto; | ||||
|       grid-template-areas: "search-bar-input search-bar-button"; | ||||
|  | ||||
|       @media screen and (max-width: $medium-devices) { | ||||
|         grid-template-columns: auto auto; | ||||
|         grid-template-rows: auto; | ||||
|         grid-template-areas: "search-bar-input search-bar-button"; | ||||
|       } | ||||
|  | ||||
|       @media screen and (max-width: $small-devices) { | ||||
|         grid-template-columns: auto; | ||||
|         grid-template-rows: auto; | ||||
|         grid-template-areas: "search-bar-input"; | ||||
|  | ||||
|         .search-bar-button { | ||||
|           display: none; | ||||
|         } | ||||
|       } | ||||
|  | ||||
|       .search-bar-input { | ||||
|         grid-area: search-bar-input; | ||||
|         background: $pedagogy-light-blue; | ||||
|       } | ||||
|  | ||||
|       .search-bar-button { | ||||
|         grid-area: search-bar-button; | ||||
|         background: $pedagogy-orange; | ||||
|         color: white; | ||||
|         font-weight: bold; | ||||
|         margin-left: 20px; | ||||
|       } | ||||
|     } | ||||
|  | ||||
|     .radio-department { | ||||
|       grid-area: radio-department; | ||||
|     } | ||||
|  | ||||
|     .radio-credit-type { | ||||
|       grid-area: radio-credit-type; | ||||
|     } | ||||
|  | ||||
|     .radio-semester { | ||||
|       grid-area: radio-semester; | ||||
|     } | ||||
|  | ||||
|     .radio-guide input[type="radio"], | ||||
|     input[type="checkbox"] { | ||||
|       display: none; | ||||
|     } | ||||
|     .radio-guide { | ||||
|       margin-top: 10px; | ||||
|       color: white; | ||||
|     } | ||||
|     .radio-guide label { | ||||
|       display: inline-block; | ||||
|       background-color: $pedagogy-blue; | ||||
|       padding: 10px 20px; | ||||
|       font-family: Arial, sans-serif; | ||||
|       font-size: 16px; | ||||
|       border-radius: 4px; | ||||
|     } | ||||
|     .radio-guide input[type="radio"]:checked + label { | ||||
|       background-color: $pedagogy-orange; | ||||
|     } | ||||
|     .radio-guide input[type="checkbox"]:checked + label { | ||||
|       background-color: $pedagogy-orange; | ||||
|     } | ||||
|     .radio-guide label:hover { | ||||
|       background-color: $pedagogy-hover-blue; | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   #uv_detail { | ||||
|     color: #062f38; | ||||
|  | ||||
|     .uv-quick-info-container { | ||||
|       display: grid; | ||||
|       grid-template-columns: 20% 20% 20% 20% auto; | ||||
|       grid-template-rows: auto auto; | ||||
|       grid-template-areas: | ||||
|       "hours-cm hours-td hours-tp hours-te hours-the" | ||||
|       "department credit-type semester . ."; | ||||
|     } | ||||
|  | ||||
|     .department { | ||||
|       grid-area: department; | ||||
|     } | ||||
|  | ||||
|     .credit-type { | ||||
|       grid-area: credit-type; | ||||
|     } | ||||
|  | ||||
|     .semester { | ||||
|       grid-area: semester; | ||||
|     } | ||||
|  | ||||
|     .hours-cm { | ||||
|       grid-area: hours-cm; | ||||
|     } | ||||
|  | ||||
|     .hours-td { | ||||
|       grid-area: hours-td; | ||||
|     } | ||||
|  | ||||
|     .hours-tp { | ||||
|       grid-area: hours-tp; | ||||
|     } | ||||
|  | ||||
|     .hours-te { | ||||
|       grid-area: hours-te; | ||||
|     } | ||||
|  | ||||
|     .hours-the { | ||||
|       grid-area: hours-the; | ||||
|     } | ||||
|  | ||||
|     #leave_comment_not_allowed { | ||||
|       p { | ||||
|         text-align: center; | ||||
|         color: red; | ||||
|       } | ||||
|     } | ||||
|  | ||||
|     #leave_comment { | ||||
|       .leave-comment-grid-container { | ||||
|         display: grid; | ||||
|         grid-template-columns: 270px auto; | ||||
|         grid-template-rows: 100%; | ||||
|         grid-template-areas: "stars comment"; | ||||
|  | ||||
|         @media screen and (max-width: $large-devices) { | ||||
|           grid-template-columns: 100%; | ||||
|           grid-template-rows: auto auto; | ||||
|           grid-template-areas: | ||||
|           "stars" | ||||
|           "comment"; | ||||
|         } | ||||
|       } | ||||
|  | ||||
|       .ui-accordion-content { | ||||
|         background-color: $white-color; | ||||
|         border-color: $pedagogy-orange; | ||||
|         border-right: none; | ||||
|       } | ||||
|  | ||||
|       .form-stars { | ||||
|         grid-area: stars; | ||||
|       } | ||||
|  | ||||
|       .form-comment { | ||||
|         grid-area: comment; | ||||
|       } | ||||
|  | ||||
|       .ui-accordion-header { | ||||
|         background-color: $pedagogy-orange; | ||||
|         color: $pedagogy-white-text; | ||||
|         clip-path: polygon(0 0%, 0 100%, 30% 100%, 33% 0); | ||||
|  | ||||
|         @media screen and (max-width: $large-devices) { | ||||
|           clip-path: none; | ||||
|         } | ||||
|       } | ||||
|  | ||||
|       .ui-accordion-header-icon { | ||||
|         color: $pedagogy-white-text; | ||||
|         margin-right: 10px; | ||||
|       } | ||||
|  | ||||
|       .input-stars { | ||||
|         margin-top: 20px; | ||||
|       } | ||||
|  | ||||
|       input[type="submit"] { | ||||
|         float: right; | ||||
|       } | ||||
|     } | ||||
|  | ||||
|     .uv-details-container { | ||||
|       display: grid; | ||||
|       grid-template-columns: 150px 100px auto; | ||||
|       grid-template-rows: 156px 1fr; | ||||
|       grid-template-areas: | ||||
|       "grade grade-stars uv-infos" | ||||
|       ". . uv-infos"; | ||||
|  | ||||
|       @media screen and (max-width: $large-devices) { | ||||
|         grid-template-columns: 50% 50%; | ||||
|         grid-template-rows: auto auto; | ||||
|         grid-template-areas: | ||||
|         "grade grade-stars" | ||||
|         "uv-infos uv-infos"; | ||||
|       } | ||||
|     } | ||||
|  | ||||
|     .grade { | ||||
|       grid-area: grade; | ||||
|       color: $pedagogy-white-text; | ||||
|       background-color: $pedagogy-blue; | ||||
|       padding-right: 10px; | ||||
|  | ||||
|       > p { | ||||
|         text-align: right; | ||||
|         font-weight: bold; | ||||
|       } | ||||
|     } | ||||
|  | ||||
|     .grade-stars { | ||||
|       grid-area: grade-stars; | ||||
|       color: $pedagogy-white-text; | ||||
|       background-color: $pedagogy-blue; | ||||
|       font-weight: bold; | ||||
|     } | ||||
|  | ||||
|     .uv-infos { | ||||
|       grid-area: uv-infos; | ||||
|       padding-left: 10px; | ||||
|     } | ||||
|  | ||||
|     .comment-container { | ||||
|       display: grid; | ||||
|       grid-template-columns: 300px auto; | ||||
|       grid-template-rows: auto auto auto; | ||||
|       grid-template-areas: | ||||
|       "grade-block comment" | ||||
|       "grade-block info" | ||||
|       "comment-end-bar comment-end-bar"; | ||||
|       margin-bottom: 30px; | ||||
|       margin-top: 10px; | ||||
|  | ||||
|       @media screen and (max-width: $large-devices) { | ||||
|         grid-template-columns: auto; | ||||
|         grid-template-rows: auto auto auto auto; | ||||
|         grid-template-areas: | ||||
|         "grade-block" | ||||
|         "comment" | ||||
|         "info" | ||||
|         "comment-end-bar"; | ||||
|       } | ||||
|  | ||||
|       .grade-block { | ||||
|         grid-area: grade-block; | ||||
|         width: 300px; | ||||
|  | ||||
|         display: grid; | ||||
|         grid-template-columns: 150px 150px; | ||||
|         grid-template-rows: 156px auto; | ||||
|         grid-template-areas: | ||||
|         "grade-type grade-stars" | ||||
|         "grade-extension grade-extension"; | ||||
|         grid-gap: 15px; | ||||
|  | ||||
|         clip-path: polygon(0 0, 0 100%, 100% 100%, 100% 30px, 270px 0); | ||||
|         align-items: start; | ||||
|  | ||||
|         background-color: $pedagogy-blue; | ||||
|  | ||||
|         @media screen and (max-width: $large-devices) { | ||||
|           grid-template-columns: 50% auto; | ||||
|           grid-template-rows: auto; | ||||
|           grid-template-areas: "grade-type grade-stars"; | ||||
|           width: auto; | ||||
|           clip-path: none; | ||||
|           align-content: space-evenly; | ||||
|           align-items: end; | ||||
|         } | ||||
|  | ||||
|         .grade-extension { | ||||
|           grid-area: grade-extension; | ||||
|           background-color: $pedagogy-blue; | ||||
|         } | ||||
|  | ||||
|         .grade-type { | ||||
|           grid-area: grade-type; | ||||
|  | ||||
|           > p { | ||||
|             color: $pedagogy-white-text; | ||||
|             font-weight: bold; | ||||
|             text-align: right; | ||||
|           } | ||||
|         } | ||||
|  | ||||
|         .grade-stars { | ||||
|           grid-area: grade-stars; | ||||
|         } | ||||
|       } | ||||
|  | ||||
|       .comment { | ||||
|         grid-area: comment; | ||||
|  | ||||
|         display: grid; | ||||
|         grid-template-columns: auto; | ||||
|         grid-template-rows: auto auto; | ||||
|         grid-template-areas: | ||||
|         "anchor" | ||||
|         "markdown"; | ||||
|  | ||||
|         @media screen and (max-width: $large-devices) { | ||||
|           border-left: solid; | ||||
|           border-right: solid; | ||||
|           border-color: $pedagogy-blue; | ||||
|         } | ||||
|  | ||||
|         .anchor { | ||||
|           grid-area: anchor; | ||||
|           text-align: right; | ||||
|           margin-right: 15px; | ||||
|         } | ||||
|  | ||||
|         .markdown { | ||||
|           grid-area: markdown; | ||||
|  | ||||
|           min-height: 139px; | ||||
|           margin-top: 0; | ||||
|           margin-right: 0; | ||||
|           padding: 10px; | ||||
|           text-align: justify; | ||||
|           overflow: auto; | ||||
|         } | ||||
|       } | ||||
|  | ||||
|       .info { | ||||
|         grid-area: info; | ||||
|         padding-bottom: 10px; | ||||
|  | ||||
|         @media screen and (max-width: $large-devices) { | ||||
|           border-left: solid; | ||||
|           border-right: solid; | ||||
|           border-color: $pedagogy-blue; | ||||
|         } | ||||
|  | ||||
|         .status-reported { | ||||
|           color: red; | ||||
|           float: left; | ||||
|           padding-left: 10px; | ||||
|         } | ||||
|  | ||||
|         .actions { | ||||
|           float: right; | ||||
|         } | ||||
|       } | ||||
|  | ||||
|       .comment-end-bar { | ||||
|         grid-area: comment-end-bar; | ||||
|  | ||||
|         display: grid; | ||||
|         grid-template-columns: 33% auto auto; | ||||
|         grid-template-rows: 2.5em; | ||||
|         grid-template-areas: "author date report"; | ||||
|  | ||||
|         background-color: $pedagogy-blue; | ||||
|         margin-top: -1px; | ||||
|  | ||||
|         @media screen and (max-width: $large-devices) { | ||||
|           grid-template-columns: auto; | ||||
|           grid-template-rows: auto auto auto; | ||||
|           grid-template-areas: | ||||
|           "report" | ||||
|           "date" | ||||
|           "author"; | ||||
|           margin-top: 0; | ||||
|           text-align: center; | ||||
|         } | ||||
|  | ||||
|         .author { | ||||
|           grid-area: author; | ||||
|  | ||||
|           padding-top: 6px; | ||||
|           padding-left: 20px; | ||||
|  | ||||
|           background-color: $pedagogy-orange; | ||||
|           clip-path: polygon(0 10px, 0 100%, 350px 200%, 300px 10px); | ||||
|  | ||||
|           @media screen and (max-width: $large-devices) { | ||||
|             clip-path: none; | ||||
|             padding: 0; | ||||
|             padding-bottom: 7px; | ||||
|           } | ||||
|  | ||||
|           a { | ||||
|             color: $pedagogy-white-text; | ||||
|             font-weight: bold; | ||||
|           } | ||||
|  | ||||
|           a:hover { | ||||
|             color: $pedagogy-hover-blue; | ||||
|           } | ||||
|         } | ||||
|  | ||||
|         .date { | ||||
|           grid-area: date; | ||||
|           color: $pedagogy-white-text; | ||||
|  | ||||
|           @media screen and (max-width: $large-devices) { | ||||
|             padding-bottom: 7px; | ||||
|           } | ||||
|         } | ||||
|  | ||||
|         .report { | ||||
|           grid-area: report; | ||||
|           justify-self: right; | ||||
|           padding-right: 30px; | ||||
|           padding-left: 30px; | ||||
|  | ||||
|           a { | ||||
|             color: $pedagogy-white-text; | ||||
|           } | ||||
|  | ||||
|           a:hover { | ||||
|             color: $pedagogy-hover-blue; | ||||
|           } | ||||
|  | ||||
|           @media screen and (max-width: $large-devices) { | ||||
|             text-align: center; | ||||
|             justify-self: inherit; | ||||
|             padding-bottom: 7px; | ||||
|             background-color: $white-color; | ||||
|  | ||||
|             border-left: solid; | ||||
|             border-right: solid; | ||||
|             border-color: $pedagogy-blue; | ||||
|  | ||||
|             a { | ||||
|               color: $black-color; | ||||
|             } | ||||
|           } | ||||
|         } | ||||
|       } | ||||
|     } | ||||
|   } | ||||
| } | ||||
| @@ -1,4 +1,3 @@ | ||||
|  | ||||
| {% extends "core/base.jinja" %} | ||||
|  | ||||
| {% block title %} | ||||
| @@ -9,6 +8,11 @@ | ||||
|   <script src="{{ static('core/js/alpinejs.min.js') }}" defer></script> | ||||
| {% endblock %} | ||||
|  | ||||
| {% block additional_css %} | ||||
|   <link rel="stylesheet" href="{{ scss('pedagogy/css/pedagogy.scss') }}"> | ||||
|   <link rel="stylesheet" href="{{ scss('core/pagination.scss') }}"> | ||||
| {% endblock %} | ||||
|  | ||||
| {% block head %} | ||||
|   {{ super() }} | ||||
|   <meta name="viewport" content="width=device-width, initial-scale=0.6, maximum-scale=2"> | ||||
| @@ -40,101 +44,107 @@ | ||||
|         </div> | ||||
|         <div class="radio-department"> | ||||
|           <div class="radio-guide"> | ||||
|             {% for (display_name, real_name) in [ | ||||
|             {% set departments = [ | ||||
|             ("EDIM", "EDIM"), ("ENERGIE", "EE"), ("IMSI", "IMSI"), | ||||
|             ("INFO", "GI"), ("GMC", "MC"), ("HUMA", "HUMA"), ("TC", "TC") | ||||
|             ] %} | ||||
|             <input | ||||
|               type="checkbox" | ||||
|               name="department" | ||||
|               id="radio{{ real_name }}" | ||||
|               value="{{ real_name }}" | ||||
|               x-model="department" | ||||
|             /> | ||||
|             <label for="radio{{ real_name }}">{% trans %}{{ display_name }}{% endtrans %}</label> | ||||
| {% endfor %} | ||||
| </div> | ||||
| </div> | ||||
| <div class="radio-credit-type"> | ||||
|   <div class="radio-guide"> | ||||
|     {% for credit_type in ["CS", "TM", "EC", "QC", "OM"] %} | ||||
|       <input | ||||
|         type="checkbox" | ||||
|         name="credit_type" | ||||
|         id="radio{{ credit_type }}" | ||||
|         value="{{ credit_type }}" | ||||
|         x-model="credit_type" | ||||
|       /> | ||||
|       <label for="radio{{ credit_type }}">{% trans %}{{ credit_type }}{% endtrans %}</label> | ||||
|     {% endfor %} | ||||
|   </div> | ||||
| </div> | ||||
|             {% for (display_name, real_name) in departments %} | ||||
|               <input | ||||
|                 type="checkbox" | ||||
|                 name="department" | ||||
|                 id="radio{{ real_name }}" | ||||
|                 value="{{ real_name }}" | ||||
|                 x-model="department" | ||||
|               /> | ||||
|               <label for="radio{{ real_name }}">{% trans %}{{ display_name }}{% endtrans %}</label> | ||||
|             {% endfor %} | ||||
|           </div> | ||||
|         </div> | ||||
|         <div class="radio-credit-type"> | ||||
|           <div class="radio-guide"> | ||||
|             {% for credit_type in ["CS", "TM", "EC", "QC", "OM"] %} | ||||
|               <input | ||||
|                 type="checkbox" | ||||
|                 name="credit_type" | ||||
|                 id="radio{{ credit_type }}" | ||||
|                 value="{{ credit_type }}" | ||||
|                 x-model="credit_type" | ||||
|               /> | ||||
|               <label for="radio{{ credit_type }}">{% trans %}{{ credit_type }}{% endtrans %}</label> | ||||
|             {% endfor %} | ||||
|           </div> | ||||
|         </div> | ||||
|  | ||||
| <div class="radio-semester"> | ||||
|   <div class="radio-guide"> | ||||
|     <input type="checkbox" name="semester" id="radioAUTUMN" value="AUTUMN" x-model="semester"/> | ||||
|     <label for="radioAUTUMN"><i class="fa fa-leaf"></i></label> | ||||
|     <input type="checkbox" name="semester" id="radioSPRING" value="SPRING" x-model="semester"/> | ||||
|     <label for="radioSPRING"><i class="fa fa-sun-o"></i></label> | ||||
|         <div class="radio-semester"> | ||||
|           <div class="radio-guide"> | ||||
|             <input type="checkbox" name="semester" id="radioAUTUMN" value="AUTUMN" x-model="semester"/> | ||||
|             <label for="radioAUTUMN"><i class="fa fa-leaf"></i></label> | ||||
|             <input type="checkbox" name="semester" id="radioSPRING" value="SPRING" x-model="semester"/> | ||||
|             <label for="radioSPRING"><i class="fa fa-sun-o"></i></label> | ||||
|           </div> | ||||
|         </div> | ||||
|       </div> | ||||
|     </form> | ||||
|     <table id="dynamic_view"> | ||||
|       <thead> | ||||
|         <tr> | ||||
|           <td>{% trans %}UV{% endtrans %}</td> | ||||
|           <td>{% trans %}Title{% endtrans %}</td> | ||||
|           <td>{% trans %}Department{% endtrans %}</td> | ||||
|           <td>{% trans %}Credit type{% endtrans %}</td> | ||||
|           <td><i class="fa fa-leaf"></i></td> | ||||
|           <td><i class="fa fa-sun-o"></i></td> | ||||
|           {% if can_create_uv %} | ||||
|             <td>{% trans %}Edit{% endtrans %}</td> | ||||
|             <td>{% trans %}Delete{% endtrans %}</td> | ||||
|           {% endif %} | ||||
|         </tr> | ||||
|       </thead> | ||||
|       <tbody id="dynamic_view_content"> | ||||
|         <template x-for="uv in uvs.results" :key="uv.id"> | ||||
|           <tr @click="window.location.href = `/pedagogy/uv/${uv.id}`" class="clickable"> | ||||
|             <td><a :href="`/pedagogy/uv/${uv.id}`" x-text="uv.code"></a></td> | ||||
|             <td x-text="uv.title"></td> | ||||
|             <td x-text="uv.department"></td> | ||||
|             <td x-text="uv.credit_type"></td> | ||||
|             <td><i :class="uv.semester.includes('AUTUMN') && 'fa fa-leaf'"></i></td> | ||||
|             <td><i :class="uv.semester.includes('SPRING') && 'fa fa-sun-o'"></i></td> | ||||
|             {% if can_create_uv -%} | ||||
|               <td><a :href="`/pedagogy/uv/${uv.id}/edit`">{% trans %}Edit{% endtrans %}</a></td> | ||||
|               <td><a :href="`/pedagogy/uv/${uv.id}/delete`">{% trans %}Delete{% endtrans %}</a></td> | ||||
|             {%- endif -%} | ||||
|           </tr> | ||||
|         </template> | ||||
|       </tbody> | ||||
|     </table> | ||||
|     <nav class="pagination" x-show="max_page() > 1"> | ||||
|       <button @click="page--" :disabled="page <= 1"> | ||||
|         <i class="fa fa-caret-left"></i> | ||||
|       </button> | ||||
|       <template x-for="i in max_page()"> | ||||
|         <button x-text="i" @click="page = i" :class="(page === i) && 'active'"></button> | ||||
|       </template> | ||||
|       <button @click="page++" :disabled="page >= max_page()"> | ||||
|         <i class="fa fa-caret-right"></i> | ||||
|       </button> | ||||
|     </nav> | ||||
|   </div> | ||||
| </div> | ||||
| </div> | ||||
| </form> | ||||
| <table id="dynamic_view"> | ||||
|   <thead> | ||||
|     <tr> | ||||
|       <td>{% trans %}UV{% endtrans %}</td> | ||||
|       <td>{% trans %}Title{% endtrans %}</td> | ||||
|       <td>{% trans %}Department{% endtrans %}</td> | ||||
|       <td>{% trans %}Credit type{% endtrans %}</td> | ||||
|       <td><i class="fa fa-leaf"></i></td> | ||||
|       <td><i class="fa fa-sun-o"></i></td> | ||||
|       {% if can_create_uv %} | ||||
|         <td>{% trans %}Edit{% endtrans %}</td> | ||||
|         <td>{% trans %}Delete{% endtrans %}</td> | ||||
|       {% endif %} | ||||
|     </tr> | ||||
|   </thead> | ||||
|   <tbody id="dynamic_view_content"> | ||||
|     <template x-for="uv in uvs.results" :key="uv.id"> | ||||
|       <tr @click="window.location.href = `/pedagogy/uv/${uv.id}`"> | ||||
|         <td><a :href="`/pedagogy/uv/${uv.id}`" x-text="uv.code"></a></td> | ||||
|         <td x-text="uv.title"></td> | ||||
|         <td x-text="uv.department"></td> | ||||
|         <td x-text="uv.credit_type"></td> | ||||
|         <td><i :class="uv.semester.includes('AUTUMN') && 'fa fa-leaf'"></i></td> | ||||
|         <td><i :class="uv.semester.includes('SPRING') && 'fa fa-sun-o'"></i></td> | ||||
|         {% if can_create_uv -%} | ||||
|           <td><a :href="`/pedagogy/uv/${uv.id}/edit`">{% trans %}Edit{% endtrans %}</a></td> | ||||
|           <td><a :href="`/pedagogy/uv/${uv.id}/delete`">{% trans %}Delete{% endtrans %}</a></td> | ||||
|         {%- endif -%} | ||||
|       </tr> | ||||
|     </template> | ||||
|   </tbody> | ||||
| </table> | ||||
| <nav id="pagination" class="hidden" :style="max_page() == 0 && 'display: none;'"> | ||||
|   <button @click="page--" :disabled="page == 1">{% trans %}Previous{% endtrans %}</button> | ||||
|   <template x-for="i in max_page()"> | ||||
|     <button x-text="i" @click="page = i" :class="i == page && 'active'"></button> | ||||
|   </template> | ||||
|   <button @click="page++" :disabled="page == max_page()">{% trans %}Next{% endtrans %}</button> | ||||
| </nav> | ||||
| </div> | ||||
| <script> | ||||
|   const initialUrlParams = new URLSearchParams(window.location.search); | ||||
|   <script> | ||||
|     const initialUrlParams = new URLSearchParams(window.location.search); | ||||
|  | ||||
|   function update_query_string(key, value) { | ||||
|     const url = new URL(window.location.href); | ||||
|     if (!value) { | ||||
|       url.searchParams.delete(key) | ||||
|     } else if (Array.isArray(value)) { | ||||
|       url.searchParams.delete(key) | ||||
|       value.forEach((v) => url.searchParams.append(key, v)) | ||||
|     } else { | ||||
|       url.searchParams.set(key, value); | ||||
|     function update_query_string(key, value) { | ||||
|       const url = new URL(window.location.href); | ||||
|       if (!value) { | ||||
|             {# If the value is null, undefined or empty => delete it #} | ||||
|         url.searchParams.delete(key) | ||||
|       } else if (Array.isArray(value)) { | ||||
|         url.searchParams.delete(key) | ||||
|         value.forEach((v) => url.searchParams.append(key, v)) | ||||
|       } else { | ||||
|         url.searchParams.set(key, value); | ||||
|       } | ||||
|       history.pushState(null, document.title, url.toString()); | ||||
|     } | ||||
|     history.pushState(null, document.title, url.toString()); | ||||
|   } | ||||
|  | ||||
|     {# | ||||
|     How does this work : | ||||
| @@ -145,50 +155,50 @@ | ||||
|     then fetch the corresponding data from the API. | ||||
|     This data will then be displayed on the result part of the page. | ||||
|     #} | ||||
|   const page_default = 1; | ||||
|   const page_size_default = 100; | ||||
|   document.addEventListener("alpine:init", () => { | ||||
|     Alpine.data("uv_search", () => ({ | ||||
|       uvs: [], | ||||
|       page: initialUrlParams.get("page") || page_default, | ||||
|       page_size: initialUrlParams.get("page_size") || page_size_default, | ||||
|       search: initialUrlParams.get("search") || "", | ||||
|       department: initialUrlParams.getAll("department"), | ||||
|       credit_type: initialUrlParams.getAll("credit_type"), | ||||
|     const page_default = 1; | ||||
|     const page_size_default = 100; | ||||
|     document.addEventListener("alpine:init", () => { | ||||
|       Alpine.data("uv_search", () => ({ | ||||
|         uvs: [], | ||||
|         page: parseInt(initialUrlParams.get("page")) || page_default, | ||||
|         page_size: parseInt(initialUrlParams.get("page_size")) || page_size_default, | ||||
|         search: initialUrlParams.get("search") || "", | ||||
|         department: initialUrlParams.getAll("department"), | ||||
|         credit_type: initialUrlParams.getAll("credit_type"), | ||||
|             {# The semester is easier to use on the backend as an enum (spring/autumn/both/none) | ||||
|             and easier to use on the frontend as an array ([spring, autumn]). | ||||
|             Thus there is some conversion involved when both communicate together #} | ||||
|       semester: initialUrlParams.has("semester") ? | ||||
|       initialUrlParams.get("semester").split("_AND_") : [], | ||||
|         semester: initialUrlParams.has("semester") ? | ||||
|         initialUrlParams.get("semester").split("_AND_") : [], | ||||
|  | ||||
|       async init() { | ||||
|         let search_params = ["search", "department", "credit_type", "semester"]; | ||||
|         let pagination_params = ["semester", "page"]; | ||||
|         search_params.forEach((param) => { | ||||
|           this.$watch(param, async () => { | ||||
|         async init() { | ||||
|           let search_params = ["search", "department", "credit_type", "semester"]; | ||||
|           let pagination_params = ["semester", "page"]; | ||||
|           search_params.forEach((param) => { | ||||
|             this.$watch(param, async () => { | ||||
|                         {# Reset pagination on search #} | ||||
|             this.page = page_default; | ||||
|             this.page_size = page_size_default; | ||||
|               this.page = page_default; | ||||
|               this.page_size = page_size_default; | ||||
|             }); | ||||
|           }); | ||||
|         }); | ||||
|         search_params.concat(pagination_params).forEach((param) => { | ||||
|           this.$watch(param, async (value) => { | ||||
|             update_query_string(param, value); | ||||
|             await this.fetch_data();  {# reload data on form change #} | ||||
|           search_params.concat(pagination_params).forEach((param) => { | ||||
|             this.$watch(param, async (value) => { | ||||
|               update_query_string(param, value); | ||||
|               await this.fetch_data();  {# reload data on form change #} | ||||
|             }); | ||||
|           }); | ||||
|         }); | ||||
|         await this.fetch_data();  {# load initial data #} | ||||
|       }, | ||||
|           await this.fetch_data();  {# load initial data #} | ||||
|         }, | ||||
|  | ||||
|       async fetch_data() { | ||||
|         const url = "{{ url("api:fetch_uvs") }}" + window.location.search; | ||||
|         this.uvs = await (await fetch(url)).json(); | ||||
|       }, | ||||
|         async fetch_data() { | ||||
|           const url = "{{ url("api:fetch_uvs") }}" + window.location.search; | ||||
|           this.uvs = await (await fetch(url)).json(); | ||||
|         }, | ||||
|  | ||||
|       max_page() { | ||||
|         return Math.round(this.uvs.count / this.page_size); | ||||
|       } | ||||
|     })) | ||||
|   }) | ||||
| </script> | ||||
|         max_page() { | ||||
|           return Math.ceil(this.uvs.count / this.page_size); | ||||
|         } | ||||
|       })) | ||||
|     }) | ||||
|   </script> | ||||
| {% endblock content %} | ||||
		Reference in New Issue
	
	Block a user