├── .editorconfig ├── .gitignore ├── LICENSE ├── README.md ├── gulpfile.js ├── index.html ├── package.json ├── scripts ├── app.cjsx ├── components │ ├── Config.cjsx │ ├── Context.cjsx │ ├── Contexts.cjsx │ ├── CreateContext.cjsx │ ├── Jar.cjsx │ ├── JarLoad.cjsx │ ├── Jars.cjsx │ ├── Job.cjsx │ ├── JobResult.cjsx │ ├── JobSubmit.cjsx │ ├── Jobs.cjsx │ └── Main.cjsx ├── events │ ├── click-job.coffee │ ├── context-loaded.coffee │ ├── context-removed.coffee │ └── jar-loaded.coffee └── services │ ├── api.coffee │ ├── binary-send.coffee │ ├── pretty-print.coffee │ └── time.coffee └── styles ├── _colors.sass └── main.sass /.editorconfig: -------------------------------------------------------------------------------- 1 | # EditorConfig helps developers define and maintain consistent 2 | # coding styles between different editors and IDEs 3 | # editorconfig.org 4 | 5 | root = true 6 | 7 | 8 | [*] 9 | 10 | # Change these settings to your own preference 11 | indent_style = space 12 | indent_size = 2 13 | 14 | # We recommend you to keep these unchanged 15 | end_of_line = lf 16 | charset = utf-8 17 | trim_trailing_whitespace = true 18 | insert_final_newline = true 19 | 20 | [*.md] 21 | trim_trailing_whitespace = false 22 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .tmp 3 | .idea 4 | dist 5 | node_modules 6 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | 2 | Apache License 3 | Version 2.0, January 2004 4 | http://www.apache.org/licenses/ 5 | 6 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 7 | 8 | 1. Definitions. 9 | 10 | "License" shall mean the terms and conditions for use, reproduction, 11 | and distribution as defined by Sections 1 through 9 of this document. 12 | 13 | "Licensor" shall mean the copyright owner or entity authorized by 14 | the copyright owner that is granting the License. 15 | 16 | "Legal Entity" shall mean the union of the acting entity and all 17 | other entities that control, are controlled by, or are under common 18 | control with that entity. For the purposes of this definition, 19 | "control" means (i) the power, direct or indirect, to cause the 20 | direction or management of such entity, whether by contract or 21 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 22 | outstanding shares, or (iii) beneficial ownership of such entity. 23 | 24 | "You" (or "Your") shall mean an individual or Legal Entity 25 | exercising permissions granted by this License. 26 | 27 | "Source" form shall mean the preferred form for making modifications, 28 | including but not limited to software source code, documentation 29 | source, and configuration files. 30 | 31 | "Object" form shall mean any form resulting from mechanical 32 | transformation or translation of a Source form, including but 33 | not limited to compiled object code, generated documentation, 34 | and conversions to other media types. 35 | 36 | "Work" shall mean the work of authorship, whether in Source or 37 | Object form, made available under the License, as indicated by a 38 | copyright notice that is included in or attached to the work 39 | (an example is provided in the Appendix below). 40 | 41 | "Derivative Works" shall mean any work, whether in Source or Object 42 | form, that is based on (or derived from) the Work and for which the 43 | editorial revisions, annotations, elaborations, or other modifications 44 | represent, as a whole, an original work of authorship. For the purposes 45 | of this License, Derivative Works shall not include works that remain 46 | separable from, or merely link (or bind by name) to the interfaces of, 47 | the Work and Derivative Works thereof. 48 | 49 | "Contribution" shall mean any work of authorship, including 50 | the original version of the Work and any modifications or additions 51 | to that Work or Derivative Works thereof, that is intentionally 52 | submitted to Licensor for inclusion in the Work by the copyright owner 53 | or by an individual or Legal Entity authorized to submit on behalf of 54 | the copyright owner. For the purposes of this definition, "submitted" 55 | means any form of electronic, verbal, or written communication sent 56 | to the Licensor or its representatives, including but not limited to 57 | communication on electronic mailing lists, source code control systems, 58 | and issue tracking systems that are managed by, or on behalf of, the 59 | Licensor for the purpose of discussing and improving the Work, but 60 | excluding communication that is conspicuously marked or otherwise 61 | designated in writing by the copyright owner as "Not a Contribution." 62 | 63 | "Contributor" shall mean Licensor and any individual or Legal Entity 64 | on behalf of whom a Contribution has been received by Licensor and 65 | subsequently incorporated within the Work. 66 | 67 | 2. Grant of Copyright License. Subject to the terms and conditions of 68 | this License, each Contributor hereby grants to You a perpetual, 69 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 70 | copyright license to reproduce, prepare Derivative Works of, 71 | publicly display, publicly perform, sublicense, and distribute the 72 | Work and such Derivative Works in Source or Object form. 73 | 74 | 3. Grant of Patent License. Subject to the terms and conditions of 75 | this License, each Contributor hereby grants to You a perpetual, 76 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 77 | (except as stated in this section) patent license to make, have made, 78 | use, offer to sell, sell, import, and otherwise transfer the Work, 79 | where such license applies only to those patent claims licensable 80 | by such Contributor that are necessarily infringed by their 81 | Contribution(s) alone or by combination of their Contribution(s) 82 | with the Work to which such Contribution(s) was submitted. If You 83 | institute patent litigation against any entity (including a 84 | cross-claim or counterclaim in a lawsuit) alleging that the Work 85 | or a Contribution incorporated within the Work constitutes direct 86 | or contributory patent infringement, then any patent licenses 87 | granted to You under this License for that Work shall terminate 88 | as of the date such litigation is filed. 89 | 90 | 4. Redistribution. You may reproduce and distribute copies of the 91 | Work or Derivative Works thereof in any medium, with or without 92 | modifications, and in Source or Object form, provided that You 93 | meet the following conditions: 94 | 95 | (a) You must give any other recipients of the Work or 96 | Derivative Works a copy of this License; and 97 | 98 | (b) You must cause any modified files to carry prominent notices 99 | stating that You changed the files; and 100 | 101 | (c) You must retain, in the Source form of any Derivative Works 102 | that You distribute, all copyright, patent, trademark, and 103 | attribution notices from the Source form of the Work, 104 | excluding those notices that do not pertain to any part of 105 | the Derivative Works; and 106 | 107 | (d) If the Work includes a "NOTICE" text file as part of its 108 | distribution, then any Derivative Works that You distribute must 109 | include a readable copy of the attribution notices contained 110 | within such NOTICE file, excluding those notices that do not 111 | pertain to any part of the Derivative Works, in at least one 112 | of the following places: within a NOTICE text file distributed 113 | as part of the Derivative Works; within the Source form or 114 | documentation, if provided along with the Derivative Works; or, 115 | within a display generated by the Derivative Works, if and 116 | wherever such third-party notices normally appear. The contents 117 | of the NOTICE file are for informational purposes only and 118 | do not modify the License. You may add Your own attribution 119 | notices within Derivative Works that You distribute, alongside 120 | or as an addendum to the NOTICE text from the Work, provided 121 | that such additional attribution notices cannot be construed 122 | as modifying the License. 123 | 124 | You may add Your own copyright statement to Your modifications and 125 | may provide additional or different license terms and conditions 126 | for use, reproduction, or distribution of Your modifications, or 127 | for any such Derivative Works as a whole, provided Your use, 128 | reproduction, and distribution of the Work otherwise complies with 129 | the conditions stated in this License. 130 | 131 | 5. Submission of Contributions. Unless You explicitly state otherwise, 132 | any Contribution intentionally submitted for inclusion in the Work 133 | by You to the Licensor shall be under the terms and conditions of 134 | this License, without any additional terms or conditions. 135 | Notwithstanding the above, nothing herein shall supersede or modify 136 | the terms of any separate license agreement you may have executed 137 | with Licensor regarding such Contributions. 138 | 139 | 6. Trademarks. This License does not grant permission to use the trade 140 | names, trademarks, service marks, or product names of the Licensor, 141 | except as required for reasonable and customary use in describing the 142 | origin of the Work and reproducing the content of the NOTICE file. 143 | 144 | 7. Disclaimer of Warranty. Unless required by applicable law or 145 | agreed to in writing, Licensor provides the Work (and each 146 | Contributor provides its Contributions) on an "AS IS" BASIS, 147 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 148 | implied, including, without limitation, any warranties or conditions 149 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 150 | PARTICULAR PURPOSE. You are solely responsible for determining the 151 | appropriateness of using or redistributing the Work and assume any 152 | risks associated with Your exercise of permissions under this License. 153 | 154 | 8. Limitation of Liability. In no event and under no legal theory, 155 | whether in tort (including negligence), contract, or otherwise, 156 | unless required by applicable law (such as deliberate and grossly 157 | negligent acts) or agreed to in writing, shall any Contributor be 158 | liable to You for damages, including any direct, indirect, special, 159 | incidental, or consequential damages of any character arising as a 160 | result of this License or out of the use or inability to use the 161 | Work (including but not limited to damages for loss of goodwill, 162 | work stoppage, computer failure or malfunction, or any and all 163 | other commercial damages or losses), even if such Contributor 164 | has been advised of the possibility of such damages. 165 | 166 | 9. Accepting Warranty or Additional Liability. While redistributing 167 | the Work or Derivative Works thereof, You may choose to offer, 168 | and charge a fee for, acceptance of support, warranty, indemnity, 169 | or other liability obligations and/or rights consistent with this 170 | License. However, in accepting such obligations, You may act only 171 | on Your own behalf and on Your sole responsibility, not on behalf 172 | of any other Contributor, and only if You agree to indemnify, 173 | defend, and hold each Contributor harmless for any liability 174 | incurred by, or claims asserted against, such Contributor by reason 175 | of your accepting any such warranty or additional liability. 176 | 177 | END OF TERMS AND CONDITIONS -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Spark JobServer Frontend 2 | ======================== 3 | 4 | This is a single page application that can be used to monitor and drive the [Spark JobServer](https://github.com/spark-jobserver/spark-jobserver). 5 | 6 | Usage 7 | ------ 8 | 9 | The application can be used both inside the JobServer itself, or standalone. In the first case, build the application and deploy it inside `spark-jobserver/main/resources/html`. If you want to use it from the outside, you will have to patch the JobServer routes to add [CORS](http://en.wikipedia.org/wiki/Cross-origin_resource_sharing) support. 10 | 11 | Build and development 12 | ---------------------- 13 | 14 | To build the application, you will need [node.js](http://nodejs.org/), [npm](https://www.npmjs.org/), [gulp](http://gulpjs.com/) and [browserify](http://browserify.org/). First, install the dependencies with 15 | 16 | npm install 17 | 18 | Then, you can have a development version with live reload with 19 | 20 | gulp watch 21 | 22 | When you are done, create a production ready version of the JS bundle inside the `dist` folder: 23 | 24 | gulp build 25 | 26 | If you want to serve the application directly from the JobServer, you will need to run the following task, that uses different paths: 27 | 28 | gulp build-jobserver 29 | 30 | License 31 | ------- 32 | 33 | [Apache 2](http://opensource.org/licenses/Apache-2.0) -------------------------------------------------------------------------------- /gulpfile.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var gulp = require('gulp'), 4 | changed = require('gulp-changed'), 5 | sass = require('gulp-sass'), 6 | csso = require('gulp-csso'), 7 | useref = require('gulp-useref'), 8 | autoprefixer = require('gulp-autoprefixer'), 9 | prefix = require('gulp-prefix'), 10 | browserify = require('browserify'), 11 | watchify = require('watchify'), 12 | source = require('vinyl-source-stream'), 13 | buffer = require('vinyl-buffer'), 14 | reactify = require('reactify'), 15 | coffeereactify = require('coffee-reactify'), 16 | uglify = require('gulp-uglify'), 17 | del = require('del'), 18 | notify = require('gulp-notify'), 19 | browserSync = require('browser-sync'), 20 | reload = browserSync.reload, 21 | p = { 22 | cjsx: './scripts/app.cjsx', 23 | sass: 'styles/main.sass', 24 | bundle: 'app.js', 25 | distJs: 'dist/js', 26 | distCss: 'dist/css' 27 | }; 28 | 29 | gulp.task('clean', function(cb) { 30 | del(['dist'], cb); 31 | }); 32 | 33 | gulp.task('browserSync', function() { 34 | browserSync({ 35 | server: { 36 | baseDir: ['./', 'dist/'] 37 | } 38 | }) 39 | }); 40 | 41 | gulp.task('watchify', function() { 42 | var bundler = watchify(browserify(p.cjsx, watchify.args)); 43 | 44 | function rebundle() { 45 | return bundler 46 | .bundle() 47 | .on('error', notify.onError()) 48 | .pipe(source(p.bundle)) 49 | .pipe(gulp.dest(p.distJs)) 50 | .pipe(reload({stream: true})); 51 | } 52 | 53 | bundler.transform(coffeereactify) 54 | .on('update', rebundle); 55 | return rebundle(); 56 | }); 57 | 58 | gulp.task('build-jobserver', ['build'], function () { 59 | return gulp.src('dist/index.html') 60 | .pipe(prefix('html/', null, true)) 61 | .pipe(gulp.dest('dist')); 62 | }); 63 | 64 | gulp.task('build', ['styles', 'browserify'], function () { 65 | var assets = useref.assets(); 66 | 67 | return gulp.src('index.html') 68 | .pipe(assets) 69 | .pipe(csso()) 70 | .pipe(assets.restore()) 71 | .pipe(useref()) 72 | .pipe(gulp.dest('dist')); 73 | }); 74 | 75 | gulp.task('browserify', ['clean'], function() { 76 | browserify(p.cjsx) 77 | .transform(coffeereactify) 78 | .bundle() 79 | .pipe(source(p.bundle)) 80 | .pipe(buffer()) 81 | .pipe(uglify()) 82 | .pipe(gulp.dest(p.distJs)); 83 | }); 84 | 85 | function buildStyles() { 86 | return gulp.src(p.sass) 87 | .pipe(changed(p.distCss)) 88 | .pipe(sass({errLogToConsole: true, sourceComments: 'normal'})) 89 | .on('error', notify.onError()) 90 | .pipe(autoprefixer('last 1 version')) 91 | .pipe(csso()) 92 | .pipe(gulp.dest(p.distCss)) 93 | .pipe(reload({stream: true})); 94 | } 95 | 96 | gulp.task('watchStyles', buildStyles); 97 | 98 | gulp.task('styles', ['clean'], buildStyles); 99 | 100 | gulp.task('watchTask', function() { 101 | gulp.watch(p.scss, ['styles']); 102 | }); 103 | 104 | gulp.task('watch', ['clean'], function() { 105 | gulp.start(['browserSync', 'watchTask', 'watchify', 'watchStyles']); 106 | }); 107 | 108 | gulp.task('default', function() { 109 | console.log('Run "gulp watch, gulp build or build-jobserver"'); 110 | }); 111 | -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Spark JobServer 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "jobserver-frontend", 3 | "version": "0.1.0", 4 | "description": "Frontend for Spark JobServer", 5 | "repository": "https://github.com/unicredit/spark-jobserver-frontend", 6 | "dependencies": { 7 | "bootstrap": "3.3.1", 8 | "moment": "2.8.4", 9 | "ramda": "0.8.0", 10 | "react": "0.12.0", 11 | "react-bootstrap": "0.13.0", 12 | "react-router": "0.11.4", 13 | "react-select": "0.2.7", 14 | "rest": "1.2.0", 15 | "signals": "1.0.0", 16 | "when": "3.6.3" 17 | }, 18 | "devDependencies": { 19 | "browser-sync": "^1.6.2", 20 | "browserify": "^6.2.0", 21 | "coffee-reactify": "^2.1.0", 22 | "del": "^0.1.3", 23 | "gulp": "^3.8.9", 24 | "gulp-autoprefixer": "1.0.1", 25 | "gulp-changed": "^1.0.0", 26 | "gulp-csso": "^0.2.9", 27 | "gulp-notify": "^2.0.0", 28 | "gulp-prefix": "^0.0.13", 29 | "gulp-sass": "^1.2.2", 30 | "gulp-uglify": "^1.0.1", 31 | "gulp-useref": "^1.0.2", 32 | "reactify": "^0.15.2", 33 | "vinyl-buffer": "^1.0.0", 34 | "vinyl-source-stream": "^1.0.0", 35 | "watchify": "^2.1.0" 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /scripts/app.cjsx: -------------------------------------------------------------------------------- 1 | # @cjsx React.DOM 2 | 3 | # Copyright 2014 UniCredit S.p.A. 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. 16 | 17 | React = require('react/addons') 18 | { Route, Redirect } = Router = require('react-router') 19 | 20 | Main = require('./components/Main.cjsx') 21 | Jobs = require('./components/Jobs.cjsx') 22 | JobResult = require('./components/JobResult.cjsx') 23 | JobSubmit = require('./components/JobSubmit.cjsx') 24 | Jars = require('./components/Jars.cjsx') 25 | Contexts = require('./components/Contexts.cjsx') 26 | 27 | 28 | window.onload = -> 29 | routes = 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | Router.run routes, (Handler) -> 40 | React.render(, document.body) -------------------------------------------------------------------------------- /scripts/components/Config.cjsx: -------------------------------------------------------------------------------- 1 | # @cjsx React.DOM 2 | 3 | # Copyright 2014 UniCredit S.p.A. 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. 16 | 17 | 18 | React = require('react/addons') 19 | 20 | api = require('../services/api.coffee') 21 | prettyPrint = require('../services/pretty-print.coffee') 22 | 23 | 24 | module.exports = React.createClass 25 | componentWillMount: -> 26 | api.jobConfig(@props.id).then (result) => @setState(config: result) 27 | 28 | getInitialState: -> 29 | config: null 30 | 31 | render: -> 32 | if not @state.config then return null 33 | 34 |


