Table des matières

TD n°6 - Boards

-- Contexte

Ce projet a été donné l'année dernière en évaluation.

Dans le cadre de l'évaluation du potentiel d'Angular pour les projets de votre entreprise, vous travaillez sur un projet Exemple permettant de gérer les User stories de projets Scrum.

En voici les principales caractéristiques :

-- Eléments à implémenter

  • Respecter les normes, nommages et consignes données ⇒ 1 point
  • Usage de Browserify pour créer un unique bundle ⇒ 1 point

-- Squelette de l'application, routage (3 points)

//TODO 2.1.1

Le dossier root de votre application devra être de la forme : prenom.nom

Créer la structure suivante :

Emplacement Fichier Rôle
/ index.html Fichier principal
/js Fichiers js
app.js Fichier principal de l'application (module)
router.js Fichier de routage
/js/controllers contrôleurs
story.js Définit le contrôleur storyController
stories.js Définit le contrôleur storiesController
/js/directives directives
/js/services services
/templates templates HTML
/css Feuille(s) de styles

//TODO 2.1.2

Implémenter le routage suivant :

URL Composante Valeur
/ Description Affiche la liste des user stories
template templates/stories.html
contrôleur storiesController
alias storiesCtrl
/story/:code Description Affiche la user story correspondant à code
template templates/story.html
contrôleur storyController
alias storyCtrl
/ Route par défaut

-- Service (1.5 points)

//TODO 2.2

Le service dataService simule la connexion à un web service ; il est défini de la façon suivante :

steps, stories, tags et devs seront définis “en dur” à l'intérieur du service dans l'équivalent de variables privées :

    var steps=["todo","In progress","done"];
    var stories=[
                    {"code":"B22","description":"En tant que créateur, je veux ajouter et gérer les réponses d'une question [methods] .",
                        "tags":[{"color":"red","label":"bug"},{"color":"orange","label":"Admin"}],
                        "dev":{"identite":"James Gosling"},
                        "tasks":[{"content":"get reponse/all","do":false},{"content":"get reponse/:id","do":false},{"content":"put reponse","do":false},{"content":" post reponse/:id","do":false}],
                        "step": "todo"
                    },
                    {"code":"E120","description":"En tant que créateur, je veux créer / Modifier des quiz [methods]",
                        "tasks":[{"content":"get questionnaire/:id","do":false}],
                        "tags":[]
                    },
                    {"code":"E140","description":"En tant que créateur, je souhaite gérer les utilisateurs [methods]",
                        "tasks":[{"content":"get user/all","do":true},{"content":"get user/:id","do":true},{"content":"put user","do":true}],
                        "dev":{"identite":"Rod Johnson"},
                        "tags":[{"color":"orange","label":"Admin"}],
                        "step":"done"
                    }
    ];
    var tags=[{"color":"red","label":"bug"},{"color":"#cc317c","label":"question"},{"color":"#159818","label":"help wanted"},{"color":"#cccccc","label":"duplicate"},{"color":"#0052cc","label":"todo"}];
    var devs=[{"identite":"James Gosling"},{"identite":"Rod Johnson"},{"identite":"Linus Torvalds"}];

Service datas.js (dataService)
Variables privées stories
Tableau des user stories
steps
Tableau des steps existantes
tags
Tableau des tags disponibles
devs
Tableau des développeurs
Méthodes publiques getStories()
retourne stories
getSteps()
retourne steps
getTags()
retourne tags
getDevs()
Retourne devs
getStory(code)
Retourne la user story correspondant au code donné, null si le code est inexistant

Créez dataService, implémentez les méthodes publiques.
Il faudra ensuite injecter dataService aux 2 contrôleurs storiesController et StoryController

-- Url /stories ou / (3.5 points)

//TODO 2.3

Affiche la liste des user stories.

Créer le template /templates/stories.html, associé au contrôleur /js/controllers/stories.js

Controller stories.js (storiesController)
Variables publiques stories
Tableau des user stories
selected
story sélectionnée
Méthodes publiques goto(story)
Accède à l'url story/:code en utilisant le service $location

Comportement de l'interface :

-- Directive storyHeader (2 points)

//TODO 2.4

On souhaite intégrer l'entête de chaque story affichée à l'url /stories dans une directive, pour la réutiliser plus facilement dans la page suivante, pour présenter le détail de chaque story.

