Mudanças entre as edições de "Avalia+"
(→Exemplo controller AngularJS) |
(→Directives) |
||
Linha 226: | Linha 226: | ||
===Directives=== | ===Directives=== | ||
+ | |||
+ | <p> | ||
+ | Quase todas as diretivas ficam centralizadas no module <b>directives</b>, com exceção de algumas third party (tooltip, popover e etc). | ||
+ | </p> | ||
+ | <p> | ||
+ | A vantagem de adotar um modulo centralizador é que as diretivas que são injetadas são somente aquelas carregadas (arquivo .js) pelo BunfleConfig.cs. | ||
+ | </p> | ||
+ | |||
+ | ====alert==== | ||
+ | <p>dependência: <b>../services/_bundle/notification/notification.js</b></p> | ||
+ | <p>Composto por 2 diretivas:</p> | ||
+ | <p> | ||
+ | * <b>alert</b> - responsável por 'vigiar' o service <b>$notification</b> e criar/excluir uma nova notificação visual (html). | ||
+ | * <b>autoClose</b> - responsável por 'empilhar' as notificações em chamadas assíncronas e remover no término do tempo de permanência na pilha. | ||
+ | </p> | ||
+ | <p> | ||
+ | - exemplo: | ||
+ | <pre> | ||
+ | <alert></alert> | ||
+ | </pre> | ||
+ | </p> | ||
+ | |||
+ | ====checkbox-group==== | ||
+ | <p>Utiliza um model para armazenar uma lista de checkbox selecionados</p> | ||
+ | <p> | ||
+ | - exemplo: | ||
+ | <pre> | ||
+ | <div data-ng-repeat="($indexPeriodo, periodo) in periodoCurso.lista track by $indexPeriodo"> | ||
+ | <input id="checkbox_{{$indexPeriodo}}" type="checkbox" checklist-model="periodoCurso.selecionados" checklist-value="periodo" /> | ||
+ | <label for="checkbox_{{$indexPeriodo}}">{{periodo.Description}}</label> | ||
+ | </div> | ||
+ | </pre> | ||
+ | </p> | ||
+ | |||
===Filters=== | ===Filters=== | ||
===Models=== | ===Models=== |
Edição das 11h03min de 31 de outubro de 2016
Índice
Descrição
Descrever nesta área o que é o produto, quais as necessidades de negócio pretende atender, a quem se destina.
Funcionalidades de Ouro
Nesta seção, insira 3 ou 4 funcionalidades que diferenciam e destacam o produto. De preferência coloque apenas os nomes das funcionalidades
Link do Product Backlog
Nesta seção, insira o link do Product Backlog do produto
Arquitetura BD
Imagem da modelagem de tabelas
Arquitetura Front-End
O Avalia+ não se utiliza de rotas virtuais do ArgularJS, diferentemente de uma aplicação SPA[1]).
Todos os componentes (construídos internamente) do Avalia+ (controllers, directives, filters, services e etc) são construídos baseados no pattern IIFE[2]
Estrutura funcional
- Pastas (negrito)
- Arquivos (negrito + itálico)
- css
- vendor
- angular-motion
- modules - animações utilizaveis com angularJS ng-animate
- awesome-bootstrap-checkbox.css - customizações de layout realizadas sobre os campos checkbox/radio do html
- bootstrap.css - franework
- font-awesome.css - customização de fontes para bootstrap
- angular-motion
- prova.css - estilos para gerar .pdf da prova
- style.scss - estilos gerais do sistema
- vendor
- fonts - fontes awesome/material
- images - imagens gerais do sistema/manual do sistema em .pdf
- js
- angular
- controllers - rotas 'físicas' asp.NET
- directives
- _bundle - todas as diretivas utilizadas no sistema
- directives.js - modulo centralizador de diretivas
- factories
- _bundle - todas as 'factories' utilizadas no sistema
- filters
- _bundle - todos os filtros utilizados no sistema
- models - todos os 'models' são serviços que são construídos com base na utilização dos serviços nativos '$http/$resource'
- services
- _bundle - todos os serviços utilizados no sistema
- services.js - modulo centralizador de serviços
- services.interceptor.js - modulo responsável por interceptar todas requisições realizadas sobre AJAX
- vendor
- angular - framework AngularJS
- compressor - realiza a compressão de arquivos de imagem (.jpg ideal) utilizando canvas do html
- datepicker - plugin para exibição e utilização de calendário
- highcharts - plugin para exibição gráficos
- redactor - plugin editor de textos
- resumable - plugin para realizar uploads com possibilidade de pause
- bootstrap-3.2.0.js
- jquery-2.1.1.js
- jquery-ui.js
- jquery.signalR-2.2.0.js - conexão com websocket com suporte para tecnologia asp.NET
- mathJax.js - framework para exibição de formulas matemáticas complexas através de LaTeX, MathML[3]</b
- <b>moment.js - plugin para formatação de datas
- angular
- tests
Controllers
Todos os controllers AngularJS (construídos internamente) são baseados em:
- getter
- na maioria dos controllers é injetado os módulos base (centralizadores) ['services', 'filters', 'directives]
angular.module('appMain', ['services', 'filters', 'directives']);
- setter
- nome é baseado no prefix + suffix : [nome da View asp.NET] + ["Controller"]
angular.module('appMain').controller("FormAbsenceReasonController", FormAbsenceReasonController); function FormAbsenceReasonController() {};
- injector
- realiza as injeções de dependências
FormAbsenceReasonController.$inject = ['$scope', '$rootScope', '$window', '$notification', '$util', 'AbsenceReasonModel'];
- instanciar function no escopo
- funções que são criadas e atribuídas ao escopo angular devem possuir um nome para facilitar o rastreamento de erros no console. Funções anônimas atribuídas diretamente ao escopo do Angular perdem a rastreabilidade em determinados casos.
- funções atribuídas ao escopo ficam visíveis através dos $scopes do angular, algumas pessoas preferem utilizar funções no escopo se realmente for necessário seu uso na view (.html), e optam por deixa-las privadas (não atribuídas ao escopo angular).
- se for implementado o uso de testes unitários devido ao ciclo de vida do angular o Jasmine[4] só consegue enxergar funções públicas (presentes no escopo do angular), recomenda-se cautela quando ao uso de funções privadas em soluções angular.
//função publica: para acesso no escopo do angularJS $scope.minhaFuncPublic = function __minhaFuncPublic() { }; //função publica: para acesso no escopo do angularJS, porém anônima $scope.minhaFuncPublicAnonymous = function () { }; //função privada: sem acesso no escopo do angularJS function minhaFunc() { };
Exemplo controller AngularJS
- arquivo: formAbsenceReasonController.js
/** * function Cadastro/Edição Absence Reason Controller * @namespace Controller * @author Julio Cesar da Silva - 02/03/2016 */ (function (angular, $) { 'use strict'; //~SETTER angular .module('appMain', ['services', 'filters', 'directives']); //~GETTER angular .module('appMain') .controller("FormAbsenceReasonController", FormAbsenceReasonController); FormAbsenceReasonController.$inject = ['$scope', '$rootScope', '$window', '$notification', '$util', 'AbsenceReasonModel']; function FormAbsenceReasonController($scope, $rootScope, $window, $notification, $util, AbsenceReasonModel) { $scope.params = $util.getUrlParams(); $scope.absenceReason = { Description: undefined }; function Init() { $notification.clear(); if ($scope.params.Id !== undefined) { AbsenceReasonModel.findSimple({ Id: $scope.params.Id }, function (result) { if (result.success) { $scope.absenceReason = result.absenceReason; } else { $notification[result.type ? result.type : 'error'](result.message); } }); } }; $scope.setNewDefault = function setNewDefault() { if (!$scope.absenceReason.IsDefault) { angular.element('#modal').modal('show'); } $scope.absenceReason.IsDefault = true; }; $scope.salvar = function __salvar() { if ($scope.verifica()) { AbsenceReasonModel.save($scope.absenceReason, function (result) { if (result.success) { $notification.success(result.message); $window.location.href = '/AbsenceReason/List'; } else { $notification[result.type ? result.type : 'error'](result.message); } }); } }; $scope.voltar = function __voltar() { $window.location.href = '/AbsenceReason/List'; }; $scope.verifica = function __verifica() { if (!$scope.absenceReason.Description) { $notification.alert('O campo "Descrição" é obrigatório.'); angular.element('#description').focus(); return false; } return true; }; Init(); }; })(angular, jQuery);
- arquivo: ~\AbsenceReason\Form.html
<!DOCTYPE html> <html data-ng-app="appMain"> <head> <meta charset="utf-8" /> <title>FormAbsenceReason</title> </head> <body> <div class="wellCustom" data-ng-controller="FormAbsenceReasonController"> </div> </body> </html>
Directives
Quase todas as diretivas ficam centralizadas no module directives, com exceção de algumas third party (tooltip, popover e etc).
A vantagem de adotar um modulo centralizador é que as diretivas que são injetadas são somente aquelas carregadas (arquivo .js) pelo BunfleConfig.cs.
alert
dependência: ../services/_bundle/notification/notification.js
Composto por 2 diretivas:
- alert - responsável por 'vigiar' o service $notification e criar/excluir uma nova notificação visual (html).
- autoClose - responsável por 'empilhar' as notificações em chamadas assíncronas e remover no término do tempo de permanência na pilha.
- exemplo:
<alert></alert>
checkbox-group
Utiliza um model para armazenar uma lista de checkbox selecionados
- exemplo:
<div data-ng-repeat="($indexPeriodo, periodo) in periodoCurso.lista track by $indexPeriodo"> <input id="checkbox_{{$indexPeriodo}}" type="checkbox" checklist-model="periodoCurso.selecionados" checklist-value="periodo" /> <label for="checkbox_{{$indexPeriodo}}">{{periodo.Description}}</label> </div>
Filters
Models
Services
Versões dos frameworks
Framework | versão | customizado p/ necessidade interna | Ref. |
angularJS | 1.4.9 | |
https://angularjs.org/ |
compressor | 0.1 | |
Mstech |
datepicker | 2012 | |
http://www.eyecon.ro/bootstrap-datepicker |
highcharts | 4.0.4 | |
http://www.highcharts.com/ |
redactor | 10.2.5 | |
https://imperavi.com/redactor/ |
resumable | x.x | |
http://github.com/23/resumable.js |
bootstrap | 3.2.0 | |
http://getbootstrap.com/ |
jquery | 2.1.1 | |
https://jquery.com/ |
jqueryui | 1.10.3 | |
http://jqueryui.com |
jquery.signalR.core | 2.2.0 | |
http://signalr.net/ |
mathJax | x.x | |
https://www.mathjax.org/ |
moment | 2.10.6 | |
http://momentjs.com/ |
Estrutura de pastas
├───css │ │ prova.css │ │ style.css │ │ style.css.map │ │ style.min.css │ │ style.scss │ │ │ ├───vendor │ │ │ awesome-bootstrap-checkbox.css │ │ │ bootstrap.css │ │ │ font-awesome.css │ │ │ │ │ └───angular-motion │ │ │ angular-motion.css │ │ │ │ │ └───modules │ │ collapse.css │ │ fade-and-slide.css │ │ fade.css │ │ flip.css │ │ menu.css │ │ popover-fade.css │ │ │ └───_bundle │ angular.css │ ├───fonts │ ├───images │ ├───js │ ├───angular │ │ ├───controllers │ │ │ ├───absenceReason │ │ │ │ formAbsenceReasonController.js │ │ │ │ listAbsenceReasonController.js │ │ │ │ │ │ │ ├───adherence │ │ │ │ adherenceController.js │ │ │ │ │ │ │ ├───answerSheet │ │ │ │ answerSheetLotController.js │ │ │ │ answerSheetStudentController.js │ │ │ │ batchDetailsController.js │ │ │ │ customTooltip.html │ │ │ │ schoolLotMenu.html │ │ │ │ testLotMenu.html │ │ │ │ │ │ │ ├───cognitiveCompetence │ │ │ │ formCognitiveCompetenceController.js │ │ │ │ listCognitiveCompetenceController.js │ │ │ │ │ │ │ ├───correction │ │ │ │ correctionController.js │ │ │ │ correctionResultController.js │ │ │ │ │ │ │ ├───correlatedSkill │ │ │ │ formCorrelatedSkillController.js │ │ │ │ │ │ │ ├───discipline │ │ │ │ formDisciplineController.js │ │ │ │ listDisciplineController.js │ │ │ │ │ │ │ ├───evaluationMatrix │ │ │ │ evaluationMatrixController.js │ │ │ │ evaluationMatrixListController.js │ │ │ │ │ │ │ ├───file │ │ │ │ fileController.js │ │ │ │ fileMenu.html │ │ │ │ │ │ │ ├───home │ │ │ │ homeController.js │ │ │ │ │ │ │ ├───item │ │ │ │ formItemController.js │ │ │ │ listItemController.js │ │ │ │ listItemMenu.html │ │ │ │ │ │ │ ├───itemLevel │ │ │ │ formItemLevelController.js │ │ │ │ listItemLevelController.js │ │ │ │ │ │ │ ├───itemType │ │ │ │ itemTypeFormController.js │ │ │ │ itemTypeListController.js │ │ │ │ │ │ │ ├───modelEvaluationMatrix │ │ │ │ modelEvaluationMatrixController.js │ │ │ │ modelEvaluationMatrixListController.js │ │ │ │ │ │ │ ├───modelTest │ │ │ │ modelTestController.js │ │ │ │ modelTestListController.js │ │ │ │ │ │ │ ├───parameter │ │ │ │ parameterController.js │ │ │ │ parameterMenu.html │ │ │ │ parameterVersionableMenu.html │ │ │ │ │ │ │ ├───performanceLevel │ │ │ │ formPerformanceLevelController.js │ │ │ │ listPerformanceLevelController.js │ │ │ │ │ │ │ ├───reportAnswerSheet │ │ │ │ reportAnswerSheetDREController.js │ │ │ │ reportAnswerSheetFilesController.js │ │ │ │ reportAnswerSheetSchoolController.js │ │ │ │ │ │ │ ├───reportCorrection │ │ │ │ reportClasseController.js │ │ │ │ reportDREController.js │ │ │ │ reportSchoolController.js │ │ │ │ reportStudentController.js │ │ │ │ │ │ │ ├───reportItem │ │ │ │ reportItemController.js │ │ │ │ │ │ │ ├───reportTest │ │ │ │ graphicPerformanceSchoolController.js │ │ │ │ performanceItemController.js │ │ │ │ performanceSchoolController.js │ │ │ │ performanceSkillController.js │ │ │ │ │ │ │ ├───test │ │ │ │ indexRequestRevokeMenu.html │ │ │ │ menu-test-import-tpl.html │ │ │ │ testAdministrateController.js │ │ │ │ testController.js │ │ │ │ testImportController.js │ │ │ │ testListController.js │ │ │ │ testListMenu.html │ │ │ │ testReportController.js │ │ │ │ testRequestRevokeController.js │ │ │ │ testResponsesController.js │ │ │ │ testRevokeController.js │ │ │ │ │ │ │ └───testType │ │ │ formTestTypeController.js │ │ │ listTestTypeController.js │ │ │ │ │ ├───directives │ │ │ │ directives.js │ │ │ │ │ │ │ └───_bundle │ │ │ ├───alert │ │ │ │ alert.css │ │ │ │ alert.js │ │ │ │ │ │ │ ├───checkbox-group │ │ │ │ ckeckbox-group.js │ │ │ │ │ │ │ ├───collapse │ │ │ │ collapse.js │ │ │ │ │ │ │ ├───combox │ │ │ │ cbdirective.css │ │ │ │ cbdirective2.js │ │ │ │ │ │ │ ├───datepicker │ │ │ │ datepicker-directive.js │ │ │ │ │ │ │ ├───fieldinteger │ │ │ │ fieldinteger.js │ │ │ │ │ │ │ ├───highcharts │ │ │ │ highcharts-ng.js │ │ │ │ │ │ │ ├───item-brief │ │ │ │ item-brief.html │ │ │ │ item-brief.js │ │ │ │ │ │ │ ├───menu │ │ │ │ menu.html │ │ │ │ menu.js │ │ │ │ sitemas.html │ │ │ │ │ │ │ ├───modal │ │ │ │ modal.js │ │ │ │ │ │ │ ├───modal-alert │ │ │ │ modal-alert.js │ │ │ │ │ │ │ ├───ng-change-file │ │ │ │ ng-change-file.js │ │ │ │ │ │ │ ├───ngShowLoading │ │ │ │ ngShowLoading.js │ │ │ │ │ │ │ ├───notification-filter │ │ │ │ notification.filter.js │ │ │ │ │ │ │ ├───page │ │ │ │ page.css │ │ │ │ page.js │ │ │ │ │ │ │ ├───popover │ │ │ │ │ popover.html │ │ │ │ │ popover.js │ │ │ │ │ tooltip.html │ │ │ │ │ tooltip.js │ │ │ │ │ │ │ │ │ └───helpers │ │ │ │ date-parser.js │ │ │ │ debounce.js │ │ │ │ dimensions.js │ │ │ │ parse-options.js │ │ │ │ raf.js │ │ │ │ │ │ │ ├───preloading │ │ │ │ preloading.css │ │ │ │ preloading.js │ │ │ │ │ │ │ ├───radio-select │ │ │ │ radio-select.js │ │ │ │ │ │ │ ├───rating │ │ │ │ rating-directive.js │ │ │ │ rating.css │ │ │ │ │ │ │ ├───redactor-directive │ │ │ │ redactor-directive.js │ │ │ │ │ │ │ ├───reportFilters │ │ │ │ filtersTpl.html │ │ │ │ reportFilters.js │ │ │ │ │ │ │ ├───subject-selector │ │ │ │ subject-selector-directive.js │ │ │ │ subject-selector.css │ │ │ │ │ │ │ ├───tags-input │ │ │ │ ng-tags-input.css │ │ │ │ ng-tags-input.js │ │ │ │ │ │ │ ├───uploader │ │ │ │ upload.js │ │ │ │ uploader.js │ │ │ │ │ │ │ ├───websocketLoader │ │ │ │ websocketLoader.css │ │ │ │ websocketLoader.js │ │ │ │ │ │ │ └───writemaths │ │ │ rangy-core.js │ │ │ textinputs_jquery.js │ │ │ writemaths-directive.js │ │ │ writemaths.css │ │ │ writemaths.js │ │ │ │ │ ├───factories │ │ │ └───_bundle │ │ │ └───cache │ │ │ jcache.module.js │ │ │ JVirtualCaching.js │ │ │ │ │ ├───filters │ │ │ │ filters.js │ │ │ │ │ │ │ └───_bundle │ │ │ ├───between │ │ │ │ between.js │ │ │ │ │ │ │ ├───changeBlankSpace │ │ │ │ changeBlankSpace.js │ │ │ │ │ │ │ ├───minimize │ │ │ │ minimize.js │ │ │ │ │ │ │ ├───moment │ │ │ │ moment.js │ │ │ │ │ │ │ ├───tagToString │ │ │ │ tagToString.js │ │ │ │ │ │ │ └───trustedHtml │ │ │ trustedHtml.js │ │ │ │ │ ├───instances │ │ │ └───test │ │ │ book.js │ │ │ │ │ ├───models │ │ │ ├───AbsenceReason │ │ │ │ absenceReasonModel.js │ │ │ │ │ │ │ ├───adherence │ │ │ │ adherenceApiModel.js │ │ │ │ adherenceModel.js │ │ │ │ │ │ │ ├───answerSheet │ │ │ │ answerSheetModel.js │ │ │ │ │ │ │ ├───cognitiveCompetence │ │ │ │ cognitiveCompetenceModel.js │ │ │ │ │ │ │ ├───correction │ │ │ │ correctionApiModel.js │ │ │ │ correctionModel.js │ │ │ │ │ │ │ ├───correlatedSkill │ │ │ │ correlatedSkillModel.js │ │ │ │ │ │ │ ├───course │ │ │ │ courseModel.js │ │ │ │ │ │ │ ├───discipline │ │ │ │ disciplineModel.js │ │ │ │ │ │ │ ├───evaluationMatrix │ │ │ │ evaluationMatrixModel.js │ │ │ │ │ │ │ ├───evaluationMatrixCourse │ │ │ │ evaluationMatrixCourseModel.js │ │ │ │ │ │ │ ├───EvaluationMatrixCourseCurriculumGrade │ │ │ │ EvaluationMatrixCourseCurriculumGradeModel.js │ │ │ │ │ │ │ ├───file │ │ │ │ fileModel.js │ │ │ │ │ │ │ ├───formatType │ │ │ │ formatTypeModel.js │ │ │ │ │ │ │ ├───Integration │ │ │ │ ├───course │ │ │ │ │ courseModel.js │ │ │ │ │ │ │ │ │ ├───curriculumGrade │ │ │ │ │ curriculumGradeModel.js │ │ │ │ │ │ │ │ │ ├───levelEducation │ │ │ │ │ levelEducationModel.js │ │ │ │ │ │ │ │ │ └───modality │ │ │ │ modalityModel.js │ │ │ │ │ │ │ ├───item │ │ │ │ itemModel.js │ │ │ │ │ │ │ ├───itemLevel │ │ │ │ itemLevelModel.js │ │ │ │ │ │ │ ├───itemSituation │ │ │ │ itemSituationModel.js │ │ │ │ │ │ │ ├───itemType │ │ │ │ itemTypeModel.js │ │ │ │ │ │ │ ├───modelEvaluationMatrix │ │ │ │ modelEvaluationMatrixModel.js │ │ │ │ │ │ │ ├───modelSkillLevel │ │ │ │ modelSkillLevelModel.js │ │ │ │ │ │ │ ├───modelTestModel │ │ │ │ modelTestModel.js │ │ │ │ │ │ │ ├───parameter │ │ │ │ parameterModel.js │ │ │ │ │ │ │ ├───performanceLevel │ │ │ │ performanceLevelModel.js │ │ │ │ │ │ │ ├───reportAnswerSheet │ │ │ │ reportAnswerSheetModel.js │ │ │ │ │ │ │ ├───reportCorrection │ │ │ │ reportCorrectionModel.js │ │ │ │ │ │ │ ├───reportItem │ │ │ │ reportItemModel.js │ │ │ │ │ │ │ ├───reportTest │ │ │ │ reportTestModel.js │ │ │ │ │ │ │ ├───skill │ │ │ │ skillModel.js │ │ │ │ │ │ │ ├───test │ │ │ │ testAdministrateModel.js │ │ │ │ testImportExportModel.js │ │ │ │ testListModel.js │ │ │ │ testModel.js │ │ │ │ testRequestRevokeModel.js │ │ │ │ testRevokeModel.js │ │ │ │ │ │ │ ├───TestPerformanceLevel │ │ │ │ testPerformanceLevelModel.js │ │ │ │ │ │ │ ├───testType │ │ │ │ testTypeModel.js │ │ │ │ │ │ │ ├───testTypeCourse │ │ │ │ testTypeCourseModel.js │ │ │ │ │ │ │ ├───testTypeCourseCurriculumGrade │ │ │ │ testTypeCourseCurriculumGradeModel.js │ │ │ │ │ │ │ ├───testTypeItemLevel │ │ │ │ testTypeItemLevelModel.js │ │ │ │ │ │ │ └───typeLevelEducation │ │ │ typeLevelEducationModel.js │ │ │ │ │ └───services │ │ │ services.interceptor.js │ │ │ services.js │ │ │ │ │ └───_bundle │ │ ├───notification │ │ │ notification.js │ │ │ │ │ ├───pager │ │ │ services.js │ │ │ │ │ ├───util │ │ │ util.js │ │ │ │ │ └───websocket │ │ websocket.js │ │ │ └───vendor │ │ bootstrap-3.2.0.js │ │ jquery-2.1.1.js │ │ jquery-ui.js │ │ jquery.signalR-2.2.0.js │ │ mathJax.js │ │ moment.js │ │ │ ├───angular-1.4.9 │ │ │ angular-animate.js │ │ │ angular-aria.js │ │ │ angular-cookies.js │ │ │ angular-loader.js │ │ │ angular-message-format.js │ │ │ angular-messages.js │ │ │ angular-mocks.js │ │ │ angular-resource.js │ │ │ angular-route.js │ │ │ angular-sanitize.js │ │ │ angular-scenario.js │ │ │ angular-touch.js │ │ │ angular.js │ │ │ │ │ └───i18n │ ├───compressor │ │ compressor.js │ │ │ ├───datepicker │ │ datepicker.css │ │ datepicker.js │ │ │ ├───highcharts-4.0.4 │ │ │ highcharts-3d.js │ │ │ highcharts-all.js │ │ │ highcharts-more.js │ │ │ highcharts.js │ │ │ │ │ └───modules │ │ exporting.js │ │ no-data-to-display.js │ │ │ ├───redactor │ │ accents.gif │ │ accents_ext.gif │ │ arrows.gif │ │ brackets.gif │ │ clips.js │ │ fontcolor.js │ │ fontfamily.js │ │ fontsize.js │ │ foreign.gif │ │ function.png │ │ greeklower.gif │ │ greekupper.gif │ │ imagemanager.js │ │ mathLatex.css │ │ mathLatex.js │ │ matrix.gif │ │ operators.gif │ │ redactor-font.eot │ │ redactor.css │ │ redactor.js │ │ redactor.less │ │ relations.gif │ │ subsupset.gif │ │ symbols.gif │ │ table.js │ │ │ └───resumable-js │ resumable.js │ test.html │ └───tests │ conf.js │ jasmine-runner.html │ karma.conf.js │ package.json │ ├───e2e │ └───controllers │ OMRController.e2e.js │ └───unit │ razor.js │ ├───controllers │ fileController.test.js │ formItemController.test.js │ ├───directives ├───factories ├───filters ├───models └───services