--------------------------------------------------------------------------------
/scripts/components/Context.cjsx:
--------------------------------------------------------------------------------
 1 | # @cjsx React.DOM
 2 | 
 3 | # Copyright 2014 UniCredit S.p.A.
 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.
16 | 
17 | React = require('react/addons')
18 | Button = require('react-bootstrap/Button')
19 | Modal = require('react-bootstrap/Modal')
20 | ModalTrigger = require('react-bootstrap/ModalTrigger')
21 | 
22 | api = require('../services/api.coffee')
23 | contextRemoved = require('../events/context-removed.coffee')
24 | 
25 | 
26 | ConfirmDelete = React.createClass
27 |   delete: ->
28 |     @props.onDelete()
29 |     @props.onRequestHide()
30 | 
31 |   render: ->
32 |     
33 |       
34 |

Are you sure to delete context { @props.name }?

35 |
36 |
37 | 38 | 39 |
40 |
41 | 42 | 43 | module.exports = React.createClass 44 | delete: -> 45 | api.deleteContext(@props.name).then (response) => 46 | contextRemoved.dispatch @props.name 47 | 48 | render: -> 49 | modal = 50 | 51 | 52 | { @props.name } 53 | 54 | 55 | 56 | 57 | 58 | -------------------------------------------------------------------------------- /scripts/components/Contexts.cjsx: -------------------------------------------------------------------------------- 1 | # @cjsx React.DOM 2 | 3 | # Copyright 2014 UniCredit S.p.A. 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. 16 | 17 | React = require('react/addons') 18 | Row = require('react-bootstrap/Row') 19 | 20 | api = require('../services/api.coffee') 21 | contextLoaded = require('../events/context-loaded.coffee') 22 | contextRemoved = require('../events/context-removed.coffee') 23 | Context = require('./Context.cjsx') 24 | CreateContext = require('./CreateContext.cjsx') 25 | 26 | 27 | module.exports = React.createClass 28 | componentWillMount: -> 29 | api.contexts().then (result) => @setState(contexts: result) 30 | contextLoaded.add @uploaded 31 | contextRemoved.add @removed 32 | 33 | componentWillUnmount: -> 34 | contextLoaded.remove @uploaded 35 | contextRemoved.remove @removed 36 | 37 | removed: (context) -> 38 | contexts = @state.contexts.filter (c) -> c != context 39 | @setState(contexts: contexts) 40 | 41 | uploaded: -> 42 | api.contexts().then (result) => @setState(contexts: result, success: true) 43 | 44 | getInitialState: -> 45 | contexts: [] 46 | success: false 47 | 48 | render: -> 49 | contextList = @state.contexts.map (context) => 50 | 51 |
52 | 53 |

