MIRA - Um framework Javascript para construção de interfaces adaptativas em aplicações REST

0 %
100 %
Information about MIRA - Um framework Javascript para construção de interfaces adaptativas...

Published on September 26, 2015

Author: ebertti

Source: slideshare.net

1. Um framework Javascript para construção de interfaces adaptativas em aplicações REST Apoio W3C Brazil Office | NiC.br | Microsoft Brasil Open Source http://mira.tecweb.inf.puc-rio.br/

2. Olá, eu sou Ezequiel Bertti • MSc Engenharia de Software para Web • Arquiteto de Sistema • Desenvolvedor FullStack • https://twitter.com/ebertti • https://github.com/ebertti • https://br.linkedin.com/in/ebertti • ebertti@gmail.com EBertti, Ezeq, .exe, Exec, Zeq ou Zequinha

3. Bagagem Simples/PHP/Java C#/Asp.net Python/Django Javascript/Backbone Desktop Web Backend Frontend Bacharel Mestrado Pesquisa 0 1 2 3 4 5 6 7 8 9 10 11 12 Acadêmica Foco Profissional

4. Quantos dispositivos acessam sua aplicação?

5. Alguns poucos...

6. A responsividade resolve?

7. As vezes SIM!

8. E nesses casos?

9. Qual o esforço necessário para desenvolver a interface de uma aplicação? Qual a proporção de tempo? De linhas de código? De testes? E depois de “pronto”? Como é dar manutenção?

10. Podemos dizer que é quase a metade de tudo Tipicamente, a interface gráfica, representa cerca de 48% do código fonte, requer cerca de 45% do tempo de desenvolvimento e de 50% do tempo de aplicação, e atinge 37% do tempo de manutenção [1] [1] BRAD A. MYERS, M. B. R. Survey on user interface programming 37% 50% 45% 48% 0% 20% 40% 60% 80% 100% Manutenção Aplicação Desenvolvimento Código Fonte Interface Outros

11. Ferramentas para diminuir o tamanho do problema

12. Mas e quando a regra de negócio muda? Quando o modelo de dados muda? Quando uma validação muda? Quando um bug é encontrado? Como fazer para dar manutenção a tantas interfaces?

13. Mogiana Paulista[2] agradece [2] Região com a maior produção de café no Brasil

14. Abordagem convencional para construção de interface

15. URI Contexto Dado Exibição Exemplo: http://meudominio.com.br/feed/xbox-one Parser: (assunto)/(subtipo) Protocolo: http Domain: meudominio.com.br View: listar Tipo: feed Subtipo: xbox-one SELECT * FROM feed WHERE subtipo == ‘xbox-one’; <html> <body> <div id="feeds"> {% for feed in feeds %} <div class="feed"> <img src="{{ feed.image }}"/> <h3> <a href="{{ feed.link }}">{{ feed.title }}</a> </h3> </div> {% endfor %} </div> </body> </html>

16. Atualizando as visualizações de feed com novas regras • Destacar tipos de feed com css • External → out • Internal → in • Tweet → twt • Alguns feeds podem não ter link • Alguns feeds podem ter imagem, e conter link, caso o feed tenha link <html><body><div id="feeds"> {% for feed in feeds %} <div class="feed {% if feed.type == 'external' %} out {% elif feed.type == 'internal' %} in {% elif feed.type == 'tweet' %} twt {% endif %}"> {% if feed.image %} {% if feed.link %} <a href="{{ feed.link }}"> <img src="{{ feed.image }}"/> </a> {% else %} <img src="{{ feed.image }}"/> {% endif %} {% endif %} <h3> {% if feed.link %} <a href="{{ feed.link }}">{{ feed.title }}</a> {% else %} {{ feed.title }} {% endif %} </h3> </div> {% endfor %} </div></body></html>

17. <div id="feeds"> <div ng-repeat="feed in feeds" ng-class="['feed', { out:feed.type == 'external', in:feed.type == 'internal', twt:feed.type == 'tweet' }]"> <a ng-if="feed.link && feed.image"> <img ng-src="feed.image"/> </a> <img ng-hide="feed.link" ng-show="feed.image“ ng-src="feed.image"/> <h3> <a ng-if="feed.link" ng-href="feed.link"> {{ feed.title }} </a> <span ng-hide="feed.link"> {{ feed.title }} </span> </h3> </div> </div> E com um framework moderno, não muda mui

18. Você reparou que algo não mudou?

19. A estrutura da comunicação

20. Como o MIRA pode ajudar? Model Interface for REST Aplications

21. Interface dirigida por modelos utilizando regras para adaptar as interfaces Modelo de dados Seleção de interface Interface Abstrata Interface concreta Widgets Concretos Projetista (analista/arquiteto/engenheiro) UX (desenvolvedor/designer)

22. Estrutura de uma interface com MIRA Dado Contexto Interface Exibição

