Focus

http://get-focus.github.io/formation-focus

Pourquoi Focus?

Klee fait des applications sur mesure

Les missions de Focus

Remettre l'humain au centre UX

Capter et digérer l'innovation

Developer Experience DX

Les livrables

  • Support de communication et d'aide à la vente
  • Les templates de page
  • Libraries JS
  • Showcase de composants
  • Blog d'articles UX / Tech
  • Documentation technique focus-docs
  • Extensions prêtes à l'emploi (notifs, comments, ...)

Objectifs

Faire rapidement et facilement 80 % des écrans de l'application

  • Respecter les maquettes
  • Composants UX prêt à l'emploi

Faire facilement du sur mesure 20 % des écrans de l'application

Le bureau Focus

  • Validation de choix avant de se lancer ?
  • Conception de maquettes
  • Validation des maquettes
  • Conception technique d'écran
  • Pour partager vos bonnes idées

Je n'arrive pas à faire rentrer mon écran dans le pattern

    Mon client veut un écran un peu funky

    Je trouve un bug sur Focus

    Des suggestions ou problèmes:

    • focus-bureau@kleegroup.com
    • Slack Focus community
    • Validation des maquettes
    • Conception technique d'écran
    • Pour partager vos bonnes idées.

    github

    GetFocus.io

    # Les librairies coeur ## [Focus Core](https://github.com/KleeGroup/focus-core) ## [Focus Components](https://github.com/KleeGroup/focus-components)
    # Les extensions ## [Focus file](https://github.com/KleeGroup/focus-file) ## [Focus Notification](https://github.com/KleeGroup/focus-notification) ## [Focus Comments](https://github.com/KleeGroup/focus-comments)
    # Documentation ## [Focus Showcase](https://github.com/KleeGroup/focus-showcase) ## [Focus docs](https://github.com/KleeGroup/focus-docs) ## [Focus demo](https://github.com/KleeGroup/focus-demo)
    # Outils ## [Focus eslint](https://github.com/KleeGroup/eslint-config-focus) ## [Focus webpack](https://github.com/KleeGroup/webpack-focus)

    Contribuez à Focus

    Articles, Fork, issues, PR, doc, tuto, DX ...

    Focus.js

    Le router de l'application

    ## [Router](https://github.com/reactjs/react-router) ![router](https://cloud.githubusercontent.com/assets/286966/15237848/4daec5de-18d2-11e6-8b77-b5e3387014c9.png)

    Et voici l'exemple

    ```javascript import React from 'react'; import { Route, IndexRoute } from 'react-router'; import AppLayout from '../components/layout' import HomeRoute from './home-route'; import MasterdataRoutes from './masterdata-routes'; import MoviesRoutes from './movies-route'; import PersonsRoutes from './persons-route'; import SearchRoutes from './advanced-search-route'; import ErrorRoutes from './error-route'; export default { path: `${__BASE_URL__}`, indexRoute: { onEnter: ({ params }, replace) => replace(`${__BASE_URL__}home`) }, component: AppLayout, childRoutes: [...HomeRoute, ...MasterdataRoutes, ...MoviesRoutes, ...PersonsRoutes, ...SearchRoutes, ...ErrorRoutes] }; import React from 'react'; import MovieDetailView from '../views/movie/detail'; const route = [ { path: 'movies/:id', component: (props) => () } ]; export default route; ```

    Les domaines et les définitions

    ## les domaines - Responsable de la validation - Du composant de rendu (consultation, édition) - formatage des données - On peut les utiliser pour le style - Utilisation intelligente avec `fieldFor`
    ## example du domaine do-date.js ```javascript import moment from 'moment'; import {Date as DateComponent} from 'focus-components/components/input'; export default { InputComponent: DateComponent, formatter: date => date ? moment(date, moment.ISO_8601).format('DD/MM/YYYY') : '', format: ['DD/MM/YYYY', 'DD-MM-YYYY', 'D MMM YYYY'] }; ```
    ## Les définitions - Générées depuis le modèle de données - Lie le modèle de données ayu domaines - Chaque table a des champs - Chaque champ a un domaine - Chaque champ porte l'information requis / non requis
    ## example de définitions ```javascript export const movie = { code: { domain: 'DO_ID', required: true }, title: { domain: 'DO_LABEL_LONG', required: true }, creationDate: { domain: 'DO_DATE', required: false } } // fieldFor(creationDate) ```

    Flux by Focus

    ## flux by Facebook ![flux](https://facebook.github.io/flux/img/flux-simple-f8-diagram-with-client-action-1300w.png)
    ## Architecture ![archi](https://cloud.githubusercontent.com/assets/286966/15237742/4df03ccc-18d1-11e6-9753-97777780453b.png)
    # les stores ![stores](https://s3.amazonaws.com/media-p.slid.es/uploads/52889/images/1647931/store.PNG)
    # Flux ![flux1](https://s3.amazonaws.com/media-p.slid.es/uploads/52889/images/1647945/focus-flux1.PNG)
    # flux ![flux2](https://s3.amazonaws.com/media-p.slid.es/uploads/52889/images/1647946/focus-flux2.PNG)
    # Service - Un service est une fonction - Un service appelle une url construite grâce à [urlbuilder](https://github.com/KleeGroup/focus-core/blob/develop/src/list/action-builder.js) - Un service retourne une `Promise` - On peut utiliser la méthode `fetch` de [focus](https://github.com/KleeGroup/focus-core/blob/develop/src/network/fetch.js)

    Exemple de service (retourne impérativement une Promise)

    						
    import fetch from 'focus-core/network/fetch';
    //Fait une reqête ajax
    import movieUrl from '../config/server/movies';
    // Les urls de ws sont configurées
    export default {
        loadMovie(id) {
            return fetch(movieUrl.loadMovie({urlData: {id}}));
        },
        saveMovieSynopsis(data) {
            return fetch(movieUrl.saveMovie({urlData: {id: data.id}, data: {data}}));
        },
        saveMovieCaracteristics(data) {
            return fetch(movieUrl.saveMovie({urlData: {id: data.id}, data: {data}}));
        }
    }
    						
    					
    # store - Un store est un objet qui contient une grappe de données - Associé à une notion de grappe d'objet ([corestore](https://github.com/KleeGroup/focus-core/blob/develop/src/store/CoreStore.js)) - Il existe des stores spécialisées ([recherche](https://github.com/KleeGroup/focus-core/tree/develop/src/store/search), [liste](https://github.com/KleeGroup/focus-core/tree/develop/src/store/search)) - Il peut notifier: d'un changement, d'une erreur - Chaque noeud de données peut avoir un statut

    Exemple de store

    						
    import {CoreStore} from 'focus-core/store';
    const movieStore = new CoreStore({
        definition: {
            movie: 'movie',
    		actors: 'actors'
        }
    });
    
    export default movieStore;
    						
    					
    # action - Une action est une fonction - Une action doit appeller un service - Avec le retour (après l'appel serveur) - Dispatch le résultat dans le `dispatcher` - On peut utiliser le `actionBuilder` ([detail](https://github.com/KleeGroup/focus-core/blob/develop/src/application/action-builder.js), [recherche](https://github.com/KleeGroup/focus-core/blob/develop/src/search/action-builder.js), [liste](https://github.com/KleeGroup/focus-core/blob/develop/src/list/action-builder.js))

    Exemple d'action

    						
    import actionBuilder from 'focus-core/application/action-builder';
    import {loadMovie, saveMovieSynopsis} from '../services/movie';
    
    export const synopsisActions = {
        load: actionBuilder({
            node: 'movie',
            service: loadMovie,
            shouldDumpStoreOnActionCall: true,
            status: 'loaded'
        }),
        save: actionBuilder({
            node: 'movie',
            service: saveMovieSynopsis,
            shouldDumpStoreOnActionCall: true,
            status: 'saved'
        })
    }
    						
    					

    Un exemple de composant mis en musique

    						
    //librairies
    import React, {PropTypes} from 'react';
    import FocusComponents from 'focus-components';
    
    // web components
    import Panel from 'focus-components/components/panel';
    import {mixin as formMixin} from 'focus-components/common/form';
    
    //stores & actions
    import movieStore from '../../../stores/movie';
    import {caracteristicsActions} from '../../../action/movie';
    
    export default React.createClass({
        displayName: 'MovieCaracteristics',
        propTypes: {
            id: PropTypes.number
        },
        mixins: [formMixin],
        definitionPath: 'movie',
        stores: [{store: movieStore, properties: ['movie']}],
        action: caracteristicsActions,
    
        /** @inheritDoc */
        renderContent() {
            return (
                
                    {this.fieldFor('title')}
                    {this.fieldFor('originalTitle')}
                    {this.fieldFor('keywords')}
                    {this.fieldFor('runtime')}
                    {this.fieldFor('movieType')}
                    {this.fieldFor('productionYear')}
                    {this.fieldFor('trailerName')}
                    {this.fieldFor('trailerHRef')}
                
            );
        }
    });
    						
    					
    ## tutos - [Faire une page de détail](http://kleegroup.github.io/focus-docs/tutorial/detail.html) - [Faire une page de liste](http://kleegroup.github.io/focus-docs/tutorial/list.html)
    ## Structure applicative - [Focus docs](http://kleegroup.github.io/focus-docs/getting-started/starter-kit.html) - [Focus demo app](https://github.com/KleeGroup/focus-demo-app)