459 lines
28 KiB
HTML
459 lines
28 KiB
HTML
<div class="d-flex align-items-start">
|
|
<h2 class="text-truncate">
|
|
{{exercice.title}}
|
|
<small ng-if="themes && themes[exercice.id_theme]"><a href="themes/{{ exercice.id_theme }}" title="{{themes[exercice.id_theme].authors | stripHTML}}">{{themes[exercice.id_theme].name}}</a></small>
|
|
</h2>
|
|
<div class="btn-group" role="group" ng-if="themes[exercice.id_theme?exercice.id_theme:'0'].exercices">
|
|
<a href="exercices/{{ themes[exercice.id_theme?exercice.id_theme:'0'].exercices[my_ex_num[exercice.id]-1].id }}" title="Exercice précédent" ng-class="{'disabled': !themes[exercice.id_theme?exercice.id_theme:'0'].exercices[my_ex_num[exercice.id]-1]}" class="btn btn-sm btn-light"><span class="glyphicon glyphicon-chevron-left" aria-hidden="true"></span></a>
|
|
<a href="exercices/{{ themes[exercice.id_theme?exercice.id_theme:'0'].exercices[my_ex_num[exercice.id]-1+2].id }}" title="Exercice suivant" ng-class="{'disabled': !themes[exercice.id_theme?exercice.id_theme:'0'].exercices[my_ex_num[exercice.id]-1+2]}" class="btn btn-sm btn-light"><span class="glyphicon glyphicon-chevron-right" aria-hidden="true"></span></a>
|
|
</div>
|
|
<div class="ml-auto d-flex flex-row-reverse text-nowrap">
|
|
<a href="exercices/{{exercice.id}}/resolution" ng-disabled="!exercice.videoURI" class="ml-2 btn btn-sm btn-info"><span class="glyphicon glyphicon-facetime-video" aria-hidden="true"></span> Vidéo</a>
|
|
<a href="exercices/{{exercice.id}}/flags" class="ml-2 btn btn-sm btn-success"><span class="glyphicon glyphicon-flag" aria-hidden="true"></span> Flags</a>
|
|
<button type="button" ng-click="syncExo()" ng-class="{'disabled': inSync}" class="ml-2 btn btn-sm btn-light"><span class="glyphicon glyphicon-refresh" aria-hidden="true"></span> Synchroniser</button>
|
|
<a href="{{exercice.forge_link}}" target="_blank" class="ml-2 btn btn-sm btn-dark" ng-if="exercice.forge_link"><span class="glyphicon glyphicon-folder-open" aria-hidden="true"></span> Voir sur la forge</a>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="row mb-5">
|
|
|
|
<form class="col-md-8" ng-submit="saveExercice()">
|
|
<div class="form-group row" ng-repeat="field in fields">
|
|
<label for="{{ field }}" class="col-sm-1 col-form-label-sm">{{ field | capitalize }}</label>
|
|
<div class="col-sm-11">
|
|
<input type="text" class="form-control form-control-sm" id="{{ field }}" ng-model="exercice[field]" ng-if="field != 'statement' && field != 'issue' && field != 'issuekind' && field != 'overview' && field != 'resolution' && field != 'finished' && field != 'depend' && field != 'gain' && field != 'coefficient' && field != 'wip' && field != 'disabled' && field != 'background_color'">
|
|
<input type="checkbox" id="{{ field }}" ng-model="exercice[field]" ng-if="field == 'wip' || field == 'disabled'">
|
|
<input type="text" class="form-control form-control-sm" id="{{ field }}" ng-model="exercice[field]" ng-if="field == 'gain'" integer>
|
|
<input type="text" class="form-control form-control-sm" id="{{ field }}" ng-model="exercice[field]" ng-if="field == 'coefficient'" float>
|
|
<textarea class="form-control form-control-sm" id="{{field}}" ng-model="exercice[field]" ng-if="field == 'statement' || field == 'overview' || field == 'finished' || field == 'resolution' || field == 'issue'"></textarea>
|
|
<select class="form-control form-control-sm" id="{{field}}" ng-model="exercice[field]" ng-options="ex.id as ex.title group by ex.path.split('/')[0] for ex in exercices" ng-if="field == 'depend'">
|
|
<option value="">Aucune</option>
|
|
</select>
|
|
<select class="form-control form-control-sm" id="{{field}}" ng-model="exercice[field]" ng-options="v for v in ['primary', 'secondary', 'success', 'danger', 'warning', 'info', 'light', 'dark']" ng-if="field == 'issuekind'"></select>
|
|
<input type="color" class="form-control form-control-sm" id="{{ field }}" ng-model="exercice[field]" ng-if="field == 'background_color'" color>
|
|
</div>
|
|
</div>
|
|
<div class="text-right" ng-show="exercice.id">
|
|
<button type="submit" class="btn btn-primary"><span class="glyphicon glyphicon-save" aria-hidden="true"></span> Save</button>
|
|
<button type="button" class="btn btn-danger" ng-click="deleteExercice()"><span class="glyphicon glyphicon-remove" aria-hidden="true"></span> Delete</button>
|
|
</div>
|
|
<div class="text-right" ng-show="!exercice.id">
|
|
<button type="submit" class="btn btn-primary"><span class="glyphicon glyphicon-plus" aria-hidden="true"></span> Create exercice</button>
|
|
</div>
|
|
</form>
|
|
|
|
<div class="col-md-4 accordion" ng-show="exercice.id" id="accordionExercice">
|
|
|
|
<div class="mb-2" style="overflow-y: auto; max-height: 250px" ng-controller="ExerciceClaimsController" ng-show="claims.length">
|
|
<table class="table table-sm table-hover table-striped">
|
|
<tbody>
|
|
<tr ng-repeat="claim in claims | orderBy: 'priority'" ng-click="show(claim.id)" ng-class="{'table-info': claim.priority == 'medium', 'table-warning': claim.priority == 'high', 'table-danger': claim.priority == 'critical'}" ng-if="showClosed || (claim.state != 'closed' && claim.state != 'invalid')">
|
|
<td ng-bind="claim.subject"></td>
|
|
<td><a ng-href="teams/{{ claim.id_team}}" style="background-color: {{ claim.team.color | toColor }}" ng-bind="claim.team.name"></a></td>
|
|
<td ng-bind="claim.state"></td>
|
|
<td ng-repeat="assignee in assignees" ng-if="assignee.id == claim.id_assignee" ng-bind="assignee.name"></td>
|
|
</tr>
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
|
|
<div class="card border-secondary" ng-controller="ExerciceStatsController">
|
|
<div class="card-header bg-primary text-light" type="button" data-toggle="collapse" data-target="#collapseStats" aria-expanded="true" aria-controls="collapseStats">
|
|
<h4 class="m-0"><small class="glyphicon glyphicon-chevron-right" aria-hidden="true"></small> Statistiques</h4>
|
|
</div>
|
|
<div class="collapse show" id="collapseStats" aria-labelledby="headingStats" data-parent="#accordionExercice">
|
|
<dl class="row mt-2 ml-2">
|
|
<dt class="col-sm-6 text-truncate" title="Nombre de points actuel">Points actuels</dt>
|
|
<dd class="col-sm-6"><ng-pluralize count="stats.current_gain" when="{'0': '0 points', 'one': '{} point', 'other': '{} points'}"></ng-pluralize></dd>
|
|
|
|
<dt class="col-sm-6 text-truncate" title="Nombre d'équipes">Défi tenté par</dt>
|
|
<dd class="col-sm-6"><ng-pluralize count="stats.team_tries" when="{'0': 'aucune équipe', 'one': '{} équipe', 'other': '{} équipes'}"></ng-pluralize></dd>
|
|
|
|
<dt class="col-sm-6 text-truncate" title="Nombre de tentatives">Nombre de tentatives</dt>
|
|
<dd class="col-sm-6"><ng-pluralize count="stats.total_tries" when="{'0': 'aucune tentative', 'one': '{} tentative', 'other': '{} tentatives'}"></ng-pluralize></dd>
|
|
|
|
<dt class="col-sm-6 text-truncate" title="Défi validé par">Défi validé par</dt>
|
|
<dd class="col-sm-6"><ng-pluralize count="stats.solved_count" when="{'0': 'aucune équipe', 'one': '{} équipe', 'other': '{} équipes'}"></ng-pluralize></dd>
|
|
|
|
<dt class="col-sm-6 text-truncate" title="Drapeaux validés">Drapeaux validés</dt>
|
|
<dd class="col-sm-6" title="{{ stats.flag_solved }}" ng-if="stats.flag_solved">{{ stats.flag_solved.length }}</dd>
|
|
<dd class="col-sm-6" title="{{ stats.flag_solved }}" ng-if="!stats.flag_solved">aucun</dd>
|
|
|
|
<dt class="col-sm-6 text-truncate" title="QCM validés">QCM validés</dt>
|
|
<dd class="col-sm-6" title="{{ stats.mcq_solved }}" ng-if="stats.mcq_solved">{{ stats.mcq_solved.length }}</dd>
|
|
<dd class="col-sm-6" title="{{ stats.mcq_solved }}" ng-if="!stats.mcq_solved">aucun</dd>
|
|
</dl>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="card border-secondary" ng-controller="ExerciceFilesController">
|
|
<div class="card-header bg-secondary text-light" type="button" data-toggle="collapse" data-target="#collapseFiles" aria-expanded="true" aria-controls="collapseFiles">
|
|
<h4 class="m-0"><small class="glyphicon glyphicon-chevron-right" aria-hidden="true"></small> Téléchargements</h4>
|
|
</div>
|
|
<div class="collapse" id="collapseFiles" aria-labelledby="headingFiles" data-parent="#accordionExercice">
|
|
<div class="list-group">
|
|
<div class="btn-toolbar bg-secondary justify-content-end" role="toolbar">
|
|
<div class="btn-group" role="group">
|
|
<button type="button" ng-click="syncFiles()" class="btn btn-sm btn-light"><span class="glyphicon glyphicon-refresh" aria-hidden="true"></span> Synchroniser</button>
|
|
</div>
|
|
</div>
|
|
<form ng-submit="saveFile()" class="list-group-item bg-light text-dark" ng-repeat="file in files">
|
|
<div class="row form-group">
|
|
<input type="text" ng-model="file.name" class="col form-control form-control-sm" placeholder="Nom de fichier">
|
|
<a href="../files{{file.path}}" class="btn btn-sm btn-secondary col-auto"><span class="glyphicon glyphicon-download" aria-hidden="true"></span></a>
|
|
<button type="submit" class="btn btn-sm btn-success col-auto"><span class="glyphicon glyphicon-ok" aria-hidden="true"></span></button><br>
|
|
<button type="button" ng-click="deleteFile()" class="btn btn-sm btn-danger col-auto"><span class="glyphicon glyphicon-remove" aria-hidden="true"></span></button>
|
|
</div>
|
|
<div class="cksum">
|
|
Taille : <span title="{{ file.size }} octets">{{ file.size | size }}</span> ‐
|
|
BLAKE2b : <samp title="{{ file.checksum | cksum }}">{{ file.checksum | cksum }}</samp>
|
|
</div>
|
|
<div class="col-auto custom-control custom-checkbox">
|
|
<input type="checkbox" class="custom-control-input" ng-model="file.published" id="f{{file.id}}">
|
|
<label class="custom-control-label" for="f{{file.id}}">Publié aux équipes</label>
|
|
</div>
|
|
<div>
|
|
Dépend de la validation de :
|
|
<span ng-if="!file.depends">aucun flag</span>
|
|
<ul ng-if="file.depends">
|
|
<dependancy ng-repeat="dep in file.depends" dep="dep" deleteDep="deleteFileDep"></dependancy>
|
|
</ul>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="card border-info" ng-controller="ExerciceHintsController">
|
|
<div class="card-header bg-info text-light" type="button" data-toggle="collapse" data-target="#collapseHints" aria-expanded="true" aria-controls="collapseHints">
|
|
<h4 class="m-0"><small class="glyphicon glyphicon-chevron-right" aria-hidden="true"></small> Indices</h4>
|
|
</div>
|
|
<div class="collapse" id="collapseHints" aria-labelledby="headingHints" data-parent="#accordionExercice">
|
|
<div class="list-group">
|
|
<div class="btn-toolbar bg-info justify-content-end" role="toolbar">
|
|
<div class="btn-group" role="group">
|
|
<button type="button" ng-click="syncHints()" class="btn btn-sm btn-light"><span class="glyphicon glyphicon-refresh" aria-hidden="true"></span> Synchroniser</button>
|
|
<button type="button" ng-click="addHint()" class="btn btn-sm btn-primary"><span class="glyphicon glyphicon-plus" aria-hidden="true"></span> Ajouter</button>
|
|
</div>
|
|
</div>
|
|
<form ng-submit="saveHint()" class="list-group-item form-horizontal bg-light text-dark" ng-repeat="hint in hints">
|
|
<input type="text" id="htitle{{hint.id}}" ng-model="hint.title" class="form-control form-control-sm" placeholder="Titre">
|
|
<textarea class="form-control form-control-sm" id="hcnt{{hint.id}}" ng-model="hint.content" ng-if="!hint.file"></textarea>
|
|
<p ng-if="hint.file">
|
|
Fichier : <samp>{{ hint.file }}</samp><br>
|
|
Hash : <samp class="cksum">{{ hint.content }}</samp><br>
|
|
</p>
|
|
<div class="row">
|
|
<div class="col-8 input-group input-group-sm mb-3">
|
|
<div class="input-group-prepend">
|
|
<span class="input-group-text" id="inputGroup-sizing-sm">Coût</span>
|
|
</div>
|
|
<input type="text" id="hcost{{hint.id}}" ng-model="hint.cost" class="form-control" integer>
|
|
</div>
|
|
<div class="col-4">
|
|
<button type="submit" class="btn btn-sm btn-success"><span class="glyphicon glyphicon-ok" aria-hidden="true"></span></button>
|
|
<button type="button" ng-click="deleteHint()" class="btn btn-sm btn-danger" ng-show="hint.id"><span class="glyphicon glyphicon-remove" aria-hidden="true"></span></button>
|
|
</div>
|
|
</div>
|
|
<div ng-controller="ExerciceHintDepsController" ng-init="init(hint)">
|
|
Dépendances :
|
|
<ul ng-if="deps.length > 0">
|
|
<dependancy ng-repeat="dep in deps" dep="dep"></dependancy>
|
|
</ul>
|
|
<span ng-if="deps.length == 0"> sans</span>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="card border-success" ng-controller="ExerciceFlagsController">
|
|
<div class="card-header bg-success text-light" type="button" data-toggle="collapse" data-target="#collapseFlags" aria-expanded="true" aria-controls="collapseFlags">
|
|
<h4 class="m-0"><small class="glyphicon glyphicon-chevron-right" aria-hidden="true"></small> Drapeaux</h4>
|
|
</div>
|
|
<div class="collapse" id="collapseFlags" aria-labelledby="headingFlags" data-parent="#accordionExercice">
|
|
<div class="list-group">
|
|
<div class="btn-toolbar bg-success justify-content-end" role="toolbar">
|
|
<div class="btn-group" role="group">
|
|
<button type="button" ng-click="syncFlags()" class="btn btn-sm btn-light"><span class="glyphicon glyphicon-refresh" aria-hidden="true"></span> Synchroniser</button>
|
|
<button type="button" ng-click="addFlag()" class="btn btn-sm btn-primary"><span class="glyphicon glyphicon-plus" aria-hidden="true"></span> Ajouter</button>
|
|
</div>
|
|
</div>
|
|
<div ng-repeat="flag in flags" class="list-group-item bg-light text-dark">
|
|
<form ng-submit="saveFlag()" class="form-horizontal">
|
|
<div class="row" id="flag-{{flag.id}}">
|
|
<input type="text" id="klabel{{flag.id}}" ng-model="flag.label" class="col form-control form-control-sm" placeholder="Intitulé" title="Intitulé">
|
|
<div class="col-auto" ng-show="flag.id">
|
|
<button type="button" ng-click="deleteFlag()" class="btn btn-sm btn-danger"><span class="glyphicon glyphicon-remove" aria-hidden="true"></span></button>
|
|
</div>
|
|
</div>
|
|
<div class="row">
|
|
<input type="text" id="kplaceholder{{flag.id}}" ng-model="flag.placeholder" class="col form-control form-control-sm" placeholder="Indication de formatage" title="Indication de formatage">
|
|
<div class="col-auto">
|
|
<button type="submit" class="btn btn-sm btn-success"><span class="glyphicon glyphicon-ok" aria-hidden="true"></span></button>
|
|
</div>
|
|
</div>
|
|
<div class="row">
|
|
<div class="col input-group" ng-if="flag.id && !flag.show_raw" style="padding:0">
|
|
<input type="text" id="kvalue{{flag.id}}" ng-model="flag.value" class="form-control form-control-sm" placeholder="Condensat" title="Condensat">
|
|
<div class="input-group-append">
|
|
<button class="btn btn-sm btn-outline-secondary" ng-click="changeValue(flag)" title="Cliquez pour éditer la valeur brute du flag, au lieu du checksum" type="button"><span class="glyphicon glyphicon-erase" aria-hidden="true"></span></button>
|
|
</div>
|
|
</div>
|
|
<input type="text" id="kflag{{flag.id}}" ng-model="flag.flag" class="col form-control form-control-sm" placeholder="Chaîne brute à valider" ng-if="!flag.id || flag.show_raw" title="Chaîne brute à valider">
|
|
<div class="col-auto custom-control custom-checkbox ml-1">
|
|
<input type="checkbox" class="custom-control-input" id="kicase{{flag.id}}" ng-model="flag.ignorecase">
|
|
<label class="custom-control-label" for="kicase{{flag.id}}">Ignore case</label>
|
|
</div>
|
|
<div class="col-auto custom-control custom-checkbox ml-1">
|
|
<input type="checkbox" class="custom-control-input" id="kmline{{flag.id}}" ng-model="flag.multiline">
|
|
<label class="custom-control-label" for="kmline{{flag.id}}">Multiline</label>
|
|
</div>
|
|
</div>
|
|
<div class="row">
|
|
<input type="text" id="kvre{{flag.id}}" ng-model="flag.capture_regexp" class="col form-control form-control-sm" placeholder="Regexp selecting validation string" title="Regexp selecting validation string">
|
|
</div>
|
|
</form>
|
|
<form ng-submit="testFlag(flag)">
|
|
<div class="input-group row">
|
|
<input type="text" id="ktest{{flag.id}}" ng-model="flag.test_str" class="form-control form-control-sm" placeholder="Test the flag">
|
|
<div class="input-group-append">
|
|
<button class="btn btn-sm btn-warning" type="submit"><span class="glyphicon glyphicon-play" aria-hidden="true"></span></button>
|
|
</div>
|
|
</div>
|
|
<div ng-controller="ExerciceFlagDepsController" ng-init="init(flag)">
|
|
Dépendances :
|
|
<ul ng-if="deps.length > 0">
|
|
<dependancy ng-repeat="dep in deps" dep="dep"></dependancy>
|
|
</ul>
|
|
<span ng-if="deps.length == 0"> sans</span>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="card border-success" ng-controller="ExerciceMCQFlagsController">
|
|
<div class="card-header bg-success text-light" type="button" data-toggle="collapse" data-target="#collapseQuizz" aria-expanded="true" aria-controls="collapseQuizz">
|
|
<h4 class="m-0"><small class="glyphicon glyphicon-chevron-right" aria-hidden="true"></small> Quizz</h4>
|
|
</div>
|
|
<div class="collapse" id="collapseQuizz" aria-labelledby="headingQuizz" data-parent="#accordionExercice">
|
|
<div class="list-group">
|
|
<div class="btn-toolbar bg-success justify-content-end" role="toolbar">
|
|
<div class="btn-group" role="group">
|
|
<button type="button" ng-click="addQuiz()" class="btn btn-sm btn-primary"><span class="glyphicon glyphicon-plus" aria-hidden="true"></span> Ajouter</button>
|
|
</div>
|
|
</div>
|
|
<form ng-submit="saveQuiz()" class="list-group-item form-horizontal bg-light text-dark" ng-repeat="(qk,q) in quiz">
|
|
<div class="form-group row" id="quiz-{{q.id}}">
|
|
<input type="text" id="qlabel{{q.id}}" ng-model="q.title" class="col form-control" placeholder="Intitulé">
|
|
<div class="col-auto" ng-show="q.id">
|
|
<button type="button" ng-click="deleteQuiz()" class="btn btn-danger"><span class="glyphicon glyphicon-remove" aria-hidden="true"></span></button>
|
|
</div>
|
|
</div>
|
|
<div class="form-group row" ng-repeat="(ck,choice) in q.entries">
|
|
<div class="col form-check">
|
|
<label class="custom-control custom-checkbox">
|
|
<input class="custom-control-input" type="checkbox" ng-model="choice.response">
|
|
<span class="custom-control-label">
|
|
<input type="text" id="kchoice{{q.id}}-{{choice.id}}" ng-model="choice.label" class="form-control form-control-sm" placeholder="Intitulé">
|
|
</span>
|
|
</label>
|
|
</div>
|
|
<div class="col-auto">
|
|
<button type="button" ng-click="deleteChoice()" class="btn btn-sm btn-danger"><span class="glyphicon glyphicon-trash" aria-hidden="true"></span></button>
|
|
</div>
|
|
</div>
|
|
<div class="form-group row">
|
|
<div class="col-auto">
|
|
<button type="button" ng-click="addChoice()" class="btn btn-primary"><span class="glyphicon glyphicon-plus" aria-hidden="true"></span> Ajouter un choix</button>
|
|
</div>
|
|
<div class="col-auto">
|
|
<button type="submit" class="btn btn-success"><span class="glyphicon glyphicon-ok" aria-hidden="true"></span></button>
|
|
</div>
|
|
</div>
|
|
<div ng-controller="ExerciceMCQDepsController" ng-init="init(q)">
|
|
Dépendances :
|
|
<ul ng-if="deps.length > 0">
|
|
<dependancy ng-repeat="dep in deps" dep="dep"></dependancy>
|
|
</ul>
|
|
<span ng-if="deps.length == 0"> sans</span>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="card border-warning" ng-controller="ExerciceTagsController">
|
|
<div class="card-header bg-warning text-light" type="button" data-toggle="collapse" data-target="#collapseTags" aria-expanded="true" aria-controls="collapseTags">
|
|
<h4 class="m-0"><small class="glyphicon glyphicon-chevron-right" aria-hidden="true"></small> Tags</h4>
|
|
</div>
|
|
<div class="collapse" id="collapseTags" aria-labelledby="headingTags" data-parent="#accordionExercice">
|
|
<div class="list-group">
|
|
<div class="btn-toolbar bg-warning justify-content-end" role="toolbar">
|
|
<div class="btn-group" role="group">
|
|
<button type="button" ng-click="addTag()" class="btn btn-sm btn-primary"><span class="glyphicon glyphicon-plus" aria-hidden="true"></span> Ajouter</button>
|
|
<button type="button" ng-click="saveTags()" class="btn btn-sm btn-success"><span class="glyphicon glyphicon-ok" aria-hidden="true"></span> Sauvegarder</button>
|
|
</div>
|
|
</div>
|
|
<form ng-submit="saveTags()" class="list-group-item bg-light text-dark">
|
|
<div class="row form-group" ng-repeat="(k, tag) in tags track by $index">
|
|
<input type="text" ng-model="tags[k]" class="col form-control form-control-sm" placeholder="#tag">
|
|
<button type="button" ng-click="deleteTag()" class="btn btn-sm btn-danger col-auto"><span class="glyphicon glyphicon-remove" aria-hidden="true"></span></button>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="mt-2" style="overflow-y: scroll; height: 450px" id="exercicehistory" ng-controller="ExerciceHistoryController">
|
|
<div class="d-flex justify-content-between align-items-start">
|
|
<h3>Historique</h3>
|
|
<div class="btn-group" role="group">
|
|
<button type="button" class="btn btn-sm btn-dark" data-toggle="modal" data-target="#appendHistoryModal" ng-show="logged"><span class="glyphicon glyphicon-plus" aria-hidden="true"></span></button>
|
|
<button type="button" class="btn btn-sm btn-primary" ng-click="refreshHistory()"><span class="glyphicon glyphicon-refresh" aria-hidden="true"></span></button>
|
|
</div>
|
|
</div>
|
|
<table class="table table-hover table-striped table-bordered bg-primary text-light">
|
|
<tbody>
|
|
<tr ng-repeat="row in history" ng-class="{'bg-ffound': row.kind == 'flag_found', 'bg-mfound': row.kind == 'mcq_found', 'bg-wchoices': row.kind == 'wchoices', 'bg-success': row.kind == 'solved', 'bg-info': row.kind == 'hint', 'bg-warning': row.kind == 'tries'}">
|
|
<td>
|
|
<nobr title="{{ row.time }}">{{ row.time | date:"mediumTime" }}</nobr><br>{{ row.kind }} <span ng-if="row.kind != 'flag_found' && row.kind != 'tries' && row.kind != 'mcq_found'">x{{ row.coefficient }}</span>
|
|
</td>
|
|
<td>
|
|
<span ng-if="row.team_id">
|
|
<a href="teams/{{ row.team_id }}">{{ row.team_name }}</a>
|
|
</span>
|
|
<span ng-if="row.secondary_title">
|
|
:
|
|
<a href="exercices/{{ row.primary }}#key-{{ row.secondary }}" ng-if="row.kind == 'flag_found' || row.kind == 'wchoices'">{{ row.secondary_title }}</a>
|
|
<a href="exercices/{{ row.primary }}#quizz-{{ row.secondary }}" ng-if="row.kind == 'mcq_found'">{{ row.secondary_title }}</a>
|
|
<a href="exercices/{{ row.primary }}#hint-{{ row.secondary }}" ng-if="row.kind == 'hint'">{{ row.secondary_title }}</a>
|
|
</span>
|
|
<span ng-if="!row.secondary_title && row.secondary && row.kind != 'solved'">: {{ row.secondary }}</span>
|
|
</td>
|
|
<td style="vertical-align: middle; padding: 0; background-color: {{ row.team_color }}" ng-show="logged">
|
|
<button type="button" data-toggle="modal" data-target="#updHistory" ng-if="row.kind != 'flag_found' && row.kind != 'tries' && row.kind != 'mcq_found'" data-idteam="{{ row.team_id }}" data-kind="{{ row.kind }}" data-time="{{ row.time }}" data-secondary="{{ row.secondary }}" data-coeff="{{ row.coefficient }}" class="float-right btn btn-sm btn-info"><span class="glyphicon glyphicon-edit" aria-hidden="true"></span></button>
|
|
<button type="button" ng-click="delHistory(row)" class="float-right btn btn-sm btn-danger"><span class="glyphicon glyphicon-remove" aria-hidden="true"></span></button>
|
|
</td>
|
|
</tr>
|
|
</tbody>
|
|
</table>
|
|
|
|
<div class="modal fade" id="updHistory" tabindex="-1" role="dialog">
|
|
<div class="modal-dialog" role="document">
|
|
<div class="modal-content bg-light">
|
|
<div class="modal-header">
|
|
<h5 class="modal-title">Édition de l'historique</h5>
|
|
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
|
|
<span aria-hidden="true">×</span>
|
|
</button>
|
|
</div>
|
|
<div class="modal-body">
|
|
<form ng-submit="updHistory()">
|
|
<div class="form-group">
|
|
<label for="historycoeff">Coefficient</label>
|
|
<input class="form-control" id="historycoeff">
|
|
</div>
|
|
</form>
|
|
</div>
|
|
<div class="modal-footer">
|
|
<button type="button" class="btn btn-secondary" data-dismiss="modal">Annuler</button>
|
|
<button type="button" class="btn btn-primary" ng-click="updHistory()">Mettre à jour</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
<script>
|
|
$('#updHistory').on('shown.bs.modal', function (event) {
|
|
var button = $(event.relatedTarget);
|
|
var modal = $(this);
|
|
|
|
modal.data('idteam', button.data('idteam'));
|
|
modal.data('kind', button.data('kind'));
|
|
modal.data('time', button.data('time'));
|
|
modal.data('secondary', button.data('secondary'));
|
|
modal.data('coeff', button.data('coeff'));
|
|
$('#historycoeff').val(button.data('coeff'));
|
|
$('#historycoeff').focus();
|
|
});
|
|
</script>
|
|
|
|
<div class="modal fade" id="appendHistoryModal" tabindex="-1" role="dialog">
|
|
<div class="modal-dialog" role="document">
|
|
<div class="modal-content bg-light">
|
|
<div class="modal-header">
|
|
<h5 class="modal-title">Ajout d'une entrée dans l'historique</h5>
|
|
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
|
|
<span aria-hidden="true">×</span>
|
|
</button>
|
|
</div>
|
|
<form ng-submit="historyAppend()">
|
|
<div class="modal-body">
|
|
<div class="form-group row">
|
|
<label for="labelflag" class="col-md-3 col-form-label">Exercice</label>
|
|
<div class="col-md-9">
|
|
<input type="text" readonly class="form-control-plaintext" value="{{ exercice.title }}">
|
|
</div>
|
|
</div>
|
|
<div class="form-group row">
|
|
<label for="tteam" class="col-md-3 col-form-label">Équipe</label>
|
|
<div class="col-md-9" ng-controller="TeamsListController">
|
|
<select class="custom-select custom-select-sm" id="tteam" ng-model="selectedTeam" ng-options="t.id as t.name for t in teams"></select>
|
|
</div>
|
|
</div>
|
|
<div class="form-group row">
|
|
<label for="tteam" class="col-md-3 col-form-label">Type d'événement</label>
|
|
<div class="col-md-9">
|
|
<select class="custom-select custom-select-sm" id="historyEvent" ng-model="selectedEvent">
|
|
<option value="tries">Tentative</option>
|
|
<option value="hint">Indice dévoilé</option>
|
|
<option value="wchoices">Liste de choix affichée</option>
|
|
<option value="flag_found">Flag trouvé</option>
|
|
<option value="mcq_found">QCM validé</option>
|
|
<option value="solved">Exercice terminé</option>
|
|
</select>
|
|
</div>
|
|
</div>
|
|
<div class="form-group row" ng-if="selectedEvent == 'hint'">
|
|
<label for="tteam" class="col-md-3 col-form-label">Indice</label>
|
|
<div class="col-md-9" ng-controller="ExerciceHintsController">
|
|
<select class="custom-select custom-select-sm" id="historySecondaryHint" ng-model="selectedSecondaryHint" ng-options="h.id as h.title for h in hints"></select>
|
|
</div>
|
|
</div>
|
|
<div class="form-group row" ng-if="selectedEvent == 'wchoices' || selectedEvent == 'flag_found'">
|
|
<label for="tteam" class="col-md-3 col-form-label">Flag</label>
|
|
<div class="col-md-9" ng-controller="ExerciceFlagsController">
|
|
<select class="custom-select custom-select-sm" id="historySecondaryFlag" ng-model="selectedSecondaryFlag" ng-options="f.id as f.label for f in flags"></select>
|
|
</div>
|
|
</div>
|
|
<div class="form-group row" ng-if="selectedEvent == 'mcq_found'">
|
|
<label for="tteam" class="col-md-3 col-form-label">QCM</label>
|
|
<div class="col-md-9" ng-controller="ExerciceMCQFlagsController">
|
|
<select class="custom-select custom-select-sm" id="historySecondaryQuiz" ng-model="selectedSecondaryFlag" ng-options="q.id as q.title for q in quiz"></select>
|
|
</div>
|
|
</div>
|
|
<div class="modal-footer">
|
|
<button type="button" class="btn btn-secondary" data-dismiss="modal">Annuler</button>
|
|
<button type="submit" class="btn btn-primary">Enregistrer</button>
|
|
</div>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<script>
|
|
$('#appendHistoryModal').on('shown.bs.modal', function (event) {
|
|
$('#tteam').trigger('focus');
|
|
});
|
|
</script>
|