23. Exemplo: http://mira.tecweb/#?URI=http://api.meudominio.com.br/feed/xbox-one api.meudominio.com.br var selection = [{ when: 'isFeed', abstract: 'feed‘ }]; var abstracts = [{ name: 'feed', widgets: [ { name:'feeds', datasource:'$data.items', children: [ { name:'feed', children:[ {name:'image', bind:'$data.image'}, {name:'title', bind:'$data.title'} ]}]}]}]; var conditions = [ {name: 'isFeed', validate:'$data.type == "feed"'}, {name: 'isExternal', validate:'$data.type == "external"'}, {name: 'isInternal', validate:'$data.type == "internal"'}, {name: 'isTweet', validate:'$data.type == "tweet"'}, {name: 'hasImage', validate:'$data.image != null'}, {name: 'hasLink', validate:'$data.link != null'}, ]; var response = { type: 'feed', items: [ { title: 'titulo', link: 'url', image: 'url_of_image', type: 'internal || ' + 'external || ' + 'tweet || ... ' } /* ... */ ]}; var concrete = [{ name:"feed", maps: [ { name:"feeds" }, { name:"feed", class:'feed' }, { name:"feed", when:'isExternal', class:'feed out' }, { name:"feed", when:'isInternal', class:'feed int' }, { name:"feed", when:'isTweet', class:'feed twt' }, { name:"image", when:"hasImage", src:"$bind"}, { name:"image", when:"hasImage,hasLink", widget:'ImageLink', href:'navigate($data.link)', src:"$bind"}, { name:"title", tag: 'h3', value:'$bind'}, { name:"title", when:"hasLink", widget:'TitleLink', value:'$bind', href:'navigate($data.link)'} ]}];

24. Um exemplo com a API REST do GitHub

25. Condições e Seleção de Interface var conditions = [{ name: 'isUser', validate: '$data.login != null' },{ name: 'hasDetail', validate: '$bind != null' },{ name: 'haveWatch', validate: '$data.watchers_count > 0' }]; var selection = [ { when: 'isUser', abstract: 'user' } ]; var response = { "login": "ebertti", "id": 140394, "avatar_url": "https://avatars.githubusercontent.com/u/140394?v=3", "gravatar_id": "", "url": "https://api.github.com/users/ebertti", "html_url": "https://github.com/ebertti", "followers_url": "https://api.github.com/users/ebertti/followers", "following_url": "https://api.github.com/users/ebertti/following{/other_user}", "gists_url": "https://api.github.com/users/ebertti/gists{/gist_id}", "starred_url": "https://api.github.com/users/ebertti/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/ebertti/subscriptions", "organizations_url": "https://api.github.com/users/ebertti/orgs", "repos_url": "https://api.github.com/users/ebertti/repos", "events_url": "https://api.github.com/users/ebertti/events{/privacy}", "received_events_url": "https://api.github.com/users/ebertti/received_events", "type": "User", "site_admin": false, "name": "Ezequiel Bertti", "company": "AmazingWorks", "blog": "www.amazingworks.com.br", "location": "Armação dos Búzios, Rio de Janeiro, Brazil", "email": "ebertti@gmail.com", "hireable": null, "bio": null, "public_repos": 19, "public_gists": 4, "followers": 32, "following": 23, "created_at": "2009-10-15T21:39:13Z", "updated_at": "2015-07-01T14:09:06Z" }; https://api.github.com /users/ebertti

26. Interface Abstrata detail box

