Compare commits

...

23 Commits

Author SHA1 Message Date
0c61fa29cd chore(deps): lock file maintenance
Some checks failed
continuous-integration/drone/push Build is failing
2024-09-23 15:15:19 +02:00
83cdee759a chore(deps): lock file maintenance 2024-09-23 15:15:19 +02:00
1adb1807b5 admin: Fix add to delegated QA manager 2024-09-23 15:14:05 +02:00
0f9d56fcbf qa: Refactor work attribution 2024-09-23 15:11:42 +02:00
8c6db30c52 ui: Fix display of sentence 2024-09-23 15:11:42 +02:00
Victor Chartraire
3316375cbb fix: Do not remove every delegated_QA on dropDelegatedQA 2024-09-18 18:55:50 +02:00
3d2606ab9c qa: Fix challenge access calculation 2024-09-18 15:18:10 +02:00
2f6c7ecd8b qa: New route to assign all exercices 2024-09-18 12:32:11 +02:00
1f295c3411 qa: Fix display for standalone exercices 2024-09-18 12:31:58 +02:00
0bf367bd3b qa: Handle single theme review 2024-09-18 11:55:13 +02:00
a82e3642a8 qa: Use GetThemesExtended to include standalones exercices 2024-09-18 11:54:52 +02:00
38fa6ec1de qa: Arrange team color 2024-09-18 11:38:41 +02:00
051d62a5fa qa: Add pointer on clickable rows 2024-09-18 11:38:25 +02:00
4c3b07db1e qa: Fix team color 2024-09-18 11:34:01 +02:00
c293b58a94 qa: Handle standalones exercices 2024-09-18 11:33:45 +02:00
a630075116 qa: Don't fail if no scenario + don't show menu item 2024-09-18 11:16:44 +02:00
7ae1517a59 qa: repositories page moved to admin 2024-09-18 11:14:25 +02:00
5a4960f9ad ui: Redraw the whole exercices when tag changes 2024-09-18 11:00:03 +02:00
0669f74395 ui: Make others menu items active when on respective page 2024-09-18 10:56:25 +02:00
5981240280 ui: Make menu tags active on tags pages 2024-09-18 10:47:59 +02:00
180ec5e29d Don't display Scenarii menu if no scenario 2024-09-18 10:47:34 +02:00
3d1b318091 dashboard: Handle standalone exercices 2024-09-18 09:08:56 +02:00
c8f70c48fa qa: Make gitlabBaseURL configurable through env 2024-09-18 08:39:41 +02:00
28 changed files with 3215 additions and 2957 deletions

View File

