admin: Can import videos

This commit is contained in:
nemunaire 2022-06-12 12:15:39 +02:00
parent dfe62e0b97
commit 223f44572e
7 changed files with 59 additions and 6 deletions

View File

@ -4,6 +4,8 @@ import (
"fmt"
"log"
"net/http"
"net/url"
"path"
"strings"
"srs.epita.fr/fic-server/admin/sync"
@ -87,6 +89,39 @@ func declareSyncRoutes(router *gin.RouterGroup) {
// Exercices
declareSyncExercicesRoutes(apiSyncRoutes)
declareSyncExercicesRoutes(apiSyncThemesRoutes)
// Videos sync imports resolution.mp4 from path stored in database.
apiSyncRoutes.POST("/videos", func(c *gin.Context) {
exercices, err := fic.GetExercices()
if err != nil {
log.Println("Unable to GetExercices:", err.Error())
c.AbortWithStatusJSON(http.StatusInternalServerError, gin.H{"errmsg": "Unable to retrieve exercices list."})
return
}
for _, e := range exercices {
if len(e.VideoURI) == 0 || !strings.HasPrefix(e.VideoURI, "$RFILES$/") {
continue
}
vpath, err := url.PathUnescape(strings.TrimPrefix(e.VideoURI, "$RFILES$/"))
if err != nil {
c.JSON(http.StatusExpectationFailed, gin.H{"errmsg": fmt.Sprintf("Unable to perform URL unescape: %s", err.Error())})
return
}
_, err = sync.ImportFile(sync.GlobalImporter, vpath, func(filePath, URI string) (interface{}, error) {
e.VideoURI = path.Join("$FILES$", strings.TrimPrefix(filePath, fic.FilesDir))
return e.Update()
})
if err != nil {
c.JSON(http.StatusExpectationFailed, gin.H{"errmsg": err.Error()})
return
}
}
c.JSON(http.StatusOK, true)
})
}
func declareSyncExercicesRoutes(router *gin.RouterGroup) {

View File

@ -740,6 +740,19 @@ angular.module("FICApp")
});
});
};
$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);
});
});
};
})
.controller("PKIController", function($scope, $rootScope, Certificate, CACertificate, Team, $location, $http) {

View File

@ -8,7 +8,7 @@
<div class="row">
<div class="col text-center" ng-if="exercice.videoURI">
<video src="vids/{{exercice.videoURI.replace('\$FILES\$/','').replace('?', '%3F')}}" controls style="height: 80vh; margin: auto;"></video>
<video src="{{exercice.videoURI.replace('\$RFILES\$/','vids/').replace('\$FILES\$/','files/').replace('?', '%3F')}}" controls style="height: 80vh; margin: auto;"></video>
</div>
<div class="col" ng-if="exercice.resolution" ng-bind-html="exercice.resolution.replaceAll('\$FILES\$/','files/')">
</div>

View File

@ -50,6 +50,7 @@
</div>
</div>
<button type="button" class="btn btn-secondary" ng-click="speedyDeepSync()" ng-disabled="deepSyncInProgress"><span class="glyphicon glyphicon-import" aria-hidden="true"></span> Synchronisation sans fichiers</button>
<button type="button" class="btn btn-info" ng-click="syncVideos()" ng-disabled="deepSyncInProgress"><span class="glyphicon glyphicon-facetime-video" aria-hidden="true"></span> Mettre à disposition les vidéos</button>
</div>
</div>
</div>

View File

@ -236,7 +236,7 @@ func BuildExercice(i Importer, theme *fic.Theme, epath string, dmap *map[int64]*
errs = append(errs, fmt.Sprintf("%q: resolution.mp4: The file is empty!", edir))
e.VideoURI = ""
} else {
e.VideoURI = strings.Replace(url.PathEscape(path.Join("$FILES$", e.VideoURI)), "%2F", "/", -1)
e.VideoURI = strings.Replace(url.PathEscape(path.Join("$RFILES$", e.VideoURI)), "%2F", "/", -1)
resolutionFound = true
}

View File

@ -10,7 +10,11 @@
</script>
<CardBody class="text-indent ratio ratio-16x9">
<iframe type="text/html" src="{uri.replace('$FILES$', base+'/resolution')}" class="embed-responsive-item" title="Vidéo de résolution">
Regardez la vidéo de résolution de ce défi&nbsp;: <a href="{uri.replace('$FILES$',base+'/resolution')}">{uri.replace('$FILES$',base+'/resolution')}</a>.
</iframe>
{#if uri.length > 0 && uri[0] === '/'}
<video controls src={uri} />
{:else}
<iframe type="text/html" src="{uri.replace('$RFILES$', base+'/resolution')}" class="embed-responsive-item" title="Vidéo de résolution">
Regardez la vidéo de résolution de ce défi&nbsp;: <a href="{uri.replace('$RFILES$',base+'/resolution')}">{uri.replace('$RFILES$',base+'/resolution')}</a>.
</iframe>
{/if}
</CardBody>

View File

@ -133,7 +133,7 @@ func MyJSONTeam(t *Team, started bool) (interface{}, error) {
if t == nil {
exercice.Overview = strings.Replace(e.Overview, "$FILES$", FilesDir, -1)
exercice.Finished = strings.Replace(e.Finished, "$FILES$", FilesDir, -1)
exercice.VideoURI = e.VideoURI
exercice.VideoURI = strings.Replace(e.VideoURI, "$FILES$", FilesDir, -1)
exercice.Resolution = strings.Replace(e.Resolution, "$FILES$", FilesDir, -1)
exercice.TotalTries = e.TriedCount()
exercice.Gain = int(float64(e.Gain) * e.Coefficient * GlobalScoreCoefficient)