27. Interface Concretastructure:[ {'user': ['avatar', {'detail': ['user_name', 'login', 'bio', 'blog', 'company', 'location']}]}, {'repository': ['repository_name', 'repository_description', {box: ['repository_watch']}]} ], maps: [ { name: 'navigation', widget: 'BootstrapNavigation', value:'"GitHub"'}, { name: 'navigation-list', widget: 'BootstrapNavigationList'}, { name: 'navigation-list-item', widget: 'BootstrapNavigationListItem', value:'$bind', href:'navigate($data.link)'}, { name: 'content', widget: 'ProfileContainer' }, { name: 'user', class:'clearfix' }, { name: 'avatar', widget: 'ProfileImage', value:'$bind' }, { name: 'detail', class:'col-xs-12 col-sm-8' }, { name: 'user_name', tag: 'h2', value: '$bind' }, { name: 'login', widget: 'ProfileDetail', detail: 'Login', value: '$bind'}, { name: 'bio', widget: 'ProfileDetail', detail: 'Bio', value: '$bind'}, { name: 'blog', widget: 'ProfileDetail', detail: 'Blog', value: '$bind'}, { name: 'company', widget: 'ProfileDetail', detail: 'Company', value: '$bind'}, { name: 'location', widget: 'ProfileDetail', detail: 'Location', value: '$bind'}, { name: 'follows_panel', class:'clearfix' }, { name: 'follows_title', tag: 'h3', class:'clearfix', value:'"Seguidores"'}, { name: 'follows' }, { name: 'follow', tag:'a', href: 'navigate($bind)'}, { name: 'follow_avatar', widget:'BootstrapSimple', md:'1', xs:'2', img:'circle,responsive', tag: 'img', src: '$bind + "s=80"', alt:'$data.login', title:'$data.login'}, { name: 'repositories_panel', class:'clearfix' }, { name: 'repositories_title', tag: 'h3', value:'"Repositórios"'}, { name: 'repositories' }, { name: 'repository', class:'media'}, { name: 'repository_name', tag: 'h4', value: '$data.name', class:'media-heading'}, { name: 'repository_description', tag: 'span', value: '$data.description'}, { name: 'box', tag: 'ul', class:'nav nav-pills nav-stacked pull-right'}, { name: 'repository_watch', widget: 'ProfileCount', icon:'eye-close', value:'$bind'}, { name: 'repository_watch', widget: 'ProfileCount', icon:'eye-open', value:'$bind', when:'haveWatch'}, { name: 'footer', widget: 'TecWebRodape' } { name: 'repository_watch', tag: 'ul', class:'nav nav-pills nav-stacked pull-right‘, children:[ { name: 'count', widget: 'ProfileCount', icon:'eye-close', value:'$bind'}, { name: 'count', widget: 'ProfileCount', icon:'eye-open', value:'$bind', when:'haveWatch'} ]} Duas formas de resolver a necessidade de widgets extras para exibir a contagem de Watch

28. E como são tratados os eventos? {name:'status', value:'Aguardando', events:{click:'marcar_feito'} }, {name:'status', value:'Feito', when:'isDone'} events.marcar_feito = function(options){ options.$dataObj.set('feito', true); }; Aguardando Feitoclick conditions = [{ name: 'isDone', validate:'$data.feito == true‘ }]; click Feito

29. Exemplo com eventos var maps = [ { name: 'input_tarefa', widget:'BootstrapFormControl', input:{type:'text', events:{ keydown:'adicionar' }, placeholder:'Descrição da Tarefa'}}, { name: 'feito', widget:'BootstrapIcon', value:'unchecked', events: { click: 'marcar' }}, { name: 'feito', when:'isFeito', widget:'BootstrapIcon', value:'check', events: { click: 'marcar' }}, { name: 'editar', widget:'BootstrapIcon', value:'edit', events: { click: 'habilitar_edicao' }}, { name: 'remover', widget:'BootstrapIcon', value:'remove', events: { click: 'remover' }}, { name: 'imagem_tarefa', when:'hasLocation', widget:'MapStatic', size:'450x200', class:'thumbnail', value:'$data.tarefa.substring($data.tarefa.indexOf("@"))'}, { name: 'tarefa', class:'lead', value:'$data.tarefa', md:'8', events: { click:'habilitar_edicao' }}, { name: 'tarefa', when:'inEdition', widget:'BootstrapFormControl', md:8, input:{ value:'$data.tarefa', events:{keydown:'editar'}} }, { name: 'tipo', alert:"warning", class:'row' }, { name: 'tipo', when:'isFeito', alert:"info", class:'row'}, ]; event.marcar = function(options){ options.$dataObj.set('feito', !options.$dataObj.get('feito')) }; event.habilitar_edicao = function(options){ if(!options.$dataObj.get('$edit')) { options.$dataObj.set('$edit', true); } else { options.$dataObj.set('$edit', undefined); } }; var conditions = [{ name: 'isFeito', validate: '$data.feito == true'}, { name: 'hasLocation', validate: '$data.tarefa.indexOf("@") != -1'}, { name: 'inEdition', validate: '$data.$edit != null'}];

30. E como eu crio meus widgets? http://mira.tecweb.inf.puc-rio.br var custom_widgets = { TitleLink: function($parent, name, $context, options, callback) { var element = document.createElement('h1'); element.id = name; element.setAttribute('class', 'title'); var link = document.createElement('a'); link.setAttribute('href', options.href); link.innerHTML = options.value; element.appendChild(link); $parent.append(element); var $element = $(element); var $link = $(link); if(callback){ callback({ $children: $link, $element: $element }) } } }; Mira.Widget.register(custom_widgets); var map = { name: 'title', widget: 'TitleLink', value:'MIRA', href: 'http://mira.tecweb.inf.puc-rio.br' }; <h1> <a href="http://mira.tecweb.inf.puc-rio.br"> MIRA </a> </h1> MIRA

31. Mas não tem um jeito mais fácil para construir estas estruturas de interface do MIRA?

32. Ferramenta de edição para Interface Abstrata http://ebertti.github.io/mira-ui

33. MIRA – Editor http://tecweblab.github.io/mira-editor/ Feito por: João Victor Magela

34. Aqui estão mais exemplos de aplicações

35. Orientador: Daniel Schwabe LINKS Exemplos: http://mira.tecweb.inf.puc-rio.br/ Documentação em Português: http://mira.tecweb.inf.puc-rio.br/docs Código: https://github.com/tecweblab/mira http://mira.codeplex.com/ Ferramentas: http://ebertti.github.io/mira-ui/ http://tecweblab.github.io/mira-editor/

Add a comment

Related pages

Conferência Web.br 2015 Vamos "re-descentralizar a Web".

MIRA – Um framework Javascript para construção de ... Um framework Javascript para construção de interfaces adaptativas em aplicações REST da ...
Read more

Conferência Web.br 2015 Vamos "re-descentralizar a Web".

... na qual as aplicações não interoperam entre si, ... Um framework Javascript para construção de interfaces adaptativas em aplicações REST
Read more