Available contexts

54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | { contextList } 62 |
Name
63 |
64 | 65 |
-------------------------------------------------------------------------------- /scripts/components/CreateContext.cjsx: -------------------------------------------------------------------------------- 1 | # @cjsx React.DOM 2 | 3 | # Copyright 2014 UniCredit S.p.A. 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. 16 | 17 | React = require('react/addons') 18 | Row = require('react-bootstrap/Row') 19 | Col = require('react-bootstrap/Col') 20 | Alert = require('react-bootstrap/Alert') 21 | Input = require('react-bootstrap/Input') 22 | Select = require('react-select') 23 | 24 | api = require('../services/api.coffee') 25 | contextLoaded = require('../events/context-loaded.coffee') 26 | 27 | 28 | units = [ 29 | { value: 'K', label: 'Kb' } 30 | { value: 'M', label: 'Mb' } 31 | { value: 'G', label: 'Gb' } 32 | ] 33 | 34 | module.exports = React.createClass 35 | mixins: [React.addons.LinkedStateMixin] 36 | 37 | getInitialState: -> 38 | cpu: null 39 | memory: null 40 | memoryUnit: 'M' 41 | error: null 42 | 43 | isInteger: (text) -> parseInt(text).toString() == text 44 | 45 | validate: (ref) -> 46 | value = if @refs[ref] then @refs[ref].getValue() 47 | if value and not @isInteger(value) then 'error' 48 | 49 | changeUnit: (unit) -> @setState(memoryUnit: unit) 50 | 51 | submit: -> 52 | if @state.cpu and not @isInteger(@state.cpu) then return 53 | if @state.memory and not @isInteger(@state.memory) then return 54 | api.createContext(@state.contextName, @state.cpu, @state.memory, @state.memoryUnit).then @handleResponse 55 | 56 | handleResponse: (response) -> 57 | if response.status.code == 200 58 | contextLoaded.dispatch true 59 | @setState(error: null) 60 | else 61 | @setState(error: response.entity.result) 62 | 63 | render: -> 64 | error = if @state.error then { @state.error } 65 | success = if @props.success and not @state.error then 'Context successfully created' 66 | 67 |
68 |