@ -564,6 +564,18 @@ angular.module("FICApp")
})
.controller("AllTeamAssociationsController", function ($scope, $http) {
$scope.newdqa = "";
$scope.addDelegatedQA = function () {
if ($scope.newdqa.length) {
if (!$scope.config.delegated_qa)
$scope.config.delegated_qa = [];
$scope.config.delegated_qa.push($scope.newdqa);
$scope.saveSettings();
$scope.newdqa = "";
}
}
$scope.allAssociations = [];
$http.get("api/teams-associations.json").then(function (response) {
$scope.allAssociations = response.data;
@ -625,28 +637,16 @@ angular.module("FICApp")
$scope.config.disablesubmitbutton = "";
};
$scope.newdqa = "";
$scope.addDelegatedQA = function() {
if ($scope.newdqa.length) {
if (!$scope.config.delegated_qa)
$scope.config.delegated_qa = [];
$scope.config.delegated_qa.push($scope.newdqa);
$scope.saveSettings();
$scope.newdqa = "";
}
}
$scope.dropDelegatedQA = function (member) {
if ($scope.config.delegated_qa) {
if (!$scope.config.delegated_qa) {
$scope.config.delegated_qa = [];
}
angular.forEach($scope.config.delegated_qa, function (m, k) {
if (member == m)
$scope.config.delegated_qa.splice(k, 1);
});
$scope.saveSettings();
}
}
$scope.saveChallengeInfo = function () {
this.challenge.duration = $scope.duration;
@ -2800,9 +2800,11 @@ function presenceCal(scope, location, data) {
.attr("width", cellSize)
.attr("height", cellSize)
.attr("transform", function (d) { return "translate(" + (d.getHours() * cellSize) + "," + (d.getMinutes() / 15 * cellSize) + ")"; })
.attr("class", function(d) { if (d >= scope.settings.start && d < scope.settings.start + scope.settings.end - scope.settings.start) return color(data.reduce(function(prev, cur){
.attr("class", function (d) {
if (d >= scope.settings.start && d < scope.settings.start + scope.settings.end - scope.settings.start) return color(data.reduce(function (prev, cur) {
cur = new Date(cur).getTime();
dv = d.getTime();
return prev + ((dv <= cur && cur < dv + 15 * 60000) ? 1 : 0);
}, 0)); });
}, 0));
});
}

View File

@ -306,7 +306,7 @@
</div>
</form>
<form ng-submit="addDelegatedQA()" class="card my-3">
<div class="card my-3">
<div class="card-header">
<h3>Managers QA</h3>
</div>
@ -318,10 +318,12 @@
<span class="glyphicon glyphicon-remove" aria-hidden="true"></span>
</button>
</li>
<li class="row">
<div class="col" ng-controller="AllTeamAssociationsController">
</ul>
<form class="row" ng-controller="AllTeamAssociationsController" ng-submit="addDelegatedQA()">
<div class="col">
<select class="form-control form-control-sm" ng-model="newdqa">
<option ng-repeat="(i,m) in allAssociations" ng-value="m">{{ m }}</option>
<option ng-selected="newdqa == m" ng-repeat="(i,m) in allAssociations" ng-value="m">{{ m }}</option>
</select>
</div>
<div class="col input-group">
@ -330,10 +332,9 @@
<button class="btn btn-sm btn-success" ng-disabled="!newdqa.length"><span class="glyphicon glyphicon-plus" aria-hidden="true"></span></button>
</span>
</div>
</li>
</ul>
</div>
</form>
</div>
</div>
<form ng-submit="saveChallengeInfo()" class="card my-3">
<div class="card-header">

View File

@ -365,7 +365,7 @@
<div class="carousel slide" data-interval="12000" style="padding-bottom: 0px" autocarousel>
<div class="carousel-inner">
<div class="carousel-item" ng-repeat="theme in themes" ng-class="{active: $first}">
<div class="carousel-caption text-indent">
<div class="carousel-caption text-indent" ng-if="theme.urlid !== '_'">
<div class="card-img-top theme-card" style="background-image: url('{{ theme.image.substr(0, theme.image.length-3) }}thumb.jpg')"></div>
<h3 class="text-left" ng-bind="theme.name"></h3>
<p class="text-justify" style="font-size: 111%" ng-bind-html="theme.headline"></p>
@ -377,7 +377,8 @@
</div>
<div class="card niceborder bg-dark" ng-if="s.type == 'exercice' && !s.params.hide">
<div class="card-img-top theme-card" style="background-image: url('{{themes[my.exercices[s.params.exercice].theme_id].image}}')"></div>
<div class="card-img-top theme-card" style="background-image: url('{{exercices[s.params.exercice].image}}')" ng-if="exercices[s.params.exercice] && exercices[s.params.exercice].image"></div>
<div class="card-img-top theme-card" style="background-image: url('{{themes[my.exercices[s.params.exercice].theme_id].image}}')" ng-if="!exercices[s.params.exercice] || !exercices[s.params.exercice].image"></div>
<div class="card-body text-light">
<h3 style="font-size: 1.0rem; text-weight: bold; overflow: hidden; text-overflow: ellipsis; white-space: nowrap">Défi <em>{{ exercices[s.params.exercice].title }}</em> du thème <em>{{ themes[my.exercices[s.params.exercice].theme_id].name }}</em></h3>
<p ng-bind-html="my.exercices[s.params.exercice].overview"></p>
@ -397,7 +398,8 @@
Challenges à la une
</span>
</div>
<div class="card-img-top theme-card" style="background-image: url('{{themes[my.exercices[lastExercice].theme_id].image}}')"></div>
<div class="card-img-top theme-card" style="background-image: url('{{exercices[lastExercice].image}}')" ng-if="exercices[lastExercice] && exercices[lastExercice].image"></div>
<div class="card-img-top theme-card" style="background-image: url('{{themes[my.exercices[lastExercice].theme_id].image}}')" ng-if="!exercices[s.params.exercice] || !exercices[s.params.exercice].image"></div>
<div class="card-body text-light">
<h3 style="font-size: 1.0rem; text-weight: bold; overflow: hidden; text-overflow: ellipsis; white-space: nowrap"><em>{{ exercices[lastExercice].title }}</em> du thème <em>{{ themes[my.exercices[lastExercice].theme_id].name }}</em></h3>
<p ng-bind-html="my.exercices[lastExercice].overview"></p>

View File

@ -468,9 +468,9 @@
}
},
"node_modules/@eslint-community/regexpp": {
"version": "4.11.0",
"resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.11.0.tgz",
"integrity": "sha512-G/M/tIiMrTAxEWRfLfQJMmGNX28IxBg4PBz8XqQhqUHLFI6TL2htpIB1iQCj144V5ee/JaKyT9/WZ0MGZWfA7A==",
"version": "4.11.1",
"resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.11.1.tgz",
"integrity": "sha512-m4DVN9ZqskZoLU5GlWZadwDnYo3vAEydiUayB9widCl9ffWx2IvPnp6n3on5rJmziJSw9Bv+Z3ChDVdMwXCY8Q==",
"dev": true,
"license": "MIT",
"engines": {
@ -681,9 +681,9 @@
}
},
"node_modules/@rollup/rollup-android-arm-eabi": {
"version": "4.21.2",
"resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.21.2.tgz",
"integrity": "sha512-fSuPrt0ZO8uXeS+xP3b+yYTCBUd05MoSp2N/MFOgjhhUhMmchXlpTQrTpI8T+YAwAQuK7MafsCOxW7VrPMrJcg==",
"version": "4.21.3",
"resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.21.3.tgz",
"integrity": "sha512-MmKSfaB9GX+zXl6E8z4koOr/xU63AMVleLEa64v7R0QF/ZloMs5vcD1sHgM64GXXS1csaJutG+ddtzcueI/BLg==",
"cpu": [
"arm"
],
@ -695,9 +695,9 @@
]
},
"node_modules/@rollup/rollup-android-arm64": {
"version": "4.21.2",
"resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.21.2.tgz",
"integrity": "sha512-xGU5ZQmPlsjQS6tzTTGwMsnKUtu0WVbl0hYpTPauvbRAnmIvpInhJtgjj3mcuJpEiuUw4v1s4BimkdfDWlh7gA==",
"version": "4.21.3",
"resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.21.3.tgz",
"integrity": "sha512-zrt8ecH07PE3sB4jPOggweBjJMzI1JG5xI2DIsUbkA+7K+Gkjys6eV7i9pOenNSDJH3eOr/jLb/PzqtmdwDq5g==",
"cpu": [
"arm64"
],
@ -709,9 +709,9 @@
]
},
"node_modules/@rollup/rollup-darwin-arm64": {
"version": "4.21.2",
"resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.21.2.tgz",
"integrity": "sha512-99AhQ3/ZMxU7jw34Sq8brzXqWH/bMnf7ZVhvLk9QU2cOepbQSVTns6qoErJmSiAvU3InRqC2RRZ5ovh1KN0d0Q==",
"version": "4.21.3",
"resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.21.3.tgz",
"integrity": "sha512-P0UxIOrKNBFTQaXTxOH4RxuEBVCgEA5UTNV6Yz7z9QHnUJ7eLX9reOd/NYMO3+XZO2cco19mXTxDMXxit4R/eQ==",
"cpu": [
"arm64"
],
@ -723,9 +723,9 @@
]
},
"node_modules/@rollup/rollup-darwin-x64": {
"version": "4.21.2",
"resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.21.2.tgz",
"integrity": "sha512-ZbRaUvw2iN/y37x6dY50D8m2BnDbBjlnMPotDi/qITMJ4sIxNY33HArjikDyakhSv0+ybdUxhWxE6kTI4oX26w==",
"version": "4.21.3",
"resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.21.3.tgz",
"integrity": "sha512-L1M0vKGO5ASKntqtsFEjTq/fD91vAqnzeaF6sfNAy55aD+Hi2pBI5DKwCO+UNDQHWsDViJLqshxOahXyLSh3EA==",
"cpu": [
"x64"
],
@ -737,9 +737,9 @@
]
},
"node_modules/@rollup/rollup-linux-arm-gnueabihf": {
"version": "4.21.2",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.21.2.tgz",
"integrity": "sha512-ztRJJMiE8nnU1YFcdbd9BcH6bGWG1z+jP+IPW2oDUAPxPjo9dverIOyXz76m6IPA6udEL12reYeLojzW2cYL7w==",
"version": "4.21.3",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.21.3.tgz",
"integrity": "sha512-btVgIsCjuYFKUjopPoWiDqmoUXQDiW2A4C3Mtmp5vACm7/GnyuprqIDPNczeyR5W8rTXEbkmrJux7cJmD99D2g==",
"cpu": [
"arm"
],
@ -751,9 +751,9 @@
]
},
"node_modules/@rollup/rollup-linux-arm-musleabihf": {
"version": "4.21.2",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.21.2.tgz",
"integrity": "sha512-flOcGHDZajGKYpLV0JNc0VFH361M7rnV1ee+NTeC/BQQ1/0pllYcFmxpagltANYt8FYf9+kL6RSk80Ziwyhr7w==",
"version": "4.21.3",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.21.3.tgz",
"integrity": "sha512-zmjbSphplZlau6ZTkxd3+NMtE4UKVy7U4aVFMmHcgO5CUbw17ZP6QCgyxhzGaU/wFFdTfiojjbLG3/0p9HhAqA==",
"cpu": [
"arm"
],
@ -765,9 +765,9 @@
]
},
"node_modules/@rollup/rollup-linux-arm64-gnu": {
"version": "4.21.2",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.21.2.tgz",
"integrity": "sha512-69CF19Kp3TdMopyteO/LJbWufOzqqXzkrv4L2sP8kfMaAQ6iwky7NoXTp7bD6/irKgknDKM0P9E/1l5XxVQAhw==",
"version": "4.21.3",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.21.3.tgz",
"integrity": "sha512-nSZfcZtAnQPRZmUkUQwZq2OjQciR6tEoJaZVFvLHsj0MF6QhNMg0fQ6mUOsiCUpTqxTx0/O6gX0V/nYc7LrgPw==",
"cpu": [
"arm64"
],
@ -779,9 +779,9 @@
]
},
"node_modules/@rollup/rollup-linux-arm64-musl": {
"version": "4.21.2",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.21.2.tgz",
"integrity": "sha512-48pD/fJkTiHAZTnZwR0VzHrao70/4MlzJrq0ZsILjLW/Ab/1XlVUStYyGt7tdyIiVSlGZbnliqmult/QGA2O2w==",
"version": "4.21.3",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.21.3.tgz",
"integrity": "sha512-MnvSPGO8KJXIMGlQDYfvYS3IosFN2rKsvxRpPO2l2cum+Z3exiExLwVU+GExL96pn8IP+GdH8Tz70EpBhO0sIQ==",
"cpu": [
"arm64"
],
@ -793,9 +793,9 @@
]
},
"node_modules/@rollup/rollup-linux-powerpc64le-gnu": {
"version": "4.21.2",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.21.2.tgz",
"integrity": "sha512-cZdyuInj0ofc7mAQpKcPR2a2iu4YM4FQfuUzCVA2u4HI95lCwzjoPtdWjdpDKyHxI0UO82bLDoOaLfpZ/wviyQ==",
"version": "4.21.3",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.21.3.tgz",
"integrity": "sha512-+W+p/9QNDr2vE2AXU0qIy0qQE75E8RTwTwgqS2G5CRQ11vzq0tbnfBd6brWhS9bCRjAjepJe2fvvkvS3dno+iw==",
"cpu": [
"ppc64"
],
@ -807,9 +807,9 @@
]
},
"node_modules/@rollup/rollup-linux-riscv64-gnu": {
"version": "4.21.2",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.21.2.tgz",
"integrity": "sha512-RL56JMT6NwQ0lXIQmMIWr1SW28z4E4pOhRRNqwWZeXpRlykRIlEpSWdsgNWJbYBEWD84eocjSGDu/XxbYeCmwg==",
"version": "4.21.3",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.21.3.tgz",
"integrity": "sha512-yXH6K6KfqGXaxHrtr+Uoy+JpNlUlI46BKVyonGiaD74ravdnF9BUNC+vV+SIuB96hUMGShhKV693rF9QDfO6nQ==",
"cpu": [
"riscv64"
],
@ -821,9 +821,9 @@
]
},
"node_modules/@rollup/rollup-linux-s390x-gnu": {
"version": "4.21.2",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.21.2.tgz",
"integrity": "sha512-PMxkrWS9z38bCr3rWvDFVGD6sFeZJw4iQlhrup7ReGmfn7Oukrr/zweLhYX6v2/8J6Cep9IEA/SmjXjCmSbrMQ==",
"version": "4.21.3",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.21.3.tgz",
"integrity": "sha512-R8cwY9wcnApN/KDYWTH4gV/ypvy9yZUHlbJvfaiXSB48JO3KpwSpjOGqO4jnGkLDSk1hgjYkTbTt6Q7uvPf8eg==",
"cpu": [
"s390x"
],
@ -835,9 +835,9 @@
]
},
"node_modules/@rollup/rollup-linux-x64-gnu": {
"version": "4.21.2",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.21.2.tgz",
"integrity": "sha512-B90tYAUoLhU22olrafY3JQCFLnT3NglazdwkHyxNDYF/zAxJt5fJUB/yBoWFoIQ7SQj+KLe3iL4BhOMa9fzgpw==",
"version": "4.21.3",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.21.3.tgz",
"integrity": "sha512-kZPbX/NOPh0vhS5sI+dR8L1bU2cSO9FgxwM8r7wHzGydzfSjLRCFAT87GR5U9scj2rhzN3JPYVC7NoBbl4FZ0g==",
"cpu": [
"x64"
],
@ -849,9 +849,9 @@
]
},
"node_modules/@rollup/rollup-linux-x64-musl": {
"version": "4.21.2",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.21.2.tgz",
"integrity": "sha512-7twFizNXudESmC9oneLGIUmoHiiLppz/Xs5uJQ4ShvE6234K0VB1/aJYU3f/4g7PhssLGKBVCC37uRkkOi8wjg==",
"version": "4.21.3",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.21.3.tgz",
"integrity": "sha512-S0Yq+xA1VEH66uiMNhijsWAafffydd2X5b77eLHfRmfLsRSpbiAWiRHV6DEpz6aOToPsgid7TI9rGd6zB1rhbg==",
"cpu": [
"x64"
],
@ -863,9 +863,9 @@
]
},
"node_modules/@rollup/rollup-win32-arm64-msvc": {
"version": "4.21.2",
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.21.2.tgz",
"integrity": "sha512-9rRero0E7qTeYf6+rFh3AErTNU1VCQg2mn7CQcI44vNUWM9Ze7MSRS/9RFuSsox+vstRt97+x3sOhEey024FRQ==",
"version": "4.21.3",
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.21.3.tgz",
"integrity": "sha512-9isNzeL34yquCPyerog+IMCNxKR8XYmGd0tHSV+OVx0TmE0aJOo9uw4fZfUuk2qxobP5sug6vNdZR6u7Mw7Q+Q==",
"cpu": [
"arm64"
],
@ -877,9 +877,9 @@
]
},
"node_modules/@rollup/rollup-win32-ia32-msvc": {
"version": "4.21.2",
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.21.2.tgz",
"integrity": "sha512-5rA4vjlqgrpbFVVHX3qkrCo/fZTj1q0Xxpg+Z7yIo3J2AilW7t2+n6Q8Jrx+4MrYpAnjttTYF8rr7bP46BPzRw==",
"version": "4.21.3",
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.21.3.tgz",
"integrity": "sha512-nMIdKnfZfzn1Vsk+RuOvl43ONTZXoAPUUxgcU0tXooqg4YrAqzfKzVenqqk2g5efWh46/D28cKFrOzDSW28gTA==",
"cpu": [
"ia32"
],
@ -891,9 +891,9 @@
]
},
"node_modules/@rollup/rollup-win32-x64-msvc": {
"version": "4.21.2",
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.21.2.tgz",
"integrity": "sha512-6UUxd0+SKomjdzuAcp+HAmxw1FlGBnl1v2yEPSabtx4lBfdXHDVsW7+lQkgz9cNFJGY3AWR7+V8P5BqkD9L9nA==",
"version": "4.21.3",
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.21.3.tgz",
"integrity": "sha512-fOvu7PCQjAj4eWDEuD8Xz5gpzFqXzGlxHZozHP4b9Jxv9APtdxL6STqztDzMLuRXEc4UpXGGhx029Xgm91QBeA==",
"cpu": [
"x64"
],
@ -915,9 +915,9 @@
}
},
"node_modules/@sveltejs/kit": {
"version": "2.5.26",
"resolved": "https://registry.npmjs.org/@sveltejs/kit/-/kit-2.5.26.tgz",
"integrity": "sha512-8l1JTIM2L+bS8ebq1E+nGjv/YSKSnD9Q19bYIUkc41vaEG2JjVUx6ikvPIJv2hkQAuqJLzoPrXlKk4KcyWOv3Q==",
"version": "2.5.27",
"resolved": "https://registry.npmjs.org/@sveltejs/kit/-/kit-2.5.27.tgz",
"integrity": "sha512-CcbRTzl+65oWljAASL6UlxM4x3NWwd0fjq5fQOfP243vs50myFQ8lil0fr3Im6HeeQqYUCtnv8HjO8REWVPjTw==",
"dev": true,
"hasInstallScript": true,
"license": "MIT",
@ -1101,12 +1101,12 @@
"license": "Python-2.0"
},
"node_modules/aria-query": {
"version": "5.3.0",
"resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.3.0.tgz",
"integrity": "sha512-b0P0sZPKtyu8HkeRAfCq0IfURZK+SuwMjY1UXGBU27wpAiTwQAIlq56IbIO+ytk/JjS1fMR14ee5WBBfKi5J6A==",
"version": "5.3.1",
"resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.3.1.tgz",
"integrity": "sha512-Z/ZeOgVl7bcSYZ/u/rh0fOpvEpq//LZmdbkXyc7syVzjPAhfOa9ebsdTSjEBDU4vs5nC98Kfduj1uFo0qyET3g==",
"license": "Apache-2.0",
"dependencies": {
"dequal": "^2.0.3"
"engines": {
"node": ">= 0.4"
}
},
"node_modules/axobject-query": {
@ -1394,15 +1394,6 @@
"node": ">=0.10.0"
}
},
"node_modules/dequal": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz",
"integrity": "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==",
"license": "MIT",
"engines": {
"node": ">=6"
}
},
"node_modules/devalue": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/devalue/-/devalue-5.0.0.tgz",
@ -1552,9 +1543,9 @@
}
},
"node_modules/eslint-plugin-svelte": {
"version": "2.43.0",
"resolved": "https://registry.npmjs.org/eslint-plugin-svelte/-/eslint-plugin-svelte-2.43.0.tgz",
"integrity": "sha512-REkxQWvg2pp7QVLxQNa+dJ97xUqRe7Y2JJbSWkHSuszu0VcblZtXkPBPckkivk99y5CdLw4slqfPylL2d/X4jQ==",
"version": "2.44.0",
"resolved": "https://registry.npmjs.org/eslint-plugin-svelte/-/eslint-plugin-svelte-2.44.0.tgz",
"integrity": "sha512-wav4MOs02vBb1WjvTCYItwJCxMkuk2Z4p+K/eyjL0N/z7ahXLP+0LtQQjiKc2ezuif7GnZLbD1F3o1VHzSvdVg==",
"dev": true,
"license": "MIT",
"dependencies": {
@ -1568,7 +1559,7 @@
"postcss-safe-parser": "^6.0.0",
"postcss-selector-parser": "^6.1.0",
"semver": "^7.6.2",
"svelte-eslint-parser": "^0.41.0"
"svelte-eslint-parser": "^0.41.1"
},
"engines": {
"node": "^14.17.0 || >=16.0.0"
@ -2316,9 +2307,9 @@
}
},
"node_modules/postcss": {
"version": "8.4.45",
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.45.tgz",
"integrity": "sha512-7KTLTdzdZZYscUc65XmjFiB73vBhBfbPztCYdUNvlaso9PrzjzcmjqBPR0lNGkcVlcO4BjiO5rK/qNz+XAen1Q==",
"version": "8.4.47",
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.47.tgz",
"integrity": "sha512-56rxCq7G/XfB4EkXq9Egn5GCqugWvDFjafDOThIdMBsI15iqPqR5r15TfSr1YPYeEI19YeaXMCbY6u88Y76GLQ==",
"dev": true,
"funding": [
{
@ -2337,8 +2328,8 @@
"license": "MIT",
"dependencies": {
"nanoid": "^3.3.7",
"picocolors": "^1.0.1",
"source-map-js": "^1.2.0"
"picocolors": "^1.1.0",
"source-map-js": "^1.2.1"
},
"engines": {
"node": "^10 || ^12 || >=14"
@ -2535,9 +2526,9 @@
}
},
"node_modules/rollup": {
"version": "4.21.2",
"resolved": "https://registry.npmjs.org/rollup/-/rollup-4.21.2.tgz",
"integrity": "sha512-e3TapAgYf9xjdLvKQCkQTnbTKd4a6jwlpQSJJFokHGaX2IVjoEqkIIhiQfqsi0cdwlOD+tQGuOd5AJkc5RngBw==",
"version": "4.21.3",
"resolved": "https://registry.npmjs.org/rollup/-/rollup-4.21.3.tgz",
"integrity": "sha512-7sqRtBNnEbcBtMeRVc6VRsJMmpI+JU1z9VTvW8D4gXIYQFz0aLcsE6rRkyghZkLfEgUZgVvOG7A5CVz/VW5GIA==",
"dev": true,
"license": "MIT",
"dependencies": {
@ -2551,22 +2542,22 @@
"npm": ">=8.0.0"
},
"optionalDependencies": {
"@rollup/rollup-android-arm-eabi": "4.21.2",
"@rollup/rollup-android-arm64": "4.21.2",
"@rollup/rollup-darwin-arm64": "4.21.2",
"@rollup/rollup-darwin-x64": "4.21.2",
"@rollup/rollup-linux-arm-gnueabihf": "4.21.2",
"@rollup/rollup-linux-arm-musleabihf": "4.21.2",
"@rollup/rollup-linux-arm64-gnu": "4.21.2",
"@rollup/rollup-linux-arm64-musl": "4.21.2",
"@rollup/rollup-linux-powerpc64le-gnu": "4.21.2",
"@rollup/rollup-linux-riscv64-gnu": "4.21.2",
"@rollup/rollup-linux-s390x-gnu": "4.21.2",
"@rollup/rollup-linux-x64-gnu": "4.21.2",
"@rollup/rollup-linux-x64-musl": "4.21.2",
"@rollup/rollup-win32-arm64-msvc": "4.21.2",
"@rollup/rollup-win32-ia32-msvc": "4.21.2",
"@rollup/rollup-win32-x64-msvc": "4.21.2",
"@rollup/rollup-android-arm-eabi": "4.21.3",
"@rollup/rollup-android-arm64": "4.21.3",
"@rollup/rollup-darwin-arm64": "4.21.3",
"@rollup/rollup-darwin-x64": "4.21.3",
"@rollup/rollup-linux-arm-gnueabihf": "4.21.3",
"@rollup/rollup-linux-arm-musleabihf": "4.21.3",
"@rollup/rollup-linux-arm64-gnu": "4.21.3",
"@rollup/rollup-linux-arm64-musl": "4.21.3",
"@rollup/rollup-linux-powerpc64le-gnu": "4.21.3",
"@rollup/rollup-linux-riscv64-gnu": "4.21.3",
"@rollup/rollup-linux-s390x-gnu": "4.21.3",
"@rollup/rollup-linux-x64-gnu": "4.21.3",
"@rollup/rollup-linux-x64-musl": "4.21.3",
"@rollup/rollup-win32-arm64-msvc": "4.21.3",
"@rollup/rollup-win32-ia32-msvc": "4.21.3",
"@rollup/rollup-win32-x64-msvc": "4.21.3",
"fsevents": "~2.3.2"
}
},
@ -2813,9 +2804,9 @@
}
},
"node_modules/svelte-eslint-parser": {
"version": "0.41.0",
"resolved": "https://registry.npmjs.org/svelte-eslint-parser/-/svelte-eslint-parser-0.41.0.tgz",
"integrity": "sha512-L6f4hOL+AbgfBIB52Z310pg1d2QjRqm7wy3kI1W6hhdhX5bvu7+f0R6w4ykp5HoDdzq+vGhIJmsisaiJDGmVfA==",
"version": "0.41.1",
"resolved": "https://registry.npmjs.org/svelte-eslint-parser/-/svelte-eslint-parser-0.41.1.tgz",
"integrity": "sha512-08ndI6zTghzI8SuJAFpvMbA/haPSGn3xz19pjre19yYMw8Nw/wQJ2PrZBI/L8ijGTgtkWCQQiLLy+Z1tfaCwNA==",
"dev": true,
"license": "MIT",
"dependencies": {
@ -2973,9 +2964,9 @@
"license": "MIT"
},
"node_modules/vite": {
"version": "5.4.3",
"resolved": "https://registry.npmjs.org/vite/-/vite-5.4.3.tgz",
"integrity": "sha512-IH+nl64eq9lJjFqU+/yrRnrHPVTlgy42/+IzbOdaFDVlyLgI/wDlf+FCobXLX1cT0X5+7LMyH1mIy2xJdLfo8Q==",
"version": "5.4.5",
"resolved": "https://registry.npmjs.org/vite/-/vite-5.4.5.tgz",
"integrity": "sha512-pXqR0qtb2bTwLkev4SE3r4abCNioP3GkjvIDLlzziPpXtHgiJIjuKl+1GN6ESOT3wMjG3JTeARopj2SwYaHTOA==",
"dev": true,
"license": "MIT",
"dependencies": {

View File

@ -1,5 +1,6 @@
<script>
import { base } from '$app/paths';
import { page } from '$app/stores';
import {
Badge,
@ -62,7 +63,7 @@
<NavbarToggler on:click={() => (isOpen = !isOpen)} />
<Collapse {isOpen} navbar expand="md" on:update={handleUpdate}>
<Nav navbar>
<NavItem>
<NavItem active={$page.route && $page.route.id === "/"}>
<NavLink href=".">
<Icon name="house" />
Accueil
@ -71,7 +72,7 @@
<NavThemes />
<NavTags />
{#if $settings && $settings.end - $settings.start > 0 && $teams && Object.keys($teams).length}
<NavItem>
<NavItem active={$page.route && $page.route.id === "/rank"}>
<NavLink href="rank">
<Icon name="sort-down" />
Classement
@ -79,7 +80,7 @@
</NavItem>
{/if}
<HeaderIssues />
<NavItem>
<NavItem active={$page.route && $page.route.id === "/rules"}>
<NavLink href="rules">
<Icon name="signpost-split" />
Aide

View File

@ -1,4 +1,6 @@
<script>
import { page } from '$app/stores';
import {
Badge,
Icon,
@ -24,7 +26,7 @@
</script>
{#if $issues.length}
<NavItem>
<NavItem active={$page.route && $page.route.id === "/issues"}>
<NavLink href="issues">
<Icon name="bug" />
Problèmes

View File

@ -1,4 +1,6 @@
<script>
import { page } from '$app/stores';
import {
Badge,
Dropdown,
@ -14,7 +16,7 @@
let filter = "";
</script>
<Dropdown nav inNavbar>
<Dropdown nav inNavbar active={$page.params.tag}>
<DropdownToggle nav caret>
<Icon name="tags" />
Tags

View File

@ -14,6 +14,7 @@
import { myThemes, themes } from '$lib/stores/mythemes.js';
</script>
{#if $themes.length > 0 && ($themes[0].id != 0 || $themes.length > 1)}
<Dropdown nav inNavbar active={$current_theme && $current_theme.id != 0}>
<DropdownToggle nav caret>
<Icon name="tv" />
@ -54,6 +55,7 @@
</div>
</DropdownMenu>
</Dropdown>
{/if}
{#if $themesStore && $themesStore["0"] && $themesStore["0"].exercices}
<Dropdown nav inNavbar active={$current_theme && $current_theme && $current_theme.id == 0}>
<DropdownToggle nav caret>

View File

@ -73,7 +73,9 @@
</Column>
</Table>
{:else}
<CardBody>
Vous n'avez fait aucune action vous faisant gagner ou perdre des points.
</CardBody>
{/if}
<button class="btn btn-primary" on:click={refresh_scores}>
<Icon name="arrow-clockwise" />

View File

@ -45,6 +45,7 @@
{#if exercices.length}
<Row cols="3">
{#key exercices}
{#each exercices as {theme, exercice, index} (index)}
<Col class="mb-3">
<CardTheme
@ -54,6 +55,7 @@
/>
</Col>
{/each}
{/key}
</Row>
{:else}
<p class="lead">

View File

@ -56,6 +56,26 @@ func GetThemes() ([]*Theme, error) {
}
}
// GetThemesExtended returns a list of Themes including standalone exercices.
func GetThemesExtended() ([]*Theme, error) {
if themes, err := GetThemes(); err != nil {
return nil, err
} else {
// Append standalone exercices fake-themes
stdthm := &Theme{
Name: "Défis indépendants",
URLId: "_",
Path: "exercices",
}
if exercices, err := stdthm.GetExercices(); err == nil && len(exercices) > 0 {
themes = append(themes, stdthm)
}
return themes, nil
}
}
// GetTheme retrieves a Theme from its identifier.
func GetTheme(id int64) (*Theme, error) {
t := &Theme{}

View File

@ -38,6 +38,10 @@ func init() {
oidcRedirectURL = v
}
if v, ok := os.LookupEnv("FIC_GITLAB_BASEURL"); ok {
gitlabBaseURL = v
}
flag.StringVar(&oidcRedirectURL, "oidc-redirect", oidcRedirectURL, "Base URL for the redirect after connection")
flag.StringVar(&gitlabBaseURL, "gitlab-baseurl", gitlabBaseURL, "Base URL of the Gitlab instance")
flag.StringVar(&gitlabClientID, "gitlab-clientid", os.Getenv("FIC_GITLAB_CLIENT_ID"), "ClientID for GitLab's OIDC")

View File

@ -118,7 +118,7 @@ func getExerciceQA(c *gin.Context) {
func exportQA(c *gin.Context) {
var report string
themes, err := fic.GetThemes()
themes, err := fic.GetThemesExtended()
if err != nil {
log.Println("Unable to GetThemes: ", err.Error())
c.AbortWithStatusJSON(http.StatusInternalServerError, gin.H{"errmsg": fmt.Sprintf("Unable to list themes: %s", err.Error())})
@ -191,7 +191,7 @@ type ExportReport struct {
func exportQAJSON(c *gin.Context) {
report := map[string]ExportTheme{}
themes, err := fic.GetThemes()
themes, err := fic.GetThemesExtended()
if err != nil {
log.Println("Unable to GetThemes: ", err.Error())
c.AbortWithStatusJSON(http.StatusInternalServerError, gin.H{"errmsg": fmt.Sprintf("Unable to list themes: %s", err.Error())})

View File

@ -1,8 +1,11 @@
package api
import (
"fmt"
"log"
"net/http"
"strconv"
"strings"
"srs.epita.fr/fic-server/libfic"
@ -17,6 +20,7 @@ func declareTodoRoutes(router *gin.RouterGroup) {
}
func declareTodoManagerRoutes(router *gin.RouterGroup) {
router.POST("/qa_assign_work", assignWork)
router.POST("/qa_my_exercices.json", addQAView)
router.POST("/qa_work.json", createQATodo)
@ -235,3 +239,80 @@ func deleteQATodo(c *gin.Context) {
c.Status(http.StatusOK)
}
}
type QAAssignWork struct {
Turns int `json:"turns"`
Start int `json:"start"`
TeamPrefix string `json:"team_prefix"`
TeamAssistants string `json:"team_assistants"`
}
func assignWork(c *gin.Context) {
var uaw QAAssignWork
if err := c.ShouldBindJSON(&uaw); err != nil {
c.AbortWithStatusJSON(http.StatusBadRequest, gin.H{"errmsg": err.Error()})
return
}
if uaw.Turns == 0 {
uaw.Turns = 1
}
if uaw.TeamPrefix == "" {
uaw.TeamPrefix = "FIC Groupe "
}
if uaw.TeamAssistants == "" {
uaw.TeamAssistants = "assistants"
}
teams, err := fic.GetTeams()
if err != nil {
log.Println("Unable to GetTeams: ", err.Error())
c.AbortWithStatusJSON(http.StatusInternalServerError, gin.H{"errmsg": fmt.Sprintf("Unable to list teams: %s", err.Error())})
return
}
// Remove assistant team
for tid := len(teams) - 1; tid >= 0; tid-- {
team := teams[tid]
if strings.Contains(strings.ToLower(team.Name), uaw.TeamAssistants) {
teams = append(teams[:tid], teams[tid+1:]...)
}
}
exercices, err := fic.GetExercices()
if err != nil {
log.Println("Unable to GetExercices: ", err.Error())
c.AbortWithStatusJSON(http.StatusInternalServerError, gin.H{"errmsg": fmt.Sprintf("Unable to list exercices: %s", err.Error())})
return
}
// Struct to store reported team (due to owned exercice)
var teamIdStack []int64
for i := 0; i < uaw.Turns; i++ {
for eid, ex := range exercices {
team := teams[(uaw.Start+eid+uaw.Turns*i)%len(teams)]
if len(teamIdStack) > 0 {
teamIdStack = append(teamIdStack, team.Id)
team, _ = fic.GetTeam(teamIdStack[0])
teamIdStack = append([]int64{}, teamIdStack[1:]...)
}
j := 0
// Find a team not responsible for this exercice
for (strings.Contains(ex.Path, "grp") && strings.Contains(ex.Path, "-grp"+strings.TrimPrefix(team.Name, uaw.TeamPrefix)+"-")) || (!strings.Contains(ex.Path, "grp") && strings.HasPrefix(ex.Path, strings.TrimPrefix(team.Name, uaw.TeamPrefix)+"-")) {
j += 1
teamIdStack = append(teamIdStack, team.Id)
team = teams[(uaw.Start+eid+uaw.Turns*i+j)%len(teams)]
}
_, err := team.NewQATodo(ex.Id)
if err != nil {
c.AbortWithStatusJSON(http.StatusBadRequest, gin.H{"errmsg": err.Error()})
return
}
}
}
c.JSON(http.StatusOK, "true")
}

View File

@ -15,6 +15,11 @@ import (
func reloadSettings(config *settings.Settings) {
api.ManagerUsers = config.DelegatedQA
fic.UnlockedChallengeDepth = config.UnlockedChallengeDepth
fic.UnlockedChallengeUpTo = config.UnlockedChallengeUpTo
fic.UnlockedStandaloneExercices = config.UnlockedStandaloneExercices
fic.UnlockedStandaloneExercicesByThemeStepValidation = config.UnlockedStandaloneExercicesByThemeStepValidation
fic.UnlockedStandaloneExercicesByStandaloneExerciceValidation = config.UnlockedStandaloneExercicesByStandaloneExerciceValidation
}
func main() {

195
qa/ui/package-lock.json generated
View File

@ -459,9 +459,9 @@
}
},
"node_modules/@eslint-community/regexpp": {
"version": "4.11.0",
"resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.11.0.tgz",
"integrity": "sha512-G/M/tIiMrTAxEWRfLfQJMmGNX28IxBg4PBz8XqQhqUHLFI6TL2htpIB1iQCj144V5ee/JaKyT9/WZ0MGZWfA7A==",
"version": "4.11.1",
"resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.11.1.tgz",
"integrity": "sha512-m4DVN9ZqskZoLU5GlWZadwDnYo3vAEydiUayB9widCl9ffWx2IvPnp6n3on5rJmziJSw9Bv+Z3ChDVdMwXCY8Q==",
"dev": true,
"license": "MIT",
"engines": {
@ -672,9 +672,9 @@
}
},
"node_modules/@rollup/rollup-android-arm-eabi": {
"version": "4.21.2",
"resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.21.2.tgz",
"integrity": "sha512-fSuPrt0ZO8uXeS+xP3b+yYTCBUd05MoSp2N/MFOgjhhUhMmchXlpTQrTpI8T+YAwAQuK7MafsCOxW7VrPMrJcg==",
"version": "4.21.3",
"resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.21.3.tgz",
"integrity": "sha512-MmKSfaB9GX+zXl6E8z4koOr/xU63AMVleLEa64v7R0QF/ZloMs5vcD1sHgM64GXXS1csaJutG+ddtzcueI/BLg==",
"cpu": [
"arm"
],
@ -686,9 +686,9 @@
]
},
"node_modules/@rollup/rollup-android-arm64": {
"version": "4.21.2",
"resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.21.2.tgz",
"integrity": "sha512-xGU5ZQmPlsjQS6tzTTGwMsnKUtu0WVbl0hYpTPauvbRAnmIvpInhJtgjj3mcuJpEiuUw4v1s4BimkdfDWlh7gA==",
"version": "4.21.3",
"resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.21.3.tgz",
"integrity": "sha512-zrt8ecH07PE3sB4jPOggweBjJMzI1JG5xI2DIsUbkA+7K+Gkjys6eV7i9pOenNSDJH3eOr/jLb/PzqtmdwDq5g==",
"cpu": [
"arm64"
],
@ -700,9 +700,9 @@
]
},
"node_modules/@rollup/rollup-darwin-arm64": {
"version": "4.21.2",
"resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.21.2.tgz",
"integrity": "sha512-99AhQ3/ZMxU7jw34Sq8brzXqWH/bMnf7ZVhvLk9QU2cOepbQSVTns6qoErJmSiAvU3InRqC2RRZ5ovh1KN0d0Q==",
"version": "4.21.3",
"resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.21.3.tgz",
"integrity": "sha512-P0UxIOrKNBFTQaXTxOH4RxuEBVCgEA5UTNV6Yz7z9QHnUJ7eLX9reOd/NYMO3+XZO2cco19mXTxDMXxit4R/eQ==",
"cpu": [
"arm64"
],
@ -714,9 +714,9 @@
]
},
"node_modules/@rollup/rollup-darwin-x64": {
"version": "4.21.2",
"resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.21.2.tgz",
"integrity": "sha512-ZbRaUvw2iN/y37x6dY50D8m2BnDbBjlnMPotDi/qITMJ4sIxNY33HArjikDyakhSv0+ybdUxhWxE6kTI4oX26w==",
"version": "4.21.3",
"resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.21.3.tgz",
"integrity": "sha512-L1M0vKGO5ASKntqtsFEjTq/fD91vAqnzeaF6sfNAy55aD+Hi2pBI5DKwCO+UNDQHWsDViJLqshxOahXyLSh3EA==",
"cpu": [
"x64"
],
@ -728,9 +728,9 @@
]
},
"node_modules/@rollup/rollup-linux-arm-gnueabihf": {
"version": "4.21.2",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.21.2.tgz",
"integrity": "sha512-ztRJJMiE8nnU1YFcdbd9BcH6bGWG1z+jP+IPW2oDUAPxPjo9dverIOyXz76m6IPA6udEL12reYeLojzW2cYL7w==",
"version": "4.21.3",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.21.3.tgz",
"integrity": "sha512-btVgIsCjuYFKUjopPoWiDqmoUXQDiW2A4C3Mtmp5vACm7/GnyuprqIDPNczeyR5W8rTXEbkmrJux7cJmD99D2g==",
"cpu": [
"arm"
],
@ -742,9 +742,9 @@
]
},
"node_modules/@rollup/rollup-linux-arm-musleabihf": {
"version": "4.21.2",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.21.2.tgz",
"integrity": "sha512-flOcGHDZajGKYpLV0JNc0VFH361M7rnV1ee+NTeC/BQQ1/0pllYcFmxpagltANYt8FYf9+kL6RSk80Ziwyhr7w==",
"version": "4.21.3",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.21.3.tgz",
"integrity": "sha512-zmjbSphplZlau6ZTkxd3+NMtE4UKVy7U4aVFMmHcgO5CUbw17ZP6QCgyxhzGaU/wFFdTfiojjbLG3/0p9HhAqA==",
"cpu": [
"arm"
],
@ -756,9 +756,9 @@
]
},
"node_modules/@rollup/rollup-linux-arm64-gnu": {
"version": "4.21.2",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.21.2.tgz",
"integrity": "sha512-69CF19Kp3TdMopyteO/LJbWufOzqqXzkrv4L2sP8kfMaAQ6iwky7NoXTp7bD6/irKgknDKM0P9E/1l5XxVQAhw==",
"version": "4.21.3",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.21.3.tgz",
"integrity": "sha512-nSZfcZtAnQPRZmUkUQwZq2OjQciR6tEoJaZVFvLHsj0MF6QhNMg0fQ6mUOsiCUpTqxTx0/O6gX0V/nYc7LrgPw==",
"cpu": [
"arm64"
],
@ -770,9 +770,9 @@
]
},
"node_modules/@rollup/rollup-linux-arm64-musl": {
"version": "4.21.2",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.21.2.tgz",
"integrity": "sha512-48pD/fJkTiHAZTnZwR0VzHrao70/4MlzJrq0ZsILjLW/Ab/1XlVUStYyGt7tdyIiVSlGZbnliqmult/QGA2O2w==",
"version": "4.21.3",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.21.3.tgz",
"integrity": "sha512-MnvSPGO8KJXIMGlQDYfvYS3IosFN2rKsvxRpPO2l2cum+Z3exiExLwVU+GExL96pn8IP+GdH8Tz70EpBhO0sIQ==",
"cpu": [
"arm64"
],
@ -784,9 +784,9 @@
]
},
"node_modules/@rollup/rollup-linux-powerpc64le-gnu": {
"version": "4.21.2",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.21.2.tgz",
"integrity": "sha512-cZdyuInj0ofc7mAQpKcPR2a2iu4YM4FQfuUzCVA2u4HI95lCwzjoPtdWjdpDKyHxI0UO82bLDoOaLfpZ/wviyQ==",
"version": "4.21.3",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.21.3.tgz",
"integrity": "sha512-+W+p/9QNDr2vE2AXU0qIy0qQE75E8RTwTwgqS2G5CRQ11vzq0tbnfBd6brWhS9bCRjAjepJe2fvvkvS3dno+iw==",
"cpu": [
"ppc64"
],
@ -798,9 +798,9 @@
]
},
"node_modules/@rollup/rollup-linux-riscv64-gnu": {
"version": "4.21.2",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.21.2.tgz",
"integrity": "sha512-RL56JMT6NwQ0lXIQmMIWr1SW28z4E4pOhRRNqwWZeXpRlykRIlEpSWdsgNWJbYBEWD84eocjSGDu/XxbYeCmwg==",
"version": "4.21.3",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.21.3.tgz",
"integrity": "sha512-yXH6K6KfqGXaxHrtr+Uoy+JpNlUlI46BKVyonGiaD74ravdnF9BUNC+vV+SIuB96hUMGShhKV693rF9QDfO6nQ==",
"cpu": [
"riscv64"
],
@ -812,9 +812,9 @@
]
},
"node_modules/@rollup/rollup-linux-s390x-gnu": {
"version": "4.21.2",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.21.2.tgz",
"integrity": "sha512-PMxkrWS9z38bCr3rWvDFVGD6sFeZJw4iQlhrup7ReGmfn7Oukrr/zweLhYX6v2/8J6Cep9IEA/SmjXjCmSbrMQ==",
"version": "4.21.3",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.21.3.tgz",
"integrity": "sha512-R8cwY9wcnApN/KDYWTH4gV/ypvy9yZUHlbJvfaiXSB48JO3KpwSpjOGqO4jnGkLDSk1hgjYkTbTt6Q7uvPf8eg==",
"cpu": [
"s390x"
],
@ -826,9 +826,9 @@
]
},
"node_modules/@rollup/rollup-linux-x64-gnu": {
"version": "4.21.2",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.21.2.tgz",
"integrity": "sha512-B90tYAUoLhU22olrafY3JQCFLnT3NglazdwkHyxNDYF/zAxJt5fJUB/yBoWFoIQ7SQj+KLe3iL4BhOMa9fzgpw==",
"version": "4.21.3",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.21.3.tgz",
"integrity": "sha512-kZPbX/NOPh0vhS5sI+dR8L1bU2cSO9FgxwM8r7wHzGydzfSjLRCFAT87GR5U9scj2rhzN3JPYVC7NoBbl4FZ0g==",
"cpu": [
"x64"
],
@ -840,9 +840,9 @@
]
},
"node_modules/@rollup/rollup-linux-x64-musl": {
"version": "4.21.2",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.21.2.tgz",
"integrity": "sha512-7twFizNXudESmC9oneLGIUmoHiiLppz/Xs5uJQ4ShvE6234K0VB1/aJYU3f/4g7PhssLGKBVCC37uRkkOi8wjg==",
"version": "4.21.3",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.21.3.tgz",
"integrity": "sha512-S0Yq+xA1VEH66uiMNhijsWAafffydd2X5b77eLHfRmfLsRSpbiAWiRHV6DEpz6aOToPsgid7TI9rGd6zB1rhbg==",
"cpu": [
"x64"
],
@ -854,9 +854,9 @@
]
},
"node_modules/@rollup/rollup-win32-arm64-msvc": {
"version": "4.21.2",
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.21.2.tgz",
"integrity": "sha512-9rRero0E7qTeYf6+rFh3AErTNU1VCQg2mn7CQcI44vNUWM9Ze7MSRS/9RFuSsox+vstRt97+x3sOhEey024FRQ==",
"version": "4.21.3",
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.21.3.tgz",
"integrity": "sha512-9isNzeL34yquCPyerog+IMCNxKR8XYmGd0tHSV+OVx0TmE0aJOo9uw4fZfUuk2qxobP5sug6vNdZR6u7Mw7Q+Q==",
"cpu": [
"arm64"
],
@ -868,9 +868,9 @@
]
},
"node_modules/@rollup/rollup-win32-ia32-msvc": {
"version": "4.21.2",
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.21.2.tgz",
"integrity": "sha512-5rA4vjlqgrpbFVVHX3qkrCo/fZTj1q0Xxpg+Z7yIo3J2AilW7t2+n6Q8Jrx+4MrYpAnjttTYF8rr7bP46BPzRw==",
"version": "4.21.3",
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.21.3.tgz",
"integrity": "sha512-nMIdKnfZfzn1Vsk+RuOvl43ONTZXoAPUUxgcU0tXooqg4YrAqzfKzVenqqk2g5efWh46/D28cKFrOzDSW28gTA==",
"cpu": [
"ia32"
],
@ -882,9 +882,9 @@
]
},
"node_modules/@rollup/rollup-win32-x64-msvc": {
"version": "4.21.2",
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.21.2.tgz",
"integrity": "sha512-6UUxd0+SKomjdzuAcp+HAmxw1FlGBnl1v2yEPSabtx4lBfdXHDVsW7+lQkgz9cNFJGY3AWR7+V8P5BqkD9L9nA==",
"version": "4.21.3",
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.21.3.tgz",
"integrity": "sha512-fOvu7PCQjAj4eWDEuD8Xz5gpzFqXzGlxHZozHP4b9Jxv9APtdxL6STqztDzMLuRXEc4UpXGGhx029Xgm91QBeA==",
"cpu": [
"x64"
],
@ -906,9 +906,9 @@
}
},
"node_modules/@sveltejs/kit": {
"version": "2.5.26",
"resolved": "https://registry.npmjs.org/@sveltejs/kit/-/kit-2.5.26.tgz",
"integrity": "sha512-8l1JTIM2L+bS8ebq1E+nGjv/YSKSnD9Q19bYIUkc41vaEG2JjVUx6ikvPIJv2hkQAuqJLzoPrXlKk4KcyWOv3Q==",
"version": "2.5.27",
"resolved": "https://registry.npmjs.org/@sveltejs/kit/-/kit-2.5.27.tgz",
"integrity": "sha512-CcbRTzl+65oWljAASL6UlxM4x3NWwd0fjq5fQOfP243vs50myFQ8lil0fr3Im6HeeQqYUCtnv8HjO8REWVPjTw==",
"dev": true,
"hasInstallScript": true,
"license": "MIT",
@ -1077,12 +1077,12 @@
"license": "Python-2.0"
},
"node_modules/aria-query": {
"version": "5.3.0",
"resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.3.0.tgz",
"integrity": "sha512-b0P0sZPKtyu8HkeRAfCq0IfURZK+SuwMjY1UXGBU27wpAiTwQAIlq56IbIO+ytk/JjS1fMR14ee5WBBfKi5J6A==",
"version": "5.3.1",
"resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.3.1.tgz",
"integrity": "sha512-Z/ZeOgVl7bcSYZ/u/rh0fOpvEpq//LZmdbkXyc7syVzjPAhfOa9ebsdTSjEBDU4vs5nC98Kfduj1uFo0qyET3g==",
"license": "Apache-2.0",
"dependencies": {
"dequal": "^2.0.3"
"engines": {
"node": ">= 0.4"
}
},
"node_modules/axobject-query": {
@ -1300,15 +1300,6 @@
"node": ">=0.10.0"
}
},
"node_modules/dequal": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz",
"integrity": "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==",
"license": "MIT",
"engines": {
"node": ">=6"
}
},
"node_modules/devalue": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/devalue/-/devalue-5.0.0.tgz",
@ -1458,9 +1449,9 @@
}
},
"node_modules/eslint-plugin-svelte": {
"version": "2.43.0",
"resolved": "https://registry.npmjs.org/eslint-plugin-svelte/-/eslint-plugin-svelte-2.43.0.tgz",
"integrity": "sha512-REkxQWvg2pp7QVLxQNa+dJ97xUqRe7Y2JJbSWkHSuszu0VcblZtXkPBPckkivk99y5CdLw4slqfPylL2d/X4jQ==",
"version": "2.44.0",
"resolved": "https://registry.npmjs.org/eslint-plugin-svelte/-/eslint-plugin-svelte-2.44.0.tgz",
"integrity": "sha512-wav4MOs02vBb1WjvTCYItwJCxMkuk2Z4p+K/eyjL0N/z7ahXLP+0LtQQjiKc2ezuif7GnZLbD1F3o1VHzSvdVg==",
"dev": true,
"license": "MIT",
"dependencies": {
@ -1474,7 +1465,7 @@
"postcss-safe-parser": "^6.0.0",
"postcss-selector-parser": "^6.1.0",
"semver": "^7.6.2",
"svelte-eslint-parser": "^0.41.0"
"svelte-eslint-parser": "^0.41.1"
},
"engines": {
"node": "^14.17.0 || >=16.0.0"
@ -2143,9 +2134,9 @@
"license": "ISC"
},
"node_modules/postcss": {
"version": "8.4.45",
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.45.tgz",
"integrity": "sha512-7KTLTdzdZZYscUc65XmjFiB73vBhBfbPztCYdUNvlaso9PrzjzcmjqBPR0lNGkcVlcO4BjiO5rK/qNz+XAen1Q==",
"version": "8.4.47",
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.47.tgz",
"integrity": "sha512-56rxCq7G/XfB4EkXq9Egn5GCqugWvDFjafDOThIdMBsI15iqPqR5r15TfSr1YPYeEI19YeaXMCbY6u88Y76GLQ==",
"dev": true,
"funding": [
{
@ -2164,8 +2155,8 @@
"license": "MIT",
"dependencies": {
"nanoid": "^3.3.7",
"picocolors": "^1.0.1",
"source-map-js": "^1.2.0"
"picocolors": "^1.1.0",
"source-map-js": "^1.2.1"
},
"engines": {
"node": "^10 || ^12 || >=14"
@ -2349,9 +2340,9 @@
}
},
"node_modules/rollup": {
"version": "4.21.2",
"resolved": "https://registry.npmjs.org/rollup/-/rollup-4.21.2.tgz",
"integrity": "sha512-e3TapAgYf9xjdLvKQCkQTnbTKd4a6jwlpQSJJFokHGaX2IVjoEqkIIhiQfqsi0cdwlOD+tQGuOd5AJkc5RngBw==",
"version": "4.21.3",
"resolved": "https://registry.npmjs.org/rollup/-/rollup-4.21.3.tgz",
"integrity": "sha512-7sqRtBNnEbcBtMeRVc6VRsJMmpI+JU1z9VTvW8D4gXIYQFz0aLcsE6rRkyghZkLfEgUZgVvOG7A5CVz/VW5GIA==",
"dev": true,
"license": "MIT",
"dependencies": {
@ -2365,22 +2356,22 @@
"npm": ">=8.0.0"
},
"optionalDependencies": {
"@rollup/rollup-android-arm-eabi": "4.21.2",
"@rollup/rollup-android-arm64": "4.21.2",
"@rollup/rollup-darwin-arm64": "4.21.2",
"@rollup/rollup-darwin-x64": "4.21.2",
"@rollup/rollup-linux-arm-gnueabihf": "4.21.2",
"@rollup/rollup-linux-arm-musleabihf": "4.21.2",
"@rollup/rollup-linux-arm64-gnu": "4.21.2",
"@rollup/rollup-linux-arm64-musl": "4.21.2",
"@rollup/rollup-linux-powerpc64le-gnu": "4.21.2",
"@rollup/rollup-linux-riscv64-gnu": "4.21.2",
"@rollup/rollup-linux-s390x-gnu": "4.21.2",
"@rollup/rollup-linux-x64-gnu": "4.21.2",
"@rollup/rollup-linux-x64-musl": "4.21.2",
"@rollup/rollup-win32-arm64-msvc": "4.21.2",
"@rollup/rollup-win32-ia32-msvc": "4.21.2",
"@rollup/rollup-win32-x64-msvc": "4.21.2",
"@rollup/rollup-android-arm-eabi": "4.21.3",
"@rollup/rollup-android-arm64": "4.21.3",
"@rollup/rollup-darwin-arm64": "4.21.3",
"@rollup/rollup-darwin-x64": "4.21.3",
"@rollup/rollup-linux-arm-gnueabihf": "4.21.3",
"@rollup/rollup-linux-arm-musleabihf": "4.21.3",
"@rollup/rollup-linux-arm64-gnu": "4.21.3",
"@rollup/rollup-linux-arm64-musl": "4.21.3",
"@rollup/rollup-linux-powerpc64le-gnu": "4.21.3",
"@rollup/rollup-linux-riscv64-gnu": "4.21.3",
"@rollup/rollup-linux-s390x-gnu": "4.21.3",
"@rollup/rollup-linux-x64-gnu": "4.21.3",
"@rollup/rollup-linux-x64-musl": "4.21.3",
"@rollup/rollup-win32-arm64-msvc": "4.21.3",
"@rollup/rollup-win32-ia32-msvc": "4.21.3",
"@rollup/rollup-win32-x64-msvc": "4.21.3",
"fsevents": "~2.3.2"
}
},
@ -2553,9 +2544,9 @@
}
},
"node_modules/svelte-eslint-parser": {
"version": "0.41.0",
"resolved": "https://registry.npmjs.org/svelte-eslint-parser/-/svelte-eslint-parser-0.41.0.tgz",
"integrity": "sha512-L6f4hOL+AbgfBIB52Z310pg1d2QjRqm7wy3kI1W6hhdhX5bvu7+f0R6w4ykp5HoDdzq+vGhIJmsisaiJDGmVfA==",
"version": "0.41.1",
"resolved": "https://registry.npmjs.org/svelte-eslint-parser/-/svelte-eslint-parser-0.41.1.tgz",
"integrity": "sha512-08ndI6zTghzI8SuJAFpvMbA/haPSGn3xz19pjre19yYMw8Nw/wQJ2PrZBI/L8ijGTgtkWCQQiLLy+Z1tfaCwNA==",
"dev": true,
"license": "MIT",
"dependencies": {
@ -2700,9 +2691,9 @@
"license": "MIT"
},
"node_modules/vite": {
"version": "5.4.3",
"resolved": "https://registry.npmjs.org/vite/-/vite-5.4.3.tgz",
"integrity": "sha512-IH+nl64eq9lJjFqU+/yrRnrHPVTlgy42/+IzbOdaFDVlyLgI/wDlf+FCobXLX1cT0X5+7LMyH1mIy2xJdLfo8Q==",
"version": "5.4.5",
"resolved": "https://registry.npmjs.org/vite/-/vite-5.4.5.tgz",
"integrity": "sha512-pXqR0qtb2bTwLkev4SE3r4abCNioP3GkjvIDLlzziPpXtHgiJIjuKl+1GN6ESOT3wMjG3JTeARopj2SwYaHTOA==",
"dev": true,
"license": "MIT",
"dependencies": {

View File

@ -23,6 +23,7 @@
} from '@sveltestrap/sveltestrap';
import { auth, gitlab, version } from '$lib/stores/auth';
import { themes } from '$lib/stores/themes';
export let activemenu = "";
$: {
@ -50,6 +51,7 @@
<span class="d-none d-md-inline">Accueil</span>
</NavLink>
</NavItem>
{#if $themes.length}
<NavItem>
<NavLink
href="themes"
@ -59,6 +61,7 @@
<span class="d-none d-md-inline">Scénarios</span>
</NavLink>
</NavItem>
{/if}
<NavItem>
<NavLink
href="exercices"
@ -78,15 +81,6 @@
<span class="d-none d-md-inline">Équipes</span>
</NavLink>
</NavItem>
<NavItem>
<NavLink
href="repositories"
active={activemenu === 'repositories'}
>
<Icon name="archive" />
<span class="d-none d-md-inline">Dépôts</span>
</NavLink>
</NavItem>
{/if}
</Nav>
<Nav class="ms-auto text-light" navbar>

View File

@ -83,6 +83,8 @@
<td>
{#if $exercicesIdx.length == 0 && $themesIdx.length == 0}
<Spinner size="sm" />
{:else if !$themesIdx[$exercicesIdx[todo.id_exercice].id_theme]}
Défis indépendants
{:else}
<a href="themes/{$exercicesIdx[todo.id_exercice].id_theme}">
{$themesIdx[$exercicesIdx[todo.id_exercice].id_theme].name}

View File

@ -29,6 +29,7 @@
style="overflow-y: auto"
>
{#await themesP then themes}
{#if Object.keys(themes).length > 1}
<Row
style={'min-width:'+15*Object.keys(themes).length + 'vw'}
>
@ -69,5 +70,48 @@
</Col>
{/each}
</Row>
{:else}
{#each Object.keys(themes) as tname}
{#if themes[tname].exercices}
{#each themes[tname].exercices as exercice}
<Row
style={'min-width:'+15*Object.keys(themes).length + 'vw'}
>
<Col style="border-right: 1px solid lightgray">
<h3
class="text-center py-3 mb-3"
style="border-bottom: 2px solid black"
on:click={() => goto(`exercices/${exercice.exercice.id}`)}
>
{exercice.exercice.title}
</h3>
{#if exercice.reports}
{#each exercice.reports as report}
<Card
class="mb-3"
color={state2Color(report.report.state)}
style="cursor: pointer"
on:click={() => goto(`exercices/${exercice.exercice.id}/${report.report.id}`)}
>
<CardBody class="p-2">
{report.report.subject}
{#if report.comments}
<Badge
class="float-end"
>
{report.comments.length}
</Badge>
{/if}
</CardBody>
</Card>
{/each}
<hr />
{/if}
</Col>
</Row>
{/each}
{/if}
{/each}
{/if}
{/await}
</div>

View File

@ -44,6 +44,7 @@ export const exercicesByTheme = derived(
const exercices_idx = { };
for (const e of $exercices) {
if (!e.id_theme) e.id_theme = 0;
if (!exercices_idx[e.id_theme]) {
exercices_idx[e.id_theme] = []
}

View File

@ -16,6 +16,7 @@ export function createTodosStore(team) {
refresh: async () => {
const list = await getQATodo(team);
list.map((e) => e.id += 10000000);
list.push(...await getQAWork(team));
update((m) => list);
return list;

View File

@ -22,11 +22,14 @@ export class Team {
toHexColor() {
let num = this.color;
num >>>= 0;
let b = num & 0xFF,
g = (num & 0xFF00) >>> 8,
r = (num & 0xFF0000) >>> 16,
let b = (num & 0xFF).toString(16),
g = ((num & 0xFF00) >>> 8).toString(16),
r = ((num & 0xFF0000) >>> 16).toString(16),
a = ( (num & 0xFF000000) >>> 24 ) / 255 ;
return "#" + r.toString(16) + g.toString(16) + b.toString(16);
if (r.length <= 1) r = "0" + r;
if (g.length <= 1) g = "0" + g;
if (b.length <= 1) b = "0" + b;
return "#" + r + g + b;
}
}

View File

@ -23,7 +23,12 @@ export class Theme {
export async function getThemes() {
const res = await fetch(`api/themes`, {headers: {'Accept': 'application/json'}})
if (res.status == 200) {
return (await res.json()).map((t) => new Theme(t));
const data = await res.json();
if (data) {
return data.map((t) => new Theme(t));
} else {
return [];
}
} else {
throw new Error((await res.json()).errmsg);
}

View File

@ -43,7 +43,7 @@
<tbody>
{#each exercices as exercice (exercice.id)}
{#if exercice.title.indexOf(query) >= 0}
<tr on:click={() => show(exercice.id)}>
<tr on:click={() => show(exercice.id)} style="cursor: pointer">
{#each fieldsExercices as field}
<td>
{@html exercice[field]}

View File

@ -4,7 +4,12 @@
import { teams } from '$lib/stores/teams';
import {
Button,
Container,
FormGroup,
Input,
Label,
Spinner,
Table,
} from '@sveltestrap/sveltestrap';
@ -16,6 +21,44 @@
function show(id) {
goto("teams/" + id)
}
let start = 0;
let turns = 3;
let team_prefix = "";
let team_assistants = "";
let assignInProgress = false;
async function assignExercices() {
assignInProgress = true;
const res = await fetch(`api/qa_assign_work`, {
method: 'POST',
headers: {'Accept': 'application/json'},
body: JSON.stringify({
start,
turns,
team_prefix,
team_assistants,
}),
})
if (res.status == 200) {
teams.refresh();
assignInProgress = false;
} else {
assignInProgress = false;
throw new Error((await res.json()).errmsg);
}
}
async function deleteAssignation() {
const res = await fetch(`api/qa_assign_work`, {
method: 'DELETE',
});
if (res.status == 200) {
teams.refresh();
} else {
throw new Error((await res.json()).errmsg);
}
}
</script>
<Container class="mt-2 mb-5">
@ -39,10 +82,19 @@
<tbody>
{#each $teams as team (team.id)}
{#if team.name.indexOf(query) >= 0}
<tr on:click={() => show(team.id)}>
<tr on:click={() => show(team.id)} style="cursor: pointer">
{#each fields as field}
<td class:text-end={field == "image"}>
{#if field == "color"}
<div
class="badge"
style={"background-color: " + team.toHexColor()}
>
{team.toHexColor()}
</div>
{:else}
{team[field]}
{/if}
</td>
{/each}
</tr>
@ -50,4 +102,48 @@
{/each}
</tbody>
</Table>
<hr>
<h2>
Assigner des exercices aux équipes
</h2>
<form on:submit|preventDefault={assignExercices}>
<FormGroup>
<Label for="ae-start">Compteur de départ</Label>
<Input type="number" id="ae-start" bind:value={start} />
<p class="form-text">
Incrémenter de 1 pour chaque nouveau challenge blanc, cela décale l'attribution des exercices.
</p>
</FormGroup>
<FormGroup>
<Label for="ae-turns">Nombre d'itérations</Label>
<Input type="number" id="ae-turns" bind:value={turns} />
</FormGroup>
<FormGroup>
<Label for="ae-prefix">Préfixe des noms d'équipes</Label>
<Input id="ae-prefix" bind:value={team_prefix} placeholder="FIC Groupe" />
</FormGroup>
<FormGroup>
<Label for="ae-assistants">Nom de l'équipe assistants</Label>
<Input id="ae-assistants" bind:value={team_assistants} placeholder="Assistants" />
</FormGroup>
<Button
type="submit"
disabled={assignInProgress}
color="primary"
>
{#if assignInProgress}
<Spinner size="sm" />
{/if}
Assigner des exercices
</Button>
<Button
type="button"
color="danger"
on:click={deleteAssignation}
>
Supprimer toute assignation
</Button>
</form>
</Container>

View File

@ -102,6 +102,8 @@
<td>
{#if $exercicesIdx.length == 0 && $themesIdx.length == 0}
<Spinner size="sm" />
{:else if !$themesIdx[$exercicesIdx[todo.id_exercice].id_theme]}
Défis indépendants
{:else}
<a href="themes/{$exercicesIdx[todo.id_exercice].id_theme}">
{$themesIdx[$exercicesIdx[todo.id_exercice].id_theme].name}
@ -141,7 +143,7 @@
bind:value={newTodo}
>
{#each Object.keys($exercicesByTheme) as thid}
<optgroup label={$themesIdx[thid].name}>
<optgroup label={(thid != "0" ? $themesIdx[thid].name : "Exercices indépendants")}>
{#each $exercicesByTheme[thid] as exercice (exercice.id)}
<option value={exercice.id}>{exercice.title}</option>
{/each}
@ -171,7 +173,9 @@
bind:value={newThemeTodo}
>
{#each Object.keys($exercicesByTheme) as thid}
{#if thid != "0"}
<option value={$themesIdx[thid].id}>{$themesIdx[thid].name}</option>
{/if}
{/each}
</select>
<Button

View File

@ -60,7 +60,7 @@
<tbody>
{#each $themes as theme (theme.id)}
{#if theme.name.indexOf(query) >= 0 || theme.authors.indexOf(query) >= 0 || theme.intro.indexOf(query) >= 0}
<tr on:click={() => show(theme.id)}>
<tr on:click={() => show(theme.id)} style="cursor: pointer">
{#each fields as field}
<td class:text-end={field == "image"}>
{#if field == "image"}

View File

@ -63,7 +63,7 @@
<tbody>
{#each exercices as exercice (exercice.id)}
{#if exercice.title.indexOf(query) >= 0}
<tr on:click={() => show(exercice.id)}>
<tr on:click={() => show(exercice.id)} style="cursor: pointer">
{#each fieldsExercices as field}
<td>
{@html exercice[field]}