2016-12-26 00:16:49 +00:00
angular . module ( "FICApp" , [ "ngRoute" , "ngResource" , "ngSanitize" ] )
2024-09-18 16:06:23 +00:00
. config ( function ( $routeProvider , $locationProvider ) {
$routeProvider
. when ( "/themes" , {
controller : "ThemesListController" ,
templateUrl : "views/theme-list.html"
} )
. when ( "/themes/:themeId" , {
controller : "ThemeController" ,
templateUrl : "views/theme.html"
} )
. when ( "/themes/:themeId/exercices/:exerciceId" , {
controller : "ExerciceController" ,
templateUrl : "views/exercice.html"
} )
. when ( "/repositories" , {
controller : "RepositoriesController" ,
templateUrl : "views/repositories.html"
} )
. when ( "/sync" , {
controller : "SyncController" ,
templateUrl : "views/sync.html"
} )
. when ( "/settings" , {
controller : "SettingsController" ,
templateUrl : "views/settings.html"
} )
. when ( "/pki" , {
controller : "PKIController" ,
templateUrl : "views/pki.html"
} )
. when ( "/exercices" , {
controller : "AllExercicesListController" ,
templateUrl : "views/exercice-list.html"
} )
. when ( "/exercices/:exerciceId" , {
controller : "ExerciceController" ,
templateUrl : "views/exercice.html"
} )
. when ( "/exercices/:exerciceId/flags" , {
controller : "ExerciceController" ,
templateUrl : "views/exercice-flags.html"
} )
. when ( "/exercices/:exerciceId/resolution" , {
controller : "ExerciceController" ,
templateUrl : "views/exercice-resolution.html"
} )
. when ( "/tags" , {
controller : "TagsListController" ,
templateUrl : "views/tags.html"
} )
. when ( "/teams" , {
controller : "TeamsListController" ,
templateUrl : "views/team-list.html"
} )
. when ( "/teams/print" , {
controller : "TeamsListController" ,
templateUrl : "views/team-print.html"
} )
. when ( "/teams/export" , {
controller : "TeamsListController" ,
templateUrl : "views/team-export.html"
} )
. when ( "/teams/:teamId" , {
controller : "TeamController" ,
templateUrl : "views/team-edit.html"
} )
. when ( "/teams/:teamId/stats" , {
controller : "TeamController" ,
templateUrl : "views/team-stats.html"
} )
. when ( "/teams/:teamId/score" , {
controller : "TeamController" ,
templateUrl : "views/team-score.html"
} )
. when ( "/public/:screenId" , {
controller : "PublicController" ,
templateUrl : "views/public.html"
} )
. when ( "/files" , {
controller : "FilesListController" ,
templateUrl : "views/file-list.html"
} )
. when ( "/events" , {
controller : "EventsListController" ,
templateUrl : "views/event-list.html"
} )
. when ( "/events/:eventId" , {
controller : "EventController" ,
templateUrl : "views/event.html"
} )
. when ( "/claims" , {
controller : "ClaimsListController" ,
templateUrl : "views/claim-list.html"
} )
. when ( "/claims/:claimId" , {
controller : "ClaimController" ,
templateUrl : "views/claim.html"
} )
. when ( "/" , {
templateUrl : "views/home.html"
} ) ;
$locationProvider . html5Mode ( true ) ;
} ) ;
2016-01-13 00:22:54 +00:00
2018-01-17 00:21:32 +00:00
function setCookie ( name , value , days ) {
2024-09-18 16:06:23 +00:00
var expires ;
if ( days ) {
var date = new Date ( ) ;
date . setTime ( date . getTime ( ) + ( days * 24 * 60 * 60 * 1000 ) ) ;
expires = "; expires=" + date . toGMTString ( ) ;
} else {
expires = "" ;
}
document . cookie = encodeURIComponent ( name ) + "=" + encodeURIComponent ( value ) + expires + "; path=/" ;
2018-01-17 00:21:32 +00:00
}
function getCookie ( name ) {
2024-09-18 16:06:23 +00:00
var nameEQ = encodeURIComponent ( name ) + "=" ;
var ca = document . cookie . split ( ';' ) ;
for ( var i = 0 ; i < ca . length ; i ++ ) {
var c = ca [ i ] ;
while ( c . charAt ( 0 ) === ' ' )
c = c . substring ( 1 , c . length ) ;
if ( c . indexOf ( nameEQ ) === 0 )
return decodeURIComponent ( c . substring ( nameEQ . length , c . length ) ) ;
}
return null ;
2018-01-17 00:21:32 +00:00
}
2018-01-07 23:41:23 +00:00
angular . module ( "FICApp" )
2024-09-18 16:06:23 +00:00
. directive ( 'autofocus' , [ '$timeout' , function ( $timeout ) {
return {
restrict : 'A' ,
link : function ( $scope , $element ) {
$timeout ( function ( ) {
$element [ 0 ] . focus ( ) ;
} ) ;
}
}
} ] )
. component ( 'toast' , {
bindings : {
date : '=' ,
msg : '=' ,
timeout : '=' ,
title : '=' ,
variant : '=' ,
yesNo : '=' ,
onyes : '=' ,
onno : '=' ,
} ,
controller : function ( $element ) {
if ( this . timeout === 0 )
$element . children ( 0 ) . toast ( { autohide : false } ) ;
else if ( ! this . timeout && this . timeout !== 0 )
$element . children ( 0 ) . toast ( { delay : 7000 } ) ;
else
$element . children ( 0 ) . toast ( { delay : this . timeout } ) ;
$element . children ( 0 ) . toast ( 'show' ) ;
$element . children ( 0 ) . on ( 'hidden.bs.toast' , function ( ) {
$element . children ( 0 ) . toast ( 'dispose' ) ;
} ) ;
this . yesFunc = function ( ) {
$element . children ( 0 ) . toast ( 'hide' ) ;
if ( this . onyes )
this . onyes ( ) ;
}
this . noFunc = function ( ) {
$element . children ( 0 ) . toast ( 'hide' ) ;
if ( this . onno )
this . onno ( ) ;
}
} ,
template : ` <div class="toast mb-2" role="alert" aria-live="assertive" aria-atomic="true">
2020-03-08 11:48:25 +00:00
< div class = "toast-header" >
< span ng - if = "$ctrl.variant" class = "badge badge-pill badge-{{ $ctrl.variant }}" style = "padding: .25em .66em" > & nbsp ; < / s p a n > & n b s p ;
< strong class = "mr-auto" ng - bind = "$ctrl.title" > < / s t r o n g >
< small class = "text-muted" ng - bind = "$ctrl.date" > just now < / s m a l l >
< button type = "button" class = "ml-2 mb-1 close" data - dismiss = "toast" aria - label = "Close" >
< span aria - hidden = "true" > & times ; < / s p a n >
< / b u t t o n >
< / d i v >
2022-05-31 14:41:36 +00:00
< div class = "toast-body text-break" ng - bind - html = "$ctrl.msg" ng - if = "$ctrl.msg" > < / d i v >
2020-03-08 11:48:25 +00:00
< div class = "d-flex justify-content-around mb-1" ng - if = "$ctrl.yesNo" >
< button type = "button" class = "ml-2 btn btn-sm btn-success" ng - click = "$ctrl.yesFunc()" > Yes < / b u t t o n >
< button type = "button" class = "btn btn-sm btn-danger" ng - click = "$ctrl.noFunc()" > No < / b u t t o n >
< / d i v >
< / d i v > `
2024-09-18 16:06:23 +00:00
} ) ;
2018-01-07 23:41:23 +00:00
2016-01-13 00:22:54 +00:00
angular . module ( "FICApp" )
2024-09-18 16:06:23 +00:00
. factory ( "Version" , function ( $resource ) {
return $resource ( "api/version" )
} )
. factory ( "Timestamp" , function ( $resource ) {
return $resource ( "api/timestamps.json" )
} )
. factory ( "Health" , function ( $resource ) {
return $resource ( "api/health.json" )
} )
. factory ( "Monitor" , function ( $resource ) {
return $resource ( "api/monitor/:machineId" , { machineId : '@id' } )
} )
. factory ( "Event" , function ( $resource ) {
return $resource ( "api/events/:eventId" , { eventId : '@id' } , {
'update' : { method : 'PUT' } ,
} )
} )
. factory ( "Claim" , function ( $resource ) {
return $resource ( "api/claims/:claimId" , { claimId : '@id' } , {
'update' : { method : 'PUT' } ,
} )
} )
. factory ( "ClaimAssignee" , function ( $resource ) {
return $resource ( "api/claims-assignees/:assigneeId" , { assigneeId : '@id' } , {
'update' : { method : 'PUT' } ,
} )
} )
. factory ( "Certificate" , function ( $resource ) {
return $resource ( "api/certs/:serial" , { serial : '@id' } , {
'update' : { method : 'PUT' } ,
} )
} )
. factory ( "CACertificate" , function ( $resource ) {
return $resource ( "api/ca/:serial" , { serial : '@id' } )
} )
. factory ( "File" , function ( $resource ) {
return $resource ( "api/files/:fileId" , { fileId : '@id' } )
} )
. factory ( "ROSettings" , function ( $resource ) {
return $resource ( "api/settings-ro.json" )
} )
. factory ( "Settings" , function ( $resource ) {
return $resource ( "api/settings.json" , null , {
'update' : { method : 'PUT' } ,
} )
} )
. factory ( "NextSettings" , function ( $resource ) {
return $resource ( "api/settings-next/:tsId" , { tsId : '@id' } , {
'update' : { method : 'PUT' } ,
} )
} )
. factory ( "SettingsChallenge" , function ( $resource ) {
return $resource ( "api/challenge.json" , null , {
'update' : { method : 'PUT' } ,
} )
} )
. factory ( "Scene" , function ( $resource ) {
return $resource ( "api/public/:screenId" , { screenId : '@id' } , {
'update' : { method : 'PUT' } ,
} )
} )
. factory ( "Team" , function ( $resource ) {
return $resource ( "api/teams/:teamId" , { teamId : '@id' } , {
'update' : { method : 'PUT' } ,
} )
} )
. factory ( "TeamCertificate" , function ( $resource ) {
return $resource ( "api/teams/:teamId/certificates" , { teamId : '@id' } )
} )
. factory ( "TeamAssociation" , function ( $resource ) {
return $resource ( "api/teams/:teamId/associations/:assoc" , { teamId : '@teamId' , assoc : '@assoc' } )
} )
. factory ( "TeamMember" , function ( $resource ) {
return $resource ( "api/teams/:teamId/members" , { teamId : '@id' } , {
'save' : { method : 'PUT' } ,
} )
} )
. factory ( "TeamMy" , function ( $resource ) {
return $resource ( "api/teams/:teamId/my.json" , { teamId : '@id' } )
} )
. factory ( "Teams" , function ( $resource ) {
return $resource ( "api/teams.json" )
} )
. factory ( "TeamHistory" , function ( $resource ) {
return $resource ( "api/teams/:teamId/history.json" , { teamId : '@id' } )
} )
. factory ( "TeamScore" , function ( $resource ) {
return $resource ( "api/teams/:teamId/score-grid.json" , { teamId : '@id' } )
} )
. factory ( "TeamStats" , function ( $resource ) {
return $resource ( "api/teams/:teamId/stats.json" , { teamId : '@id' } )
} )
. factory ( "TeamPresence" , function ( $resource ) {
return $resource ( "api/teams/:teamId/tries" , { teamId : '@id' } )
} )
. factory ( "Theme" , function ( $resource ) {
return $resource ( "api/themes/:themeId" , { themeId : '@id' } , {
update : { method : 'PUT' }
} ) ;
} )
. factory ( "Themes" , function ( $resource ) {
return $resource ( "api/themes.json" , null , {
'get' : { method : 'GET' } ,
} )
} )
. factory ( "ThemedExercice" , function ( $resource ) {
return $resource ( "api/themes/:themeId/exercices/:exerciceId" , { themeId : '@id' , exerciceId : '@idExercice' } , {
update : { method : 'PUT' }
} )
} )
. factory ( "Exercice" , function ( $resource ) {
return $resource ( "api/exercices/:exerciceId" , { exerciceId : '@id' } , {
update : { method : 'PUT' } ,
patch : { method : 'PATCH' }
} )
} )
. factory ( "ExerciceClaims" , function ( $resource ) {
return $resource ( "api/exercices/:exerciceId/claims" , { exerciceId : '@idExercice' } )
} )
. factory ( "ExerciceTags" , function ( $resource ) {
return $resource ( "api/exercices/:exerciceId/tags" , { exerciceId : '@idExercice' } , {
update : { method : 'PUT' }
} )
} )
. factory ( "ExerciceHistory" , function ( $resource ) {
return $resource ( "api/exercices/:exerciceId/history.json" , { exerciceId : '@id' } )
} )
. factory ( "ExercicesStats" , function ( $resource ) {
return $resource ( "api/exercices_stats.json" , { themeId : '@id' } )
} )
. factory ( "ExerciceStats" , function ( $resource ) {
return $resource ( "api/exercices/:exerciceId/stats.json" , { exerciceId : '@id' } )
} )
. factory ( "ExerciceFile" , function ( $resource ) {
return $resource ( "api/exercices/:exerciceId/files/:fileId" , { exerciceId : '@idExercice' , fileId : '@id' } , {
update : { method : 'PUT' }
} )
} )
. factory ( "ExerciceHint" , function ( $resource ) {
return $resource ( "api/exercices/:exerciceId/hints/:hintId" , { exerciceId : '@idExercice' , hintId : '@id' } , {
update : { method : 'PUT' }
} )
} )
. factory ( "ExerciceHintDeps" , function ( $resource ) {
return $resource ( "api/exercices/:exerciceId/hints/:hintId/dependancies" , { exerciceId : '@idExercice' , hintId : '@id' } )
} )
. factory ( "ExerciceFlag" , function ( $resource ) {
return $resource ( "api/exercices/:exerciceId/flags/:flagId" , { exerciceId : '@idExercice' , flagId : '@id' } , {
update : { method : 'PUT' }
} )
} )
. factory ( "ExerciceFlagChoices" , function ( $resource ) {
return $resource ( "api/exercices/:exerciceId/flags/:flagId/choices/:choiceId" , { exerciceId : '@idExercice' , flagId : '@idFlag' , choiceId : '@id' } , {
'update' : { method : 'PUT' } ,
} )
} )
. factory ( "ExerciceFlagDeps" , function ( $resource ) {
return $resource ( "api/exercices/:exerciceId/flags/:flagId/dependancies" , { exerciceId : '@idExercice' , flagId : '@id' } )
} )
. factory ( "ExerciceMCQFlag" , function ( $resource ) {
return $resource ( "api/exercices/:exerciceId/quiz/:mcqId" , { exerciceId : '@idExercice' , mcqId : '@id' } , {
update : { method : 'PUT' }
} )
} )
. factory ( "ExerciceMCQDeps" , function ( $resource ) {
return $resource ( "api/exercices/:exerciceId/quiz/:mcqId/dependancies" , { exerciceId : '@idExercice' , mcqId : '@id' } )
2016-12-15 23:51:56 +00:00
} ) ;
2016-01-13 00:22:54 +00:00
angular . module ( "FICApp" )
2024-09-18 16:06:23 +00:00
. filter ( "countHints" , function ( ) {
return function ( input ) {
if ( input == undefined )
return 0 ;
return input . reduce ( function ( sum , n ) { return sum + ( n . content || n . file ) ? 1 : 0 ; } , 0 ) ;
}
} )
. filter ( "toColor" , function ( ) {
return function ( num ) {
num >>>= 0 ;
var b = ( num & 0xFF ) . toString ( 16 ) ,
g = ( ( num & 0xFF00 ) >>> 8 ) . toString ( 16 ) ,
r = ( ( num & 0xFF0000 ) >>> 16 ) . toString ( 16 ) ,
a = ( ( num & 0xFF000000 ) >>> 24 ) / 255 ;
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 ;
}
} )
. filter ( "cksum" , function ( ) {
return function ( input ) {
if ( input == undefined )
return input ;
var raw = atob ( input ) . toString ( 16 ) ;
var hex = '' ;
for ( var i = 0 ; i < raw . length ; i ++ ) {
var _hex = raw . charCodeAt ( i ) . toString ( 16 )
hex += ( _hex . length == 2 ? _hex : '0' + _hex ) ;
}
return hex
}
} )
. component ( 'dependancy' , {
bindings : {
dep : '=' ,
deleteDep : '=' ,
} ,
controller : function ( ) { } ,
template : `
2020-01-23 13:23:02 +00:00
< li >
< span ng - if = "$ctrl.dep.label" > Flag { { $ctrl . dep . label } } < / s p a n >
< span ng - if = "$ctrl.dep.title" > QCM { { $ctrl . dep . title } } < / s p a n >
< button type = "button" class = "btn btn-sm btn-danger" ng - if = "$ctrl.deleteDep" ng - click = "$ctrl.deleteDep()" > < span class = "glyphicon glyphicon-trash" > < / s p a n > < / b u t t o n >
< / l i >
`
2024-09-18 16:06:23 +00:00
} )
2023-06-17 00:07:27 +00:00
2024-09-18 16:06:23 +00:00
. directive ( 'color' , function ( ) {
return {
require : 'ngModel' ,
link : function ( scope , ele , attr , ctrl ) {
ctrl . $formatters . unshift ( function ( num ) {
num >>>= 0 ;
var b = ( num & 0xFF ) . toString ( 16 ) ,
g = ( ( num & 0xFF00 ) >>> 8 ) . toString ( 16 ) ,
r = ( ( num & 0xFF0000 ) >>> 16 ) . toString ( 16 ) ,
a = ( ( num & 0xFF000000 ) >>> 24 ) / 255 ;
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 ;
} ) ;
ctrl . $parsers . unshift ( function ( viewValue ) {
var result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i . exec ( viewValue ) ;
return result ? (
parseInt ( result [ 1 ] , 16 ) * 256 * 256 +
parseInt ( result [ 2 ] , 16 ) * 256 +
parseInt ( result [ 3 ] , 16 )
) : 0 ;
} ) ;
2024-02-09 16:56:05 +00:00
}
2024-09-18 16:06:23 +00:00
} ;
} )
2023-07-25 07:04:31 +00:00
2024-09-18 16:06:23 +00:00
. directive ( 'integer' , function ( ) {
return {
require : 'ngModel' ,
link : function ( scope , ele , attr , ctrl ) {
ctrl . $parsers . unshift ( function ( viewValue ) {
return parseInt ( viewValue , 10 ) ;
} ) ;
}
} ;
} )
. directive ( 'float' , function ( ) {
return {
require : 'ngModel' ,
link : function ( scope , ele , attr , ctrl ) {
ctrl . $parsers . unshift ( function ( viewValue ) {
return parseFloat ( viewValue , 10 ) ;
} ) ;
}
} ;
} )
. run ( function ( $rootScope , $http , $interval , $timeout , Settings , $location ) {
$rootScope . $location = $location ;
$rootScope . Utils = {
keys : Object . keys
} ;
$rootScope . refreshSettings = function ( ) {
$http . get ( "api/settings.json" ) . then ( function ( response ) {
response . data . start = new Date ( response . data . start ) ;
response . data . end = new Date ( response . data . end ) ;
response . data . generation = new Date ( response . data . generation ) ;
if ( $rootScope . settings && $rootScope . settings . activateTime instanceof Date )
response . data . activateTime = $rootScope . settings . activateTime ;
$rootScope . settings = response . data ;
$rootScope . recvTime ( response ) ;
} )
}
$rootScope . refreshSettings ( ) ;
$interval ( $rootScope . refreshSettings , 10000 ) ;
$rootScope . toasts = [ ] ;
$rootScope . addToast = function ( kind , title , msg , yesFunc , noFunc , tmout ) {
$rootScope . toasts . unshift ( {
variant : kind ,
title : title ,
msg : msg ,
timeout : tmout ,
yesFunc : yesFunc ,
noFunc : noFunc ,
2019-02-05 00:44:41 +00:00
} ) ;
2024-09-18 16:06:23 +00:00
}
2017-12-17 23:30:23 +00:00
2024-09-18 16:06:23 +00:00
$rootScope . staticFilesNeedUpdate = 0 ;
$rootScope . staticRegenerationInProgress = false ;
$rootScope . regenerateStaticFiles = function ( ) {
$rootScope . staticRegenerationInProgress = true ;
$http . post ( "api/full-generation" ) . then ( function ( response ) {
$rootScope . staticFilesNeedUpdate = 0 ;
$rootScope . staticRegenerationInProgress = false ;
$rootScope . addToast ( 'success' , 'Regeneration ended' ) ;
} , function ( response ) {
$rootScope . staticRegenerationInProgress = false ;
$rootScope . addToast ( 'error' , 'An error occurs when saving settings:' , response . data . errmsg ) ;
} )
}
2019-01-19 07:01:29 +00:00
2024-09-18 16:06:23 +00:00
$rootScope . $on ( '$locationChangeStart' , function ( event , next , current ) {
if ( $rootScope . staticFilesNeedUpdate ) {
$timeout ( function ( ) {
document . getElementById ( "circle1" ) . classList . add ( "play" ) ;
} , 10 ) ;
$timeout ( function ( ) {
document . getElementById ( "circle1" ) . classList . remove ( "play" ) ;
} , 710 ) ;
$timeout ( function ( ) {
document . getElementById ( "circle2" ) . classList . add ( "play" ) ;
} , 50 ) ;
$timeout ( function ( ) {
document . getElementById ( "circle2" ) . classList . remove ( "play" ) ;
} , 750 ) ;
}
2016-12-26 02:44:04 +00:00
} ) ;
2024-09-18 16:06:23 +00:00
$rootScope . logged = parseInt ( getCookie ( "myassignee" ) ) > 0 ;
} )
2018-01-17 00:21:32 +00:00
2024-09-18 16:06:23 +00:00
. controller ( "VersionController" , function ( $scope , Version ) {
$scope . v = Version . get ( ) ;
} )
2018-12-08 20:17:37 +00:00
2024-09-18 16:06:23 +00:00
. controller ( "TimestampController" , function ( $scope , $interval , Timestamp ) {
$scope . t = Timestamp . get ( ) ;
var refresh = function ( ) {
$scope . t = Timestamp . get ( ) ;
}
var myinterval = $interval ( refresh , 2500 ) ;
$scope . $on ( '$destroy' , function ( ) { $interval . cancel ( myinterval ) ; } ) ;
} )
2018-11-21 00:19:13 +00:00
2024-09-18 16:06:23 +00:00
. controller ( "HealthController" , function ( $scope , $interval , Health , $http ) {
var refresh = function ( ) {
$scope . health = Health . query ( ) ;
2018-11-21 00:19:13 +00:00
}
2024-09-18 16:06:23 +00:00
refresh ( ) ;
var myinterval = $interval ( refresh , 2500 ) ;
$scope . drop _submission = function ( path ) {
$scope . addToast ( 'info' , 'Delete submission' , 'Ensure this submission is not interesting. Continue?' ,
function ( ) {
$http . delete ( "api/submissions" + path ) . then ( function ( response ) {
refresh ( ) ;
} , function ( response ) {
$scope . addToast ( 'danger' , 'An error occurs when deleting submission:' , response . data . errmsg ) ;
} ) ;
}
) ;
}
$scope . $on ( '$destroy' , function ( ) { $interval . cancel ( myinterval ) ; } ) ;
} )
2018-11-21 00:19:13 +00:00
2024-09-18 16:06:23 +00:00
. controller ( "MonitorController" , function ( $scope , Monitor ) {
$scope . monitor = Monitor . get ( ) ;
} )
2017-12-17 14:39:20 +00:00
2024-09-18 16:06:23 +00:00
. controller ( "AllTeamAssociationsController" , function ( $scope , $http ) {
$scope . allAssociations = [ ] ;
$http . get ( "api/teams-associations.json" ) . then ( function ( response ) {
$scope . allAssociations = response . data ;
} )
} )
2023-04-03 23:49:38 +00:00
2024-09-18 16:06:23 +00:00
. controller ( "SettingsController" , function ( $scope , $rootScope , NextSettings , Settings , SettingsChallenge , $location , $http , $interval ) {
$scope . nextsettings = NextSettings . query ( ) ;
$scope . erase = false ;
$scope . editNextSettings = function ( ns ) {
$scope . activateTime = new Date ( ns . date ) ;
$rootScope . settings . activateTime = $scope . activateTime ;
$scope . erase = true ;
Object . keys ( ns . values ) . forEach ( function ( k ) {
$scope . config [ k ] = ns . values [ k ] ;
} ) ;
$scope . config . enableExerciceDepend = $scope . config . unlockedChallengeDepth >= 0 ;
$scope . config . disabledsubmitbutton = $scope . config . disablesubmitbutton && $scope . config . disablesubmitbutton . length > 0 ;
}
$scope . deleteNextSettings = function ( ns ) {
ns . $delete ( ) . then ( function ( ) {
$scope . nextsettings = NextSettings . query ( ) ;
} )
}
$scope . displayDangerousActions = false ;
$scope . config = Settings . get ( ) ;
$scope . dist _config = { } ;
$scope . config . $promise . then ( function ( response ) {
response . start = new Date ( response . start ) ;
if ( response . end ) response . end = new Date ( response . end ) ;
else response . end = null ;
response . generation = new Date ( response . generation ) ;
response . activateTime = new Date ( response . activateTime ) ;
$scope . dist _config = Object . assign ( { } , response ) ;
response . enableExerciceDepend = response . unlockedChallengeDepth >= 0 ;
response . disabledsubmitbutton = response . disablesubmitbutton && response . disablesubmitbutton . length > 0 ;
} )
$scope . challenge = SettingsChallenge . get ( ) ;
$scope . duration = 360 ;
$scope . activateTime = "" ;
$scope . challenge . $promise . then ( function ( c ) {
if ( c . duration )
$scope . duration = c . duration ;
2019-07-12 17:17:17 +00:00
} ) ;
2019-02-03 21:30:29 +00:00
2024-09-18 16:06:23 +00:00
$scope . exerciceDependChange = function ( ) {
if ( $scope . config . enableExerciceDepend )
$scope . config . unlockedChallengeDepth = 0 ;
else
$scope . config . unlockedChallengeDepth = - 1 ;
} ;
$scope . submitButtonStateChange = function ( ) {
if ( $scope . config . disabledsubmitbutton )
$scope . config . disablesubmitbutton = "Mise à jour en cours..." ;
else
$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 ) {
$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 ( ) ;
}
2016-12-26 00:23:31 +00:00
2024-09-18 16:06:23 +00:00
$scope . saveChallengeInfo = function ( ) {
this . challenge . duration = $scope . duration ;
this . challenge . $update ( function ( response ) {
$scope . addToast ( 'success' , 'Infos du challenge mises à jour avec succès !' ) ;
} , function ( response ) {
$scope . addToast ( 'danger' , 'An error occurs when saving challenge info:' , response . data . errmsg ) ;
} ) ;
}
$scope . saveSettings = function ( msg ) {
if ( msg === undefined ) { msg = 'New settings saved!' ; }
if ( this . config . end == "" ) this . config . end = null ;
var nStart = this . config . start ;
var nEnd = this . config . end ;
var nGen = this . config . generation ;
var state = this . config . enableExerciceDepend ;
this . config . unlockedChallengeDepth = ( this . config . enableExerciceDepend ? this . config . unlockedChallengeDepth : - 1 )
this . config . disablesubmitbutton = ( this . config . disabledsubmitbutton ? this . config . disablesubmitbutton : '' )
var updateQuery = { } ;
if ( this . activateTime && this . activateTime != '' ) {
updateQuery [ 't' ] = this . activateTime ;
this . activateTime = null ;
}
if ( this . erase ) {
updateQuery [ 'erase' ] = true ;
this . erase = false ;
}
this . config . $update ( updateQuery , function ( response ) {
$scope . dist _config = Object . assign ( { } , response ) ;
$scope . addToast ( 'success' , msg ) ;
$scope . nextsettings = NextSettings . query ( ) ;
response . enableExerciceDepend = response . unlockedChallengeDepth >= 0 ;
response . disabledsubmitbutton = response . disablesubmitbutton && response . disablesubmitbutton . length > 0 ;
$rootScope . settings . start = new Date ( nStart ) ;
if ( nEnd ) {
$rootScope . settings . end = new Date ( nEnd ) ;
} else {
$rootScope . settings . end = null ;
}
$rootScope . settings . generation = new Date ( nGen ) ;
$scope . updateActivateTime ( ) ;
} , function ( response ) {
$scope . addToast ( 'danger' , 'An error occurs when saving settings:' , response . data . errmsg ) ;
} ) ;
}
$scope . launchChallenge = function ( ) {
var ts = $rootScope . getSrvTime ( ) . getTime ( ) - $rootScope . getSrvTime ( ) . getTime ( ) % 60000 ;
this . config . start = new Date ( ts + 120000 ) ;
this . config . end = new Date ( ts + 120000 + this . duration * 60000 ) ;
$scope . addToast ( 'info' , 'Challenge ready to start,' , 'propagate the changes?' ,
function ( ) {
$scope . saveSettings ( ) ;
} ) ;
}
$scope . updateActivateTime = function ( ) {
$rootScope . settings . activateTime = this . activateTime ;
}
$scope . updActivateTime = function ( modulo ) {
if ( modulo ) {
var ts = Math . floor ( ( new Date ( this . config . end ) - $rootScope . getSrvTime ( ) . getTime ( ) - ( 60000 * modulo / 2 ) ) / ( 60000 * modulo ) ) * ( 60000 * modulo ) ;
var d = new Date ( this . config . end ) - ts ;
this . activateTime = new Date ( d ) ;
this . updateActivateTime ( ) ;
} else {
this . activateTime = null ;
this . updateActivateTime ( ) ;
}
}
$scope . reset = function ( type ) {
var txts = {
"settings" : "En validant, vous remettrez les paramètres de cette page à leur valeur initiale, y compris la date de début du challenge." ,
"challengeInfo" : "En validant, vous effacerez les informations descriptives du challenge." ,
"challenges" : "En validant, vous retirerez toutes les données statiques des challenges." ,
"teams" : "En validant, vous supprimerez l'ensemble des équipes enregistreées." ,
"game" : "En validant, vous supprimerez toutes les tentatives, les validations, ... faites par les équipes." ,
}
$scope . addToast ( 'warning' , txts [ type ] , 'Êtes-vous sûr de vouloir continuer ?' ,
function ( ) {
if ( confirm ( "Êtes-vous vraiment sûr ?\n" + txts [ type ] ) ) {
$http . post ( "api/reset" , { "type" : type } ) . then ( function ( time ) {
$scope . addToast ( 'success' , type + 'reseted' ) ;
$location . url ( "/" ) ;
} , function ( response ) {
$scope . addToast ( 'danger' , 'An error occurs when reseting ' + type + ':' , response . data . errmsg ) ;
} ) ;
}
} ) ;
} ;
$scope . switchToProd = function ( ) {
$scope . addToast ( 'warning' , "Activer le mode challenge ?" , "L'activation du mode challenge est temporaire (vous devriez plutôt relancer le daemon avec l'option `-4real`). Ce mode permet d'éviter les mauvaises manipulations et désactive le hook git de synchronisation automatique. Êtes-vous sûr de vouloir continuer ?" ,
function ( ) {
$http . put ( "api/prod" , true ) . then ( function ( time ) {
$rootScope . refreshSettings ( )
$scope . addToast ( 'success' , 'Mode challenge activé' ) ;
} , function ( response ) {
$scope . addToast ( 'danger' , 'An error occurs when activating challenge mode:' , response . data . errmsg ) ;
} ) ;
} ) ;
} ;
} )
2016-12-26 00:23:31 +00:00
2024-09-18 16:06:23 +00:00
. controller ( "RepositoriesController" , function ( $scope , $http ) {
$http . get ( "api/repositories" ) . then ( function ( response ) {
$scope . repositories = response . data . repositories ;
} ) ;
} )
. component ( 'repositoryUptodate' , {
bindings : {
repository : '<' ,
} ,
controller : function ( $http ) {
var ctrl = this ;
ctrl . status = { } ;
ctrl . color = "badge-secondary" ;
ctrl . $onInit = function ( ) {
$http . post ( "api/repositories/" + ctrl . repository . path ) . then ( function ( response ) {
ctrl . status = response . data ;
if ( ctrl . repository . hash . startsWith ( ctrl . status . hash ) ) {
ctrl . color = "badge-success" ;
} else {
ctrl . color = "badge-danger" ;
}
} ) ;
} ;
} ,
template : ` <span class="badge {{ $ ctrl.color }}">{{ $ ctrl.status.hash }}</span> <small>{{ $ ctrl.status.text }}</small> `
} )
2016-12-26 00:23:31 +00:00
2024-09-18 16:06:23 +00:00
. controller ( "SyncController" , function ( $scope , $rootScope , ROSettings , $location , $http , $interval ) {
$scope . displayDangerousActions = false ;
$scope . configro = ROSettings . get ( ) ;
var needRefreshSyncReportWhenReady = false ;
var refreshSyncReport = function ( ) {
needRefreshSyncReportWhenReady = false ;
$http . get ( "full_import_report.json" ) . then ( function ( response ) {
$scope . syncReport = response . data ;
} )
} ;
refreshSyncReport ( )
var progressInterval = $interval ( function ( ) {
$http . get ( "api/sync/deep" ) . then ( function ( response ) {
if ( response . data . progress && response . data . progress != 255 )
needRefreshSyncReportWhenReady = true ;
else if ( needRefreshSyncReportWhenReady )
refreshSyncReport ( ) ;
if ( response . data && response . data . progress ) {
$scope . syncPercent = Math . floor ( response . data . progress * 100 / 255 ) ;
$scope . syncProgress = Math . floor ( response . data . progress * 100 / 255 ) + " %" ;
} else {
$scope . syncProgress = response . data ;
$scope . syncPercent = 0 ;
}
} , function ( response ) {
$scope . syncPercent = 0 ;
if ( response . data && response . data . errmsg )
$scope . syncProgress = response . data . errmsg ;
else
$scope . syncProgress = response . data ;
} )
} , 1500 ) ;
$scope . $on ( '$destroy' , function ( ) { $interval . cancel ( progressInterval ) ; } ) ;
$scope . deepSyncInProgress = false ;
$scope . deepSync = function ( theme ) {
if ( theme ) {
question = 'Faire une synchronisation intégrale du thème ' + theme . name + ' ?'
url = "api/sync/deep/" + theme . id
} else {
question = 'Faire une synchronisation intégrale ?'
url = "api/sync/deep"
}
$scope . addToast ( 'warning' , question , '' ,
function ( ) {
$scope . deepSyncInProgress = true ;
$http . post ( url ) . then ( function ( ) {
$scope . deepSyncInProgress = false ;
$scope . addToast ( 'success' , 'Synchronisation intégrale terminée.' , '<a href="check_import.html" target="_self">Voir le rapport</a>.' , null , null , 15000 ) ;
} , function ( response ) {
$scope . deepSyncInProgress = false ;
$scope . addToast ( 'warning' , 'Synchronisation intégrale terminée.' , '<a href="check_import.html" target="_self">Voir le rapport</a>.' , null , null , 15000 ) ;
} ) ;
} ) ;
} ;
$scope . speedyDeepSync = function ( ) {
$scope . addToast ( 'warning' , 'Faire une synchronisation profonde rapide, sans s\'occuper des fichiers ?' , '' ,
function ( ) {
$scope . deepSyncInProgress = true ;
$http . post ( "api/sync/speed" ) . then ( function ( ) {
$scope . deepSyncInProgress = false ;
$scope . addToast ( 'success' , 'Synchronisation profonde rapide terminée.' , '<a href="check_import.html" target="_self">Voir le rapport</a>.' , null , null , 15000 ) ;
} , function ( response ) {
$scope . deepSyncInProgress = false ;
$scope . addToast ( 'warning' , 'Synchronisation profinde rapide terminée.' , '<a href="check_import.html" target="_self">Voir le rapport</a>.' , null , null , 15000 ) ;
} ) ;
} ) ;
} ;
$scope . baseSync = function ( ) {
$scope . addToast ( 'warning' , 'Tirer les mises à jour du dépôt ?' , '' ,
function ( ) {
$scope . deepSyncInProgress = true ;
$http . post ( "api/sync/base" ) . then ( function ( ) {
$scope . deepSyncInProgress = false ;
$scope . addToast ( 'success' , 'Mise à jour terminée.' ) ;
} , function ( response ) {
$scope . deepSyncInProgress = false ;
$scope . addToast ( 'danger' , 'Mise à jour terminée.' , response . data . errmsg ) ;
} ) ;
} ) ;
} ;
$scope . syncVideos = function ( ) {
$scope . addToast ( 'warning' , 'Synchroniser les vidéos de résolution ?' , 'ATTENTION il ne faut pas lancer cette synchronisation durant le challenge. Seulement une fois le challenge terminé, cela permet de rendre les vidéos accessibles dans l\'interface joueurs.' ,
function ( ) {
$scope . deepSyncInProgress = true ;
$http . post ( "api/sync/videos" ) . then ( function ( ) {
$scope . deepSyncInProgress = false ;
$scope . addToast ( 'success' , 'Import des vidéos terminé.' ) ;
} , function ( response ) {
$scope . deepSyncInProgress = false ;
$scope . addToast ( 'danger' , 'Import des vidéos terminé.' , response . data . errmsg ) ;
} ) ;
} ) ;
} ;
$scope . dropSoluces = function ( ) {
$scope . addToast ( 'warning' , 'Effacer les solutions' , 'Ceci va retirer les textes de résolution de la base de données ainsi que les liens vers les vidéos.' ,
function ( ) {
$scope . deepSyncInProgress = true ;
$http . post ( "api/sync/drop_soluces" ) . then ( function ( ) {
$scope . deepSyncInProgress = false ;
$scope . addToast ( 'success' , 'Effacement des solutions terminé.' ) ;
} , function ( response ) {
$scope . deepSyncInProgress = false ;
$scope . addToast ( 'danger' , 'Effacement des solutions terminé avec des erreurs.' , response . data . errmsg ) ;
} ) ;
} ) ;
} ;
} )
2020-01-23 13:23:02 +00:00
2024-09-18 16:06:23 +00:00
. controller ( "PKIController" , function ( $scope , $rootScope , Certificate , CACertificate , Team , $location , $http ) {
var ts = Date . now ( ) - Date . now ( ) % 86400000 ;
var d = new Date ( ts ) ;
var f = new Date ( ts + 3 * 86400000 ) ;
$scope . newca = {
notAfter : f . toISOString ( ) ,
notBefore : d . toISOString ( ) ,
} ;
2016-12-26 00:23:31 +00:00
2024-09-18 16:06:23 +00:00
$scope . teams = Team . query ( ) ;
$scope . certificates = Certificate . query ( ) ;
$scope . ca = CACertificate . get ( ) ;
2020-01-28 13:05:00 +00:00
2024-09-18 16:06:23 +00:00
$scope . revoke = function ( ) {
var targetserial = $ ( "#revokeModal" ) . data ( "certificate" ) ;
if ( targetserial ) {
Certificate . delete ( { serial : targetserial } ) . $promise . then (
function ( ) {
$ ( '#revokeModal' ) . modal ( 'hide' ) ;
$scope . certificates = Certificate . query ( ) . $promise . then ( function ( certificates ) {
certificates . forEach ( function ( certificate , cid ) {
certificate . serial = parseInt ( certificate . id ) . toString ( 16 ) ;
} ) ;
} ) ;
} , function ( response ) {
$scope . addToast ( 'danger' , 'An error occurs when trying to associate certificate:' , response . data . errmsg ) ;
}
) ;
}
} ;
$scope . validateSearch = function ( keyEvent ) {
if ( keyEvent . which === 13 ) {
var myCertificate = null ;
$scope . certificates . forEach ( function ( certificate ) {
if ( String ( certificate . id ) . indexOf ( $scope . query . toUpperCase ( ) ) >= 0 ) {
if ( myCertificate === null )
myCertificate = certificate ;
else
myCertificate = false ;
}
} ) ;
if ( myCertificate && myCertificate . id _team == null ) {
$ ( '#associationModal' ) . data ( 'certificate' , myCertificate . id )
$ ( '#associationModal' ) . modal ( )
}
}
} ;
$scope . validatePKIForm = function ( keyEvent ) {
if ( keyEvent . which === 13 )
$scope . associate ( )
} ;
$scope . associate = function ( ) {
var targetserial = $ ( "#associationModal" ) . data ( "certificate" ) ;
if ( ! targetserial ) return ;
Certificate . update ( { serial : targetserial } , { id _team : $scope . selectedTeam } ) . $promise . then (
function ( ) {
$ ( '#associationModal' ) . modal ( 'hide' ) ;
$scope . certificates = Certificate . query ( ) ;
$scope . selectedTeam = null ;
} , function ( response ) {
$scope . addToast ( 'danger' , 'An error occurs when trying to associate certificate:' , response . data . errmsg ) ;
}
) ;
} ;
$scope . generateCA = function ( ) {
$http . post ( "api/ca/new" , $scope . newca ) . then ( function ( ) {
$scope . ca = CACertificate . get ( ) ;
} , function ( response ) {
$scope . addToast ( 'danger' , 'An error occurs when generating CA:' , response . data . errmsg ) ;
} ) ;
} ;
$scope . renewCA = function ( ) {
$scope . ca = { } ;
} ;
$scope . generateCert = function ( ) {
$http . post ( "api/certs" ) . then ( function ( ) {
$scope . certificates = Certificate . query ( ) ;
} , function ( response ) {
$scope . addToast ( 'danger' , 'An error occurs when generating certificate:' , response . data . errmsg ) ;
} ) ;
} ;
$scope . generateHtpasswd = function ( ) {
$http . post ( "api/htpasswd" ) . then ( function ( ) {
$scope . addToast ( 'success' , 'Fichier htpasswd généré avec succès' ) ;
} , function ( response ) {
$scope . addToast ( 'danger' , 'An error occurs when generating htpasswd file:' , response . data . errmsg ) ;
} ) ;
} ;
$scope . removeHtpasswd = function ( ) {
$http . delete ( "api/htpasswd" ) . then ( function ( ) {
$scope . addToast ( 'success' , 'Fichier htpasswd supprimé avec succès' ) ;
} , function ( response ) {
$scope . addToast ( 'danger' , 'An error occurs when deleting htpasswd file:' , response . data . errmsg ) ;
} ) ;
} ;
} )
2020-01-23 13:23:02 +00:00
2024-09-18 16:06:23 +00:00
. controller ( "PublicController" , function ( $scope , $rootScope , $routeParams , $location , Scene , Theme , Teams , Exercice ) {
$scope . propagationtime = null ;
$scope . presetName = "" ;
$scope . screens = [ 0 , 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 ] ;
$scope . screenid = $routeParams . screenId ;
$scope . display = Scene . get ( { screenId : $routeParams . screenId } ) ;
$scope . listScenes = Scene . get ( ) ;
$scope . themes = Theme . query ( ) ;
$scope . teams = Teams . get ( ) ;
2018-06-24 16:12:26 +00:00
2024-09-18 16:06:23 +00:00
$scope . chScreen = function ( sid ) {
if ( $scope . screenid )
$location . url ( "/public/" + $scope . screenid ) ;
else
$location . url ( "/public/" ) ;
}
2018-06-24 16:12:26 +00:00
2024-09-18 16:06:23 +00:00
$scope . types = {
"welcome" : "Messages de bienvenue" ,
"countdown" : "Compte à rebours" ,
"message" : "Message" ,
"panel" : "Boîte" ,
"carousel" : "Carousel" ,
"exercice" : "Exercice" ,
"table" : "Tableau" ,
"rank" : "Classement" ,
"graph" : "Graphique" ,
} ;
$scope . typeside = {
"welcome" : "Messages de bienvenue" ,
"themes" : "Présentation des thèmes" ,
"exercice_follow" : "Dernier exercice des événements" ,
"exercice" : "Exercice" ,
"rank" : "Classement" ,
"graph" : "Graphique" ,
"message" : "Message" ,
"panel" : "Boîte" ,
} ;
$scope . welcome _types = {
"teams" : "Accueil des équipes" ,
"public" : "Accueil du public" ,
} ;
$scope . carousel _types = {
"exercices" : "Exercices" ,
"teams" : "Équipes" ,
"themes" : "Thèmes" ,
"ranking" : "Classement" ,
} ;
$scope . colors = {
"primary" : "Primaire" ,
"secondary" : "Secondaire" ,
"info" : "Info" ,
"success" : "Success" ,
"warning" : "Warning" ,
"danger" : "Danger" ,
"light" : "Clair" ,
"dark" : "Foncé" ,
} ;
$scope . rank _types = {
"general" : "Classement général" ,
"final" : "Classement final" ,
} ;
$scope . rank _types _side = {
"carousel" : "Classement général carousel" ,
"general" : "Classement général" ,
} ;
$scope . table _types = {
"levels" : "Niveaux d'exercices" ,
"teams" : "Équipes" ,
} ;
$scope . exercices = Exercice . query ( ) ;
$scope . clearScene = function ( ) {
$scope . someUpdt = true ;
$scope . display . scenes = [ ] ;
} ;
$scope . presetScene = function ( scene ) {
$scope . someUpdt = true ;
if ( scene == "registration" ) {
$scope . display . scenes = [
{
type : "welcome" ,
params : { kind : "teams" , url : "https://fic.srs.epita.fr/" } ,
} ,
{
type : "welcome" ,
params : { kind : "public" , notitle : true } ,
} ,
] ;
$scope . display . side = [
{
type : "themes" ,
params : { } ,
} ,
] ;
}
else if ( scene == "welcome" ) {
$scope . display . scenes = [
{
type : "carousel" ,
params : { color : "info" , kind : "themes" , title : "Présentation des entreprises ciblées" } ,
} ,
] ;
$scope . display . side = [
{
type : "welcome" ,
params : { kind : "public" } ,
} ,
] ;
}
else if ( scene == "start" ) {
$scope . display . scenes = [
{
type : "welcome" ,
params : { kind : "public" } ,
} ,
{
type : "countdown" ,
params : { color : "success" , end : null , lead : "Go, go, go !" , title : "Le challenge forensic va bientôt commencer !" } ,
} ,
] ;
$scope . display . side = [
{
type : "themes" ,
params : { } ,
} ,
] ;
}
else if ( scene == "end" ) {
$scope . display . scenes = [
{
type : "rank" ,
params : { which : "final" } ,
} ,
{
type : "table" ,
params : { kind : "teams" , themes : $scope . themes . map ( function ( z , i ) { return z . id ; } ) , total : true , teams : [ ] } ,
} ,
] ;
angular . forEach ( $scope . teams , function ( team , tid ) {
if ( team . rank >= 1 && team . rank <= 4 )
$scope . display . scenes [ 1 ] . params . teams . push ( tid )
} ) ;
$scope . display . side = [
{
type : "rank" ,
params : { which : "carousel" } ,
} ,
{
type : "graph" ,
params : { teams : [ ] , height : 400 , legend : false , hide : true } ,
} ,
{
type : "message" ,
params : { html : '<div class="row"><div class="col"><a href="http://www.epita.fr/" class="align-middle text-center"><img class="mt-4" src="/img/epita.png" alt="Epita"></a></div><div class="col mr-3"> <a href="http://www.epita.fr/"><img src="/img/comcyber.png" alt="Réserves de cyberdéfense" style="height: 100px;"></a></div></div>' , hide : true } ,
} ,
] ;
angular . forEach ( $scope . teams , function ( team , tid ) {
if ( team . rank >= 1 && team . rank <= 9 )
$scope . display . side [ 1 ] . params . teams . push ( tid )
} ) ;
$scope . display . hideEvents = true ;
$scope . display . hideCountdown = true ;
}
else if ( scene == "summary" ) {
$scope . display . scenes = [
{
type : "table" ,
params : { kind : "levels" , levels : [ 1 , 2 , 3 , 4 , 5 ] , themes : $scope . themes . map ( function ( z , i ) { return z . id ; } ) , total : true } ,
} ,
{
type : "graph" ,
params : { teams : [ ] , height : 337 , legend : true } ,
} ,
] ;
angular . forEach ( $scope . teams , function ( team , tid ) {
if ( team . rank >= 1 && team . rank <= 9 )
$scope . display . scenes [ 1 ] . params . teams . push ( tid )
} ) ;
$scope . display . side = [
{
type : "exercice_follow" ,
params : { } ,
} ,
] ;
$scope . display . hideEvents = false ;
$scope . display . hideCountdown = false ;
}
else if ( scene == "summary2" ) {
$scope . display . scenes = [
{
type : "graph" ,
params : { teams : [ ] , height : 400 , legend : false } ,
} ,
{
type : "rank" ,
params : { limit : 10 , which : "general" , legend : true } ,
} ,
] ;
angular . forEach ( $scope . teams , function ( team , tid ) {
if ( team . rank >= 1 && team . rank <= 9 )
$scope . display . scenes [ 0 ] . params . teams . push ( tid )
} ) ;
$scope . display . side = [
{
type : "exercice_follow" ,
params : { } ,
} ,
] ;
$scope . display . hideEvents = false ;
$scope . display . hideCountdown = false ;
}
else if ( scene == "summary3" ) {
$scope . display . scenes = [
{
type : "table" ,
params : { kind : "levels" , levels : [ 1 , 2 , 3 , 4 , 5 ] , themes : $scope . themes . map ( function ( z , i ) { return z . id ; } ) , total : true } ,
} ,
{
type : "rank" ,
params : { limit : 10 , which : "general" , legend : false } ,
} ,
] ;
$scope . display . side = [
{
type : "exercice_follow" ,
params : { } ,
} ,
] ;
$scope . display . hideEvents = false ;
$scope . display . hideCountdown = false ;
}
else if ( scene == "happyhour" ) {
$scope . display . customCountdown = {
show : true ,
shadow : "#E8CF5C" ,
end : new Date ( $rootScope . getSrvTime ( ) . getTime ( ) + 1802000 ) . toISOString ( ) ,
before : "Heure joyeuse : chaque résolution compte double !" ,
after : "Heure joyeuse terminée !" ,
}
}
else if ( scene == "freehintquarter" ) {
$scope . display . customCountdown = {
show : true ,
shadow : "#3DD28F" ,
end : new Date ( $rootScope . getSrvTime ( ) . getTime ( ) + 902000 ) . toISOString ( ) ,
before : "Quart d'heure facile : indices dévoilés !" ,
after : "Quart d'heure facile terminée !" ,
}
}
} ;
2018-06-24 16:12:26 +00:00
2024-09-18 16:06:23 +00:00
$scope . genSceneCountdownDate = function ( scene , duration ) {
scene . params . end = ( new Date ( $rootScope . getSrvTime ( ) . getTime ( ) + duration ) ) . toISOString ( ) ;
}
$scope . genCustomCountdownDate = function ( duration ) {
if ( duration == null ) {
$scope . display . customCountdown . end = $rootScope . settings . activateTime ;
} else {
$scope . display . customCountdown . end = ( new Date ( $rootScope . getSrvTime ( ) . getTime ( ) + duration ) ) . toISOString ( ) ;
}
}
$scope . loadFile = function ( fname ) {
$scope . display = Scene . get ( { screenId : fname } ) ;
$scope . someUpdt = true ;
} ;
$scope . deleteFile = function ( fname ) {
Scene . delete ( { screenId : fname } ) ;
$scope . listScenes = Scene . get ( ) ;
} ;
$scope . latePropagation = function ( ) {
$scope . someUpdt = false ;
var prms = Scene . update ( { screenId : $scope . screenid , t : $scope . propagationTime } , $scope . display ) ;
prms . $promise . then ( function ( ) {
$scope . addToast ( 'success' , 'Scene successfully planned!' ) ;
} , function ( response ) {
$scope . addToast ( 'danger' , 'An error occurs when planning scene:' , response . data . errmsg ) ;
} ) ;
} ;
$scope . savePreset = function ( ) {
$scope . someUpdt = false ;
var prms = Scene . update ( { screenId : $scope . screenid , p : $scope . presetName } , $scope . display ) ;
prms . $promise . then ( function ( ) {
$scope . addToast ( 'success' , 'Preset successfully saved!' ) ;
} , function ( response ) {
$scope . addToast ( 'danger' , 'An error occurs when saving preset:' , response . data . errmsg ) ;
} ) ;
} ;
$scope . saveScenes = function ( ) {
$scope . someUpdt = false ;
var prms = Scene . update ( { screenId : $scope . screenid } , $scope . display ) ;
prms . $promise . then ( function ( ) {
$scope . addToast ( 'success' , 'Scene successfully published!' ) ;
} , function ( response ) {
$scope . addToast ( 'danger' , 'An error occurs when saving scene:' , response . data . errmsg ) ;
} ) ;
} ;
$scope . addSide = function ( ) {
$scope . someUpdt = true ;
$scope . display . side . push ( { params : { } } ) ;
} ;
$scope . delSide = function ( s ) {
$scope . someUpdt = true ;
angular . forEach ( $scope . display . side , function ( scene , k ) {
if ( scene == s )
$scope . display . side . splice ( k , 1 ) ;
} ) ;
} ;
$scope . upSide = function ( s ) {
$scope . someUpdt = true ;
angular . forEach ( $scope . display . side , function ( scene , k ) {
if ( scene == s && k > 0 ) {
$scope . display . side . splice ( k , 1 ) ;
$scope . display . side . splice ( k - 1 , 0 , scene ) ;
}
} ) ;
} ;
$scope . downSide = function ( s ) {
$scope . someUpdt = true ;
var move = true ;
angular . forEach ( $scope . display . side , function ( scene , k ) {
if ( move && scene == s ) {
$scope . display . side . splice ( k , 1 ) ;
$scope . display . side . splice ( k + 1 , 0 , scene ) ;
move = false ;
}
} ) ;
} ;
$scope . addScene = function ( ) {
$scope . someUpdt = true ;
$scope . display . scenes . push ( { params : { } } ) ;
} ;
$scope . delScene = function ( s ) {
$scope . someUpdt = true ;
angular . forEach ( $scope . display . scenes , function ( scene , k ) {
if ( scene == s )
$scope . display . scenes . splice ( k , 1 ) ;
} ) ;
} ;
$scope . upScene = function ( s ) {
$scope . someUpdt = true ;
angular . forEach ( $scope . display . scenes , function ( scene , k ) {
if ( scene == s && k > 0 ) {
$scope . display . scenes . splice ( k , 1 ) ;
$scope . display . scenes . splice ( k - 1 , 0 , scene ) ;
}
} ) ;
} ;
$scope . downScene = function ( s ) {
$scope . someUpdt = true ;
var move = true ;
angular . forEach ( $scope . display . scenes , function ( scene , k ) {
if ( move && scene == s ) {
$scope . display . scenes . splice ( k , 1 ) ;
$scope . display . scenes . splice ( k + 1 , 0 , scene ) ;
move = false ;
}
} ) ;
} ;
} )
. controller ( "FilesListController" , function ( $scope , File , $location , $http , $rootScope ) {
$scope . files = File . query ( ) ;
$scope . errfnd = null ;
$scope . errzip = null ;
$scope . fields = [ "id" , "path" , "name" , "size" ] ;
$scope . clearFiles = function ( id ) {
File . delete ( function ( ) {
$rootScope . staticFilesNeedUpdate ++ ;
$scope . files = [ ] ;
} ) ;
} ;
$scope . gunzipFile = function ( f ) {
f . gunzipWIP = true ;
$http ( {
url : "api/files/" + f . id + "/gunzip" ,
method : "POST"
} ) . then ( function ( response ) {
f . gunzipWIP = false ;
f . err = true ;
} , function ( response ) {
f . gunzipWIP = false ;
$scope . inSync = false ;
$scope . errzip += 1 ;
f . err = response . data . errmsg ;
} )
} ;
$scope . checksum = function ( f ) {
f . checkWIP = true ;
$http ( {
url : "api/files/" + f . id + "/check" ,
method : "POST"
} ) . then ( function ( response ) {
f . checkWIP = false ;
f . err = true ;
} , function ( response ) {
f . checkWIP = false ;
$scope . inSync = false ;
$scope . errfnd += 1 ;
f . err = response . data . errmsg ;
} )
} ;
$scope . checksumAll = function ( ) {
$scope . errfnd = null ;
angular . forEach ( $scope . files , function ( file ) {
$scope . checksum ( file ) ;
} ) ;
if ( $scope . errfnd === null ) $scope . errfnd = 0 ;
} ;
$scope . gunzipFiles = function ( ) {
$scope . errzip = null ;
angular . forEach ( $scope . files , function ( file ) {
$scope . gunzipFile ( file ) ;
} ) ;
if ( $scope . errzip === null ) $scope . errzip = 0 ;
} ;
$scope . show = function ( f ) {
$location . url ( "/exercices/" + f . idExercice ) ;
} ;
} )
. controller ( "EventsListController" , function ( $scope , Event , $location ) {
$scope . events = Event . query ( ) ;
$scope . fields = [ "id" , "kind" , "txt" , "time" ] ;
$scope . clearEvents = function ( id ) {
Event . delete ( function ( ) {
$scope . events = [ ] ;
} ) ;
} ;
$scope . show = function ( id ) {
$location . url ( "/events/" + id ) ;
} ;
} )
. controller ( "EventController" , function ( $scope , Event , $routeParams , $location ) {
$scope . event = Event . get ( { eventId : $routeParams . eventId } ) ;
$scope . fields = [ "kind" , "txt" , "time" ] ;
$scope . kinds = {
"secondary" : "Par défaut" ,
"primary" : "Mise en valeur" ,
"info" : "Info" ,
"warning" : "Warning" ,
"success" : "Success" ,
"danger" : "Danger" ,
"light" : "Clair" ,
"dark" : "Foncé" ,
} ;
$scope . saveEvent = function ( ) {
if ( this . event . id ) {
this . event . $update ( ) ;
} else {
this . event . $save ( function ( ) {
$location . url ( "/events/" + $scope . event . id ) ;
} ) ;
}
}
$scope . deleteEvent = function ( ) {
this . event . $remove ( function ( ) { $location . url ( "/events/" ) ; } ) ;
}
} )
. controller ( "AssigneesListController" , function ( $scope , ClaimAssignee , $location ) {
$scope . assignees = ClaimAssignee . query ( ) ;
$scope . setMyAId = function ( aid ) {
setCookie ( "myassignee" , aid , 5 ) ;
$location . url ( "/claims/" ) ;
}
$scope . whoami = getCookie ( "myassignee" ) ;
$scope . newAssignee = function ( ) {
$scope . assignees . push ( new ClaimAssignee ( ) ) ;
}
$scope . edit = function ( a ) {
a . edit = true ;
}
$scope . updateAssignee = function ( a ) {
if ( a . id ) {
a . $update ( function ( ) { $location . url ( "/claims/" ) ; } ) ;
} else {
a . $save ( )
}
}
$scope . removeAssignee = function ( a ) {
a . $remove ( function ( ) { $location . url ( "/claims/" ) ; } ) ;
}
} )
. controller ( "ClaimsTinyListController" , function ( $scope , Claim , ClaimAssignee , $interval ) {
$scope . whoami = getCookie ( "myassignee" ) ;
var priorities = {
"low" : 1 ,
"medium" : 2 ,
"high" : 3 ,
"critical" : 4 ,
} ;
$scope . priorities = [
"secondary" ,
"light" ,
"info" ,
"warning" ,
"danger" ,
] ;
var refresh = function ( ) {
Claim . query ( ) . $promise . then ( function ( claims ) {
$scope . newClaims = 0 ;
$scope . newClaimsMaxLevel = 0 ;
$scope . myClaims = 0 ;
$scope . myClaimsMaxLevel = 0 ;
claims . forEach ( function ( claim , cid ) {
if ( $scope . whoami && ! claim . id _assignee && claim . state == 'new' ) {
$scope . newClaims ++ ;
if ( priorities [ claim . priority ] > $scope . newClaimsMaxLevel )
$scope . newClaimsMaxLevel = priorities [ claim . priority ] ;
}
else if ( $scope . whoami && claim . id _assignee == $scope . whoami && claim . state != 'closed' && claim . state != 'invalid' ) {
$scope . myClaims ++ ;
if ( claim . state == 'new' && priorities [ claim . priority ] > $scope . myClaimsMaxLevel )
$scope . myClaimsMaxLevel = priorities [ claim . priority ] ;
}
} )
} ) ;
} ;
refresh ( ) ;
$interval ( refresh , 10000 ) ;
} )
. controller ( "ClaimsListController" , function ( $scope , Claim , ClaimAssignee , Teams , $interval , $location ) {
var refresh = function ( ) {
$scope . claims = Claim . query ( ) ;
$scope . assignees = ClaimAssignee . query ( ) ;
}
refresh ( ) ;
var myinterval = $interval ( refresh , 10000 ) ;
$scope . $on ( '$destroy' , function ( ) { $interval . cancel ( myinterval ) ; } ) ;
$scope . whoami = getCookie ( "myassignee" ) ;
$scope . teams = Teams . get ( ) ;
$scope . fields = [ "subject" , "id_team" , "state" , "id_assignee" , "last_update" , "id" ] ;
$scope . order = "priority" ;
$scope . chOrder = function ( no ) {
$scope . order = no ;
} ;
$scope . clearClaims = function ( id ) {
Claim . delete ( function ( ) {
$scope . claims = [ ] ;
} ) ;
} ;
$scope . show = function ( id ) {
$location . url ( "/claims/" + id ) ;
} ;
} )
. controller ( "ClaimLastUpdateController" , function ( $scope , $http ) {
$scope . init = function ( claim ) {
$http . get ( "api/claims/" + claim . id + "/last_update" ) . then ( function ( response ) {
if ( response . data )
$scope . last _update = response . data ;
else
$scope . last _update = claim . creation ;
claim . last _update = $scope . last _update ;
} , function ( response ) {
$scope . last _update = claim . creation ;
} )
}
} )
. controller ( "ClaimController" , function ( $scope , Claim , ClaimAssignee , Teams , Exercice , $routeParams , $location , $http , $rootScope ) {
$scope . claim = Claim . get ( { claimId : $routeParams . claimId } , function ( v ) {
v . id _team = "" + v . id _team ;
if ( ! v . priority )
v . priority = "medium" ;
} ) ;
if ( $routeParams . claimId == "new" )
$scope . fields = [ "id_team" , "id_exercice" , "subject" , "priority" , "id_assignee" ] ;
2020-01-29 17:18:25 +00:00
else
2024-09-18 16:06:23 +00:00
$scope . fields = [ "subject" , "priority" , "id_exercice" , "id_assignee" , "id_team" , "creation" , "state" ] ;
$scope . assignees = ClaimAssignee . query ( ) ;
$scope . comm = { ndescription : "" } ;
$scope . whoami = Math . floor ( getCookie ( "myassignee" ) ) ;
$scope . teams = Teams . get ( ) ;
$scope . exercices = Exercice . query ( ) ;
$scope . namedFields = {
"subject" : "Objet" ,
"id_assignee" : "Assigné à" ,
"state" : "État" ,
"id_team" : "Équipe" ,
"id_exercice" : "Challenge" ,
"creation" : "Création" ,
"priority" : "Priorité" ,
"description" : "Description" ,
} ;
$scope . states = {
"new" : "Nouveau" ,
"need-info" : "Besoin d'infos" ,
"confirmed" : "Confirmé" ,
"in-progress" : "En cours" ,
"need-review" : "Fait" ,
"closed" : "Clos" ,
"invalid" : "Invalide" ,
} ;
$scope . priorities = {
"low" : "Basse" ,
"medium" : "Moyenne" ,
"high" : "Haute" ,
"critical" : "Critique" ,
} ;
$scope . changeState = function ( state ) {
this . claim . state = state ;
if ( ( state == "in-progress" || state == "invalid" ) && this . claim . id _assignee )
this . claim . id _assignee = $scope . whoami ;
if ( this . claim . id )
this . saveClaim ( state == "invalid" || state == "closed" ) ;
}
$scope . assignToMe = function ( ) {
this . claim . id _assignee = $scope . whoami ;
if ( this . claim . id )
this . saveClaim ( false ) ;
}
$scope . updateDescription = function ( description ) {
$http ( {
url : "api/claims/" + $scope . claim . id + "/descriptions" ,
method : "PUT" ,
data : description
} ) . then ( function ( response ) {
$scope . claim = Claim . get ( { claimId : $routeParams . claimId } , function ( v ) {
v . id _team = "" + v . id _team ;
if ( ! v . priority )
v . priority = "medium" ;
} ) ;
} ) ;
}
$scope . saveDescription = function ( ) {
$http ( {
url : "api/claims/" + $scope . claim . id ,
method : "POST" ,
data : {
"id_assignee" : $scope . whoami ,
"content" : $scope . comm . ndescription
}
} ) . then ( function ( response ) {
$location . url ( "/claims/" + $scope . claim . id + "/" ) ;
} ) ;
}
$scope . saveClaim = function ( backToList ) {
this . claim . whoami = $scope . whoami ;
if ( this . claim . id _team ) {
this . claim . id _team = parseInt ( this . claim . id _team , 10 ) ;
} else {
this . claim . id _team = null ;
}
if ( this . claim . id ) {
this . claim . $update ( function ( v ) {
v . id _team = "" + v . id _team ;
if ( $scope . comm . ndescription )
$scope . saveDescription ( ) ;
else if ( backToList )
$location . url ( "/claims/" ) ;
else
$scope . claim = Claim . get ( { claimId : $routeParams . claimId } , function ( v ) {
v . id _team = "" + v . id _team ;
if ( ! v . priority )
v . priority = "medium" ;
} ) ;
} ) ;
} else {
this . claim . $save ( function ( ) {
if ( ! $scope . comm . ndescription )
$scope . comm . ndescription = "Création de la tâche" ;
$scope . saveDescription ( ) ;
} , function ( response ) {
$scope . addToast ( 'danger' , 'An error occurs when trying to save claim:' , response . data . errmsg ) ;
} ) ;
}
}
$scope . deleteClaim = function ( ) {
this . claim . $remove ( function ( ) { $location . url ( "/claims/" ) ; } ) ;
}
} )
. controller ( "ThemesListController" , function ( $scope , Theme , $location , $rootScope , $http ) {
$scope . themes = Theme . query ( ) ;
$scope . fields = [ "name" , "authors" , "headline" , "path" ] ;
$scope . validateSearch = function ( keyEvent ) {
if ( keyEvent . which === 13 ) {
var myTheme = null ;
$scope . themes . forEach ( function ( theme ) {
if ( String ( theme . name . toLowerCase ( ) ) . indexOf ( $scope . query . toLowerCase ( ) ) >= 0 ) {
if ( myTheme === null )
myTheme = theme ;
else
myTheme = false ;
}
} ) ;
if ( myTheme )
$location . url ( "themes/" + myTheme . id ) ;
}
} ;
$scope . show = function ( id ) {
$location . url ( "/themes/" + id ) ;
} ;
$scope . inSync = false ;
$scope . sync = function ( ) {
$scope . inSync = true ;
$http ( {
url : "api/sync/themes" ,
method : "POST"
} ) . then ( function ( response ) {
$scope . inSync = false ;
$scope . themes = Theme . query ( ) ;
$rootScope . staticFilesNeedUpdate ++ ;
if ( response . data )
$scope . addToast ( 'danger' , 'An error occurs when synchronizing theme list:' , response . data ) ;
else
$scope . addToast ( 'success' , 'Synchronisation de la liste des thèmes terminée avec succès.' ) ;
} , function ( response ) {
$scope . inSync = false ;
$scope . addToast ( 'danger' , 'An error occurs when synchronizing theme list:' , response . data . errmsg ) ;
} ) ;
} ;
} )
. controller ( "ThemeController" , function ( $scope , Theme , $routeParams , $location , $rootScope , $http ) {
$scope . theme = Theme . get ( { themeId : $routeParams . themeId } ) ;
$scope . fields = [ "name" , "urlid" , "locked" , "authors" , "headline" , "intro" , "image" , "background_color" , "partner_txt" , "partner_href" , "partner_img" ] ;
$scope . saveTheme = function ( ) {
if ( this . theme . id ) {
this . theme . $update ( ) ;
} else {
this . theme . $save ( function ( ) {
$location . url ( "/themes/" + $scope . theme . id ) ;
} ) ;
}
$rootScope . staticFilesNeedUpdate ++ ;
}
$scope . deleteTheme = function ( ) {
this . theme . $remove ( function ( ) {
$rootScope . staticFilesNeedUpdate ++ ;
$location . url ( "/themes/" ) ;
} , function ( response ) {
$scope . addToast ( 'danger' , 'An error occurs when trying to delete theme:' , response . data . errmsg ) ;
} ) ;
}
} )
. controller ( "TagsListController" , function ( $scope , $http ) {
$scope . tags = [ ] ;
$http ( {
url : "api/tags" ,
method : "GET"
} ) . then ( function ( response ) {
$scope . tags = response . data
2017-04-02 10:43:48 +00:00
} ) ;
2024-09-18 16:06:23 +00:00
} )
. controller ( "AllExercicesListController" , function ( $scope , Exercice , Theme , $routeParams , $location , $rootScope , $http , $filter ) {
$http ( {
url : "api/themes.json" ,
method : "GET"
} ) . then ( function ( response ) {
$scope . themes = response . data
2017-01-28 18:36:28 +00:00
} ) ;
2019-02-04 18:59:29 +00:00
2024-09-18 16:06:23 +00:00
$scope . exercices = Exercice . query ( ) ;
$scope . exercice = { } ; // Array used to save fields to updates in selected exercices
$scope . fields = [ "title" , "headline" ] ;
$scope . validateSearch = function ( keyEvent ) {
if ( keyEvent . which === 13 ) {
var myExercice = null ;
$scope . exercices . forEach ( function ( exercice ) {
if ( String ( exercice . title . toLowerCase ( ) ) . indexOf ( $scope . query . toLowerCase ( ) ) >= 0 ) {
if ( myExercice === null )
myExercice = exercice ;
else
myExercice = false ;
}
} ) ;
if ( myExercice )
$location . url ( "exercices/" + myExercice . id ) ;
}
} ;
$scope . toggleSelectAll = function ( ) {
angular . forEach ( $filter ( 'filter' ) ( $scope . exercices , $scope . query ) , function ( ex ) {
ex . selected = ! $scope . selectall
} )
}
$scope . updateExercices = function ( ) {
angular . forEach ( $scope . exercices , function ( ex ) {
if ( ex . selected ) {
Exercice . patch ( { exerciceId : ex . id } , $scope . exercice ) ;
}
} )
$scope . exercice = { } ;
$rootScope . staticFilesNeedUpdate ++ ;
$scope . addToast ( 'success' , 'Édition de masse terminée avec succès' ) ;
}
$scope . show = function ( id ) {
$location . url ( "/exercices/" + id ) ;
} ;
$scope . inSync = false ;
$scope . syncFull = function ( ) {
$scope . inSync = true ;
$scope . done = - 1 ;
$scope . total = 0 ;
var work = [ ] ;
var go = function ( ) {
if ( ! work . length ) {
$scope . addToast ( 'info' , "Synchronisation des exercices terminée." ) ;
$scope . inSync = false ;
return ;
}
var u = work . pop ( ) ;
$http ( {
url : u ,
method : "GET"
} ) . then ( function ( response ) {
$rootScope . staticFilesNeedUpdate ++ ;
$scope . done += 1 ;
go ( ) ;
} , function ( response ) {
$scope . done += 1 ;
go ( ) ;
} ) ;
} ;
angular . forEach ( $scope . exercices , function ( ex ) {
if ( $scope . syncFiles )
work . push ( "api/sync/exercices/" + ex . id + "/files" ) ;
if ( $scope . syncHints )
work . push ( "api/sync/exercices/" + ex . id + "/hints" ) ;
if ( $scope . syncFlags )
work . push ( "api/sync/exercices/" + ex . id + "/flags" ) ;
} ) ;
$scope . total = work . length ;
go ( ) ;
} ;
$scope . syncFiles = true ;
$scope . syncHints = true ;
$scope . syncFlags = true ;
} )
. controller ( "ExercicesListController" , function ( $scope , ThemedExercice , $location , $rootScope , $http ) {
$scope . exercices = ThemedExercice . query ( { themeId : $scope . theme . id } ) ;
$scope . fields = [ "title" , "headline" , "issue" ] ;
$scope . show = function ( id ) {
$location . url ( "/themes/" + $scope . theme . id + "/exercices/" + id ) ;
} ;
$scope . inSync = false ;
$scope . syncExo = function ( ) {
$scope . inSync = true ;
$http ( {
url : "api/sync/themes/" + $scope . theme . id + "/exercices" ,
method : "POST"
} ) . then ( function ( response ) {
$scope . inSync = false ;
$scope . exercices = ThemedExercice . query ( { themeId : $scope . theme . id } ) ;
$rootScope . staticFilesNeedUpdate ++ ;
if ( response . data )
$scope . addToast ( 'warning' , 'An error occurs when synchrinizing exercices:' , response . data ) ;
else
$scope . addToast ( 'success' , 'Synchronisation de la liste des exercices terminée avec succès.' ) ;
} , function ( response ) {
$scope . inSync = false ;
$scope . addToast ( 'danger' , 'An error occurs when synchrinizing exercices:' , response . data . errmsg ) ;
} ) ;
} ;
} )
. controller ( "ExerciceController" , function ( $scope , $rootScope , Exercice , ThemedExercice , $routeParams , $location , $http ) {
if ( $routeParams . themeId && $routeParams . exerciceId == "new" ) {
$scope . exercice = new ThemedExercice ( ) ;
} else {
$scope . exercice = Exercice . get ( { exerciceId : $routeParams . exerciceId } ) ;
}
$scope . my _ex _num = { } ;
$http ( {
url : "api/themes.json" ,
method : "GET"
} ) . then ( function ( response ) {
$scope . themes = response . data ;
if ( $scope . exercice . id _theme ) {
for ( var k in $scope . themes [ $scope . exercice . id _theme ] . exercices ) {
var exercice = $scope . themes [ $scope . exercice . id _theme ] . exercices [ k ] ;
$scope . my _ex _num [ exercice . id ] = k ;
}
} else {
for ( var k in $scope . themes [ "0" ] . exercices ) {
var exercice = $scope . themes [ "0" ] . exercices [ k ] ;
$scope . my _ex _num [ exercice . id ] = k ;
}
}
2019-02-05 00:44:41 +00:00
} ) ;
2024-09-18 16:06:23 +00:00
$scope . exercices = Exercice . query ( ) ;
$scope . fields = [ "title" , "urlid" , "authors" , "disabled" , "statement" , "headline" , "overview" , "finished" , "depend" , "gain" , "coefficient" , "videoURI" , "image" , "background_color" , "resolution" , "issue" , "issuekind" , "wip" ] ;
$scope . inSync = false ;
$scope . syncExo = function ( ) {
$scope . inSync = true ;
$http ( {
url : $scope . exercice . id _theme ? ( "api/sync/themes/" + $scope . exercice . id _theme + "/exercices/" + $routeParams . exerciceId ) : ( "api/sync/exercices/" + $routeParams . exerciceId ) ,
method : "POST"
} ) . then ( function ( response ) {
$scope . inSync = false ;
$scope . exercice = Exercice . get ( { exerciceId : $routeParams . exerciceId } ) ;
$rootScope . staticFilesNeedUpdate ++ ;
if ( response . data )
$scope . addToast ( 'danger' , 'An error occurs when synchronizing exercice:' , response . data ) ;
else
$scope . addToast ( 'success' , "Synchronisation de l'exercice terminée avec succès." ) ;
} , function ( response ) {
$scope . inSync = false ;
$scope . addToast ( 'danger' , 'An error occurs when synchronizing exercice:' , response . data . errmsg ) ;
} ) ;
} ;
$scope . deleteExercice = function ( ) {
var tid = $scope . exercice . id _theme ;
this . exercice . $remove ( function ( ) {
$rootScope . staticFilesNeedUpdate ++ ;
$location . url ( "/themes/" + tid ) ;
} , function ( response ) {
$scope . addToast ( 'danger' , 'An error occurs when trying to delete exercice:' , response . data . errmsg ) ;
} ) ;
}
$scope . saveExercice = function ( ) {
if ( this . exercice . id ) {
this . exercice . $update ( ) ;
$rootScope . staticFilesNeedUpdate ++ ;
} else if ( $routeParams . themeId ) {
this . exercice . $save ( { themeId : $routeParams . themeId } , function ( ) {
$rootScope . staticFilesNeedUpdate ++ ;
$location . url ( "/themes/" + $scope . exercice . idTheme + "/exercices/" + $scope . exercice . id ) ;
} , function ( response ) {
$scope . addToast ( 'danger' , 'An error occurs when trying to save exercice:' , response . data . errmsg ) ;
} ) ;
}
}
$scope . selectedTeam = "" ;
$scope . validateForTeam = function ( ) {
var flagid = $ ( "#validationModal" ) . data ( "flagid" ) ;
if ( ! flagid ) return ;
var target = {
team _id : parseInt ( $ ( "#tteam" ) . val ( ) . replace ( /number:/ , '' ) ) ,
kind : $ ( "#validationModal" ) . data ( "kind" ) ,
secondary : flagid ,
} ;
$http ( {
url : "api/exercices/" + $scope . exercice . id + "/history.json" ,
method : "PUT" ,
data : target
} ) . then ( function ( response ) {
$rootScope . staticFilesNeedUpdate ++ ;
$ ( "#validationModal" ) . modal ( 'hide' ) ;
$scope . addToast ( 'success' , 'Flag validé avec succès' ) ;
} , function ( response ) {
$scope . addToast ( 'danger' , 'An error occurs when trying to validate flag for team:' , response . data . errmsg ) ;
} ) ;
}
$scope . historyAppend = function ( ) {
var secondary = null ;
if ( $ ( "#historyEvent" ) . val ( ) == "hint" )
secondary = parseInt ( $ ( "#historySecondaryHint" ) . val ( ) . replace ( /number:/ , '' ) ) ;
else if ( $ ( "#historyEvent" ) . val ( ) == "wchoices" || $ ( "#historyEvent" ) . val ( ) == "flag_found" )
secondary = parseInt ( $ ( "#historySecondaryFlag" ) . val ( ) . replace ( /number:/ , '' ) ) ;
else if ( $ ( "#historyEvent" ) . val ( ) == "mcq_found" )
secondary = parseInt ( $ ( "#historySecondaryQuiz" ) . val ( ) . replace ( /number:/ , '' ) ) ;
var target = {
team _id : parseInt ( $ ( "#tteam" ) . val ( ) . replace ( /number:/ , '' ) ) ,
kind : $ ( "#historyEvent" ) . val ( ) ,
secondary : secondary ,
} ;
$http ( {
url : "api/exercices/" + $scope . exercice . id + "/history.json" ,
method : "PUT" ,
data : target
} ) . then ( function ( response ) {
$rootScope . staticFilesNeedUpdate ++ ;
$ ( "#appendHistoryModal" ) . modal ( 'hide' ) ;
$scope . addToast ( 'success' , 'Événement ajouté avec succès' ) ;
$scope . refreshHistory ( ) ;
} , function ( response ) {
$scope . addToast ( 'danger' , 'An error occurs when trying to add event in history:' , response . data . errmsg ) ;
} ) ;
}
} )
. controller ( "SubmissionsStatsController" , function ( $scope , $http , $interval ) {
var refresh = function ( ) {
$http ( {
url : "api/submissions-stats.json" ,
} ) . then ( function ( response ) {
$scope . submissionsstats = response . data ;
} ) ;
}
var myinterval = $interval ( refresh , 15000 ) ;
refresh ( ) ;
$scope . $on ( '$destroy' , function ( ) { $interval . cancel ( myinterval ) ; } ) ;
} )
. controller ( "ValidationsStatsController" , function ( $scope , $http , $interval ) {
var refresh = function ( ) {
$http ( {
url : "api/validations-stats.json" ,
} ) . then ( function ( response ) {
$scope . validationsstats = response . data ;
} ) ;
}
var myinterval = $interval ( refresh , 15000 ) ;
refresh ( ) ;
$scope . $on ( '$destroy' , function ( ) { $interval . cancel ( myinterval ) ; } ) ;
} )
. controller ( "ExercicesStatsController" , function ( $scope , Themes , ExercicesStats ) {
$scope . themes = Themes . get ( ) ;
$scope . exercices = { } ;
ExercicesStats . query ( ) . $promise . then ( function ( exs ) {
exs . forEach ( function ( ex ) {
$scope . exercices [ ex . id _exercice ] = ex ;
} )
2019-02-04 18:59:29 +00:00
} ) ;
2024-09-18 16:06:23 +00:00
$scope . lenExoArray = [ ] ;
$scope . themes . $promise . then ( function ( themes ) {
if ( themes [ '0' ] && themes [ '0' ] . exercices . length ) {
var j = 0 ;
for ( var i = themes [ '0' ] . exercices . length / 10 ; i >= 0 ; i -- ) {
$scope . lenExoArray . push ( j ++ ) ;
}
}
} ) ;
} )
. controller ( "ExerciceStatsController" , function ( $scope , ExerciceStats , $routeParams ) {
$scope . stats = ExerciceStats . get ( { exerciceId : $routeParams . exerciceId } ) ;
} )
2019-02-04 18:59:29 +00:00
2024-09-18 16:06:23 +00:00
. controller ( "ExerciceClaimsController" , function ( $scope , ExerciceClaims , Team , ClaimAssignee , $routeParams , $location ) {
$scope . claims = ExerciceClaims . query ( { exerciceId : $routeParams . exerciceId } ) ;
$scope . assignees = ClaimAssignee . query ( ) ;
$scope . claims . $promise . then ( function ( claims ) {
claims . forEach ( function ( claim , cid ) {
$scope . claims [ cid ] . team = Team . get ( { teamId : claim . id _team } ) ;
} )
2019-02-04 18:59:29 +00:00
} ) ;
2024-09-18 16:06:23 +00:00
$scope . showClosed = false ;
$scope . show = function ( id ) {
$location . url ( "/claims/" + id ) ;
} ;
} )
. controller ( "ExerciceTagsController" , function ( $scope , ExerciceTags , $routeParams , $rootScope ) {
$scope . tags = ExerciceTags . query ( { exerciceId : $routeParams . exerciceId } ) ;
$scope . addTag = function ( ) {
$scope . tags . push ( "" ) ;
}
$scope . deleteTag = function ( ) {
$scope . tags . splice ( $scope . tags . indexOf ( this . tag ) , 1 ) ;
return $scope . saveTags ( ) ;
}
$scope . saveTags = function ( ) {
ExerciceTags . update ( { exerciceId : $routeParams . exerciceId } , this . tags ) ;
$rootScope . staticFilesNeedUpdate ++ ;
}
} )
. controller ( "ExerciceHistoryController" , function ( $scope , ExerciceHistory , $routeParams , $http , $rootScope ) {
$scope . history = [ ] ;
$scope . refreshHistory = function ( ) {
$scope . history = ExerciceHistory . query ( { exerciceId : $routeParams . exerciceId } ) ;
}
$scope . $parent . refreshHistory = $scope . refreshHistory ;
$scope . refreshHistory ( ) ;
$scope . updHistory = function ( ) {
var target = {
team _id : $ ( "#updHistory" ) . data ( "idteam" ) ,
kind : $ ( "#updHistory" ) . data ( "kind" ) ,
time : $ ( "#updHistory" ) . data ( "time" ) ,
secondary : $ ( "#updHistory" ) . data ( "secondary" ) != "" ? $ ( "#updHistory" ) . data ( "secondary" ) : null ,
coeff : parseFloat ( $ ( '#historycoeff' ) . val ( ) ) ,
} ;
if ( target ) {
$http ( {
url : "api/exercices/" + $routeParams . exerciceId + "/history.json" ,
method : "PATCH" ,
data : target
} ) . then ( function ( response ) {
$rootScope . staticFilesNeedUpdate ++ ;
$scope . history = ExerciceHistory . query ( { exerciceId : $routeParams . exerciceId } ) ;
$ ( '#updHistory' ) . modal ( 'hide' ) ;
} , function ( response ) {
$scope . addToast ( 'danger' , 'An error occurs when updating history item: ' , response . data . errmsg ) ;
} ) ;
}
}
$scope . delHistory = function ( row ) {
$http ( {
url : "api/exercices/" + $routeParams . exerciceId + "/history.json" ,
method : "DELETE" ,
data : row
} ) . then ( function ( response ) {
$rootScope . staticFilesNeedUpdate ++ ;
$scope . history = ExerciceHistory . query ( { exerciceId : $routeParams . exerciceId } ) ;
} , function ( response ) {
$scope . addToast ( 'danger' , 'An error occurs when removing history item: ' , response . data . errmsg ) ;
} ) ;
}
} )
. controller ( "ExerciceFilesController" , function ( $scope , ExerciceFile , $routeParams , $rootScope , $http ) {
$scope . files = ExerciceFile . query ( { exerciceId : $routeParams . exerciceId } ) ;
$scope . deleteFile = function ( ) {
this . file . $delete ( function ( ) {
$scope . files = ExerciceFile . query ( { exerciceId : $routeParams . exerciceId } ) ;
} ) ;
$rootScope . staticFilesNeedUpdate ++ ;
return false ;
}
$scope . deleteFileDep = function ( ) {
$http ( {
url : "api//files/" + this . file . id + "/dependancies/" + this . dep . id ,
method : "DELETE"
} ) . then ( function ( response ) {
$scope . files = ExerciceFile . query ( { exerciceId : $routeParams . exerciceId } ) ;
} , function ( response ) {
$scope . addToast ( 'danger' , 'An error occurs when removing file dep:' , response . data . errmsg ) ;
} ) ;
$rootScope . staticFilesNeedUpdate ++ ;
return false ;
}
$scope . saveFile = function ( ) {
this . file . $update ( ) ;
$rootScope . staticFilesNeedUpdate ++ ;
}
$scope . inSync = false ;
$scope . syncFiles = function ( ) {
$scope . inSync = true ;
$http ( {
url : "api/sync/exercices/" + $routeParams . exerciceId + "/files" ,
method : "POST"
} ) . then ( function ( response ) {
$scope . inSync = false ;
$rootScope . staticFilesNeedUpdate ++ ;
$scope . files = ExerciceFile . query ( { exerciceId : $routeParams . exerciceId } ) ;
if ( response . data )
$scope . addToast ( 'danger' , 'An error occurs when synchronizing flags list:' , response . data ) ;
else
$scope . addToast ( 'success' , "Synchronisation de la liste de fichiers terminée avec succès." ) ;
} , function ( response ) {
$scope . inSync = false ;
$scope . addToast ( 'danger' , 'An error occurs when synchronizing flags list:' , response . data . errmsg ) ;
} ) ;
} ;
} )
. controller ( "ExerciceHintsController" , function ( $scope , ExerciceHint , $routeParams , $rootScope , $http ) {
$scope . hints = ExerciceHint . query ( { exerciceId : $routeParams . exerciceId } ) ;
$scope . addHint = function ( ) {
$scope . hints . push ( new ExerciceHint ( ) ) ;
}
$scope . deleteHint = function ( ) {
this . hint . $delete ( function ( ) {
$scope . hints = ExerciceHint . query ( { exerciceId : $routeParams . exerciceId } ) ;
$rootScope . staticFilesNeedUpdate ++ ;
} , function ( response ) {
$scope . addToast ( 'danger' , 'An error occurs when trying to delete hint:' , response . data . errmsg ) ;
} ) ;
}
$scope . saveHint = function ( ) {
if ( this . hint . id ) {
this . hint . $update ( ) ;
} else {
this . hint . $save ( { exerciceId : $routeParams . exerciceId } ) ;
}
$rootScope . staticFilesNeedUpdate ++ ;
}
$scope . inSync = false ;
$scope . syncHints = function ( ) {
$scope . inSync = true ;
$http ( {
url : "api/sync/exercices/" + $routeParams . exerciceId + "/hints" ,
method : "POST"
} ) . then ( function ( response ) {
$scope . inSync = false ;
$scope . hints = ExerciceHint . query ( { exerciceId : $routeParams . exerciceId } ) ;
$rootScope . staticFilesNeedUpdate ++ ;
if ( response . data )
$scope . addToast ( 'danger' , 'An error occurs when synchronizing hints list:' , response . data ) ;
else
$scope . addToast ( 'success' , "Synchronisation de la liste d'indices terminée avec succès." ) ;
} , function ( response ) {
$scope . inSync = false ;
$scope . addToast ( 'danger' , 'An error occurs when synchronizing hints list:' , response . data . errmsg ) ;
} ) ;
} ;
} )
. controller ( "ExerciceHintDepsController" , function ( $scope , $routeParams , ExerciceHintDeps ) {
$scope . init = function ( hint ) {
$scope . deps = ExerciceHintDeps . query ( { exerciceId : $routeParams . exerciceId , hintId : hint . id } ) ;
}
} )
. controller ( "ExerciceFlagsController" , function ( $scope , ExerciceFlag , $routeParams , $rootScope , $http ) {
$scope . flags = ExerciceFlag . query ( { exerciceId : $routeParams . exerciceId } ) ;
$scope . flags . $promise . then ( function ( flags ) {
flags . forEach ( function ( flag , fid ) {
flags [ fid ] . values = [ '' ] ;
} ) ;
2019-07-12 17:17:17 +00:00
} ) ;
2016-10-13 17:52:54 +00:00
2024-09-18 16:06:23 +00:00
$scope . changeValue = function ( flag ) {
flag . value = undefined ;
flag . show _raw = true ;
2016-10-13 17:52:54 +00:00
}
2024-09-18 16:06:23 +00:00
$scope . addFlag = function ( ) {
$scope . flags . push ( new ExerciceFlag ( ) ) ;
}
$scope . deleteFlag = function ( ) {
this . flag . $delete ( function ( ) {
$scope . flags = ExerciceFlag . query ( { exerciceId : $routeParams . exerciceId } ) ;
$rootScope . staticFilesNeedUpdate ++ ;
} , function ( response ) {
$scope . addToast ( 'danger' , 'An error occurs when trying to delete flag:' , response . data . errmsg ) ;
} ) ;
}
$scope . saveFlag = function ( ) {
if ( this . flag . id ) {
this . flag . $update ( ) ;
} else {
this . flag . $save ( { exerciceId : $routeParams . exerciceId } ) ;
}
$rootScope . staticFilesNeedUpdate ++ ;
}
$scope . testFlag = function ( flag ) {
if ( flag . values ) {
var val = flag . value ;
treatFlagKey ( flag ) ;
flag . test _str = flag . value ;
flag . value = val ;
}
2016-10-13 17:52:54 +00:00
2024-09-18 16:06:23 +00:00
if ( flag . test _str ) {
$http ( {
url : "api/exercices/" + $routeParams . exerciceId + "/flags/" + flag . id + "/try" ,
data : { "flag" : flag . test _str } ,
method : "POST"
} ) . then ( function ( response ) {
flag . test _str = "" ;
$scope . addToast ( 'success' , "Flag Ok !" ) ;
} , function ( response ) {
flag . test _str = "" ;
$scope . addToast ( 'danger' , 'An error occurs: ' , response . data . errmsg ) ;
} ) ;
}
}
$scope . inSync = false ;
$scope . syncFlags = function ( ) {
$scope . inSync = true ;
$http ( {
url : "api/sync/exercices/" + $routeParams . exerciceId + "/flags" ,
method : "POST"
} ) . then ( function ( response ) {
$scope . inSync = false ;
$scope . flags = ExerciceFlag . query ( { exerciceId : $routeParams . exerciceId } ) ;
$rootScope . staticFilesNeedUpdate ++ ;
if ( response . data )
$scope . addToast ( 'danger' , 'An error occurs when synchronizing flags list:' , response . data ) ;
else
$scope . addToast ( 'success' , "Synchronisation de la liste de drapeaux terminée avec succès." ) ;
} , function ( response ) {
$scope . inSync = false ;
$scope . addToast ( 'danger' , 'An error occurs when synchronizing flags list:' , response . data . errmsg ) ;
} ) ;
} ;
} )
. controller ( "ExerciceFlagChoicesController" , function ( $scope , ExerciceFlagChoices , $routeParams ) {
$scope . choices = ExerciceFlagChoices . query ( { exerciceId : $routeParams . exerciceId , flagId : $scope . flag . id } )
$scope . flag . wantchoices = function ( ) {
$scope . flag . choices = { } ;
$scope . choices . forEach ( function ( choice ) {
$scope . flag . choices [ choice . value ] = choice . label
} )
}
$scope . choices . $promise . then ( function ( choices ) {
if ( $scope . flag . choices _cost == 0 && choices . length > 0 ) {
$scope . flag . wantchoices ( )
}
} )
$scope . addChoice = function ( ) {
$scope . choices . push ( new ExerciceFlagChoices ( ) )
}
$scope . saveChoice = function ( ) {
if ( this . choice . id )
this . choice . $update ( { exerciceId : $routeParams . exerciceId , flagId : this . flag . id } )
else
this . choice . $save ( { exerciceId : $routeParams . exerciceId , flagId : this . flag . id } )
}
$scope . deleteChoice = function ( ) {
if ( this . choice . id )
this . choice . $delete ( { exerciceId : $routeParams . exerciceId , flagId : this . flag . id } , function ( ) {
$scope . choices = ExerciceFlagChoices . query ( { exerciceId : $routeParams . exerciceId , flagId : $scope . flag . id } )
} )
}
} )
. controller ( "ExerciceFlagDepsController" , function ( $scope , $routeParams , ExerciceFlagDeps ) {
$scope . init = function ( flag ) {
$scope . deps = ExerciceFlagDeps . query ( { exerciceId : $routeParams . exerciceId , flagId : flag . id } ) ;
}
} )
. controller ( "ExerciceMCQFlagsController" , function ( $scope , ExerciceMCQFlag , $routeParams , $rootScope ) {
$scope . quiz = ExerciceMCQFlag . query ( { exerciceId : $routeParams . exerciceId } ) ;
2016-10-13 17:52:54 +00:00
2024-09-18 16:06:23 +00:00
$scope . addQuiz = function ( ) {
$scope . quiz . push ( new ExerciceMCQFlag ( ) ) ;
}
$scope . deleteQuiz = function ( ) {
this . q . $delete ( function ( ) {
$scope . quiz = ExerciceMCQFlag . query ( { exerciceId : $routeParams . exerciceId } ) ;
$rootScope . staticFilesNeedUpdate ++ ;
} , function ( response ) {
$scope . addToast ( 'danger' , 'An error occurs when trying to delete flag:' , response . data . errmsg ) ;
} ) ;
}
$scope . saveQuiz = function ( ) {
if ( this . q . id ) {
this . q . $update ( ) ;
} else {
this . q . $save ( { exerciceId : $routeParams . exerciceId } ) ;
}
$rootScope . staticFilesNeedUpdate ++ ;
}
$scope . addChoice = function ( ) {
this . quiz [ this . qk ] . entries . push ( { label : "" , response : false } )
}
$scope . deleteChoice = function ( ) {
this . quiz [ this . qk ] . entries . splice ( this . quiz [ this . qk ] . entries . indexOf ( this . choice ) , 1 ) ;
}
} )
. controller ( "ExerciceMCQDepsController" , function ( $scope , $routeParams , ExerciceMCQDeps ) {
$scope . init = function ( flag ) {
$scope . deps = ExerciceMCQDeps . query ( { exerciceId : $routeParams . exerciceId , mcqId : flag . id } ) ;
}
} )
. controller ( "TeamsListController" , function ( $scope , $rootScope , Team , $location , $http ) {
$scope . teams = Team . query ( ) ;
$scope . fields = [ "id" , "name" ] ;
$scope . order = [ ] ;
$scope . teams . $promise . then ( function ( teams ) {
teams . forEach ( function ( team ) {
$scope . order . push ( team . id ) ;
} ) ;
} ) ;
$scope . validateSearch = function ( keyEvent ) {
if ( keyEvent . which === 13 ) {
var myTeam = null ;
$scope . teams . forEach ( function ( team ) {
if ( String ( team . name . toLowerCase ( ) ) . indexOf ( $scope . query . toLowerCase ( ) ) >= 0 ) {
if ( myTeam === null )
myTeam = team ;
else
myTeam = false ;
}
} ) ;
if ( myTeam )
$location . url ( "teams/" + myTeam . id ) ;
}
} ;
$scope . genDexCfg = function ( ) {
$http . post ( "api/dex.yaml" ) . then ( function ( ) {
$http . post ( "api/dex-password.tpl" ) . then ( function ( ) {
$scope . addToast ( 'success' , 'Dex config refreshed.' , "Don't forget to reload/reboot frontend host." ) ;
} , function ( response ) {
$scope . addToast ( 'danger' , 'An error occurs when generating dex password tpl:' , response . data . errmsg ) ;
} ) ;
} , function ( response ) {
$scope . addToast ( 'danger' , 'An error occurs when generating dex config:' , response . data . errmsg ) ;
} ) ;
$http . post ( "api/vouch-proxy.yaml" ) . then ( function ( ) {
$scope . addToast ( 'success' , 'VouchProxy config refreshed.' , "Don't forget to reload/reboot frontend host." ) ;
} , function ( response ) {
$scope . addToast ( 'danger' , 'An error occurs when generating VouchProxy config:' , response . data . errmsg ) ;
} ) ;
}
$scope . desactiveTeams = function ( ) {
$http . post ( "api/disableinactiveteams" ) . then ( function ( ) {
$scope . teams = Team . query ( ) ;
} , function ( response ) {
$scope . addToast ( 'danger' , 'An error occurs when disabling inactive teams:' , response . data . errmsg ) ;
} ) ;
}
$scope . show = function ( id ) {
$location . url ( "/teams/" + id ) ;
} ;
} )
. controller ( "TeamMembersController" , function ( $scope , TeamMember ) {
$scope . fields = [ "firstname" , "lastname" , "nickname" , "company" ] ;
if ( $scope . team != null ) {
$scope . members = TeamMember . query ( { teamId : $scope . team . id } ) ;
$scope . newMember = function ( ) {
$scope . members . push ( new TeamMember ( ) ) ;
}
$scope . saveTeamMembers = function ( ) {
if ( this . team . id ) {
TeamMember . save ( { teamId : this . team . id } , $scope . members ) ;
}
}
$scope . removeMember = function ( member ) {
angular . forEach ( $scope . members , function ( m , k ) {
if ( member == m )
$scope . members . splice ( k , 1 ) ;
} ) ;
}
}
} )
. controller ( "TeamController" , function ( $scope , $rootScope , $location , Team , TeamMember , $routeParams , $http ) {
if ( $scope . team && $scope . team . id )
$routeParams . teamId = $scope . team . id ;
$scope . team = Team . get ( { teamId : $routeParams . teamId } ) ;
$scope . fields = [ "name" , "color" , "external_id" ] ;
$scope . saveTeam = function ( ) {
if ( this . team . id ) {
this . team . $update ( ) ;
$rootScope . staticFilesNeedUpdate ++ ;
} else {
this . team . $save ( function ( ) {
$rootScope . staticFilesNeedUpdate ++ ;
$location . url ( "/teams/" + $scope . team . id ) ;
} ) ;
}
}
$scope . resetPasswd = function ( team ) {
$http ( {
url : "api/password" ,
method : "POST"
} ) . then ( function ( response ) {
team . password = response . data . password ;
} ) ;
}
$scope . deleteTeam = function ( ) {
backName = this . team . name ;
this . team . $remove ( function ( ) { $scope . addToast ( 'success' , 'Team ' + backName + ' successfully removed.' ) ; $location . url ( "/teams/" ) ; $rootScope . staticFilesNeedUpdate ++ ; } ,
function ( response ) { $scope . addToast ( 'danger' , 'An error occurs during suppression of the team:' , response . data . errmsg ) ; } ) ;
}
$scope . showStats = function ( ) {
$location . url ( "/teams/" + $scope . team . id + "/stats" ) ;
}
$scope . showScore = function ( ) {
$location . url ( "/teams/" + $scope . team . id + "/score" ) ;
}
} )
. controller ( "TeamCertificatesController" , function ( $scope , $rootScope , TeamCertificate , $routeParams , $http ) {
$scope . certificates = TeamCertificate . query ( { teamId : $routeParams . teamId } ) ;
$scope . certificates . $promise . then ( function ( certificates ) {
certificates . forEach ( function ( certificate , cid ) {
certificate . serial = parseInt ( certificate . id ) . toString ( 16 ) ;
} ) ;
} ) ;
$scope . dissociateCertificate = function ( certificate ) {
$http ( {
url : "api/certs/" + certificate . id ,
method : "PUT" ,
data : {
id _team : null
}
} ) . then ( function ( response ) {
$scope . certificates = TeamCertificate . query ( { teamId : $routeParams . teamId } ) . $promise . then ( function ( certificates ) {
certificates . forEach ( function ( certificate , cid ) {
certificate . serial = parseInt ( certificate . id ) . toString ( 16 ) ;
} ) ;
} ) ;
$scope . addToast ( 'success' , 'Certificate successfully dissociated!' ) ;
} , function ( response ) {
$scope . addToast ( 'danger' , 'An error occurs when dissociating certiticate:' , response . data . errmsg ) ;
} ) ;
}
} )
. controller ( "TeamAssociationsController" , function ( $scope , $rootScope , TeamAssociation , $routeParams , $http ) {
$scope . associations = TeamAssociation . query ( { teamId : $routeParams . teamId } ) ;
$scope . form = { "newassoc" : "" } ;
$scope . addAssociation = function ( ) {
if ( $scope . form . newassoc ) {
TeamAssociation . save ( { teamId : $scope . team . id , assoc : $scope . form . newassoc } ) . $promise . then (
function ( ) {
$scope . form . newassoc = "" ;
$scope . associations = TeamAssociation . query ( { teamId : $routeParams . teamId } ) ;
} , function ( response ) {
if ( response . data )
$scope . addToast ( 'danger' , 'An error occurs when creating user association: ' , response . data . errmsg ) ;
} ) ;
}
}
$scope . dropAssociation = function ( assoc ) {
TeamAssociation . delete ( { teamId : $routeParams . teamId , assoc : assoc } ) . $promise . then (
function ( ) {
$scope . associations = TeamAssociation . query ( { teamId : $routeParams . teamId } ) ;
} , function ( response ) {
$scope . addToast ( 'danger' , 'An error occurs when removing user association: ' , response . data . errmsg ) ;
} ) ;
}
} )
. controller ( "TeamHistoryController" , function ( $scope , TeamHistory , $routeParams , $http , $rootScope ) {
$scope . history = TeamHistory . query ( { teamId : $routeParams . teamId } ) ;
$scope . updHistory = function ( ) {
var target = {
team _id : parseInt ( $routeParams . teamId ) ,
kind : $ ( "#updHistory" ) . data ( "kind" ) ,
time : $ ( "#updHistory" ) . data ( "time" ) ,
secondary : $ ( "#updHistory" ) . data ( "secondary" ) != "" ? $ ( "#updHistory" ) . data ( "secondary" ) : null ,
coeff : parseFloat ( $ ( '#historycoeff' ) . val ( ) ) ,
} ;
if ( target ) {
$http ( {
url : "api/exercices/" + $ ( "#updHistory" ) . data ( "primary" ) + "/history.json" ,
method : "PATCH" ,
data : target
} ) . then ( function ( response ) {
$rootScope . staticFilesNeedUpdate ++ ;
$scope . history = TeamHistory . query ( { teamId : $routeParams . teamId } ) ;
$ ( '#updHistory' ) . modal ( 'hide' ) ;
} , function ( response ) {
$scope . addToast ( 'danger' , 'An error occurs when updating history item: ' , response . data . errmsg ) ;
} ) ;
}
}
$scope . delHistory = function ( row ) {
$http ( {
url : "api/teams/" + $routeParams . teamId + "/history.json" ,
method : "DELETE" ,
data : row
} ) . then ( function ( response ) {
$rootScope . staticFilesNeedUpdate ++ ;
$scope . history = TeamHistory . query ( { teamId : $routeParams . teamId } ) ;
} , function ( response ) {
$scope . addToast ( 'danger' , 'An error occurs when removing history item: ' , response . data . errmsg ) ;
} ) ;
}
} )
. controller ( "TeamScoreController" , function ( $scope , TeamScore , TeamMy , Exercice , $routeParams ) {
$scope . scores = TeamScore . query ( { teamId : $routeParams . teamId } ) ;
$scope . my = TeamMy . get ( { teamId : $routeParams . teamId } ) ;
$scope . exercices = Exercice . query ( ) ;
} )
. controller ( "TeamStatsController" , function ( $scope , TeamStats , $routeParams ) {
$scope . teamstats = TeamStats . get ( { teamId : $routeParams . teamId } ) ;
$scope . teamstats . $promise . then ( function ( res ) {
solvedByLevelPie ( "#pieLevels" , res . levels ) ;
var themes = [ ] ;
angular . forEach ( res . themes , function ( theme , tid ) {
themes . push ( theme ) ;
} )
solvedByThemesPie ( "#pieThemes" , themes ) ;
} ) ;
} )
. controller ( "TeamsJSONController" , function ( $scope , Teams ) {
$scope . teams = Teams . get ( ) ;
$scope . teams . $promise . then ( function ( teams ) {
$scope . rank = [ ] ;
Object . keys ( teams ) . forEach ( function ( team ) {
$scope . teams [ team ] . id = team ;
$scope . rank . push ( $scope . teams [ team ] ) ;
} )
} ) ;
} )
. controller ( "TeamExercicesController" , function ( $scope , Teams , Themes , TeamMy , Exercice , $routeParams ) {
$scope . teams = Teams . get ( ) ;
$scope . themes = Themes . get ( ) ;
$scope . exercices = Exercice . query ( ) ;
$scope . my = TeamMy . get ( { teamId : $routeParams . teamId } ) ;
$scope . teams . $promise . then ( function ( res ) {
$scope . nb _teams = 0 ;
$scope . nb _reg _teams = Object . keys ( res ) . length ;
angular . forEach ( res , function ( team , tid ) {
if ( team . rank )
$scope . nb _teams += 1 ;
} , 0 ) ;
} ) ;
$scope . my . $promise . then ( function ( res ) {
$scope . solved _exercices = 0 ;
angular . forEach ( res . exercices , function ( exercice , eid ) {
if ( exercice . solved _rank ) {
$scope . solved _exercices += 1 ;
}
} , 0 ) ;
} ) ;
} )
. controller ( "PresenceController" , function ( $scope , TeamPresence , $routeParams ) {
$scope . presence = TeamPresence . query ( { teamId : $routeParams . teamId } ) ;
$scope . presence . $promise . then ( function ( res ) {
presenceCal ( $scope , "#presenceCal" , res ) ;
} ) ;
2016-10-13 17:52:54 +00:00
} ) ;
function solvedByLevelPie ( location , data ) {
2024-09-18 16:06:23 +00:00
var width = d3 . select ( location ) . node ( ) . getBoundingClientRect ( ) . width - parseInt ( d3 . select ( location ) . style ( "padding-right" ) ) - parseInt ( d3 . select ( location ) . style ( "padding-left" ) ) ,
height = d3 . select ( location ) . node ( ) . getBoundingClientRect ( ) . width - 10 ,
radius = Math . min ( width , height ) / 2 ,
innerRadius = 0.1 * radius ;
var color = d3 . scale . ordinal ( )
. range ( [ "#9E0041" , "#C32F4B" , "#E1514B" , "#F47245" , "#FB9F59" , "#FEC574" , "#FAE38C" , "#EAD195" , "#C7E89E" , "#9CD6A4" , "#6CC4A4" , "#4D9DB4" , "#4776B4" , "#5E4EA1" ] ) ;
var pie = d3 . layout . pie ( )
. sort ( null )
. value ( function ( d ) { return d . width ; } ) ;
var arc = d3 . svg . arc ( )
. innerRadius ( innerRadius )
. outerRadius ( function ( d ) {
return ( radius - innerRadius ) * ( d . data . score / 100.0 ) + innerRadius ;
} ) ;
var outlineArc = d3 . svg . arc ( )
. innerRadius ( innerRadius )
. outerRadius ( radius ) ;
var svg = d3 . select ( location ) . append ( "svg" )
. attr ( "width" , width )
. attr ( "height" , height )
. append ( "g" )
. attr ( "transform" , "translate(" + width / 2 + "," + height / 2 + ")" ) ;
data . forEach ( function ( d ) {
d . score = d . solved * 100 / d . total ;
d . width = d . tries + 1 ;
2016-10-13 17:52:54 +00:00
} ) ;
2024-09-18 16:06:23 +00:00
var path = svg . selectAll ( ".solidArc" )
. data ( pie ( data ) )
. enter ( ) . append ( "path" )
. attr ( "fill" , function ( d ) { return color ( d . data . tip ) ; } )
. attr ( "class" , "solidArc" )
. attr ( "stroke" , "gray" )
. attr ( "d" , arc ) ;
var outerPath = svg . selectAll ( ".outlineArc" )
. data ( pie ( data ) )
. enter ( ) . append ( "path" )
. attr ( "fill" , "none" )
. attr ( "stroke" , "gray" )
. attr ( "class" , "outlineArc" )
. attr ( "d" , outlineArc ) ;
var labelArc = d3 . svg . arc ( )
. outerRadius ( 0.8 * radius )
. innerRadius ( 0.8 * radius ) ;
svg . selectAll ( ".labelArc" )
. data ( pie ( data ) )
. enter ( ) . append ( "text" )
. attr ( "transform" , function ( d ) { return "translate(" + labelArc . centroid ( d ) + ")" ; } )
. attr ( "dy" , ".35em" )
. attr ( "text-anchor" , "middle" )
. text ( function ( d ) { return d . data . tip + ": " + d . data . solved + "/" + d . data . total ; } ) ;
svg . selectAll ( ".label2Arc" )
. data ( pie ( data ) )
. enter ( ) . append ( "text" )
. attr ( "transform" , function ( d ) { return "translate(" + arc . centroid ( d ) + ")" ; } )
. attr ( "dy" , ".35em" )
. attr ( "text-anchor" , "middle" )
. text ( function ( d ) { return d . data . tries ; } ) ;
2016-10-13 17:52:54 +00:00
}
function solvedByThemesPie ( location , data ) {
2024-09-18 16:06:23 +00:00
var width = d3 . select ( location ) . node ( ) . getBoundingClientRect ( ) . width - parseInt ( d3 . select ( location ) . style ( "padding-right" ) ) - parseInt ( d3 . select ( location ) . style ( "padding-left" ) ) ,
height = d3 . select ( location ) . node ( ) . getBoundingClientRect ( ) . width ,
radius = Math . min ( width , height ) / 2 ,
innerRadius = 0.1 * radius ;
var color = d3 . scale . ordinal ( )
. range ( [ "#9E0041" , "#C32F4B" , "#E1514B" , "#F47245" , "#FB9F59" , "#FEC574" , "#FAE38C" , "#EAD195" , "#C7E89E" , "#9CD6A4" , "#6CC4A4" , "#4D9DB4" , "#4776B4" , "#5E4EA1" ] ) ;
var pie = d3 . layout . pie ( )
. sort ( null )
. value ( function ( d ) { return d . width ; } ) ;
var arc = d3 . svg . arc ( )
. innerRadius ( innerRadius )
. outerRadius ( function ( d ) {
return ( radius - innerRadius ) * ( d . data . score / 100.0 ) + innerRadius ;
} ) ;
var outlineArc = d3 . svg . arc ( )
. innerRadius ( innerRadius )
. outerRadius ( radius ) ;
var svg = d3 . select ( location ) . append ( "svg" )
. attr ( "width" , width )
. attr ( "height" , height )
. append ( "g" )
. attr ( "transform" , "translate(" + width / 2 + "," + height / 2 + ")" ) ;
data . forEach ( function ( d ) {
d . score = d . solved * 100 / d . total ;
d . width = d . tries + 0.5 ;
2016-10-13 17:52:54 +00:00
} ) ;
2024-09-18 16:06:23 +00:00
var path = svg . selectAll ( ".solidArc" )
. data ( pie ( data ) )
. enter ( ) . append ( "path" )
. attr ( "fill" , function ( d ) { return color ( d . data . tip ) ; } )
. attr ( "class" , "solidArc" )
. attr ( "stroke" , "gray" )
. attr ( "d" , arc ) ;
var outerPath = svg . selectAll ( ".outlineArc" )
. data ( pie ( data ) )
. enter ( ) . append ( "path" )
. attr ( "fill" , "none" )
. attr ( "stroke" , "gray" )
. attr ( "class" , "outlineArc" )
. attr ( "d" , outlineArc ) ;
svg . selectAll ( ".label2Arc" )
. data ( pie ( data ) )
. enter ( ) . append ( "text" )
. attr ( "transform" , function ( d ) { return "translate(" + arc . centroid ( d ) + ")" ; } )
. attr ( "dy" , ".35em" )
. attr ( "text-anchor" , "middle" )
. text ( function ( d ) { return d . data . solved ; } ) ;
var labelArc = d3 . svg . arc ( )
. outerRadius ( 0.8 * radius )
. innerRadius ( 0.8 * radius ) ;
svg . selectAll ( ".labelArc" )
. data ( pie ( data ) )
. enter ( ) . append ( "text" )
. attr ( "transform" , function ( d ) { return "translate(" + labelArc . centroid ( d ) + ")" ; } )
. attr ( "dy" , ".35em" )
. attr ( "text-anchor" , "middle" )
. text ( function ( d ) { return d . data . tip + ": " + d . data . tries ; } ) ;
2016-10-13 17:52:54 +00:00
}
2017-04-02 09:38:40 +00:00
function presenceCal ( scope , location , data ) {
2024-09-18 16:06:23 +00:00
var width = d3 . select ( location ) . node ( ) . getBoundingClientRect ( ) . width ,
height = 80 ,
cellSize = 17 ; // cell size
var percent = d3 . format ( ".1%" ) ,
format = d3 . time . format ( "%H:%M" ) ;
var color = d3 . scale . quantize ( )
. domain ( [ 0 , 16 ] )
. range ( d3 . range ( 8 ) . map ( function ( d ) { return "q" + d + "-8" ; } ) ) ;
var svg = d3 . select ( location ) . selectAll ( "svg" )
. data ( d3 . range ( scope . settings . start , scope . time . start + ( scope . settings . start % 86400000 + scope . settings . end - scope . settings . start ) , 86400000 ) . map ( function ( t ) { return new Date ( t ) ; } ) )
. enter ( ) . append ( "svg" )
. attr ( "width" , width )
. attr ( "height" , height )
. attr ( "class" , "RdYlGn" )
. append ( "g" )
. attr ( "transform" , "translate(" + ( ( width - cellSize * 24 ) / 2 ) + "," + ( height - cellSize * 4 - 1 ) + ")" ) ;
svg . append ( "text" )
. attr ( "transform" , "translate(-6," + cellSize * 2.6 + ")rotate(-90)" )
. style ( "text-anchor" , "middle" )
. text ( function ( d ) { return d . getDate ( ) + "-" + ( d . getMonth ( ) + 1 ) ; } ) ;
var rect = svg . selectAll ( ".quarter" )
. data ( function ( d ) { return d3 . time . minutes ( new Date ( d . getFullYear ( ) , d . getMonth ( ) , d . getDate ( ) , 0 ) , new Date ( d . getFullYear ( ) , d . getMonth ( ) , d . getDate ( ) , 23 ) , 15 ) ; } )
. enter ( ) . append ( "rect" )
. 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 ) {
cur = new Date ( cur ) . getTime ( ) ;
dv = d . getTime ( ) ;
return prev + ( ( dv <= cur && cur < dv + 15 * 60000 ) ? 1 : 0 ) ;
} , 0 ) ) ;
} ) ;
2016-10-13 17:52:54 +00:00
}