├── .gitattributes ├── .gitignore ├── AUTHORS ├── CHANGELOG.md ├── LICENSE ├── example ├── app.yaml ├── client │ ├── .gitignore │ ├── pubspec.yaml │ ├── static │ │ ├── bootstrap │ │ │ ├── bootstrap.css │ │ │ └── bootstrap.min.css │ │ ├── css │ │ │ ├── bootflat-extensions.css │ │ │ ├── bootflat-square.css │ │ │ ├── bootflat.css │ │ │ ├── bootstrap.css │ │ │ ├── bootstrap.min.css │ │ │ ├── font-awesome.css │ │ │ ├── font-awesome.min.css │ │ │ └── style.css │ │ ├── fonts │ │ │ ├── FontAwesome.otf │ │ │ ├── fontawesome-webfont.eot │ │ │ ├── fontawesome-webfont.svg │ │ │ ├── fontawesome-webfont.ttf │ │ │ └── fontawesome-webfont.woff │ │ └── img │ │ │ ├── check_flat │ │ │ └── default.png │ │ │ └── dart_force_logo.jpg │ └── web │ │ ├── client.dart │ │ └── index.html └── server │ ├── advice │ └── text_advice.dart │ ├── controllers │ ├── about_controller.dart │ ├── count_controller.dart │ ├── error_controller.dart │ ├── login_controller.dart │ ├── path_controller.dart │ ├── post_controller.dart │ ├── redirect_controller.dart │ ├── rest │ │ ├── api_controller.dart │ │ ├── just_a_rest_controller.dart │ │ ├── readme.md │ │ └── response_body_controller.dart │ ├── secure_controller.dart │ ├── security │ │ └── session_strategy.dart │ └── status_controller.dart │ ├── interceptors │ └── random_interceptor.dart │ ├── pubspec.yaml │ ├── server.dart │ ├── test │ └── count_controller_test.dart │ └── views │ ├── about.html │ ├── count.html │ ├── error.html │ ├── form.html │ ├── info.html │ ├── locale.html │ ├── login.html │ ├── notfound.html │ ├── number.html │ ├── pathvar.html │ └── requestparam.html ├── lib ├── annotations │ ├── helpers.dart │ └── metadata.dart ├── converters │ ├── abstract_message_converter.dart │ ├── csv_message_converter.dart │ ├── http_message_converter.dart │ ├── json_http_message_converter.dart │ └── text_http_message_converter.dart ├── error │ ├── handler_exception_resolver.dart │ └── simple_exception_resolver.dart ├── force_mvc.dart ├── http │ ├── http_headers_wrapper.dart │ ├── http_input_message.dart │ ├── http_message.dart │ ├── http_message_regulator.dart │ ├── http_method.dart │ ├── http_output_message.dart │ ├── invalid_mime_type_error.dart │ ├── media_type.dart │ └── mime_type.dart ├── i18n │ ├── accept_header_locale_resolver.dart │ ├── cookie_locale_resolver.dart │ ├── default_locale_resolver.dart │ ├── fixed_locale_resolver.dart │ └── locale_resolver.dart ├── manager │ └── cookie_holder_manager.dart ├── render │ ├── mustache_render.dart │ └── view_render.dart ├── security │ ├── no_security_strategy.dart │ ├── security_context_holder.dart │ └── security_strategy.dart ├── server │ ├── force_request.dart │ ├── handler_interceptor.dart │ ├── http_request_streamer.dart │ ├── interceptors_collection.dart │ ├── model.dart │ ├── mvc_typedefs.dart │ ├── path_analyzer.dart │ ├── registry.dart │ ├── request_method.dart │ ├── response_hooks.dart │ ├── serving_assistent.dart │ ├── serving_files.dart │ ├── simple_web_server.dart │ └── web_application.dart ├── test.dart └── utils │ └── mime_type_utils.dart ├── pubspec.yaml ├── readme.md ├── resources └── dart_force_logo.jpg └── test ├── locale_resolver_test.dart ├── locale_test.dart └── path_test.dart /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | 4 | # Custom for Visual Studio 5 | *.cs diff=csharp 6 | *.sln merge=union 7 | *.csproj merge=union 8 | *.vbproj merge=union 9 | *.fsproj merge=union 10 | *.dbproj merge=union 11 | 12 | # Standard to msysgit 13 | *.doc diff=astextplain 14 | *.DOC diff=astextplain 15 | *.docx diff=astextplain 16 | *.DOCX diff=astextplain 17 | *.dot diff=astextplain 18 | *.DOT diff=astextplain 19 | *.pdf diff=astextplain 20 | *.PDF diff=astextplain 21 | *.rtf diff=astextplain 22 | *.RTF diff=astextplain 23 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /dart-forcemvc2.iml 2 | # Dart excludes 3 | packages 4 | .packages 5 | .project 6 | .children 7 | *.js 8 | pubspec.lock 9 | .idea 10 | /dart-forcemvc.iml 11 | /.settings/ 12 | .pub 13 | -------------------------------------------------------------------------------- /AUTHORS: -------------------------------------------------------------------------------- 1 | Originally written by: 2 | Joris Hermans - http://github.com/jorishermans 3 | 4 | With contributions by: 5 | Robert Åkerblom-Andersson - https://github.com/Scorpiion 6 | Domenico Monaco - https://github.com/kiuz 7 | Nicolas Garnier - https://github.com/nicolasgarnier 8 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | ### Changelog ### 2 | 3 | This file contains highlights of what changes on each version of the forcemvc package. 4 | 5 | #### Pub version 0.8.2 & version 0.8.5 #### 6 | 7 | - Update version of wired to v0.4.5 8 | - improve @ResponseBody & httpmessageconverter logic 9 | 10 | #### Pub version 0.8.1 #### 11 | 12 | - Introducing @RestController 13 | - improve @ResponseBody 14 | - solve path variables with dash, issue #32 15 | 16 | #### Pub version 0.8.0 #### 17 | 18 | - Updating dependencies on logging 19 | - Clean up code 20 | - introduce @ResponseBody 21 | - HttpMessageConverters and HttpMessageRegulator are also available in this release with a JsonHttpMessageConverter implementation 22 | 23 | #### Pub version 0.7.3 #### 24 | 25 | - Introducing a new annotation @ResponseStatus, so we can indicate status code of the response 26 | 27 | #### Pub version 0.7.2 #### 28 | 29 | - Adopt code to async/await 30 | - Extract locale to an other dependency 31 | 32 | #### Pub version 0.7.1+1 #### 33 | 34 | - Improve the flow of client serving 35 | - Add more logging 36 | 37 | #### Pub version 0.7.1 #### 38 | 39 | - Allow completely handling the HttpResponse 40 | 41 | #### Pub version 0.7.0 #### 42 | 43 | - update forcemvc to wired 4.3 44 | - add web config and an easy change towards core components with di 45 | * SecurityContextHolder 46 | * HandlerExceptionResolver 47 | * LocaleResolver 48 | * ServingAssistent 49 | 50 | #### Pub version 0.6.1+1 #### 51 | 52 | - add improvement on static handling internally 53 | 54 | #### Pub version 0.6.1 #### 55 | 56 | - remove start page and use this instead! 57 | 58 | app.static("/", "index.html"); 59 | 60 | #### Pub Version 0.6.0+1 #### 61 | 62 | - Tighter version constraint on exported package 63 | 64 | #### Pub Version 0.6.0 #### 65 | 66 | - WebServer becomes WebApplication dart class 67 | - The .on method becomes .use method 68 | - app.static will skip the view rendering logic, ideal for angular and polymer applications 69 | - simplify code on some parts 70 | 71 | #### Pub Version 0.5.10 #### 72 | 73 | - Extending the possibilities of a Rest interface. 74 | 75 | #### Pub Version 0.5.9+1 #### 76 | 77 | - Fix a bug so that @Authentication works, and takes up BASIC as a role. 78 | 79 | #### Pub Version 0.5.9 #### 80 | 81 | - Improve the startup functionality, by adding startup fallback mechanism 82 | 83 | #### Pub Version 0.5.8 #### 84 | 85 | - Make the default value to startpage empty. 86 | It is better to use: 87 | 88 | app.use('/', (req, model) { 89 | return "index"; 90 | }); 91 | 92 | then startPage: "index.html" 93 | 94 | Be aware that then it becomes a template and that when you use polymer or angular you need to use another delimiter. 95 | 96 | #### Pub version 0.5.7+1 #### 97 | 98 | - Deprecate the method on, it is too confusing with the on method of dart force, the method 'use' is now the prefered way. 99 | - Fixing a crash when the startPage is not found. 100 | 101 | #### Pub version 0.5.7 #### 102 | 103 | - Changing the main class of WebServer to WebApplication. 104 | - Making WebServer Deprecated 105 | 106 | #### Pub version 0.5.6+1 #### 107 | 108 | - Fix issue serving without pub serve 109 | - put more control in accept_header_locale 110 | 111 | #### Pub version 0.5.6 #### 112 | 113 | - Apply pub serve trick also to view render logic. 114 | - Fallbacks / error handling when a resource is not been found. 115 | 116 | #### Pub version 0.5.5 #### 117 | 118 | - Add locale resolver mechanics into the framework 119 | - Easy use of the locale in the controller 120 | 121 | #### Pub version 0.5.4 #### 122 | 123 | - Add required boolean into @RequestParam(required: true) 124 | - Pub serve trick, issue 23 is been solved. 125 | 126 | #### Pub version 0.5.3+1 #### 127 | 128 | - Small adjustments so dart force can also work on appengine. 129 | 130 | #### Pub version 0.5.3 #### 131 | 132 | - Add better 404 handling 133 | - Serving the Client files from their URL relative to the script's location 134 | - Make dart-forcemvc WebServer compatible with App Engine Dart 135 | 136 | #### Pub version 0.5.2+1 #### 137 | 138 | - Fixing 'Replace only the first occurrence of /build' 139 | 140 | #### Pub version 0.5.2 #### 141 | 142 | - package 'Force IT' is been renamed to 'wired' 143 | 144 | #### Pub version 0.5.1 #### 145 | 146 | - Add Type checking in @ExceptionHandler 147 | 148 | #### Pub version 0.5.0+1 #### 149 | 150 | - Add getAuthentication in MVCAnnotationHelper 151 | 152 | #### Pub version 0.5.0 #### 153 | 154 | - Add PreauthorizeRoles and PreauthorizeFunc Annotations 155 | - Add possibility to define authorization roles 156 | - Define and extend the way security works in forcemvc 157 | - Upgrade to the latest version of 'force it' 158 | 159 | #### Pub version 0.4.0+1 & 0.4.0+2 #### 160 | 161 | - Adding MVCAnnotationHelper, with the method hasAuthentication(obj) to the package 162 | 163 | #### Pub version 0.4.0 #### 164 | 165 | - Remove parentheses from annotations. 166 | - Update to the latest version (0.2.0) of force_it 167 | - Add example folder to the git repository 168 | 169 | #### Pub version 0.3.8 #### 170 | 171 | - Introducing @ControllerAdvice so that you can make methods with @ModelAttribute & @ExceptionHandler that has inpact to all the controller 172 | 173 | #### Pub version 0.3.7 #### 174 | 175 | - General error handling with a HandlerExceptionResolver 176 | - Introducing the annotation @ExceptionHandler so you can use that in your @Controller classes when an error is happening. 177 | 178 | #### Pub version 0.3.6+1 #### 179 | 180 | - First steps in error handling 181 | 182 | #### Pub version 0.3.6 #### 183 | 184 | - Adding startSecure method, so you can start your webserver over SSL. 185 | 186 | #### Pub version 0.3.5+1 #### 187 | 188 | - Update package configuration 189 | 190 | #### Pub version 0.3.5 #### 191 | 192 | - Provide a class MockForceRequest to mock more easily ForceRequest in unittests 193 | - Upgrade of the unittest package and introducing of the mock package 194 | 195 | #### Pub version 0.3.4+1 & 0.3.4+2 & 0.3.4+3 #### 196 | 197 | - update rules for mustache rendering the view 198 | 199 | #### Pub version 0.3.4 #### 200 | 201 | - Add @RequestMapping on an object level possible 202 | 203 | #### Pub version 0.3.3+1 #### 204 | 205 | - Make @RequestParam working without a value 206 | 207 | #### Pub version 0.3.3 #### 208 | 209 | - Error logging when the server don't start 210 | - Add responseHooks into the web_server 211 | - Using variable name of the annotated @RequestParam when value is empty 212 | 213 | #### Pub version 0.3.2+1 & 0.3.2+2 #### 214 | 215 | - improve serving code of the start page. 216 | 217 | #### Pub version 0.3.2 #### 218 | 219 | - load values into your webserver from yaml files 220 | - cors 221 | - small improvement on the model object, it allows you to put anything in it 222 | 223 | #### Pub version 0.3.1 #### 224 | 225 | Fix a problem with serving dart files. 226 | 227 | #### Pub version 0.3.0+1 #### 228 | 229 | Fix a bug with passing by the startPage. 230 | 231 | #### Pub version 0.3.0 #### 232 | 233 | Add 'force it' package into this new version of the forcemvc so you can use @Autowired in the @Controller classes. 234 | 235 | #### Pub version 0.2.4 #### 236 | 237 | Add easier bootstrapping of the logging functionality serverside. 238 | 239 | #### Pub version 0.2.3 #### 240 | 241 | Implemented changes to the security api. Add an optional parameter {data} in the security strategy checkAuthorization class. 242 | 243 | #### Pub version 0.2.2 #### 244 | 245 | Refactoring of the use of webSockets, also provide httpRequest in the flow, so you get access to httpsession. 246 | 247 | #### Pub version 0.2.1+2 #### 248 | 249 | Make the security rules more general. 250 | 251 | #### Pub version 0.2.1+1 #### 252 | 253 | Make the securityContextHolder object in webserver public accessible. 254 | 255 | #### Pub version 0.2.1 #### 256 | 257 | New structure! 258 | 259 | #### Pub version 0.2.0 #### 260 | 261 | Adding security and authentication functionality 262 | 263 | #### Pub version 0.1.13+5 #### 264 | 265 | Move transformation method to the view renderer! 266 | 267 | #### Pub version 0.1.13+4 #### 268 | 269 | More logging! 270 | 271 | #### Pub version 0.1.13+1 & 0.1.13+2 #### 272 | 273 | Adding slashes in src="...", it will become src="/..." when needed of the template rendering is been performed! 274 | 275 | #### Pub version 0.1.13 #### 276 | 277 | Depend upon mustache4dart and not upon mustache anymore! 278 | 279 | #### Pub version 0.1.12+2 #### 280 | 281 | Small improvement on the view rendering part! 282 | 283 | #### Pub version 0.1.12+1 #### 284 | 285 | Changed ../build/ folder to ../build/web/ 286 | 287 | #### Pub version 0.1.12 #### 288 | 289 | Check also view, template files in the build folder, so after pub build in the web folder! 290 | 291 | #### Pub version 0.1.11+3 #### 292 | 293 | Better logging for view rendering! 294 | 295 | #### Pub version 0.1.11+2 #### 296 | 297 | Implement getPostRawData, so you can get the raw posted data! 298 | 299 | #### Pub version 0.1.11+1 #### 300 | 301 | Adapt getPostData to disable jsonifying the data! 302 | 303 | #### Pub version 0.1.11 #### 304 | 305 | Adding asynchronous requests to the possibilities now! 306 | 307 | #### Pub version 0.1.10 #### 308 | 309 | Fixing in @RequestMapping, the method part! 310 | 311 | #### Pub version 0.1.9+4 #### 312 | 313 | Adding redirect functionality. 314 | 315 | #### Pub version 0.1.9+3 #### 316 | 317 | Removing dependency on Uuid. 318 | 319 | #### Pub version 0.1.9+2 #### 320 | 321 | Add HttpSession & HttpHeaders in possible arguments in a controller method 322 | 323 | #### Pub version 0.1.9+1 #### 324 | 325 | Solve an issue with the code, please update! 326 | 327 | #### Pub version 0.1.9 #### 328 | 329 | Adding @RequestParam, so you can add this annotation to the controller class if you want to have easy access to querystring parameters. 330 | 331 | #### Pub version 0.1.8+3 #### 332 | 333 | Make static folder configurable and some small improvements on the regex expression. 334 | 335 | #### Pub version 0.1.8+2 #### 336 | 337 | Static folder for serving static files to the client! 338 | 339 | #### Pub version 0.1.8+1 #### 340 | 341 | Improved accesability of path variables. 342 | 343 | #### Pub version 0.1.8 #### 344 | 345 | New ways of view rendering and getting the templates. 346 | 347 | #### Pub version 0.1.7+2 & 0.1.7+3 #### 348 | 349 | Cleanup code webserver. Solving an issue! 350 | 351 | #### Pub version 0.1.7+1 #### 352 | 353 | Updated this buildPath: '../build/web' to get it working in Dart 1.2 354 | 355 | #### Pub version 0.1.7 #### 356 | 357 | Extend ForceRequest with getPostData and getPostParams to support post methods. 358 | 359 | #### Pub version 0.1.6 #### 360 | 361 | Adding path variables to the mvc part. 362 | 363 | #### Pub version 0.1.5 #### 364 | 365 | Serving .dart files much easier, putting it in the framework itself. 366 | 367 | #### Pub version 0.1.4 #### 368 | 369 | Adding interceptors to the game, so you can write interceptor classes to intercept a request. 370 | 371 | #### Pub version 0.1.3 #### 372 | 373 | Updating dependency on force mirrors, it solves a bug with invocation. 374 | Controller scanning, so you don't need to register a class, just annotate it with @Controller. 375 | 376 | #### Pub version 0.1.2+4 & 0.1.2+5 #### 377 | 378 | Adding an improvement of force mirrors invoke. 379 | 380 | #### Pub version 0.1.2+3 #### 381 | 382 | Solving issue with dependency management 383 | 384 | #### Pub version 0.1.2+2 #### 385 | 386 | Add dependency to forcemirrors. 387 | 388 | #### Pub version 0.1.2+1 #### 389 | 390 | Adding tests for mirrorhelpers and refactor code to improve annotation handling. 391 | 392 | #### Pub version 0.1.2 #### 393 | 394 | Adding the ModelAttribute annotation into the mvc framework. 395 | 396 | #### Pub version 0.1.0 #### 397 | 398 | Adding an abstraction ForceRequest, a wrapper around httprequest. 399 | 400 | #### Pub version 0.1.0 #### 401 | 402 | Adding renderer and model to the mvc part of it. 403 | Adding mustache as a new dependency for the rendering part. 404 | 405 | #### Pub version 0.0.6 & 0.0.7 #### 406 | 407 | Fixing issue with annotations of RequestMapping 408 | 409 | #### Pub version 0.0.5 #### 410 | 411 | Introducing Simple Web Server 412 | 413 | #### Pub version 0.0.5 #### 414 | 415 | Introduction of the model 416 | 417 | #### Pub version 0.0.4 #### 418 | 419 | Update version of uuid 420 | 421 | #### Pub version 0.0.3 #### 422 | 423 | Adding RequestMethod class into the project 424 | 425 | #### Pub version 0.0.2 #### 426 | 427 | Adding documentation and solving issues. 428 | 429 | #### Pub version 0.0.1 #### 430 | 431 | Setup of the project, moved basic_server.dart to this package and make it usable in the dart force main package. 432 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2013, Joris Hermans 2 | 3 | Joris: https://twitter.com/jorishermans 4 | 5 | Licensed under the Apache License, Version 2.0 (the "License"); 6 | you may not use this file except in compliance with the License. 7 | You may obtain a copy of the License at 8 | 9 | http://www.apache.org/licenses/LICENSE-2.0 10 | 11 | Unless required by applicable law or agreed to in writing, software 12 | distributed under the License is distributed on an "AS IS" BASIS, 13 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | See the License for the specific language governing permissions and 15 | limitations under the License. -------------------------------------------------------------------------------- /example/app.yaml: -------------------------------------------------------------------------------- 1 | name: Force MVC Example 2 | 3 | server: 4 | - url: / 5 | 6 | client: 7 | - url: /web 8 | match: preregex 9 | dir: web 10 | 11 | - url: /static 12 | match: preregex 13 | dir: static 14 | -------------------------------------------------------------------------------- /example/client/.gitignore: -------------------------------------------------------------------------------- 1 | /build/** 2 | /build/ 3 | -------------------------------------------------------------------------------- /example/client/pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: client 2 | dependencies: 3 | browser: any 4 | 5 | -------------------------------------------------------------------------------- /example/client/static/css/bootflat-extensions.css: -------------------------------------------------------------------------------- 1 | /* 2 | Bootflat 1.0.1 3 | Designed & Built by flathemes, http://www.flathemes.com 4 | Licensed under MIT License, http://opensource.org/licenses/mit-license.html 5 | 6 | Thanks for supporting our website and enjoy! 7 | */ 8 | /*------------------------------------*\ 9 | $bubble 10 | \*------------------------------------*/ 11 | .bubble-body { 12 | position: relative; 13 | padding: 3px; 14 | background-color: #ecf0f1; 15 | border-radius: 3px; 16 | overflow: visible; 17 | } 18 | .pull-left ~ .bubble-body { 19 | margin-left: 60px; 20 | } 21 | .pull-right ~ .bubble-body { 22 | margin-right: 60px; 23 | } 24 | .bubble-body .bubble-inner { 25 | min-height: 32px; 26 | border: 1px solid #d3d7d7; 27 | background-color: #fbfbfb; 28 | } 29 | .bubble-body .bubble-heading { 30 | padding: 0 10px; 31 | border-bottom: 1px solid #d3d7d7; 32 | background-color: #f4f4f4; 33 | font-size: 12px; 34 | font-weight: bold; 35 | color: #222; 36 | overflow: hidden; 37 | white-space: nowrap; 38 | text-overflow: ellipsis; 39 | height: 33px; 40 | line-height: 33px; 41 | } 42 | .bubble-body .bubble-content { 43 | padding: 10px; 44 | font-size: 13px; 45 | overflow: auto; 46 | width: 100%; 47 | line-height: 1.7; 48 | } 49 | .bubble-body .bubble-inner { 50 | margin-bottom: 0; 51 | -webkit-border-radius: 0; 52 | -moz-border-radius: 0; 53 | border-radius: 0; 54 | } 55 | .bubble-body .bubble-inner .bubble { 56 | margin: 0 10px; 57 | padding-top: 10px; 58 | border-top: 1px solid #ecf0f1; 59 | } 60 | .bubble-body .bubble-inner .bubble .bubble { 61 | margin: 0; 62 | } 63 | .bubble-body .bubble-inner .bubble-body:before, 64 | .bubble-body .bubble-inner .bubble-body:after { 65 | display: none; 66 | } 67 | .bubble-body .bubble-inner .bubble-body, 68 | .bubble-body .bubble-inner .bubble-inner { 69 | padding: 0; 70 | border: none; 71 | background-color: transparent; 72 | } 73 | .bubble-body .bubble-inner .bubble-inner .bubble-heading { 74 | padding: 0; 75 | border-bottom: none; 76 | background-color: transparent; 77 | height: auto; 78 | line-height: normal; 79 | } 80 | .bubble-body .bubble-inner .bubble-inner .bubble-content { 81 | padding: 0; 82 | font-size: 13px; 83 | overflow: auto; 84 | width: 100%; 85 | line-height: 1.5; 86 | } 87 | .bubble-arrow-left:before, 88 | .bubble-arrow-right:after { 89 | position: absolute; 90 | top: 15px; 91 | content: ""; 92 | display: block; 93 | height: 0; 94 | width: 0; 95 | border-width: 10px; 96 | border-style: solid; 97 | } 98 | .bubble-arrow-left:before { 99 | border-color: transparent #ecf0f1 transparent transparent; 100 | left: -20px; 101 | } 102 | .bubble-arrow-right:after { 103 | border-color: transparent transparent transparent #ecf0f1; 104 | right: -20px; 105 | } 106 | /*------------------------------------*\ 107 | $breadcrumb-arrow 108 | \*------------------------------------*/ 109 | .breadcrumb-arrow { 110 | padding: 0; 111 | list-style:none; 112 | background-color: #ecf0f1; 113 | height:36px; 114 | line-height: 36px; 115 | } 116 | .breadcrumb-arrow li:first-child a { 117 | border-top-left-radius: 4px; 118 | border-bottom-left-radius: 4px; 119 | } 120 | .breadcrumb-arrow li, 121 | .breadcrumb-arrow li a, 122 | .breadcrumb-arrow li span{ 123 | display:-moz-inline-box; 124 | display:inline-table; 125 | display:inline-block; 126 | zoom:1; 127 | *display:inline; 128 | vertical-align:top; 129 | } 130 | .breadcrumb-arrow li:not(:first-child) { 131 | margin-left: -5px; 132 | } 133 | .breadcrumb-arrow li + li:before { 134 | padding: 0; 135 | content: ""; 136 | } 137 | .breadcrumb-arrow li span { 138 | padding: 0 10px; 139 | } 140 | .breadcrumb-arrow li a, 141 | .breadcrumb-arrow li:not(:first-child) span { 142 | padding:0 10px 0 25px; 143 | height:35px; 144 | line-height:35px; 145 | } 146 | .breadcrumb-arrow li:first-child a { 147 | padding: 0 10px; 148 | } 149 | .breadcrumb-arrow li a { 150 | position:relative; 151 | border:1px solid #3da8e3; 152 | color:#fff; 153 | background-color:#3da8e3; 154 | text-decoration:none; 155 | } 156 | .breadcrumb-arrow li [class^="icon-"], 157 | .breadcrumb-arrow ul li [class*=" icon-"] { 158 | top: 0; 159 | } 160 | .breadcrumb-arrow-arrow li:first-child a { 161 | padding-left:10px; 162 | } 163 | .breadcrumb-arrow li a:before, 164 | .breadcrumb-arrow li a:after { 165 | position:absolute; 166 | top:0; 167 | content:''; 168 | width: 0; 169 | height: 0; 170 | border-top: 17px solid transparent; 171 | border-bottom: 17px solid transparent; 172 | } 173 | .breadcrumb-arrow li a:before { 174 | right: -10px; 175 | border-left-width: 10px; 176 | border-left-style:solid; 177 | border-left-color:#3da8e3; 178 | z-index:3; 179 | } 180 | .breadcrumb-arrow li a:after{ 181 | right: -11px; 182 | border-left: 10px solid #2980b9; 183 | z-index:2; 184 | } 185 | .breadcrumb-arrow li a:hover, 186 | .breadcrumb-arrow li a:focus { 187 | background-color:#3598ce; 188 | border: 1px solid #3598ce; 189 | } 190 | .breadcrumb-arrow li a:hover:before, 191 | .breadcrumb-arrow li a:focus:before { 192 | border-left-color: #3598ce; 193 | } 194 | .breadcrumb-arrow li a:active { 195 | background-color:#2980b9; 196 | border: 1px solid #2980b9; 197 | } 198 | .breadcrumb-arrow li a:active:before, 199 | .breadcrumb-arrow li a:active:after { 200 | border-left-color:#2980b9; 201 | } 202 | .breadcrumb-arrow li span{ 203 | color:#bdc3c7; 204 | } 205 | /*------------------------------------*\ 206 | $nav-tabs-panel 207 | \*------------------------------------*/ 208 | .nav-tabs-panel, 209 | .nav-tabs-panel.nav-justified { 210 | margin-bottom: 15px; 211 | border-bottom: 1px solid #2986b9; 212 | background-color: #ecf0f1; 213 | } 214 | .nav-tabs-panel .tab-default, 215 | .nav-tabs-panel.nav-justified .tab-default { 216 | margin-right: 0; 217 | padding: 11px 15px; 218 | border-bottom: none; 219 | color: #292929; 220 | } 221 | .nav-tabs-panel.nav-justified .active .tab-default, 222 | .nav-tabs-panel.nav-justified .active .tab-default:hover, 223 | .nav-tabs-panel.nav-justified .active .tab-default:focus, 224 | .nav-tabs-panel .active .tab-default, 225 | .nav-tabs-panel .active .tab-default:hover, 226 | .nav-tabs-panel .active .tab-default:focus { 227 | border-color: transparent transparent #2986b9 transparent; 228 | border-bottom-style:solid; 229 | border-width: 0 0 3px 0; 230 | color: #fff; 231 | background-color: #3da8e3; 232 | -webkit-border-radius: 0; 233 | -moz-border-radius: 0; 234 | border-radius: 0; 235 | } 236 | .nav-tabs-panel li a:hover, 237 | .nav-tabs-panel li a:focus { 238 | border-color: transparent transparent transparent; 239 | background-color: transparent; 240 | } 241 | .nav-tabs-panel .open .dropdown-toggle, 242 | .nav-tabs-panel li.dropdown.open.active a:hover, 243 | .nav-tabs-panel li.dropdown.open.active a:focus { 244 | color: #292929; 245 | background-color: transparent; 246 | border-color: transparent; 247 | } 248 | .nav-tabs-panel .dropdown-toggle .caret, 249 | .nav-tabs-panel .dropdown-toggle:hover .caret, 250 | .nav-tabs-panel .dropdown-toggle:focus .caret, 251 | .nav-tabs-panel li.dropdown.open .caret, 252 | .nav-tabs-panel li.dropdown.open.active .caret, 253 | .nav-tabs-panel li.dropdown.open a:hover .caret, 254 | .nav-tabs-panel li.dropdown.open a:focus .caret { 255 | border-top-color: #292929; 256 | border-bottom-color: #292929; 257 | } 258 | .nav-tabs-panel .active .dropdown-toggle .caret { 259 | border-top-color: #fff; 260 | border-bottom-color: #fff; 261 | } 262 | .nav-tabs-panel .dropdown-menu { 263 | margin-top: 1px; 264 | } 265 | .nav-tabs-panel .dropdown-menu li a { 266 | background-color: transparent; 267 | } 268 | .nav-tabs-panel .dropdown-menu li.active a { 269 | background-color: #2986b9; 270 | } 271 | .nav-tabs-panel .dropdown-menu li a:hover, 272 | .nav-tabs-panel .dropdown-menu li a:focus { 273 | background-color: #2986b9; 274 | } 275 | /*------------------------------------*\ 276 | $tabs-below 277 | \*------------------------------------*/ 278 | .tabs-below .nav-tabs-panel { 279 | margin-top: 15px; 280 | margin-bottom: 0; 281 | border-top: 1px solid #2986b9; 282 | border-bottom:none; 283 | } 284 | .tabs-below .nav-tabs-panel li { 285 | margin-top: 0; 286 | } 287 | .tabs-below .nav-tabs-panel li a:hover, 288 | .tabs-below .nav-tabs-panel li a:focus { 289 | border-top-color: transparent; 290 | } 291 | .tabs-below .nav-tabs-panel .active .tab-default, 292 | .tabs-below .nav-tabs-panel .active .tab-default:hover, 293 | .tabs-below .nav-tabs-panel .active .tab-default:focus { 294 | border-bottom-color: #2986b9; 295 | } 296 | .tabs-below .nav-tabs-panel .dropdown-menu { 297 | -webkit-border-radius: 4px 4px 0 0; 298 | -moz-border-radius: 4px 4px 0 0; 299 | border-radius: 4px 4px 0 0; 300 | } 301 | /*------------------------------------*\ 302 | $tabs-left and $tabs-right 303 | \*------------------------------------*/ 304 | .tabs-left .nav-tabs-panel, 305 | .tabs-right .nav-tabs-panel { 306 | position: relative; 307 | border-bottom: none; 308 | z-index: 20; 309 | } 310 | .tabs-left .nav-tabs-panel li, 311 | .tabs-right .nav-tabs-panel li { 312 | float: none; 313 | } 314 | .tabs-left .nav-tabs-panel li .tab-default, 315 | .tabs-right .nav-tabs-panel li .tab-default { 316 | min-width: 39px; 317 | margin-bottom:0; 318 | } 319 | .tabs-left .nav-tabs-panel li .tab-default:hover, 320 | .tabs-left .nav-tabs-panel li .tab-default:focus, 321 | .tabs-right .nav-tabs-panel li .tab-default:hover, 322 | .tabs-right .nav-tabs-panel li .tab-default:focus { 323 | border-color: transparent; 324 | } 325 | .tabs-left .nav-tabs-panel { 326 | float: left; 327 | margin-right: 15px; 328 | border-right: 1px solid #2986b9; 329 | } 330 | .tabs-left .nav-tabs-panel li a { 331 | margin-right: 0; 332 | } 333 | .tabs-left .nav-tabs-panel .active .tab-default, 334 | .tabs-left .nav-tabs-panel .active .tab-default:hover, 335 | .tabs-left .nav-tabs-panel .active .tab-default:focus { 336 | border-color: transparent transparent transparent #2986b9; 337 | border-style: solid; 338 | border-width: 0 0 0 3px; 339 | } 340 | .tabs-right .nav-tabs-panel { 341 | float: right; 342 | margin-left: 15px; 343 | border-left: 1px solid #2986b9; 344 | } 345 | .tabs-right .nav-tabs-panel li a { 346 | margin-left: 0; 347 | } 348 | .tabs-right .nav-tabs-panel .active .tab-default, 349 | .tabs-right .nav-tabs-panel .active .tab-default:hover, 350 | .tabs-right .nav-tabs-panel .active .tab-default:focus { 351 | border-color: transparent #2986b9 transparent transparent; 352 | border-style: solid; 353 | border-width: 0 3px 0 0; 354 | } 355 | 356 | 357 | -------------------------------------------------------------------------------- /example/client/static/css/bootflat-square.css: -------------------------------------------------------------------------------- 1 | /* 2 | Bootflat 1.0.1 3 | Designed & Built by flathemes, http://www.flathemes.com 4 | Licensed under MIT License, http://opensource.org/licenses/mit-license.html 5 | 6 | Thanks for supporting our website and enjoy! 7 | */ 8 | /*------------------------------------*\ 9 | $default-square 10 | \*------------------------------------*/ 11 | .img-thumbnail-square, 12 | .btn-square, 13 | .btn-group-square .btn, 14 | .btn-group-square .dropdown-menu, 15 | .btn-group-square .btn, 16 | .btn-group-square .btn:first-child:not(:last-child), 17 | .btn-group-square .btn:last-child:not(:first-child), 18 | .table-bordered-square, 19 | .table-bordered-square tr:first-child th:first-child, 20 | .table-bordered-square tr:first-child th:last-child, 21 | .table-bordered-square tr:last-child td:first-child, 22 | .table-bordered-square tr:last-child td:last-child, 23 | .input-group-square .btn, 24 | .input-group-square .dropdown-menu, 25 | .input-group-square .form-control, 26 | .input-group-square .input-group-addon, 27 | .dropdown-menu-square, 28 | .dropdown-menu-square .dropdown-submenu .dropdown-menu, 29 | .form-square .form-control, 30 | .form-square .btn, 31 | .form-control-square, 32 | .label-square, 33 | .badge-square, 34 | .alert-square, 35 | .alert-square .btn, 36 | .progress-square, 37 | .breadcrumb-square, 38 | .tooltip-square .tooltip-inner, 39 | .popover-square, 40 | .nav-list-panel-square, 41 | .nav-tabs-square li > a, 42 | .tabs-below .nav-tabs-square li > a, 43 | .tabs-right .nav-tabs-square li > a, 44 | .tabs-left .nav-tabs-square li > a, 45 | .nav-tabs-square .dropdown-menu, 46 | .tabs-below .nav-tabs-square .dropdown-menu, 47 | .nav-pills-square li a, 48 | .nav-pills-square .dropdown-menu, 49 | .navbar-square, 50 | .navbar-square .dropdown-menu, 51 | .pagination-square li:first-child a, 52 | .pagination-square li:first-child span, 53 | .pagination-square li:last-child a, 54 | .pagination-square li:last-child span, 55 | .pager-square li a:hover, 56 | .pager-square li a:focus, 57 | .panel-group-square .panel, 58 | .panel-group-square .panel-heading, 59 | .panel-group-square .panel-body, 60 | /*------------------------------------*\ 61 | $extend-square 62 | \*------------------------------------*/ 63 | .breadcrumb-arrow-square li:first-child a { 64 | -webkit-border-radius: 0; 65 | -moz-border-radius: 0; 66 | border-radius: 0; 67 | } 68 | 69 | 70 | -------------------------------------------------------------------------------- /example/client/static/css/font-awesome.min.css: -------------------------------------------------------------------------------- 1 | @font-face{font-family:'FontAwesome';src:url('../fonts/fontawesome-webfont.eot?v=4.0.0');src:url('../fonts/fontawesome-webfont.eot?#iefix&v=4.0.0') format('embedded-opentype'),url('../fonts/fontawesome-webfont.woff?v=4.0.0') format('woff'),url('../fonts/fontawesome-webfont.ttf?v=4.0.0') format('truetype'),url('../fonts/fontawesome-webfont.svg?v=4.0.0#fontawesomeregular') format('svg');font-weight:normal;font-style:normal}.fa{display:inline-block;font-family:FontAwesome;font-style:normal;font-weight:normal;line-height:1;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale} 2 | .fa-lg{font-size:1.3333333333333333em;line-height:.75em;vertical-align:-15%} 3 | .fa-2x{font-size:2em} 4 | .fa-3x{font-size:3em} 5 | .fa-4x{font-size:4em} 6 | .fa-5x{font-size:5em} 7 | .fa-fw{width:1.2857142857142858em;text-align:center} 8 | .fa-ul{padding-left:0;margin-left:2.142857142857143em;list-style-type:none}.fa-ul>li{position:relative} 9 | .fa-li{position:absolute;left:-2.142857142857143em;width:2.142857142857143em;top:.14285714285714285em;text-align:center}.fa-li.fa-lg{left:-1.8571428571428572em} 10 | .fa-border{padding:.2em .25em .15em;border:solid .08em #eee;border-radius:.1em} 11 | .pull-right{float:right} 12 | .pull-left{float:left} 13 | .fa.pull-left{margin-right:.3em} 14 | .fa.pull-right{margin-left:.3em} 15 | .fa-spin{-webkit-animation:spin 2s infinite linear;-moz-animation:spin 2s infinite linear;-o-animation:spin 2s infinite linear;animation:spin 2s infinite linear} 16 | @-moz-keyframes spin{0%{-moz-transform:rotate(0deg)} 100%{-moz-transform:rotate(359deg)}}@-webkit-keyframes spin{0%{-webkit-transform:rotate(0deg)} 100%{-webkit-transform:rotate(359deg)}}@-o-keyframes spin{0%{-o-transform:rotate(0deg)} 100%{-o-transform:rotate(359deg)}}@-ms-keyframes spin{0%{-ms-transform:rotate(0deg)} 100%{-ms-transform:rotate(359deg)}}@keyframes spin{0%{transform:rotate(0deg)} 100%{transform:rotate(359deg)}}.fa-rotate-90{filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=1);-webkit-transform:rotate(90deg);-moz-transform:rotate(90deg);-ms-transform:rotate(90deg);-o-transform:rotate(90deg);transform:rotate(90deg)} 17 | .fa-rotate-180{filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=2);-webkit-transform:rotate(180deg);-moz-transform:rotate(180deg);-ms-transform:rotate(180deg);-o-transform:rotate(180deg);transform:rotate(180deg)} 18 | .fa-rotate-270{filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=3);-webkit-transform:rotate(270deg);-moz-transform:rotate(270deg);-ms-transform:rotate(270deg);-o-transform:rotate(270deg);transform:rotate(270deg)} 19 | .fa-flip-horizontal{filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=0, mirror=1);-webkit-transform:scale(-1, 1);-moz-transform:scale(-1, 1);-ms-transform:scale(-1, 1);-o-transform:scale(-1, 1);transform:scale(-1, 1)} 20 | .fa-flip-vertical{filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=2, mirror=1);-webkit-transform:scale(1, -1);-moz-transform:scale(1, -1);-ms-transform:scale(1, -1);-o-transform:scale(1, -1);transform:scale(1, -1)} 21 | .fa-stack{position:relative;display:inline-block;width:2em;height:2em;line-height:2em;vertical-align:middle} 22 | .fa-stack-1x,.fa-stack-2x{position:absolute;width:100%;text-align:center} 23 | .fa-stack-1x{line-height:inherit} 24 | .fa-stack-2x{font-size:2em} 25 | .fa-inverse{color:#fff} 26 | .fa-glass:before{content:"\f000"} 27 | .fa-music:before{content:"\f001"} 28 | .fa-search:before{content:"\f002"} 29 | .fa-envelope-o:before{content:"\f003"} 30 | .fa-heart:before{content:"\f004"} 31 | .fa-star:before{content:"\f005"} 32 | .fa-star-o:before{content:"\f006"} 33 | .fa-user:before{content:"\f007"} 34 | .fa-film:before{content:"\f008"} 35 | .fa-th-large:before{content:"\f009"} 36 | .fa-th:before{content:"\f00a"} 37 | .fa-th-list:before{content:"\f00b"} 38 | .fa-check:before{content:"\f00c"} 39 | .fa-times:before{content:"\f00d"} 40 | .fa-search-plus:before{content:"\f00e"} 41 | .fa-search-minus:before{content:"\f010"} 42 | .fa-power-off:before{content:"\f011"} 43 | .fa-signal:before{content:"\f012"} 44 | .fa-gear:before,.fa-cog:before{content:"\f013"} 45 | .fa-trash-o:before{content:"\f014"} 46 | .fa-home:before{content:"\f015"} 47 | .fa-file-o:before{content:"\f016"} 48 | .fa-clock-o:before{content:"\f017"} 49 | .fa-road:before{content:"\f018"} 50 | .fa-download:before{content:"\f019"} 51 | .fa-arrow-circle-o-down:before{content:"\f01a"} 52 | .fa-arrow-circle-o-up:before{content:"\f01b"} 53 | .fa-inbox:before{content:"\f01c"} 54 | .fa-play-circle-o:before{content:"\f01d"} 55 | .fa-rotate-right:before,.fa-repeat:before{content:"\f01e"} 56 | .fa-refresh:before{content:"\f021"} 57 | .fa-list-alt:before{content:"\f022"} 58 | .fa-lock:before{content:"\f023"} 59 | .fa-flag:before{content:"\f024"} 60 | .fa-headphones:before{content:"\f025"} 61 | .fa-volume-off:before{content:"\f026"} 62 | .fa-volume-down:before{content:"\f027"} 63 | .fa-volume-up:before{content:"\f028"} 64 | .fa-qrcode:before{content:"\f029"} 65 | .fa-barcode:before{content:"\f02a"} 66 | .fa-tag:before{content:"\f02b"} 67 | .fa-tags:before{content:"\f02c"} 68 | .fa-book:before{content:"\f02d"} 69 | .fa-bookmark:before{content:"\f02e"} 70 | .fa-print:before{content:"\f02f"} 71 | .fa-camera:before{content:"\f030"} 72 | .fa-font:before{content:"\f031"} 73 | .fa-bold:before{content:"\f032"} 74 | .fa-italic:before{content:"\f033"} 75 | .fa-text-height:before{content:"\f034"} 76 | .fa-text-width:before{content:"\f035"} 77 | .fa-align-left:before{content:"\f036"} 78 | .fa-align-center:before{content:"\f037"} 79 | .fa-align-right:before{content:"\f038"} 80 | .fa-align-justify:before{content:"\f039"} 81 | .fa-list:before{content:"\f03a"} 82 | .fa-dedent:before,.fa-outdent:before{content:"\f03b"} 83 | .fa-indent:before{content:"\f03c"} 84 | .fa-video-camera:before{content:"\f03d"} 85 | .fa-picture-o:before{content:"\f03e"} 86 | .fa-pencil:before{content:"\f040"} 87 | .fa-map-marker:before{content:"\f041"} 88 | .fa-adjust:before{content:"\f042"} 89 | .fa-tint:before{content:"\f043"} 90 | .fa-edit:before,.fa-pencil-square-o:before{content:"\f044"} 91 | .fa-share-square-o:before{content:"\f045"} 92 | .fa-check-square-o:before{content:"\f046"} 93 | .fa-move:before{content:"\f047"} 94 | .fa-step-backward:before{content:"\f048"} 95 | .fa-fast-backward:before{content:"\f049"} 96 | .fa-backward:before{content:"\f04a"} 97 | .fa-play:before{content:"\f04b"} 98 | .fa-pause:before{content:"\f04c"} 99 | .fa-stop:before{content:"\f04d"} 100 | .fa-forward:before{content:"\f04e"} 101 | .fa-fast-forward:before{content:"\f050"} 102 | .fa-step-forward:before{content:"\f051"} 103 | .fa-eject:before{content:"\f052"} 104 | .fa-chevron-left:before{content:"\f053"} 105 | .fa-chevron-right:before{content:"\f054"} 106 | .fa-plus-circle:before{content:"\f055"} 107 | .fa-minus-circle:before{content:"\f056"} 108 | .fa-times-circle:before{content:"\f057"} 109 | .fa-check-circle:before{content:"\f058"} 110 | .fa-question-circle:before{content:"\f059"} 111 | .fa-info-circle:before{content:"\f05a"} 112 | .fa-crosshairs:before{content:"\f05b"} 113 | .fa-times-circle-o:before{content:"\f05c"} 114 | .fa-check-circle-o:before{content:"\f05d"} 115 | .fa-ban:before{content:"\f05e"} 116 | .fa-arrow-left:before{content:"\f060"} 117 | .fa-arrow-right:before{content:"\f061"} 118 | .fa-arrow-up:before{content:"\f062"} 119 | .fa-arrow-down:before{content:"\f063"} 120 | .fa-mail-forward:before,.fa-share:before{content:"\f064"} 121 | .fa-resize-full:before{content:"\f065"} 122 | .fa-resize-small:before{content:"\f066"} 123 | .fa-plus:before{content:"\f067"} 124 | .fa-minus:before{content:"\f068"} 125 | .fa-asterisk:before{content:"\f069"} 126 | .fa-exclamation-circle:before{content:"\f06a"} 127 | .fa-gift:before{content:"\f06b"} 128 | .fa-leaf:before{content:"\f06c"} 129 | .fa-fire:before{content:"\f06d"} 130 | .fa-eye:before{content:"\f06e"} 131 | .fa-eye-slash:before{content:"\f070"} 132 | .fa-warning:before,.fa-exclamation-triangle:before{content:"\f071"} 133 | .fa-plane:before{content:"\f072"} 134 | .fa-calendar:before{content:"\f073"} 135 | .fa-random:before{content:"\f074"} 136 | .fa-comment:before{content:"\f075"} 137 | .fa-magnet:before{content:"\f076"} 138 | .fa-chevron-up:before{content:"\f077"} 139 | .fa-chevron-down:before{content:"\f078"} 140 | .fa-retweet:before{content:"\f079"} 141 | .fa-shopping-cart:before{content:"\f07a"} 142 | .fa-folder:before{content:"\f07b"} 143 | .fa-folder-open:before{content:"\f07c"} 144 | .fa-resize-vertical:before{content:"\f07d"} 145 | .fa-resize-horizontal:before{content:"\f07e"} 146 | .fa-bar-chart-o:before{content:"\f080"} 147 | .fa-twitter-square:before{content:"\f081"} 148 | .fa-facebook-square:before{content:"\f082"} 149 | .fa-camera-retro:before{content:"\f083"} 150 | .fa-key:before{content:"\f084"} 151 | .fa-gears:before,.fa-cogs:before{content:"\f085"} 152 | .fa-comments:before{content:"\f086"} 153 | .fa-thumbs-o-up:before{content:"\f087"} 154 | .fa-thumbs-o-down:before{content:"\f088"} 155 | .fa-star-half:before{content:"\f089"} 156 | .fa-heart-o:before{content:"\f08a"} 157 | .fa-sign-out:before{content:"\f08b"} 158 | .fa-linkedin-square:before{content:"\f08c"} 159 | .fa-thumb-tack:before{content:"\f08d"} 160 | .fa-external-link:before{content:"\f08e"} 161 | .fa-sign-in:before{content:"\f090"} 162 | .fa-trophy:before{content:"\f091"} 163 | .fa-github-square:before{content:"\f092"} 164 | .fa-upload:before{content:"\f093"} 165 | .fa-lemon-o:before{content:"\f094"} 166 | .fa-phone:before{content:"\f095"} 167 | .fa-square-o:before{content:"\f096"} 168 | .fa-bookmark-o:before{content:"\f097"} 169 | .fa-phone-square:before{content:"\f098"} 170 | .fa-twitter:before{content:"\f099"} 171 | .fa-facebook:before{content:"\f09a"} 172 | .fa-github:before{content:"\f09b"} 173 | .fa-unlock:before{content:"\f09c"} 174 | .fa-credit-card:before{content:"\f09d"} 175 | .fa-rss:before{content:"\f09e"} 176 | .fa-hdd:before{content:"\f0a0"} 177 | .fa-bullhorn:before{content:"\f0a1"} 178 | .fa-bell:before{content:"\f0f3"} 179 | .fa-certificate:before{content:"\f0a3"} 180 | .fa-hand-o-right:before{content:"\f0a4"} 181 | .fa-hand-o-left:before{content:"\f0a5"} 182 | .fa-hand-o-up:before{content:"\f0a6"} 183 | .fa-hand-o-down:before{content:"\f0a7"} 184 | .fa-arrow-circle-left:before{content:"\f0a8"} 185 | .fa-arrow-circle-right:before{content:"\f0a9"} 186 | .fa-arrow-circle-up:before{content:"\f0aa"} 187 | .fa-arrow-circle-down:before{content:"\f0ab"} 188 | .fa-globe:before{content:"\f0ac"} 189 | .fa-wrench:before{content:"\f0ad"} 190 | .fa-tasks:before{content:"\f0ae"} 191 | .fa-filter:before{content:"\f0b0"} 192 | .fa-briefcase:before{content:"\f0b1"} 193 | .fa-fullscreen:before{content:"\f0b2"} 194 | .fa-group:before{content:"\f0c0"} 195 | .fa-chain:before,.fa-link:before{content:"\f0c1"} 196 | .fa-cloud:before{content:"\f0c2"} 197 | .fa-flask:before{content:"\f0c3"} 198 | .fa-cut:before,.fa-scissors:before{content:"\f0c4"} 199 | .fa-copy:before,.fa-files-o:before{content:"\f0c5"} 200 | .fa-paperclip:before{content:"\f0c6"} 201 | .fa-save:before,.fa-floppy-o:before{content:"\f0c7"} 202 | .fa-square:before{content:"\f0c8"} 203 | .fa-reorder:before{content:"\f0c9"} 204 | .fa-list-ul:before{content:"\f0ca"} 205 | .fa-list-ol:before{content:"\f0cb"} 206 | .fa-strikethrough:before{content:"\f0cc"} 207 | .fa-underline:before{content:"\f0cd"} 208 | .fa-table:before{content:"\f0ce"} 209 | .fa-magic:before{content:"\f0d0"} 210 | .fa-truck:before{content:"\f0d1"} 211 | .fa-pinterest:before{content:"\f0d2"} 212 | .fa-pinterest-square:before{content:"\f0d3"} 213 | .fa-google-plus-square:before{content:"\f0d4"} 214 | .fa-google-plus:before{content:"\f0d5"} 215 | .fa-money:before{content:"\f0d6"} 216 | .fa-caret-down:before{content:"\f0d7"} 217 | .fa-caret-up:before{content:"\f0d8"} 218 | .fa-caret-left:before{content:"\f0d9"} 219 | .fa-caret-right:before{content:"\f0da"} 220 | .fa-columns:before{content:"\f0db"} 221 | .fa-unsorted:before,.fa-sort:before{content:"\f0dc"} 222 | .fa-sort-down:before,.fa-sort-asc:before{content:"\f0dd"} 223 | .fa-sort-up:before,.fa-sort-desc:before{content:"\f0de"} 224 | .fa-envelope:before{content:"\f0e0"} 225 | .fa-linkedin:before{content:"\f0e1"} 226 | .fa-rotate-left:before,.fa-undo:before{content:"\f0e2"} 227 | .fa-legal:before,.fa-gavel:before{content:"\f0e3"} 228 | .fa-dashboard:before,.fa-tachometer:before{content:"\f0e4"} 229 | .fa-comment-o:before{content:"\f0e5"} 230 | .fa-comments-o:before{content:"\f0e6"} 231 | .fa-flash:before,.fa-bolt:before{content:"\f0e7"} 232 | .fa-sitemap:before{content:"\f0e8"} 233 | .fa-umbrella:before{content:"\f0e9"} 234 | .fa-paste:before,.fa-clipboard:before{content:"\f0ea"} 235 | .fa-lightbulb-o:before{content:"\f0eb"} 236 | .fa-exchange:before{content:"\f0ec"} 237 | .fa-cloud-download:before{content:"\f0ed"} 238 | .fa-cloud-upload:before{content:"\f0ee"} 239 | .fa-user-md:before{content:"\f0f0"} 240 | .fa-stethoscope:before{content:"\f0f1"} 241 | .fa-suitcase:before{content:"\f0f2"} 242 | .fa-bell-o:before{content:"\f0a2"} 243 | .fa-coffee:before{content:"\f0f4"} 244 | .fa-cutlery:before{content:"\f0f5"} 245 | .fa-file-text-o:before{content:"\f0f6"} 246 | .fa-building:before{content:"\f0f7"} 247 | .fa-hospital:before{content:"\f0f8"} 248 | .fa-ambulance:before{content:"\f0f9"} 249 | .fa-medkit:before{content:"\f0fa"} 250 | .fa-fighter-jet:before{content:"\f0fb"} 251 | .fa-beer:before{content:"\f0fc"} 252 | .fa-h-square:before{content:"\f0fd"} 253 | .fa-plus-square:before{content:"\f0fe"} 254 | .fa-angle-double-left:before{content:"\f100"} 255 | .fa-angle-double-right:before{content:"\f101"} 256 | .fa-angle-double-up:before{content:"\f102"} 257 | .fa-angle-double-down:before{content:"\f103"} 258 | .fa-angle-left:before{content:"\f104"} 259 | .fa-angle-right:before{content:"\f105"} 260 | .fa-angle-up:before{content:"\f106"} 261 | .fa-angle-down:before{content:"\f107"} 262 | .fa-desktop:before{content:"\f108"} 263 | .fa-laptop:before{content:"\f109"} 264 | .fa-tablet:before{content:"\f10a"} 265 | .fa-mobile-phone:before,.fa-mobile:before{content:"\f10b"} 266 | .fa-circle-o:before{content:"\f10c"} 267 | .fa-quote-left:before{content:"\f10d"} 268 | .fa-quote-right:before{content:"\f10e"} 269 | .fa-spinner:before{content:"\f110"} 270 | .fa-circle:before{content:"\f111"} 271 | .fa-mail-reply:before,.fa-reply:before{content:"\f112"} 272 | .fa-github-alt:before{content:"\f113"} 273 | .fa-folder-o:before{content:"\f114"} 274 | .fa-folder-open-o:before{content:"\f115"} 275 | .fa-expand-o:before{content:"\f116"} 276 | .fa-collapse-o:before{content:"\f117"} 277 | .fa-smile-o:before{content:"\f118"} 278 | .fa-frown-o:before{content:"\f119"} 279 | .fa-meh-o:before{content:"\f11a"} 280 | .fa-gamepad:before{content:"\f11b"} 281 | .fa-keyboard-o:before{content:"\f11c"} 282 | .fa-flag-o:before{content:"\f11d"} 283 | .fa-flag-checkered:before{content:"\f11e"} 284 | .fa-terminal:before{content:"\f120"} 285 | .fa-code:before{content:"\f121"} 286 | .fa-reply-all:before{content:"\f122"} 287 | .fa-mail-reply-all:before{content:"\f122"} 288 | .fa-star-half-empty:before,.fa-star-half-full:before,.fa-star-half-o:before{content:"\f123"} 289 | .fa-location-arrow:before{content:"\f124"} 290 | .fa-crop:before{content:"\f125"} 291 | .fa-code-fork:before{content:"\f126"} 292 | .fa-unlink:before,.fa-chain-broken:before{content:"\f127"} 293 | .fa-question:before{content:"\f128"} 294 | .fa-info:before{content:"\f129"} 295 | .fa-exclamation:before{content:"\f12a"} 296 | .fa-superscript:before{content:"\f12b"} 297 | .fa-subscript:before{content:"\f12c"} 298 | .fa-eraser:before{content:"\f12d"} 299 | .fa-puzzle-piece:before{content:"\f12e"} 300 | .fa-microphone:before{content:"\f130"} 301 | .fa-microphone-slash:before{content:"\f131"} 302 | .fa-shield:before{content:"\f132"} 303 | .fa-calendar-o:before{content:"\f133"} 304 | .fa-fire-extinguisher:before{content:"\f134"} 305 | .fa-rocket:before{content:"\f135"} 306 | .fa-maxcdn:before{content:"\f136"} 307 | .fa-chevron-circle-left:before{content:"\f137"} 308 | .fa-chevron-circle-right:before{content:"\f138"} 309 | .fa-chevron-circle-up:before{content:"\f139"} 310 | .fa-chevron-circle-down:before{content:"\f13a"} 311 | .fa-html5:before{content:"\f13b"} 312 | .fa-css3:before{content:"\f13c"} 313 | .fa-anchor:before{content:"\f13d"} 314 | .fa-unlock-o:before{content:"\f13e"} 315 | .fa-bullseye:before{content:"\f140"} 316 | .fa-ellipsis-horizontal:before{content:"\f141"} 317 | .fa-ellipsis-vertical:before{content:"\f142"} 318 | .fa-rss-square:before{content:"\f143"} 319 | .fa-play-circle:before{content:"\f144"} 320 | .fa-ticket:before{content:"\f145"} 321 | .fa-minus-square:before{content:"\f146"} 322 | .fa-minus-square-o:before{content:"\f147"} 323 | .fa-level-up:before{content:"\f148"} 324 | .fa-level-down:before{content:"\f149"} 325 | .fa-check-square:before{content:"\f14a"} 326 | .fa-pencil-square:before{content:"\f14b"} 327 | .fa-external-link-square:before{content:"\f14c"} 328 | .fa-share-square:before{content:"\f14d"} 329 | .fa-compass:before{content:"\f14e"} 330 | .fa-toggle-down:before,.fa-caret-square-o-down:before{content:"\f150"} 331 | .fa-toggle-up:before,.fa-caret-square-o-up:before{content:"\f151"} 332 | .fa-toggle-right:before,.fa-caret-square-o-right:before{content:"\f152"} 333 | .fa-euro:before,.fa-eur:before{content:"\f153"} 334 | .fa-gbp:before{content:"\f154"} 335 | .fa-dollar:before,.fa-usd:before{content:"\f155"} 336 | .fa-rupee:before,.fa-inr:before{content:"\f156"} 337 | .fa-cny:before,.fa-rmb:before,.fa-yen:before,.fa-jpy:before{content:"\f157"} 338 | .fa-ruble:before,.fa-rouble:before,.fa-rub:before{content:"\f158"} 339 | .fa-won:before,.fa-krw:before{content:"\f159"} 340 | .fa-bitcoin:before,.fa-btc:before{content:"\f15a"} 341 | .fa-file:before{content:"\f15b"} 342 | .fa-file-text:before{content:"\f15c"} 343 | .fa-sort-alpha-asc:before{content:"\f15d"} 344 | .fa-sort-alpha-desc:before{content:"\f15e"} 345 | .fa-sort-amount-asc:before{content:"\f160"} 346 | .fa-sort-amount-desc:before{content:"\f161"} 347 | .fa-sort-numeric-asc:before{content:"\f162"} 348 | .fa-sort-numeric-desc:before{content:"\f163"} 349 | .fa-thumbs-up:before{content:"\f164"} 350 | .fa-thumbs-down:before{content:"\f165"} 351 | .fa-youtube-square:before{content:"\f166"} 352 | .fa-youtube:before{content:"\f167"} 353 | .fa-xing:before{content:"\f168"} 354 | .fa-xing-square:before{content:"\f169"} 355 | .fa-youtube-play:before{content:"\f16a"} 356 | .fa-dropbox:before{content:"\f16b"} 357 | .fa-stack-overflow:before{content:"\f16c"} 358 | .fa-instagram:before{content:"\f16d"} 359 | .fa-flickr:before{content:"\f16e"} 360 | .fa-adn:before{content:"\f170"} 361 | .fa-bitbucket:before{content:"\f171"} 362 | .fa-bitbucket-square:before{content:"\f172"} 363 | .fa-tumblr:before{content:"\f173"} 364 | .fa-tumblr-square:before{content:"\f174"} 365 | .fa-long-arrow-down:before{content:"\f175"} 366 | .fa-long-arrow-up:before{content:"\f176"} 367 | .fa-long-arrow-left:before{content:"\f177"} 368 | .fa-long-arrow-right:before{content:"\f178"} 369 | .fa-apple:before{content:"\f179"} 370 | .fa-windows:before{content:"\f17a"} 371 | .fa-android:before{content:"\f17b"} 372 | .fa-linux:before{content:"\f17c"} 373 | .fa-dribbble:before{content:"\f17d"} 374 | .fa-skype:before{content:"\f17e"} 375 | .fa-foursquare:before{content:"\f180"} 376 | .fa-trello:before{content:"\f181"} 377 | .fa-female:before{content:"\f182"} 378 | .fa-male:before{content:"\f183"} 379 | .fa-gittip:before{content:"\f184"} 380 | .fa-sun-o:before{content:"\f185"} 381 | .fa-moon-o:before{content:"\f186"} 382 | .fa-archive:before{content:"\f187"} 383 | .fa-bug:before{content:"\f188"} 384 | .fa-vk:before{content:"\f189"} 385 | .fa-weibo:before{content:"\f18a"} 386 | .fa-renren:before{content:"\f18b"} 387 | .fa-pagelines:before{content:"\f18c"} 388 | .fa-stack-exchange:before{content:"\f18d"} 389 | .fa-arrow-circle-o-right:before{content:"\f18e"} 390 | .fa-arrow-circle-o-left:before{content:"\f190"} 391 | .fa-toggle-left:before,.fa-caret-square-o-left:before{content:"\f191"} 392 | .fa-dot-circle-o:before{content:"\f192"} 393 | .fa-wheelchair:before{content:"\f193"} 394 | .fa-vimeo-square:before{content:"\f194"} 395 | .fa-turkish-lira:before,.fa-try:before{content:"\f195"} 396 | -------------------------------------------------------------------------------- /example/client/static/css/style.css: -------------------------------------------------------------------------------- 1 | 2 | body { 3 | background-color: #F8F8F8; 4 | font-family: 'Open Sans', sans-serif; 5 | font-size: 14px; 6 | font-weight: normal; 7 | line-height: 1.2em; 8 | margin: 15px; 9 | } 10 | 11 | h1, p { 12 | color: #333; 13 | } 14 | 15 | #sample_container_id { 16 | width: 100%; 17 | height: 400px; 18 | position: relative; 19 | border: 1px solid #ccc; 20 | background-color: #fff; 21 | } 22 | 23 | #sample_text_id { 24 | font-size: 24pt; 25 | text-align: center; 26 | margin-top: 140px; 27 | } 28 | 29 | #context-wrapper { 30 | min-height: 400px; 31 | } 32 | 33 | #context { 34 | position: absolute; 35 | bottom: 0; 36 | } 37 | 38 | .box { 39 | border: 1px solid #d8d8d8; 40 | -moz-border-radius: 3px; 41 | -webkit-border-radius: 3px; 42 | border-radius: 3px; 43 | background-color: #fff; 44 | border-bottom-width: 2px; 45 | margin: 10px 0 20px 0; 46 | padding: 20px 20px; 47 | } 48 | 49 | .mheight { 50 | min-height: 200px; 51 | } 52 | 53 | .small { 54 | font-size: 10pt; 55 | color: #aaa; 56 | } 57 | 58 | -------------------------------------------------------------------------------- /example/client/static/fonts/FontAwesome.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ForceUniverse/dart-forcemvc/f1199f185783c0caca699ed0b6f18113feb7d256/example/client/static/fonts/FontAwesome.otf -------------------------------------------------------------------------------- /example/client/static/fonts/fontawesome-webfont.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ForceUniverse/dart-forcemvc/f1199f185783c0caca699ed0b6f18113feb7d256/example/client/static/fonts/fontawesome-webfont.eot -------------------------------------------------------------------------------- /example/client/static/fonts/fontawesome-webfont.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ForceUniverse/dart-forcemvc/f1199f185783c0caca699ed0b6f18113feb7d256/example/client/static/fonts/fontawesome-webfont.ttf -------------------------------------------------------------------------------- /example/client/static/fonts/fontawesome-webfont.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ForceUniverse/dart-forcemvc/f1199f185783c0caca699ed0b6f18113feb7d256/example/client/static/fonts/fontawesome-webfont.woff -------------------------------------------------------------------------------- /example/client/static/img/check_flat/default.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ForceUniverse/dart-forcemvc/f1199f185783c0caca699ed0b6f18113feb7d256/example/client/static/img/check_flat/default.png -------------------------------------------------------------------------------- /example/client/static/img/dart_force_logo.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ForceUniverse/dart-forcemvc/f1199f185783c0caca699ed0b6f18113feb7d256/example/client/static/img/dart_force_logo.jpg -------------------------------------------------------------------------------- /example/client/web/client.dart: -------------------------------------------------------------------------------- 1 | import 'dart:html'; 2 | 3 | // This is a client side dart script needed by dart force in order to 4 | // bootstrap the client side of the application (?) 5 | 6 | void main() { 7 | DivElement statusElement = querySelector('#status'); 8 | statusElement.innerHtml = "Js / dart is up and running! Cool it should work like this!"; 9 | } 10 | -------------------------------------------------------------------------------- /example/client/web/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 |
5 |Force mvc is part of the dart force framework. It is a server side implementation with concepts of spring mvc. It uses annotations like @RequestMapping, @Controller, @ModelAttribute, interceptors, ... more to come.
34 | 35 |This page just will count the visits in memory on the server
43 | 44 |You can use path variables in the url to make it more dynamic! In this example it is /var/{var1}/.
53 | 54 |You can also add authentication into the controller, test it out!
58 | 59 |This interface allows for implementations based on request, session,
9 | * cookies, etc. The default implementation is AcceptHeaderLocaleResolver,
10 | * simply using the request's locale provided by the respective HTTP header.
11 | *
12 | */
13 | abstract class LocaleResolver {
14 |
15 | /**
16 | * Resolve the current locale via the given request.
17 | * Should return a default locale as fallback in any case.
18 | * @param request the request to resolve the locale for
19 | * @return the current locale (never null
)
20 | */
21 | Locale resolveLocale(ForceRequest request);
22 |
23 | /**
24 | * Set the current locale to the given one.
25 | * @param request the request to be used for locale modification
26 | * @param locale the new locale, or null
to clear the locale
27 | * @throws UnsupportedOperationException if the LocaleResolver implementation
28 | * does not support dynamic changing of the theme
29 | */
30 | void setLocale(ForceRequest request, Locale locale);
31 |
32 | }
33 |
--------------------------------------------------------------------------------
/lib/manager/cookie_holder_manager.dart:
--------------------------------------------------------------------------------
1 | part of dart_force_mvc_lib;
2 |
3 | class CookieHolderManager {
4 |
5 | static final Logger logger = new Logger('CookieManager');
6 |
7 | /**
8 | * Default path that cookies will be visible to: "/", i.e. the entire server.
9 | */
10 | static final String DEFAULT_COOKIE_PATH = "/";
11 |
12 | String cookiePath = DEFAULT_COOKIE_PATH;
13 |
14 | int cookieMaxAge;
15 | bool cookieSecure;
16 | String cookieName;
17 | String cookieDomain;
18 |
19 |
20 | /**
21 | * Add a cookie with the given value to the response,
22 | * using the cookie descriptor settings of this generator.
23 | *
24 | * Delegates to createCookie for cookie creation.
25 | * @param response the HTTP response to add the cookie to
26 | * @param cookieValue the value of the cookie to add
27 | */
28 | void addCookie(HttpResponse response, String cookieValue) {
29 | Cookie cookie = createCookie(cookieValue);
30 | int maxAge = cookieMaxAge;
31 | if (maxAge != null) {
32 | cookie.maxAge = maxAge;
33 | }
34 | if (cookieSecure) {
35 | cookie.secure = true;
36 | }
37 | response.cookies.add(cookie);
38 | logger.log(Level.INFO, "Added cookie with name [${cookieName}] and value [${cookieValue}]");
39 | }
40 |
41 | /**
42 | * Remove the cookie that this generator describes from the response.
43 | * Will generate a cookie with empty value and max age 0.
44 | *
45 | * Delegates to createCookie for cookie creation.
46 | * @param response the HTTP response to remove the cookie from
47 | */
48 | void removeCookie(HttpResponse response) {
49 | Cookie cookie = createCookie("");
50 | cookie.maxAge = 0;
51 | response.cookies.add(cookie);
52 | logger.log(Level.INFO, "Removed cookie with name [${cookieName}]");
53 | }
54 |
55 | /**
56 | * Create a cookie with the given value, using the cookie descriptor
57 | * settings of this manager (except for "cookieMaxAge").
58 | *
59 | * @param cookieValue the value of the cookie to crate
60 | * @return the cookie
61 | */
62 | Cookie createCookie(String cookieValue) {
63 | Cookie cookie = new Cookie(cookieName, cookieValue);
64 | if (cookieDomain != null) {
65 | cookie.domain = cookieDomain;
66 | }
67 | cookie.path = cookiePath;
68 | return cookie;
69 | }
70 |
71 | /**
72 | * Getting the cookie according to the request and the cookie name.
73 | *
74 | * @param request the HTTP request to retrieve the cookie from
75 | * @return the cookie
76 | */
77 | Cookie getCookie(HttpRequest request) {
78 | List> inputStream = await servingAssistent.read(clientFiles, "$view.html");
47 | var template = await inputStream.transform(UTF8.decoder).first;
48 | result = _render_impl(template, model);
49 | } catch(e) {
50 | log.severe("The '$view' can't be resolved.");
51 | }
52 | } else {
53 | viewUri = new Uri.file(clientFiles).resolve("$view.html");
54 | file = new File(viewUri.toFilePath());
55 | if (file.existsSync()) {
56 | result = await _readFile(file, model);
57 | }
58 | }
59 | }
60 |
61 | return result;
62 | }
63 |
64 | Future