La directive storyHeader, accessible en tant qu'élément, ou attribut, permettra d'afficher le contenu suivant d'une story. Il sera nécessaire de lui passer la variable story (qu'elle est en charge d'afficher) dans son scope.

On respectera la structure suivante :

Emplacement Fichier Rôle
/js/directives Dossier définissant les directives
storyHeader.js Fichier définissant la directive storyHeader
/js/directives/templates Fichiers templates
storyHeader.html Fichier template de la directive storyHeader

-- Url /stories ou / (3 points)

//TODO 2.5

Affiche les stories par step.

Filtre sur ng-repeat

On utilisera la directive ng-repeat avec un filtre (filter) composé d'une expression (testant le membre step de chaque story).

Le filtre peut faire appel à une méthode définie dans le contrôleur :

Exemple :

<div ng-repeat="item in items | filter: myCtrl.check"></div>

this.check=function(item){
    return item.code=="AAA";
};

La boucle ng-repeat affichera dans ce cas les éléments du tableau items dont le membre code est égal à “AAA”

Disposition des éléments

On utilisera le GridSystem Bootstrap pour disposer correctement les conteneurs de step sur la page :

Modifier le template stories.html et le contrôleur storiesController :

Controller stories.js (storiesController)
Méthode publique à ajouter getColClass()
Retourne la classe css à attribuer aux colonnes (col-md-x) en fonction du nombre de steps

-- Url /story/:code (3 points)

//TODO 2.6

Affiche la story correspondant au code passé dans l'url.

Comportement de l'interface :

Créer le template /templates/story.html, associé au contrôleur /js/controllers/story.js

Controller story.js (storyController)
Variables privées story
user story à afficher
Méthodes publiques toggleDone(task)
Bascule de vrai à faux et inversement le membre done de la tâche task passée en paramètre

-- A poursuivre...

//TODO 2.7

Fonctionnalités supplémentaires à implémenter :

Dans la page /stories ou / :

Super-bonus (20 garantis) :

-- Ressources

HTML/CSS

<!DOCTYPE html>
<html>
<head>
    <base href="http://127.0.0.1/yoursite/">
    <meta charset="UTF-8">
    <link rel="stylesheet" href="http://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css">
    <link rel="stylesheet" href="css/styles.css">

    <script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/2.2.2/jquery.min.js"></script>
    <script async type="text/javascript" src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/js/bootstrap.min.js"></script>


    <script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.4.9/angular.min.js"></script>
    <script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.4.9/angular-route.min.js"></script>

    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">
</head>
<body>
<div class="container">
    <div class="panel panel default">
        <div class="panel-body">
 
        </div>
    </div>
</div>
</body>
</html>

<IfModule mod_rewrite.c>
    Options +FollowSymlinks
    RewriteEngine On
    RewriteBase /yoursite/
    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteCond %{REQUEST_FILENAME} !-d
    RewriteCond %{REQUEST_URI} !.*\.(css|js|html|png|jpg|jpeg|gif|txt|ttf|woff)
    RewriteRule (.*) index.html [L]
</IfModule>

body{
    font-family: 'Segoe UI', Frutiger, 'Frutiger Linotype', 'Dejavu Sans', 'Helvetica Neue', Arial, sans-serif;
}
.story-panel{

}
.story{
    padding: 10px;
    cursor: pointer;
}
.story-code{
    font-weight: bold;
    color: crimson;
}

.story-panel span{
    vertical-align: inherit;
}
.assign-to{
    font-weight: bold;
}
.selected{
    background-color: #dff0d8;
    color: #3c763d;
}
.selected::after{
    content: '';
    display: block;
    clear: both;
}

Bootstrap

  <span class="glyphicon glyphicon-user" aria-hidden="true"></span>&nbsp;James Gosling

<span class="badge">3 tâches </span>

<span class="label" style="color: orange">Admin</span>

<button type="button" class="btn btn-default" aria-label="Left Align">
  <span class="glyphicon glyphicon-align-left" aria-hidden="true"></span>&nbsp;Texte du bouton
</button>

<div class="panel panel-default">
    <div class="panel-heading">
        En-tête
    </div>
    <div class="panel-body">Body</div>
    <ul class="list-group">
        <li class="list-group-item">
            Item 1
        </li>
        <li class="list-group-item">
            Item 2
        </li>
    </ul>
</div>