New context

69 | { error } 70 | { success } 71 | 72 | 73 | 74 | 75 | 76 | 77 | 83 | 84 | 85 | 91 | 92 | 93 |
94 | 95 | 102 | 103 | 104 | -------------------------------------------------------------------------------- /scripts/components/Jar.cjsx: -------------------------------------------------------------------------------- 1 | # @cjsx React.DOM 2 | 3 | # Copyright 2014 UniCredit S.p.A. 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. 16 | 17 | React = require('react/addons') 18 | 19 | time = require('../services/time.coffee') 20 | 21 | 22 | module.exports = React.createClass 23 | render: -> 24 | [name, date] = @props.jar 25 | 26 | 27 | { name } 28 | { time.format(date) } 29 | -------------------------------------------------------------------------------- /scripts/components/JarLoad.cjsx: -------------------------------------------------------------------------------- 1 | # @cjsx React.DOM 2 | 3 | # Copyright 2014 UniCredit S.p.A. 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. 16 | 17 | React = require('react/addons') 18 | Row = require('react-bootstrap/Row') 19 | Col = require('react-bootstrap/Col') 20 | Alert = require('react-bootstrap/Alert') 21 | Input = require('react-bootstrap/Input') 22 | 23 | api = require('../services/api.coffee') 24 | jarLoaded = require('../events/jar-loaded.coffee') 25 | 26 | 27 | module.exports = React.createClass 28 | mixins: [React.addons.LinkedStateMixin] 29 | 30 | getInitialState: -> 31 | appName: '' 32 | file: null 33 | fileType: null 34 | error: null 35 | 36 | submit: (event) -> 37 | if not @state.appName 38 | @setError('No application name') 39 | return 40 | if not @state.file 41 | @setError('No file selected') 42 | return 43 | api.jarLoad(@state.appName, @state.file, @state.fileType).then @handleResponse 44 | 45 | setError: (text) -> @setState(error: text) 46 | 47 | handleFile: (event) -> 48 | file = event.target.files[0] 49 | type = file.type 50 | reader = new FileReader() 51 | reader.onload = (upload) => 52 | @setState(file: upload.target.result, fileType: type) 53 | reader.readAsBinaryString(file) 54 | 55 | handleResponse: (response) -> 56 | if response.status.code == 200 57 | jarLoaded.dispatch true 58 | @setError(null) 59 | else 60 | console.log response 61 | @setError(response.entity.result) 62 | 63 | render: -> 64 | error = if @state.error then { @state.error } 65 | success = if @props.success and not @state.error then 'Application successfully uploaded' 66 | 67 |
68 |

