admin: new interface to manage claims

This commit is contained in:
nemunaire 2018-01-17 01:21:32 +01:00
commit 1eef71923a
10 changed files with 791 additions and 0 deletions

View file

@ -34,6 +34,7 @@
<li class="nav-item"><a class="nav-link" href="/files">Fichiers</a></li>
<li class="nav-item"><a class="nav-link" href="/public/0">Public</a></li>
<li class="nav-item"><a class="nav-link" href="/events">&Eacute;vénements</a></li>
<li class="nav-item"><a class="nav-link" href="/claims">Tâches</a></li>
<li class="nav-item"><a class="nav-link" href="/settings">Paramètres</a></li>
</ul>
</div>

View file

@ -61,12 +61,46 @@ angular.module("FICApp", ["ngRoute", "ngResource", "ngSanitize"])
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);
});
function setCookie(name, value, days) {
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=/";
}
function getCookie(name) {
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;
}
angular.module("FICApp")
.directive('autofocus', ['$timeout', function($timeout) {
return {
@ -88,6 +122,16 @@ angular.module("FICApp")
'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("File", function($resource) {
return $resource("/api/files/:fileId", { fileId: '@id' })
})
@ -616,6 +660,134 @@ angular.module("FICApp")
}
})
.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("ClaimsListController", function($scope, Claim, ClaimAssignee, Teams, $location) {
$scope.claims = Claim.query();
$scope.assignees = ClaimAssignee.query();
$scope.whoami = getCookie("myassignee");
$scope.teams = Teams.get();
$scope.fields = ["id", "state", "subject", "creation", "id_team", "id_assignee"];
$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("ClaimController", function($scope, Claim, ClaimAssignee, Teams, $routeParams, $location, $http) {
$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", "subject", "priority", "id_assignee"];
else
$scope.fields = ["state", "subject", "priority", "id_assignee", "id_team", "creation"];
$scope.assignees = ClaimAssignee.query();
$scope.whoami = Math.floor(getCookie("myassignee"));
$scope.teams = Teams.get();
$scope.namedFields = {
"subject": "Objet",
"id_assignee": "Assigné a",
"state": "État",
"id_team": "Équipe",
"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.assignToMe = function() {
this.claim.id_assignee = $scope.whoami;
if (this.claim.id)
this.saveClaim();
}
$scope.saveDescription = function() {
$http({
url: "/api/claims/" + $scope.claim.id,
method: "POST",
data: {
"id_assignee": $scope.whoami,
"content": $scope.ndescription
}
}).then(function() {
$location.url("/claims/" + $scope.claim.id);
});
}
$scope.saveClaim = function() {
if (this.claim.id_team) {
this.claim.id_team = Math.floor(this.claim.id_team);
} else {
this.claim.id_team = null;
}
if (this.claim.id) {
this.claim.$update(function(v) {
v.id_team = "" + v.id_team;
if ($scope.ndescription)
$scope.saveDescription();
else
$location.url("/claims/");
});
} else {
this.claim.$save(function() {
if (!this.ndescription)
this.ndescription = "Création de la tâche";
$scope.saveDescription();
});
}
}
$scope.deleteClaim = function() {
this.claim.$remove(function() { $location.url("/claims/");});
}
})
.controller("ThemesListController", function($scope, Theme, $location, $rootScope, $http) {
$scope.themes = Theme.query();
$scope.fields = ["id", "name"];

View file

@ -0,0 +1,61 @@
<h2>
Tâches et réclammations ({{ claims.length }})
<button ng-click="show('new')" class="float-right btn btn-sm btn-primary" style="margin-right: 10px"><span class="glyphicon glyphicon-plus" aria-hidden="true"></span> Ajouter une tâche</button>
<small style="height: 0px;">
<div class="checkbox float-right"><label><input type="checkbox" ng-model="showOnlyUnassigned"> Non assignée</label></div>
<div class="checkbox float-right"><label><input type="checkbox" ng-model="showOnlyMines" ng-show="whoami"> Que mes tâches</label></div>
<div class="checkbox float-right"><label><input type="checkbox" ng-model="showClosed"> Tâches closes</label></div>
</small>
</h2>
<p><input type="search" class="form-control" placeholder="Search" ng-model="query" autofocus></p>
<table class="table table-hover table-bordered table-striped table-sm">
<thead class="thead-dark">
<tr>
<th ng-repeat="field in fields" ng-click="chOrder(field)">
{{ field }}
</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="claim in claims | filter: query | orderBy:order" ng-click="show(claim.id)" ng-class="{'bg-info': claim.priority == 'medium', 'bg-warning': claim.priority == 'high', 'bg-danger': claim.priority == 'critical'}" ng-if="(showClosed || (claim.state != 'closed' && claim.state != 'invalid')) && (!showOnlyMines || claim.id_assignee == whoami) && (!showOnlyUnassigned || !claim.id_assignee)">
<td ng-repeat="field in fields">
{{ claim[field] }}
</td>
</tr>
</tbody>
</table>
<hr>
<div ng-controller="AssigneesListController">
<h2>
Assignables à
<button ng-click="newAssignee()" class="float-right btn btn-sm btn-primary" style="margin-right: 10px"><span class="glyphicon glyphicon-plus" aria-hidden="true"></span> Ajouter une personne</button>
</h2>
<table class="table table-hover table-bordered table-striped table-sm">
<thead class="thead-dark">
<tr>
<th>ID</th>
<th>Nom</th>
<th></th>
</tr>
</thead>
<tbody>
<tr ng-repeat="a in assignees" ng-click="edit(a)">
<td>
{{ a.id }}
</td>
<td>
<span ng-if="a.id && !a.edit">{{ a.name }}</span>
<input type="text" class="form-control form-control-sm" ng-model="a.name" ng-if="!a.id || a.edit">
</td>
<td style="width: 10%;">
<button class="btn btn-sm btn-info" ng-if="a.id" ng-click="setMyAId(a.id)" ng-class="{'disabled': whoami == a.id}"><span class="glyphicon glyphicon-user"></span></button>
<button class="btn btn-sm btn-danger" ng-if="a.id && !a.edit" ng-click="removeAssignee(a)"><span class="glyphicon glyphicon-remove"></span></button>
<button class="btn btn-sm btn-success" ng-if="!a.id || a.edit" ng-click="updateAssignee(a)"><span class="glyphicon glyphicon-ok"></span></button>
</td>
</tr>
</tbody>
</table>
</div>

View file

@ -0,0 +1,36 @@
<h2>Tâche</h2>
<form ng-submit="saveClaim()">
<div class="form-group row" ng-repeat="field in fields">
<label for="{{ field }}" class="col-sm-2 col-form-label text-right">{{ namedFields[field] }}</label>
<div class="col-sm-10">
<input type="text" class="form-control" id="{{ field }}" ng-model="claim[field]" ng-if="field != 'state' && field != 'priority' && field != 'creation' && field != 'id_team' && field != 'id_assignee' && field != 'description'">
<input type="datetime" class="form-control" id="{{ field }}" ng-model="claim[field]" ng-if="field == 'creation' && claim.id">
<select class="custom-select" id="{{ field }}" ng-model="claim[field]" ng-options="k as v for (k, v) in states" ng-if="field == 'state'"></select>
<select class="custom-select" id="{{ field }}" ng-model="claim[field]" ng-options="k as v for (k, v) in priorities" ng-if="field == 'priority'"><option value="medium">Par défaut</option></select>
<select class="custom-select" id="{{ field }}" ng-model="claim[field]" ng-options="k as t.name for (k, t) in teams" ng-if="field == 'id_team' && !claim.id" autofocus><option></option></select>
<select class="custom-select" id="{{ field }}" ng-model="claim[field]" ng-options="k as t.name for (k, t) in teams" ng-if="field == 'id_team' && claim.id"><option></option></select>
<select class="custom-select" id="{{ field }}" ng-model="claim[field]" ng-options="a.id as a.name for a in assignees" ng-if="field == 'id_assignee'"><option></option></select> <button type="button" class="btn" ng-if="field == 'id_assignee' && whoami" ng-class="{'disabled': whoami == claim[field]}" ng-click="assignToMe()">Me l'assigner</button>
</div>
</div>
<div class="form-group row" ng-show="whoami">
<label for="ndescription" class="col-sm-2 col-form-label text-right">Ajouter commentaire</label>
<div class="col-sm-10">
<textarea class="form-control" id="ndescription" ng-model="ndescription" autofocus></textarea>
</div>
</div>
<div class="text-right" ng-show="claim.id">
<button type="submit" class="btn btn-primary"><span class="glyphicon glyphicon-save" aria-hidden="true"></span> Save</button>
<button class="btn btn-danger" ng-click="deleteClaim()"><span class="glyphicon glyphicon-remove" aria-hidden="true"></span> Delete</button>
</div>
<div class="text-right" ng-show="!claim.id">
<button type="submit" class="btn btn-primary"><span class="glyphicon glyphicon-plus" aria-hidden="true"></span> Ajouter la tâche</button>
</div>
</form>
<hr>
<div ng-repeat="description in claim.descriptions" class="alert text-light" ng-class="{'alert-dark': '' + description.id_assignee != whoami, 'alert-info': '' + description.id_assignee == whoami}">
<strong>Par <em ng-if="!description.id_assignee">anonymous</em> <span ng-repeat="assignee in assignees" ng-if="assignee.id == description.id_assignee">{{ assignee.name }}</span> le {{ description.date | date:"mediumTime" }} :</strong>
{{ description.content }}
</div>