New application

69 | { error } 70 | { success } 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 |
-------------------------------------------------------------------------------- /scripts/components/Jars.cjsx: -------------------------------------------------------------------------------- 1 | # @cjsx React.DOM 2 | 3 | # Copyright 2014 UniCredit S.p.A. 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. 16 | 17 | React = require('react/addons') 18 | Row = require('react-bootstrap/Row') 19 | { compose, map, toPairs, sortBy, head } = require('ramda') 20 | 21 | api = require('../services/api.coffee') 22 | jarLoaded = require('../events/jar-loaded.coffee') 23 | Jar = require('./Jar.cjsx') 24 | JarLoad = require('./JarLoad.cjsx') 25 | 26 | 27 | module.exports = React.createClass 28 | componentWillMount: -> 29 | api.jars().then (result) => @setState(jars: result) 30 | jarLoaded.add @uploaded 31 | 32 | componentWillUnmount: -> 33 | jarLoaded.remove @uploaded 34 | 35 | uploaded: -> 36 | api.jars().then (result) => @setState(jars: result, success: true) 37 | 38 | getInitialState: -> 39 | jars: {} 40 | success: false 41 | 42 | render: -> 43 | jarList = compose( 44 | map((jar) -> ) 45 | sortBy(head) 46 | toPairs 47 | )(@state.jars) 48 | 49 |
50 | 51 |

Uploaded applications

52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | { jarList } 60 |
NameUploaded at
61 |
62 | 63 |
-------------------------------------------------------------------------------- /scripts/components/Job.cjsx: -------------------------------------------------------------------------------- 1 | # @cjsx React.DOM 2 | 3 | # Copyright 2014 UniCredit S.p.A. 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. 16 | 17 | React = require('react/addons') 18 | 19 | time = require('../services/time.coffee') 20 | clickJob = require('../events/click-job.coffee') 21 | 22 | 23 | module.exports = React.createClass 24 | click: -> 25 | clickJob.dispatch @props.job.jobId 26 | 27 | render: -> 28 | job = @props.job 29 | label = React.addons.classSet 30 | "label": true 31 | "clickable": true 32 | "label-default": job.status == "RUNNING" 33 | "label-success": job.status == "FINISHED" 34 | "label-danger": job.status == "ERROR" 35 | 36 | 37 | 38 | { job.classPath } 39 | { job.context } 40 | { time.formatSecsDuration(job.duration) } 41 | { time.format(job.startTime) } 42 | -------------------------------------------------------------------------------- /scripts/components/JobResult.cjsx: -------------------------------------------------------------------------------- 1 | # @cjsx React.DOM 2 | 3 | # Copyright 2014 UniCredit S.p.A. 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. 16 | 17 | React = require('react/addons') 18 | Router = require('react-router') 19 | Row = require('react-bootstrap/Row') 20 | Jumbotron = require('react-bootstrap/Jumbotron') 21 | 22 | Config = require('./Config.cjsx') 23 | api = require('../services/api.coffee') 24 | prettyPrint = require('../services/pretty-print.coffee') 25 | 26 | 27 | module.exports = React.createClass 28 | mixins: [ Router.State ] 29 | 30 | componentWillMount: -> 31 | api.jobResult(@getParams().id).then (result) => @setState(result) 32 | 33 | getInitialState: -> 34 | status: null 35 | result: null 36 | 37 | render: -> 38 | if @state.status == null then return null 39 | 40 | labelClass = React.addons.classSet 41 | "label": true 42 | "label-default": @state.status == "RUNNING" 43 | "label-success": @state.status == "OK" 44 | "label-danger": @state.status == "ERROR" 45 | 46 | 47 |

Job { @props.id }

48 |
49 |

50 |
51 |
52 |       

Configuration

53 | 54 | -------------------------------------------------------------------------------- /scripts/components/JobSubmit.cjsx: -------------------------------------------------------------------------------- 1 | # @cjsx React.DOM 2 | 3 | # Copyright 2014 UniCredit S.p.A. 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. 16 | 17 | React = require('react/addons') 18 | Router = require('react-router') 19 | Row = require('react-bootstrap/Row') 20 | Col = require('react-bootstrap/Col') 21 | Alert = require('react-bootstrap/Alert') 22 | Input = require('react-bootstrap/Input') 23 | Select = require('react-select') 24 | 25 | api = require('../services/api.coffee') 26 | 27 | makeOption = (param) -> 28 | value: param 29 | label: param 30 | 31 | module.exports = React.createClass 32 | mixins: [React.addons.LinkedStateMixin, Router.Navigation] 33 | 34 | componentWillMount: -> 35 | api.contexts().then (result) => 36 | @setState(contexts: result.map(makeOption)) 37 | api.jars().then (result) => @setState(applications: Object.keys(result).map(makeOption)) 38 | 39 | getInitialState: -> 40 | application: null 41 | context: null 42 | config: '' 43 | classPath: null 44 | error: null 45 | success: null 46 | applications: [] 47 | contexts: [] 48 | 49 | changeApplication: (app) -> @setState(application: app) 50 | 51 | changeContext: (context) -> @setState(context: context) 52 | 53 | backtoJobs: -> 54 | @transitionTo('jobs') 55 | 56 | submit: -> 57 | if not @state.classPath 58 | @setState(error: 'Missing classPath') 59 | return 60 | if not @state.application 61 | @setState(error: 'Missing application') 62 | return 63 | api.jobSubmit(@state.config, @state.application, @state.classPath, @state.context).then @handleResponse 64 | 65 | handleResponse: (response) -> 66 | if response.status.code == 202 67 | id = response.entity.result.jobId 68 | @setState(error: null, success: "Job successfully submitted with id #{ id }") 69 | setTimeout @backtoJobs, 3000 70 | else 71 | @setState(error: response.entity.result, success: null) 72 | 73 | render: -> 74 | error = if @state.error then { @state.error } 75 | success = if @state.success then { @state.success } 76 | 77 |
78 |

Submit job

79 | { error } 80 | { success } 81 | 82 | 83 | 84 | 87 | 88 | 89 |
90 | 91 | 99 | 100 | 101 |
102 | 103 | 110 | 111 | 112 | -------------------------------------------------------------------------------- /scripts/components/Jobs.cjsx: -------------------------------------------------------------------------------- 1 | # @cjsx React.DOM 2 | 3 | # Copyright 2014 UniCredit S.p.A. 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. 16 | 17 | React = require('react/addons') 18 | Row = require('react-bootstrap/Row') 19 | ramda = require('ramda') 20 | 21 | api = require('../services/api.coffee') 22 | Job = require('./Job.cjsx') 23 | 24 | 25 | module.exports = React.createClass 26 | componentWillMount: -> 27 | api.jobs().then (result) => @setState(jobs: result) 28 | 29 | getInitialState: -> 30 | jobs: [] 31 | 32 | render: -> 33 | jobList = ramda.reverse(@state.jobs).map (job) -> 34 | 35 | 36 |

Latest jobs

37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | { jobList } 48 |
IdJob NameContextDurationStarted at
49 |
-------------------------------------------------------------------------------- /scripts/components/Main.cjsx: -------------------------------------------------------------------------------- 1 | # @cjsx React.DOM 2 | 3 | # Copyright 2014 UniCredit S.p.A. 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. 16 | 17 | React = require('react/addons') 18 | { Link, RouteHandler, Navigation } = require('react-router') 19 | Nav = require('react-bootstrap/Nav') 20 | NavItem = require('react-bootstrap/NavItem') 21 | 22 | clickJob = require('../events/click-job.coffee') 23 | 24 | 25 | module.exports = React.createClass 26 | mixins: [Navigation] 27 | 28 | componentWillMount: -> 29 | clickJob.add (id) => 30 | @transitionTo('job', id: id) 31 | 32 | render: -> 33 |
34 | 48 | 49 |
-------------------------------------------------------------------------------- /scripts/events/click-job.coffee: -------------------------------------------------------------------------------- 1 | # Copyright 2014 UniCredit S.p.A. 2 | 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | signals = require('signals') 16 | 17 | module.exports = new signals.Signal() -------------------------------------------------------------------------------- /scripts/events/context-loaded.coffee: -------------------------------------------------------------------------------- 1 | # Copyright 2014 UniCredit S.p.A. 2 | 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | signals = require('signals') 16 | 17 | module.exports = new signals.Signal() -------------------------------------------------------------------------------- /scripts/events/context-removed.coffee: -------------------------------------------------------------------------------- 1 | # Copyright 2014 UniCredit S.p.A. 2 | 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | signals = require('signals') 16 | 17 | module.exports = new signals.Signal() -------------------------------------------------------------------------------- /scripts/events/jar-loaded.coffee: -------------------------------------------------------------------------------- 1 | # Copyright 2014 UniCredit S.p.A. 2 | 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | signals = require('signals') 16 | 17 | module.exports = new signals.Signal() -------------------------------------------------------------------------------- /scripts/services/api.coffee: -------------------------------------------------------------------------------- 1 | # Copyright 2014 UniCredit S.p.A. 2 | 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | rest = require('rest') 16 | mime = require('rest/interceptor/mime') 17 | errorCode = require('rest/interceptor/errorCode') 18 | interceptor = require('rest/interceptor') 19 | binarySend = require('./binary-send.coffee') 20 | 21 | identity = (x) -> x 22 | 23 | # needed because the server response is not valid JSON 24 | # but still uses the application/json content type 25 | fixJson = interceptor 26 | init: identity 27 | request: identity 28 | response: identity 29 | success: identity 30 | error: (resp, config, meta) -> 31 | if resp.status.code == 200 then { entity: resp.entity, status: resp.status } 32 | 33 | client = rest.wrap(mime).wrap(fixJson).wrap(errorCode, code: 500) 34 | baseUrl = '' 35 | 36 | module.exports = 37 | jobs: -> 38 | client(path: "#{ baseUrl }/jobs").then (response) -> response.entity 39 | 40 | jobResult: (id) -> 41 | client(path: "#{ baseUrl }/jobs/#{ id }").then (response) -> response.entity 42 | 43 | jobConfig: (id) -> 44 | client(path: "#{ baseUrl }/jobs/#{ id }/config").then (response) -> response.entity 45 | 46 | jobSubmit: (config, appName, classPath, context) -> 47 | params = 48 | appName: appName 49 | classPath: classPath 50 | if context then params.context = context 51 | client(path: "#{ baseUrl }/jobs", entity: config, params: params) 52 | 53 | jars: -> 54 | client(path: "#{ baseUrl }/jars").then (response) -> response.entity 55 | 56 | jarLoad: (appName, jar, type) -> 57 | binarySend("#{ baseUrl }/jars/#{ appName }", jar, type) 58 | 59 | contexts: -> 60 | client(path: "#{ baseUrl }/contexts").then (response) -> response.entity 61 | 62 | createContext: (name, cpu, memory, unit) -> 63 | unitShort = unit[0].toUpperCase() 64 | params = {} 65 | if cpu then params['num-cpu-cores'] = cpu 66 | if memory then params['memory-per-node'] = "#{ memory }#{ unitShort }" 67 | client(path: "#{ baseUrl }/contexts/#{ name }", method: 'POST', params: params) 68 | 69 | deleteContext: (name) -> 70 | client(path: "#{ baseUrl }/contexts/#{ name }", method: 'DELETE') 71 | -------------------------------------------------------------------------------- /scripts/services/binary-send.coffee: -------------------------------------------------------------------------------- 1 | When = require('when') 2 | 3 | byteValue = (x) -> x.charCodeAt(0) & 0xff 4 | 5 | sendAsBinaryDefault = (data) -> 6 | ords = Array.prototype.map.call(data, byteValue) 7 | ui8a = new Uint8Array(ords) 8 | this.send(ui8a.buffer) 9 | 10 | XMLHttpRequest.prototype.sendAsBinary ?= sendAsBinaryDefault 11 | 12 | 13 | module.exports = (url, data, type) -> 14 | deferred = When.defer() 15 | xhr = new XMLHttpRequest() 16 | xhr.open('POST', url) 17 | xhr.overrideMimeType(type) 18 | xhr.setRequestHeader("Content-Type", type) 19 | xhr.onloadend = -> 20 | entity = try 21 | JSON.parse(xhr.responseText) 22 | catch e 23 | xhr.responseText 24 | 25 | deferred.resolve 26 | status: 27 | code: xhr.status 28 | text: xhr.statusText 29 | entity: entity 30 | xhr.sendAsBinary(data) 31 | deferred.promise -------------------------------------------------------------------------------- /scripts/services/pretty-print.coffee: -------------------------------------------------------------------------------- 1 | # Copyright 2014 UniCredit S.p.A. 2 | 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | # from http://jsfiddle.net/unLSJ/ 16 | 17 | replacer = (match, pIndent, pKey, pVal, pEnd) -> 18 | key = '' 19 | val = '' 20 | str = '' 21 | r = pIndent || '' 22 | if (pKey) 23 | r = r + key + pKey.replace(/[": ]/g, '') + ': ' 24 | if (pVal) 25 | r = r + (if pVal[0] == '"' then str else val) + pVal + '' 26 | r + (pEnd || '') 27 | 28 | jsonLine = /^( *)("[\w]+": )?("[^"]*"|[\w.+-]*)?([,[{])?$/mg 29 | 30 | module.exports = 31 | json: (obj) -> 32 | JSON.stringify(obj, null, 3) 33 | .replace(/&/g, '&') 34 | .replace(/\\"/g, '"') 35 | .replace(//g, '>') 37 | .replace(jsonLine, replacer) -------------------------------------------------------------------------------- /scripts/services/time.coffee: -------------------------------------------------------------------------------- 1 | # Copyright 2014 UniCredit S.p.A. 2 | 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | moment = require('moment') 16 | 17 | secondsRegex = /(\d+\.\d*) secs/ 18 | 19 | module.exports = 20 | formatSecsDuration: (secs) -> 21 | try 22 | duration = moment.duration(parseFloat(secondsRegex.exec(secs)[1]), 'seconds') 23 | minutes = Math.floor(duration.asMinutes()) 24 | if minutes 25 | "#{ minutes } m #{ duration.seconds() } s" 26 | else 27 | "#{ duration.asSeconds().toFixed(1) } s" 28 | catch e 29 | secs 30 | 31 | format: (date) -> 32 | moment(date).format("D MMM H:mm:ss") -------------------------------------------------------------------------------- /styles/_colors.sass: -------------------------------------------------------------------------------- 1 | // Copyright 2014 UniCredit S.p.A. 2 | 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | $primary: #428BCA 16 | $background: #EEEEEE 17 | $text: #333333 -------------------------------------------------------------------------------- /styles/main.sass: -------------------------------------------------------------------------------- 1 | // Copyright 2014 UniCredit S.p.A. 2 | 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | @import _colors 16 | 17 | .clickable 18 | cursor: pointer 19 | 20 | nav 21 | margin-bottom: 20px 22 | 23 | .active 24 | background-color: $background 25 | 26 | pre 27 | background-color: ghostwhite 28 | border: 1px solid silver 29 | padding: 10px 20px 30 | margin: 20px 31 | 32 | .json-key 33 | color: brown 34 | 35 | .json-value 36 | color: navy 37 | 38 | .json-string 39 | color: olive 40 | 41 | .jar-form .alert, .context-form .alert 42 | margin: 20px 0 43 | 44 | .Select 45 | margin-top: -2px 46 | 47 | textarea 48 | resize: vertical 49 | 50 | .modal-backdrop 51 | min-height: 100% --------------------------------------------------------------------------------