You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@airavata.apache.org by ma...@apache.org on 2017/09/21 17:00:03 UTC
[33/54] [abbrv] [partial] airavata-django-portal git commit: Moving
admin_view JS into django app and moving django project back
http://git-wip-us.apache.org/repos/asf/airavata-django-portal/blob/d8d7c37a/django_airavata/apps/admin/package.json
----------------------------------------------------------------------
diff --git a/django_airavata/apps/admin/package.json b/django_airavata/apps/admin/package.json
new file mode 100644
index 0000000..f344bf9
--- /dev/null
+++ b/django_airavata/apps/admin/package.json
@@ -0,0 +1,63 @@
+{
+ "name": "admin-airavata",
+ "version": "1.0.0",
+ "description": "A Vue.js project",
+ "author": "Eldho Mathulla <em...@iu.edu>",
+ "private": true,
+ "scripts": {
+ "dev": "node build/dev-server.js",
+ "start": "node build/dev-server.js",
+ "build": "node build/build.js"
+ },
+ "dependencies": {
+ "vue": "^2.3.3",
+ "vue-resource": "^1.3.4",
+ "vue-router": "^2.7.0",
+ "vuex": "^2.4.0"
+ },
+ "devDependencies": {
+ "autoprefixer": "^7.1.3",
+ "babel-core": "^6.22.1",
+ "babel-loader": "^7.1.1",
+ "babel-plugin-transform-runtime": "^6.22.0",
+ "babel-preset-env": "^1.3.2",
+ "babel-preset-stage-2": "^6.22.0",
+ "babel-register": "^6.22.0",
+ "chalk": "^2.0.1",
+ "connect-history-api-fallback": "^1.3.0",
+ "copy-webpack-plugin": "^4.0.1",
+ "css-loader": "^0.28.0",
+ "cssnano": "^3.10.0",
+ "eventsource-polyfill": "^0.9.6",
+ "express": "^4.14.1",
+ "extract-text-webpack-plugin": "^2.0.0",
+ "file-loader": "^0.11.1",
+ "friendly-errors-webpack-plugin": "^1.1.3",
+ "html-webpack-plugin": "^2.28.0",
+ "http-proxy-middleware": "^0.17.3",
+ "opn": "^5.1.0",
+ "optimize-css-assets-webpack-plugin": "^2.0.0",
+ "ora": "^1.2.0",
+ "rimraf": "^2.6.0",
+ "semver": "^5.3.0",
+ "shelljs": "^0.7.6",
+ "url-loader": "^0.5.8",
+ "vue-loader": "^12.1.0",
+ "vue-style-loader": "^3.0.1",
+ "vue-template-compiler": "^2.3.3",
+ "webpack": "^2.6.1",
+ "webpack-bundle-analyzer": "^2.2.1",
+ "webpack-dev-middleware": "^1.10.0",
+ "webpack-hot-middleware": "^2.18.0",
+ "webpack-merge": "^4.1.0"
+ },
+ "engines": {
+ "node": ">= 4.0.0",
+ "npm": ">= 3.0.0"
+ },
+ "browserslist": [
+ "> 1%",
+ "last 2 versions",
+ "not ie <= 8"
+ ]
+}
http://git-wip-us.apache.org/repos/asf/airavata-django-portal/blob/d8d7c37a/django_airavata/apps/admin/static/django_airavata_admin/build/build.js
----------------------------------------------------------------------
diff --git a/django_airavata/apps/admin/static/django_airavata_admin/build/build.js b/django_airavata/apps/admin/static/django_airavata_admin/build/build.js
new file mode 100644
index 0000000..6b8add1
--- /dev/null
+++ b/django_airavata/apps/admin/static/django_airavata_admin/build/build.js
@@ -0,0 +1,35 @@
+require('./check-versions')()
+
+process.env.NODE_ENV = 'production'
+
+var ora = require('ora')
+var rm = require('rimraf')
+var path = require('path')
+var chalk = require('chalk')
+var webpack = require('webpack')
+var config = require('../config')
+var webpackConfig = require('./webpack.prod.conf')
+
+var spinner = ora('building for production...')
+spinner.start()
+
+rm(path.join(config.build.assetsRoot, config.build.assetsSubDirectory), err => {
+ if (err) throw err
+ webpack(webpackConfig, function (err, stats) {
+ spinner.stop()
+ if (err) throw err
+ process.stdout.write(stats.toString({
+ colors: true,
+ modules: false,
+ children: false,
+ chunks: false,
+ chunkModules: false
+ }) + '\n\n')
+
+ console.log(chalk.cyan(' Build complete.\n'))
+ console.log(chalk.yellow(
+ ' Tip: built files are meant to be served over an HTTP server.\n' +
+ ' Opening index.html over file:// won\'t work.\n'
+ ))
+ })
+})
http://git-wip-us.apache.org/repos/asf/airavata-django-portal/blob/d8d7c37a/django_airavata/apps/admin/static/django_airavata_admin/build/check-versions.js
----------------------------------------------------------------------
diff --git a/django_airavata/apps/admin/static/django_airavata_admin/build/check-versions.js b/django_airavata/apps/admin/static/django_airavata_admin/build/check-versions.js
new file mode 100644
index 0000000..100f3a0
--- /dev/null
+++ b/django_airavata/apps/admin/static/django_airavata_admin/build/check-versions.js
@@ -0,0 +1,48 @@
+var chalk = require('chalk')
+var semver = require('semver')
+var packageConfig = require('../package.json')
+var shell = require('shelljs')
+function exec (cmd) {
+ return require('child_process').execSync(cmd).toString().trim()
+}
+
+var versionRequirements = [
+ {
+ name: 'node',
+ currentVersion: semver.clean(process.version),
+ versionRequirement: packageConfig.engines.node
+ },
+]
+
+if (shell.which('npm')) {
+ versionRequirements.push({
+ name: 'npm',
+ currentVersion: exec('npm --version'),
+ versionRequirement: packageConfig.engines.npm
+ })
+}
+
+module.exports = function () {
+ var warnings = []
+ for (var i = 0; i < versionRequirements.length; i++) {
+ var mod = versionRequirements[i]
+ if (!semver.satisfies(mod.currentVersion, mod.versionRequirement)) {
+ warnings.push(mod.name + ': ' +
+ chalk.red(mod.currentVersion) + ' should be ' +
+ chalk.green(mod.versionRequirement)
+ )
+ }
+ }
+
+ if (warnings.length) {
+ console.log('')
+ console.log(chalk.yellow('To use this template, you must update following to modules:'))
+ console.log()
+ for (var i = 0; i < warnings.length; i++) {
+ var warning = warnings[i]
+ console.log(' ' + warning)
+ }
+ console.log()
+ process.exit(1)
+ }
+}
http://git-wip-us.apache.org/repos/asf/airavata-django-portal/blob/d8d7c37a/django_airavata/apps/admin/static/django_airavata_admin/build/dev-client.js
----------------------------------------------------------------------
diff --git a/django_airavata/apps/admin/static/django_airavata_admin/build/dev-client.js b/django_airavata/apps/admin/static/django_airavata_admin/build/dev-client.js
new file mode 100644
index 0000000..18aa1e2
--- /dev/null
+++ b/django_airavata/apps/admin/static/django_airavata_admin/build/dev-client.js
@@ -0,0 +1,9 @@
+/* eslint-disable */
+require('eventsource-polyfill')
+var hotClient = require('webpack-hot-middleware/client?noInfo=true&reload=true')
+
+hotClient.subscribe(function (event) {
+ if (event.action === 'reload') {
+ window.location.reload()
+ }
+})
http://git-wip-us.apache.org/repos/asf/airavata-django-portal/blob/d8d7c37a/django_airavata/apps/admin/static/django_airavata_admin/build/dev-server.js
----------------------------------------------------------------------
diff --git a/django_airavata/apps/admin/static/django_airavata_admin/build/dev-server.js b/django_airavata/apps/admin/static/django_airavata_admin/build/dev-server.js
new file mode 100644
index 0000000..28b135c
--- /dev/null
+++ b/django_airavata/apps/admin/static/django_airavata_admin/build/dev-server.js
@@ -0,0 +1,90 @@
+require('./check-versions')()
+
+var config = require('../config')
+if (!process.env.NODE_ENV) {
+ process.env.NODE_ENV = JSON.parse(config.dev.env.NODE_ENV)
+}
+
+var opn = require('opn')
+var path = require('path')
+var express = require('express')
+var webpack = require('webpack')
+var proxyMiddleware = require('http-proxy-middleware')
+var webpackConfig = require('./webpack.dev.conf')
+
+// default port where dev server listens for incoming traffic
+var port = process.env.PORT || config.dev.port
+// automatically open browser, if not set will be false
+var autoOpenBrowser = !!config.dev.autoOpenBrowser
+// Define HTTP proxies to your custom API backend
+// https://github.com/chimurai/http-proxy-middleware
+var proxyTable = config.dev.proxyTable
+
+var app = express()
+var compiler = webpack(webpackConfig)
+
+var devMiddleware = require('webpack-dev-middleware')(compiler, {
+ publicPath: webpackConfig.output.publicPath,
+ quiet: true
+})
+
+var hotMiddleware = require('webpack-hot-middleware')(compiler, {
+ log: false,
+ heartbeat: 2000
+})
+// force page reload when html-webpack-plugin template changes
+compiler.plugin('compilation', function (compilation) {
+ compilation.plugin('html-webpack-plugin-after-emit', function (data, cb) {
+ hotMiddleware.publish({ action: 'reload' })
+ cb()
+ })
+})
+
+// proxy api requests
+Object.keys(proxyTable).forEach(function (context) {
+ var options = proxyTable[context]
+ if (typeof options === 'string') {
+ options = { target: options }
+ }
+ app.use(proxyMiddleware(options.filter || context, options))
+})
+
+// handle fallback for HTML5 history API
+app.use(require('connect-history-api-fallback')())
+
+// serve webpack bundle output
+app.use(devMiddleware)
+
+// enable hot-reload and state-preserving
+// compilation error display
+app.use(hotMiddleware)
+
+// serve pure static assets
+var staticPath = path.posix.join(config.dev.assetsPublicPath, config.dev.assetsSubDirectory)
+app.use(staticPath, express.static('./static'))
+
+var uri = 'http://localhost:' + port
+
+var _resolve
+var readyPromise = new Promise(resolve => {
+ _resolve = resolve
+})
+
+console.log('> Starting dev server...')
+devMiddleware.waitUntilValid(() => {
+ console.log('> Listening at ' + uri + '\n')
+ // when env is testing, don't need open it
+ if (autoOpenBrowser && process.env.NODE_ENV !== 'testing') {
+ opn(uri)
+ }
+ _resolve()
+})
+
+var server = app.listen(port)
+
+module.exports = {
+ ready: readyPromise,
+ close: () => {
+ server.close()
+ }
+}
http://git-wip-us.apache.org/repos/asf/airavata-django-portal/blob/d8d7c37a/django_airavata/apps/admin/static/django_airavata_admin/build/utils.js
----------------------------------------------------------------------
diff --git a/django_airavata/apps/admin/static/django_airavata_admin/build/utils.js b/django_airavata/apps/admin/static/django_airavata_admin/build/utils.js
new file mode 100644
index 0000000..b1d54b4
--- /dev/null
+++ b/django_airavata/apps/admin/static/django_airavata_admin/build/utils.js
@@ -0,0 +1,71 @@
+var path = require('path')
+var config = require('../config')
+var ExtractTextPlugin = require('extract-text-webpack-plugin')
+
+exports.assetsPath = function (_path) {
+ var assetsSubDirectory = process.env.NODE_ENV === 'production'
+ ? config.build.assetsSubDirectory
+ : config.dev.assetsSubDirectory
+ return path.posix.join(assetsSubDirectory, _path)
+}
+
+exports.cssLoaders = function (options) {
+ options = options || {}
+
+ var cssLoader = {
+ loader: 'css-loader',
+ options: {
+ minimize: process.env.NODE_ENV === 'production',
+ sourceMap: options.sourceMap
+ }
+ }
+
+ // generate loader string to be used with extract text plugin
+ function generateLoaders (loader, loaderOptions) {
+ var loaders = [cssLoader]
+ if (loader) {
+ loaders.push({
+ loader: loader + '-loader',
+ options: Object.assign({}, loaderOptions, {
+ sourceMap: options.sourceMap
+ })
+ })
+ }
+
+ // Extract CSS when that option is specified
+ // (which is the case during production build)
+ if (options.extract) {
+ return ExtractTextPlugin.extract({
+ use: loaders,
+ fallback: 'vue-style-loader'
+ })
+ } else {
+ return ['vue-style-loader'].concat(loaders)
+ }
+ }
+
+ // https://vue-loader.vuejs.org/en/configurations/extract-css.html
+ return {
+ css: generateLoaders(),
+ postcss: generateLoaders(),
+ less: generateLoaders('less'),
+ sass: generateLoaders('sass', { indentedSyntax: true }),
+ scss: generateLoaders('sass'),
+ stylus: generateLoaders('stylus'),
+ styl: generateLoaders('stylus')
+ }
+}
+
+// Generate loaders for standalone style files (outside of .vue)
+exports.styleLoaders = function (options) {
+ var output = []
+ var loaders = exports.cssLoaders(options)
+ for (var extension in loaders) {
+ var loader = loaders[extension]
+ output.push({
+ test: new RegExp('\\.' + extension + '$'),
+ use: loader
+ })
+ }
+ return output
+}
http://git-wip-us.apache.org/repos/asf/airavata-django-portal/blob/d8d7c37a/django_airavata/apps/admin/static/django_airavata_admin/build/vue-loader.conf.js
----------------------------------------------------------------------
diff --git a/django_airavata/apps/admin/static/django_airavata_admin/build/vue-loader.conf.js b/django_airavata/apps/admin/static/django_airavata_admin/build/vue-loader.conf.js
new file mode 100644
index 0000000..8a346d5
--- /dev/null
+++ b/django_airavata/apps/admin/static/django_airavata_admin/build/vue-loader.conf.js
@@ -0,0 +1,18 @@
+var utils = require('./utils')
+var config = require('../config')
+var isProduction = process.env.NODE_ENV === 'production'
+
+module.exports = {
+ loaders: utils.cssLoaders({
+ sourceMap: isProduction
+ ? config.build.productionSourceMap
+ : config.dev.cssSourceMap,
+ extract: isProduction
+ }),
+ transformToRequire: {
+ video: 'src',
+ source: 'src',
+ img: 'src',
+ image: 'xlink:href'
+ }
+}
http://git-wip-us.apache.org/repos/asf/airavata-django-portal/blob/d8d7c37a/django_airavata/apps/admin/static/django_airavata_admin/build/webpack.base.conf.js
----------------------------------------------------------------------
diff --git a/django_airavata/apps/admin/static/django_airavata_admin/build/webpack.base.conf.js b/django_airavata/apps/admin/static/django_airavata_admin/build/webpack.base.conf.js
new file mode 100644
index 0000000..b3401f0
--- /dev/null
+++ b/django_airavata/apps/admin/static/django_airavata_admin/build/webpack.base.conf.js
@@ -0,0 +1,68 @@
+var path = require('path')
+var utils = require('./utils')
+var config = require('../config')
+var vueLoaderConfig = require('./vue-loader.conf')
+
+function resolve (dir) {
+ return path.join(__dirname, '..', dir)
+}
+
+module.exports = {
+ entry: {
+ app: './src/main.js'
+ },
+ output: {
+ path: config.build.assetsRoot,
+ filename: '[name].js',
+ publicPath: process.env.NODE_ENV === 'production'
+ ? config.build.assetsPublicPath
+ : config.dev.assetsPublicPath,
+ libraryTarget: 'var',
+ library: 'AiravataApp'
+ },
+ resolve: {
+ extensions: ['.js', '.vue', '.json'],
+ alias: {
+ 'vue$': 'vue/dist/vue.esm.js',
+ '@': resolve('src')
+ }
+ },
+ module: {
+ rules: [
+ {
+ test: /\.vue$/,
+ loader: 'vue-loader',
+ options: vueLoaderConfig
+ },
+ {
+ test: /\.js$/,
+ loader: 'babel-loader',
+ include: [resolve('src'), resolve('test')]
+ },
+ {
+ test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,
+ loader: 'url-loader',
+ options: {
+ limit: 10000,
+ name: utils.assetsPath('img/[name].[hash:7].[ext]')
+ }
+ },
+ {
+ test: /\.(mp4|webm|ogg|mp3|wav|flac|aac)(\?.*)?$/,
+ loader: 'url-loader',
+ options: {
+ limit: 10000,
+ name: utils.assetsPath('media/[name].[hash:7].[ext]')
+ }
+ },
+ {
+ test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/,
+ loader: 'url-loader',
+ options: {
+ limit: 10000,
+ name: utils.assetsPath('fonts/[name].[hash:7].[ext]')
+ }
+ }
+ ]
+ }
+}
http://git-wip-us.apache.org/repos/asf/airavata-django-portal/blob/d8d7c37a/django_airavata/apps/admin/static/django_airavata_admin/build/webpack.dev.conf.js
----------------------------------------------------------------------
diff --git a/django_airavata/apps/admin/static/django_airavata_admin/build/webpack.dev.conf.js b/django_airavata/apps/admin/static/django_airavata_admin/build/webpack.dev.conf.js
new file mode 100644
index 0000000..5470402
--- /dev/null
+++ b/django_airavata/apps/admin/static/django_airavata_admin/build/webpack.dev.conf.js
@@ -0,0 +1,35 @@
+var utils = require('./utils')
+var webpack = require('webpack')
+var config = require('../config')
+var merge = require('webpack-merge')
+var baseWebpackConfig = require('./webpack.base.conf')
+var HtmlWebpackPlugin = require('html-webpack-plugin')
+var FriendlyErrorsPlugin = require('friendly-errors-webpack-plugin')
+
+// add hot-reload related code to entry chunks
+Object.keys(baseWebpackConfig.entry).forEach(function (name) {
+ baseWebpackConfig.entry[name] = ['./build/dev-client'].concat(baseWebpackConfig.entry[name])
+})
+
+module.exports = merge(baseWebpackConfig, {
+ module: {
+ rules: utils.styleLoaders({ sourceMap: config.dev.cssSourceMap })
+ },
+ // cheap-module-eval-source-map is faster for development
+ devtool: '#cheap-module-eval-source-map',
+ plugins: [
+ new webpack.DefinePlugin({
+ 'process.env': config.dev.env
+ }),
+ // https://github.com/glenjamin/webpack-hot-middleware#installation--usage
+ new webpack.HotModuleReplacementPlugin(),
+ new webpack.NoEmitOnErrorsPlugin(),
+ // https://github.com/ampedandwired/html-webpack-plugin
+ new HtmlWebpackPlugin({
+ filename: 'index.html',
+ template: 'index.html',
+ inject: true
+ }),
+ new FriendlyErrorsPlugin()
+ ]
+})
http://git-wip-us.apache.org/repos/asf/airavata-django-portal/blob/d8d7c37a/django_airavata/apps/admin/static/django_airavata_admin/build/webpack.prod.conf.js
----------------------------------------------------------------------
diff --git a/django_airavata/apps/admin/static/django_airavata_admin/build/webpack.prod.conf.js b/django_airavata/apps/admin/static/django_airavata_admin/build/webpack.prod.conf.js
new file mode 100644
index 0000000..177b7fe
--- /dev/null
+++ b/django_airavata/apps/admin/static/django_airavata_admin/build/webpack.prod.conf.js
@@ -0,0 +1,120 @@
+var path = require('path')
+var utils = require('./utils')
+var webpack = require('webpack')
+var config = require('../config')
+var merge = require('webpack-merge')
+var baseWebpackConfig = require('./webpack.base.conf')
+var CopyWebpackPlugin = require('copy-webpack-plugin')
+var HtmlWebpackPlugin = require('html-webpack-plugin')
+var ExtractTextPlugin = require('extract-text-webpack-plugin')
+var OptimizeCSSPlugin = require('optimize-css-assets-webpack-plugin')
+
+var env = config.build.env
+
+var webpackConfig = merge(baseWebpackConfig, {
+ module: {
+ rules: utils.styleLoaders({
+ sourceMap: config.build.productionSourceMap,
+ extract: true
+ })
+ },
+ devtool: config.build.productionSourceMap ? '#source-map' : false,
+ output: {
+ path: config.build.assetsRoot,
+ filename: utils.assetsPath('js/[name].js'),
+ chunkFilename: utils.assetsPath('js/[id].[chunkhash].js')
+ },
+ plugins: [
+ // http://vuejs.github.io/vue-loader/en/workflow/production.html
+ new webpack.DefinePlugin({
+ 'process.env': env
+ }),
+ new webpack.optimize.UglifyJsPlugin({
+ compress: {
+ warnings: false
+ },
+ sourceMap: true
+ }),
+ // extract css into its own file
+ new ExtractTextPlugin({
+ filename: utils.assetsPath('css/[name].css')
+ }),
+ // Compress extracted CSS. We are using this plugin so that possible
+ // duplicated CSS from different components can be deduped.
+ new OptimizeCSSPlugin({
+ cssProcessorOptions: {
+ safe: true
+ }
+ }),
+ // generate dist index.html with correct asset hash for caching.
+ // you can customize output by editing /index.html
+ // see https://github.com/ampedandwired/html-webpack-plugin
+ new HtmlWebpackPlugin({
+ filename: config.build.index,
+ template: 'index.html',
+ inject: true,
+ minify: {
+ removeComments: true,
+ collapseWhitespace: true,
+ removeAttributeQuotes: true
+ // more options:
+ // https://github.com/kangax/html-minifier#options-quick-reference
+ },
+ // necessary to consistently work with multiple chunks via CommonsChunkPlugin
+ chunksSortMode: 'dependency'
+ }),
+ // split vendor js into its own file
+ new webpack.optimize.CommonsChunkPlugin({
+ name: 'vendor',
+ minChunks: function (module, count) {
+ // any required modules inside node_modules are extracted to vendor
+ return (
+ module.resource &&
+ /\.js$/.test(module.resource) &&
+ module.resource.indexOf(
+ path.join(__dirname, '../node_modules')
+ ) === 0
+ )
+ }
+ }),
+ // extract webpack runtime and module manifest to its own file in order to
+ // prevent vendor hash from being updated whenever app bundle is updated
+ new webpack.optimize.CommonsChunkPlugin({
+ name: 'manifest',
+ chunks: ['vendor']
+ }),
+ // copy custom static assets
+ new CopyWebpackPlugin([
+ {
+ from: path.resolve(__dirname, '../static'),
+ to: config.build.assetsSubDirectory,
+ ignore: ['.*']
+ }
+ ])
+ ]
+})
+
+if (config.build.productionGzip) {
+ var CompressionWebpackPlugin = require('compression-webpack-plugin')
+
+ webpackConfig.plugins.push(
+ new CompressionWebpackPlugin({
+ asset: '[path].gz[query]',
+ algorithm: 'gzip',
+ test: new RegExp(
+ '\\.(' +
+ config.build.productionGzipExtensions.join('|') +
+ ')$'
+ ),
+ threshold: 10240,
+ minRatio: 0.8
+ })
+ )
+}
+
+if (config.build.bundleAnalyzerReport) {
+ var BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin
+ webpackConfig.plugins.push(new BundleAnalyzerPlugin())
+}
+
+module.exports = webpackConfig
http://git-wip-us.apache.org/repos/asf/airavata-django-portal/blob/d8d7c37a/django_airavata/apps/admin/static/django_airavata_admin/config/dev.env.js
----------------------------------------------------------------------
diff --git a/django_airavata/apps/admin/static/django_airavata_admin/config/dev.env.js b/django_airavata/apps/admin/static/django_airavata_admin/config/dev.env.js
new file mode 100644
index 0000000..efead7c
--- /dev/null
+++ b/django_airavata/apps/admin/static/django_airavata_admin/config/dev.env.js
@@ -0,0 +1,6 @@
+var merge = require('webpack-merge')
+var prodEnv = require('./prod.env')
+
+module.exports = merge(prodEnv, {
+ NODE_ENV: '"development"'
+})
http://git-wip-us.apache.org/repos/asf/airavata-django-portal/blob/d8d7c37a/django_airavata/apps/admin/static/django_airavata_admin/config/index.js
----------------------------------------------------------------------
diff --git a/django_airavata/apps/admin/static/django_airavata_admin/config/index.js b/django_airavata/apps/admin/static/django_airavata_admin/config/index.js
new file mode 100644
index 0000000..196da1f
--- /dev/null
+++ b/django_airavata/apps/admin/static/django_airavata_admin/config/index.js
@@ -0,0 +1,38 @@
+// see http://vuejs-templates.github.io/webpack for documentation.
+var path = require('path')
+
+module.exports = {
+ build: {
+ env: require('./prod.env'),
+ index: path.resolve(__dirname, '../dist/index.html'),
+ assetsRoot: path.resolve(__dirname, '../dist'),
+ assetsSubDirectory: 'static',
+ assetsPublicPath: '/',
+ productionSourceMap: true,
+ // Gzip off by default as many popular static hosts such as
+ // Surge or Netlify already gzip all static assets for you.
+ // Before setting to `true`, make sure to:
+ // npm install --save-dev compression-webpack-plugin
+ productionGzip: false,
+ productionGzipExtensions: ['js', 'css'],
+ // Run the build command with an extra argument to
+ // View the bundle analyzer report after build finishes:
+ // `npm run build --report`
+ // Set to `true` or `false` to always turn it on or off
+ bundleAnalyzerReport: process.env.npm_config_report
+ },
+ dev: {
+ env: require('./dev.env'),
+ port: 8080,
+ autoOpenBrowser: true,
+ assetsSubDirectory: 'static',
+ assetsPublicPath: '/',
+ proxyTable: {},
+ // CSS Sourcemaps off by default because relative paths are "buggy"
+ // with this option, according to the CSS-Loader README
+ // (https://github.com/webpack/css-loader#sourcemaps)
+ // In our experience, they generally work as expected,
+ // just be aware of this issue when enabling this option.
+ cssSourceMap: false
+ }
+}
http://git-wip-us.apache.org/repos/asf/airavata-django-portal/blob/d8d7c37a/django_airavata/apps/admin/static/django_airavata_admin/config/prod.env.js
----------------------------------------------------------------------
diff --git a/django_airavata/apps/admin/static/django_airavata_admin/config/prod.env.js b/django_airavata/apps/admin/static/django_airavata_admin/config/prod.env.js
new file mode 100644
index 0000000..773d263
--- /dev/null
+++ b/django_airavata/apps/admin/static/django_airavata_admin/config/prod.env.js
@@ -0,0 +1,3 @@
+module.exports = {
+ NODE_ENV: '"production"'
+}
http://git-wip-us.apache.org/repos/asf/airavata-django-portal/blob/d8d7c37a/django_airavata/apps/admin/static/django_airavata_admin/css/admin.css
----------------------------------------------------------------------
diff --git a/django_airavata/apps/admin/static/django_airavata_admin/css/admin.css b/django_airavata/apps/admin/static/django_airavata_admin/css/admin.css
new file mode 100644
index 0000000..55c2fdf
--- /dev/null
+++ b/django_airavata/apps/admin/static/django_airavata_admin/css/admin.css
@@ -0,0 +1,29 @@
+.entry{
+ margin-top:20px;
+ display: block;
+}
+
+.entry .heading{
+ font-size:16px;
+ font-weight: bold;
+ margin-bottom: 10px;
+}
+
+.entry input,textarea{
+ width: 100%;
+ border-radius: 2px;
+ border: solid #dddddd 1px;
+ padding: 7px;
+}
+
+.main_section {
+ width: 100%;
+ display: block;
+ margin-top: 50px;
+ margin-bottom:20px;
+}
+
+.new-application-tab-main{
+ width: 65%;
+ margin-bottom:30px;
+}
http://git-wip-us.apache.org/repos/asf/airavata-django-portal/blob/d8d7c37a/django_airavata/apps/admin/static/django_airavata_admin/css/main.css
----------------------------------------------------------------------
diff --git a/django_airavata/apps/admin/static/django_airavata_admin/css/main.css b/django_airavata/apps/admin/static/django_airavata_admin/css/main.css
new file mode 100644
index 0000000..523b230
--- /dev/null
+++ b/django_airavata/apps/admin/static/django_airavata_admin/css/main.css
@@ -0,0 +1,145 @@
+html,
+body {
+ height: 100%; }
+
+body {
+ color: #333;
+ background-color: #f7f7f7; }
+
+.c-header {
+ display: flex;
+ align-items: center;
+ border-bottom: 1px solid #ddd;
+ background-color: #ffffff; }
+ .c-header__logo {
+ margin-right: 1rem;
+ width: 70px;
+ background-color: #990000; }
+ .c-header__logo svg {
+ display: block; }
+ .c-header__title {
+ font-size: 1.25rem;
+ line-height: 1; }
+ .c-header__title a {
+ color: #333; }
+ .c-header__controls {
+ margin-left: auto;
+ margin-right: 2rem; }
+
+.c-nav {
+ background-color: #444;
+ min-width: 70px;
+ min-height: 60px;
+ padding: 1rem 0;
+ margin-top: -1px;
+ display: flex; }
+ .c-nav__item {
+ color: #ccc;
+ font-size: 1.5rem;
+ display: block;
+ text-align: center;
+ line-height: 1;
+ flex-grow: 1; }
+ .c-nav__item:hover, .c-nav__item:focus {
+ color: #ffffff; }
+ .c-nav__item:active {
+ color: #bbb; }
+ .c-nav__item.is-active {
+ color: #ffffff; }
+
+@media screen and (min-width: 768px) {
+ .c-nav {
+ height: 100%;
+ flex-direction: column; }
+ .c-nav__item {
+ flex-grow: 0;
+ margin-bottom: 2rem; } }
+.stage {
+ width: 100%;
+ height: 100%;
+ display: flex;
+ flex-direction: column; }
+
+@media screen and (min-width: 768px) {
+ .stage {
+ flex-direction: row; } }
+.main-content {
+ flex-grow: 1;
+ padding: 1rem; }
+
+.sidebar {
+ flex-basis: 200px;
+ background-color: #ffffff; }
+
+.sidebar-header {
+ padding: 1.5rem;
+ display: flex;
+ align-items: center;
+ border-bottom: 1px solid #eee; }
+ .sidebar-header__title {
+ font-size: .825rem;
+ text-transform: uppercase;
+ letter-spacing: .04rem;
+ margin: 0; }
+ .sidebar-header__action {
+ margin-left: auto;
+ font-size: .825rem; }
+
+@media screen and (min-width: 768px) {
+ .sidebar {
+ min-width: 310px;
+ border-left: 1px solid #ddd; } }
+.card {
+ background-color: #fff;
+ border-radius: 4px;
+ border: none;
+ box-shadow: 0 2px 0 #eee;
+ margin-bottom: 30px; }
+
+/**
+ * Make a small card text modifier so we can still use
+ * Bootstrap's default styles if needed.
+ */
+.card-text--small {
+ line-height: 1.4;
+ font-size: .825rem; }
+
+.card.is-disabled {
+ background-color: #ddd; }
+ .card.is-disabled .card-title {
+ color: #999999; }
+ .card.is-disabled .badge {
+ background-color: #ccc;
+ color: #999999; }
+
+.card-link:hover {
+ text-decoration: none;
+ background-color: #fafafa; }
+
+.card.is-disabled .card-link:hover {
+ background-color: #ddd;
+ cursor: not-allowed; }
+
+/**
+ * Feed
+ */
+.feed {
+ list-style: none;
+ margin: 0;
+ padding: 0; }
+ .feed__list-item {
+ padding: 1.5rem;
+ border-bottom: 1px solid #eee; }
+ .feed__label {
+ font-size: .825rem;
+ text-transform: uppercase; }
+ .feed__title {
+ font-size: 1rem;
+ margin: 0; }
+ .feed__title a {
+ color: #212529; }
+ .feed__item-meta {
+ margin: 0;
+ font-size: .825rem; }
+
+/*# sourceMappingURL=main.css.map */
http://git-wip-us.apache.org/repos/asf/airavata-django-portal/blob/d8d7c37a/django_airavata/apps/admin/static/django_airavata_admin/css/main.css.map
----------------------------------------------------------------------
diff --git a/django_airavata/apps/admin/static/django_airavata_admin/css/main.css.map b/django_airavata/apps/admin/static/django_airavata_admin/css/main.css.map
new file mode 100644
index 0000000..3f5b826
--- /dev/null
+++ b/django_airavata/apps/admin/static/django_airavata_admin/css/main.css.map
@@ -0,0 +1,7 @@
+{
+"version": 3,
+"mappings": "AAAA;IACK;EACH,MAAM,EAAE,IAAI;;AAGd,IAAK;EACH,KAAK,EAAE,IAAI;EACX,gBAAgB,EAAE,OAAO;;AAG3B,SAAU;EACR,OAAO,EAAE,IAAI;EACb,WAAW,EAAE,MAAM;EACnB,aAAa,EAAE,cAAc;EAC7B,gBAAgB,EAAE,OAAO;EAEzB,eAAQ;IACN,YAAY,EAAE,IAAI;IAClB,KAAK,EAAE,IAAI;IACX,gBAAgB,EAAE,OAAO;IAEzB,mBAAI;MACF,OAAO,EAAE,KAAK;EAIlB,gBAAS;IACP,SAAS,EAAE,OAAO;IAClB,WAAW,EAAE,CAAC;IAEd,kBAAE;MACA,KAAK,EAAE,IAAI;EAIf,mBAAY;IACV,WAAW,EAAE,IAAI;IACjB,YAAY,EAAE,IAAI;;AAItB,MAAO;EACL,gBAAgB,EAAE,IAAI;EACtB,SAAS,EAAE,IAAI;EACf,UAAU,EAAE,IAAI;EAChB,OAAO,EAAE,MAAM;EACf,UAAU,EAAE,IAAI;EAChB,OAAO,EAAE,IAAI;EAEb,YAAQ;IACN,KAAK,EAAE,IAAI;IACX,SAAS,EAAE,MAAM;IACjB,OAAO,EAAE,KAAK;IACd,UAAU,EAAE,MAAM;IAClB,WAAW,EAAE,CAAC;IACd,SAAS,EAAE,CAAC;IAEZ,sCACQ;MACN,KAAK,EAAE,OAAO;IAGhB,mBAAS;MACP,KAAK,EAAE,IAAI;IAGb,sBAAY;MACV,KAAK,EAAE,OAAO;;AAKpB,oCAAqC;EACnC,MAAO;IACL,MAAM,EAAE,IAAI;IACZ,cAAc,EAAE,MAAM;IAEtB,YAAQ;MACN,SAAS,EAAE,CAAC;MACZ,aAAa,EAAE,IAAI;AAKzB,MAAO;EACL,KAAK,EAAE,IAAI;EACX,MAAM,EAAE,IAAI;EACZ,OAAO,EAAE,IAAI;EACb,cAAc,EAA
E,MAAM;;AAGxB,oCAAqC;EACnC,MAAO;IACL,cAAc,EAAE,GAAG;AAKvB,aAAc;EACZ,SAAS,EAAE,CAAC;EACZ,OAAO,EAAE,IAAI;;AAGf,QAAS;EACP,UAAU,EAAE,KAAK;EACjB,gBAAgB,EAAE,OAAO;;AAG3B,eAAgB;EACd,OAAO,EAAE,MAAM;EACf,OAAO,EAAE,IAAI;EACb,WAAW,EAAE,MAAM;EACnB,aAAa,EAAE,cAAc;EAE7B,sBAAS;IACP,SAAS,EAAE,OAAO;IAClB,cAAc,EAAE,SAAS;IACzB,cAAc,EAAE,MAAM;IACtB,MAAM,EAAE,CAAC;EAGX,uBAAU;IACR,WAAW,EAAE,IAAI;IACjB,SAAS,EAAE,OAAO;;AAItB,oCAAqC;EACnC,QAAS;IACP,SAAS,EAAE,KAAK;IAChB,WAAW,EAAE,cAAc;AAI/B,KAAM;EACJ,gBAAgB,EAAE,IAAI;EACtB,aAAa,EAAE,GAAG;EAClB,MAAM,EAAE,IAAI;EACZ,UAAU,EAAE,YAAY;EACxB,aAAa,EAAE,IAAI;;AAGrB;;;GAGG;AACH,iBAAkB;EAChB,WAAW,EAAE,GAAG;EAChB,SAAS,EAAE,OAAO;;AAGpB,iBAAkB;EAChB,gBAAgB,EAAE,IAAI;EAEtB,6BAAY;IACV,KAAK,EAAE,OAAO;EAGhB,wBAAO;IACL,gBAAgB,EAAE,IAAI;IACtB,KAAK,EAAE,OAAO;;AAIlB,gBAAiB;EACf,eAAe,EAAE,IAAI;EACrB,gBAAgB,EAAE,OAAO;;AAG3B,kCAAmC;EACjC,gBAAgB,EAAE,IAAI;EACtB,MAAM,EAAE,WAAW;;AAIrB;;GAEG;AAEH,KAAM;EACJ,UAAU,EAAE,IAAI;EAChB,MAAM,EAAE,CAAC;EACT,OAAO,EAAE,CAAC;EAEV,gBAAa;IACX,OAAO,EAAE,
MAAM;IACf,aAAa,EAAE,cAAc;EAG/B,YAAS;IACP,SAAS,EAAE,OAAO;IAClB,cAAc,EAAE,SAAS;EAG3B,YAAS;IACP,SAAS,EAAE,IAAI;IACf,MAAM,EAAE,CAAC;IAET,cAAE;MACA,KAAK,EAAE,OAAO;EAIlB,gBAAa;IACX,MAAM,EAAE,CAAC;IACT,SAAS,EAAE,OAAO",
+"sources": ["main.scss"],
+"names": [],
+"file": "main.css"
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/airavata-django-portal/blob/d8d7c37a/django_airavata/apps/admin/static/django_airavata_admin/images/delete.png
----------------------------------------------------------------------
diff --git a/django_airavata/apps/admin/static/django_airavata_admin/images/delete.png b/django_airavata/apps/admin/static/django_airavata_admin/images/delete.png
new file mode 100644
index 0000000..1419360
Binary files /dev/null and b/django_airavata/apps/admin/static/django_airavata_admin/images/delete.png differ
http://git-wip-us.apache.org/repos/asf/airavata-django-portal/blob/d8d7c37a/django_airavata/apps/admin/static/django_airavata_admin/js/App.vue
----------------------------------------------------------------------
diff --git a/django_airavata/apps/admin/static/django_airavata_admin/js/App.vue b/django_airavata/apps/admin/static/django_airavata_admin/js/App.vue
new file mode 100644
index 0000000..3615145
--- /dev/null
+++ b/django_airavata/apps/admin/static/django_airavata_admin/js/App.vue
@@ -0,0 +1,5 @@
+<template>
+ <router-view>
+
+ </router-view>
+</template>
http://git-wip-us.apache.org/repos/asf/airavata-django-portal/blob/d8d7c37a/django_airavata/apps/admin/static/django_airavata_admin/js/components/DashboardItem.vue
----------------------------------------------------------------------
diff --git a/django_airavata/apps/admin/static/django_airavata_admin/js/components/DashboardItem.vue b/django_airavata/apps/admin/static/django_airavata_admin/js/components/DashboardItem.vue
new file mode 100644
index 0000000..ebfbde9
--- /dev/null
+++ b/django_airavata/apps/admin/static/django_airavata_admin/js/components/DashboardItem.vue
@@ -0,0 +1,26 @@
+<template>
+ <div class="col-md-6 col-xl-4">
+ <div class="card">
+ <a href="#0" class="card-link text-dark" v-bind:style="'min-height:'+ height+'px;'">
+ <div class="card-body" >
+ <h2 class="card-title h5">{{dashboard_item.appModuleName}}</h2>
+ <span class="badge badge-primary mr-1" v-for="tag in dashboard_item.tags">{{tag}}</span>
+ <span class="badge badge-primary mr-1" v-if="dashboard_item.appModuleVersion" >{{dashboard_item.appModuleVersion}}</span>
+ <p class="card-text card-text--small mt-3 text-secondary">{{dashboard_item.appModuleDescription}}</p>
+ </div>
+ </a>
+ </div>
+ </div>
+</template>
+
+<script>
+ export default {
+ name: 'dashboard-item',
+ props: ['dashboard_item','tags','height'],
+ data:function () {
+ return {
+ "height":100
+ };
+ }
+ }
+</script>
http://git-wip-us.apache.org/repos/asf/airavata-django-portal/blob/d8d7c37a/django_airavata/apps/admin/static/django_airavata_admin/js/components/RecentExperiment.vue
----------------------------------------------------------------------
diff --git a/django_airavata/apps/admin/static/django_airavata_admin/js/components/RecentExperiment.vue b/django_airavata/apps/admin/static/django_airavata_admin/js/components/RecentExperiment.vue
new file mode 100644
index 0000000..b67378c
--- /dev/null
+++ b/django_airavata/apps/admin/static/django_airavata_admin/js/components/RecentExperiment.vue
@@ -0,0 +1,19 @@
+<template>
+ <li class="feed__list-item">
+ <span class="feed__label text-secondary">{{experiment.name}}</span>
+ <h2 class="feed__title mb-2"><a href="#0">{{experiment.description}}</a></h2>
+ <span class="badge badge-success" v-if="experiment.status == 'Completed'">{{experiment.status}}</span>
+ <span class="badge badge-primary" v-else-if="experiment.status == 'Created'">{{experiment.status}}</span>
+ <span class="badge badge-danger" v-else="experiment.status == 'Failed'">{{experiment.status}}</span>
+ <div class="feed__item-meta text-secondary mt-1">
+ <span>Updated</span>
+ <time>{{experiment.updated}}</time>
+ </div>
+ </li>
+</template>
+<script>
+ export default {
+ name:'recent-experiment',
+ props:['experiment']
+ }
+</script>
http://git-wip-us.apache.org/repos/asf/airavata-django-portal/blob/d8d7c37a/django_airavata/apps/admin/static/django_airavata_admin/js/components/admin/ApplicationDeployments.vue
----------------------------------------------------------------------
diff --git a/django_airavata/apps/admin/static/django_airavata_admin/js/components/admin/ApplicationDeployments.vue b/django_airavata/apps/admin/static/django_airavata_admin/js/components/admin/ApplicationDeployments.vue
new file mode 100644
index 0000000..f6a10f7
--- /dev/null
+++ b/django_airavata/apps/admin/static/django_airavata_admin/js/components/admin/ApplicationDeployments.vue
@@ -0,0 +1,110 @@
+<template>
+
+ <div class="main_section">
+
+ <div class="new-application-tab-main">
+ <h4>Application Deployments</h4>
+ <div class="entry">
+ <div class="heading">Application module</div>
+ <input type="text"/>
+ </div>
+ <div class="entry">
+ <div class="heading">Application compute host</div>
+ <input type="text"/>
+ </div>
+ <div class="entry">
+ <div class="heading">Application executable path</div>
+ <input type="text"/>
+ </div>
+ <div class="entry">
+ <div class="heading">Application Parallelism type</div>
+ <input type="text"/>
+ </div>
+ <div class="entry">
+ <div class="heading">Application deployment description</div>
+ <textarea style="height: 80px;" type="text"/>
+ </div>
+ </div>
+ <div class="new-application-tab-main">
+ <h4>Module load commands</h4>
+ <div class="entry">
+ <div class="heading">Module load commands</div>
+ <input type="text"/>
+ </div>
+ <div class="deployment-entry">
+ <input type="button" class="deployment btn" value="Add command"/>
+ </div>
+ </div>
+
+ <div class="new-application-tab-main">
+ <div class="deployment-entry">
+ <h4>Library Prepend Paths</h4>
+ <input type="button" class="deployment btn" value="Add path"/>
+ </div>
+ </div>
+ <div class="new-application-tab-main">
+ <div class="deployment-entry">
+ <h4>Library Append Paths</h4>
+ <input type="button" class="deployment btn" value="Add path"/>
+ </div>
+ </div>
+ <div class="new-application-tab-main">
+ <div class="deployment-entry">
+ <h4>Environments</h4>
+ <input type="button" class="deployment btn" value="Add environment"/>
+ </div>
+ </div>
+ <div class="new-application-tab-main">
+ <div class="deployment-entry">
+ <h4>Pre Job Commands</h4>
+ <input type="button" class="deployment btn" value="Add command"/>
+ </div>
+ </div>
+ <div class="new-application-tab-main">
+ <div class="deployment-entry">
+ <h4>Post Job Commands</h4>
+ <input type="button" class="deployment btn" value="Add command"/>
+ </div>
+ </div>
+ <div class="new-application-tab-main">
+ <div class="deployment-entry">
+ <h4>Defaults</h4>
+ <input type="button" class="deployment btn" value="Add command"/>
+ </div>
+ </div>
+ </div>
+</template>
+<style>
+ .heading {
+ font-size: 1.0em;
+ font-weight: bold;
+ margin-bottom: 10px;
+ }
+
+ .deployment.btn {
+ float: right;
+ text-align: center;
+ border-color: #007BFF;
+ border-style: solid;
+ border-radius: 3px;
+ padding-top: 5px;
+ padding-bottom: 5px;
+ padding-left: 15px;
+ padding-right: 15px;
+ color: #007BFF;
+ background-color: white;
+ width: auto;
+ float: left;
+ }
+
+ .deployment.btn:hover {
+ color: white;
+ background-color: rgba(0, 105, 217, 1);
+ }
+
+ .deployment-entry {
+ display: inline-block;
+ margin-top: 15px;
+ }
+</style>
+
http://git-wip-us.apache.org/repos/asf/airavata-django-portal/blob/d8d7c37a/django_airavata/apps/admin/static/django_airavata_admin/js/components/admin/ApplicationDetails.vue
----------------------------------------------------------------------
diff --git a/django_airavata/apps/admin/static/django_airavata_admin/js/components/admin/ApplicationDetails.vue b/django_airavata/apps/admin/static/django_airavata_admin/js/components/admin/ApplicationDetails.vue
new file mode 100644
index 0000000..f8c1c11
--- /dev/null
+++ b/django_airavata/apps/admin/static/django_airavata_admin/js/components/admin/ApplicationDetails.vue
@@ -0,0 +1,41 @@
+<template>
+
+ <div class="main_section">
+ <div class="new-application-tab-main">
+ <h4>Application Details</h4>
+ <div class="entry">
+ <div class="heading">Application Name</div>
+ <input type="text"/>
+ </div>
+ <div class="entry">
+ <div class="heading">Application Version</div>
+ <input type="text"/>
+ </div>
+ <div class="entry">
+ <div class="heading" >Experiment Description</div>
+ <textarea style="height: 80px;" type="text"/>
+ </div>
+ <new-application-buttons></new-application-buttons>
+ </div>
+ </div>
+</template>
+<script>
+ import NewApplicationButtons from './NewApplicationButtons.vue';
+ export default{
+ components:{
+ NewApplicationButtons
+ },
+ data:function () {
+ return {
+
+ };
+ }
+ }
+
+</script>
+<style>
+
+
+
+
+</style>
http://git-wip-us.apache.org/repos/asf/airavata-django-portal/blob/d8d7c37a/django_airavata/apps/admin/static/django_airavata_admin/js/components/admin/ApplicationInputField.vue
----------------------------------------------------------------------
diff --git a/django_airavata/apps/admin/static/django_airavata_admin/js/components/admin/ApplicationInputField.vue b/django_airavata/apps/admin/static/django_airavata_admin/js/components/admin/ApplicationInputField.vue
new file mode 100644
index 0000000..1afa93b
--- /dev/null
+++ b/django_airavata/apps/admin/static/django_airavata_admin/js/components/admin/ApplicationInputField.vue
@@ -0,0 +1,101 @@
+<template>
+ <div class="main_section interface-main">
+ <div class="input-field-header">
+ Input Fields
+ <img v-on:click="delete_event_trigger();" src="/static/images/delete.png"/>
+ </div>
+ <div class="entry">
+ <div class="heading">Name</div>
+ <input type="text" v-model="data.name"/>
+ </div>
+ <div class="entry">
+ <div class="heading" v-model="data.value">Value</div>
+ <input type="text"/>
+ </div>
+ <div class="entry">
+ <div class="heading" v-model="data.type">Type</div>
+ <input type="text"/>
+ </div>
+ <div class="entry">
+ <div class="heading">Application argument</div>
+ <input v-model="data.appArg" type="text"/>
+ </div>
+ <div class="entry boolean-selectors">
+ <boolean-radio-button v-bind:heading="'Data is staged'" v-bind:selectorVal="data.dataStaged"></boolean-radio-button>
+ <boolean-radio-button v-bind:heading="'Required'" v-bind:selectorVal="data.required"></boolean-radio-button>
+ </div>
+ <div class="entry boolean-selectors">
+ <boolean-radio-button v-bind:heading="'Required on command line'" v-bind:selectorVal="data.requiredOnCmd"></boolean-radio-button>
+ </div>
+ </div>
+</template>
+<script>
+ import BooleanRadioButton from './BooleanRadioButton.vue'
+ export default {
+ components:{
+ BooleanRadioButton
+ },
+ methods:{
+ delete_event_trigger:function(){
+ this.$emit('delete_input_field');
+ }
+ },
+ created:function(){
+ this.data=this.data;
+ },
+ props:{
+ data:{
+ type:Object,
+ default:function () {
+ return{
+ name:'',
+ value:'',
+ type:'',
+ appArg:'',
+ dataStaged:{'boolValue':'true'},
+ required:{'boolValue':'false'},
+ requiredOnCmd:{'boolValue':'false'}
+ };
+ }
+ }
+ },
+ watch:{
+ }
+ }
+</script>
+
+<style>
+ .input-field-header{
+ background-color: #F8F8F8;
+ width: 100%;
+ padding: 15px;
+ border: solid 1px #dddddd;
+ text-align: left;
+ }
+
+ .input-field-header img{
+ float: right;
+ }
+
+
+
+ .main_section.interface-main .entry{
+ margin-bottom: 40px;
+ margin-left:15px;
+ margin-right: 15px;
+ }
+
+ .entry.boolean-selectors{
+ display: flex;
+ }
+
+ .entry.boolean-selectors div{
+ margin-right: 60px;
+ }
+
+ .interface-main{
+ border: solid 1px #dddddd;
+ border-radius: 4px;
+ }
+
+</style>
http://git-wip-us.apache.org/repos/asf/airavata-django-portal/blob/d8d7c37a/django_airavata/apps/admin/static/django_airavata_admin/js/components/admin/ApplicationInterface.vue
----------------------------------------------------------------------
diff --git a/django_airavata/apps/admin/static/django_airavata_admin/js/components/admin/ApplicationInterface.vue b/django_airavata/apps/admin/static/django_airavata_admin/js/components/admin/ApplicationInterface.vue
new file mode 100644
index 0000000..474efbc
--- /dev/null
+++ b/django_airavata/apps/admin/static/django_airavata_admin/js/components/admin/ApplicationInterface.vue
@@ -0,0 +1,104 @@
+<template>
+
+ <div class="main_section">
+
+ <div class="new-application-tab-main">
+ <h4>Application Interface</h4>
+ <div class="entry boolean-selectors">
+ <boolean-radio-button v-bind:heading="'Enable Archiving Working Directory'" v-bind:selectorVal="work_dir"></boolean-radio-button>
+ <boolean-radio-button v-bind:heading="'Enable Optional File Inputs'" v-bind:selectorVal="optional_files"></boolean-radio-button>
+ </div>
+ <div>
+ <application-input-field class="interface-main" v-for="data in obj.inputFields" v-bind:data="data" v-bind:key="data.input_id" v-on:delete_input_field="delete_event_trigger(data.input_id);"></application-input-field>
+ </div>
+ <div class="entry">
+ <button class="interface-btn" v-on:click="addApplicationInput();">Add Application <span>input</span></button>
+ </div>
+ <div class="entry">
+ <div class="heading">Output fields</div>
+ <button class="interface-btn">Add Application <span>output</span></button>
+ </div>
+ <new-application-buttons></new-application-buttons>
+ </div>
+ </div>
+</template>
+<script>
+ import ApplicationInputField from './ApplicationInputField.vue';
+ import BooleanRadioButton from './BooleanRadioButton.vue';
+ import NewApplicationButtons from './NewApplicationButtons.vue';
+
+ import { mapGetters } from 'vuex';
+
+ export default {
+ components:{
+
+ ApplicationInputField,BooleanRadioButton,NewApplicationButtons
+ },
+ data:function () {
+ return {
+ 'id':0,
+ work_dir:{'boolValue':'false'},
+ optional_files:{'boolValue':'true'}
+ };
+ },
+ props:{
+ 'obj':{
+ type:Object,
+ default:function () {
+ return {
+ 'inputFields':[]
+ };
+ }
+ }
+ },
+ mounted:function () {
+ this.addApplicationInput();
+ },
+ methods:{
+ addApplicationInput:function () {
+ this.obj.inputFields.push({
+ input_id:this.id++,
+ name:'',
+ value:'',
+ type:'',
+ appArg:'',
+ dataStaged:{'boolValue':'true'},
+ required:{'boolValue':'false'},
+ requiredOnCmd:{'boolValue':'false'}
+ });
+ },
+ delete_event_trigger:function(input_id){
+ console.log('deleting input Field: '+input_id);
+ this.obj.inputFields=this.obj.inputFields.filter((data)=>data.input_id!=input_id);
+ },
+ }
+ };
+</script>
+<style>
+ .interface-btn{
+ color: #868E96;
+ border: solid 1px #868E96;
+ background-color: transparent;
+ text-align: center;
+ border-radius: 3px;
+ padding-top: 5px;
+ padding-bottom:5px;
+ padding-left:15px;
+ padding-right: 15px;
+ }
+ .interface-btn span{
+ font-weight: bold;
+ }
+
+ .interface-btn:hover{
+ background-color: rgba(0,105,217,1);
+ color: white;
+ }
+
+ .entry.boolean-selectors{
+ display: flex;
+ }
+
+
+</style>
+
http://git-wip-us.apache.org/repos/asf/airavata-django-portal/blob/d8d7c37a/django_airavata/apps/admin/static/django_airavata_admin/js/components/admin/BooleanRadioButton.vue
----------------------------------------------------------------------
diff --git a/django_airavata/apps/admin/static/django_airavata_admin/js/components/admin/BooleanRadioButton.vue b/django_airavata/apps/admin/static/django_airavata_admin/js/components/admin/BooleanRadioButton.vue
new file mode 100644
index 0000000..d6190d6
--- /dev/null
+++ b/django_airavata/apps/admin/static/django_airavata_admin/js/components/admin/BooleanRadioButton.vue
@@ -0,0 +1,71 @@
+<template>
+ <div class="boolean-selector-main">
+ <div class="boolean-selector-heading">{{heading}}</div>
+ <div class="boolean-selector">
+ <div>
+ <input type="radio" v-model="selectorVal.boolValue" value="true"/>
+ <label>True</label>
+ </div>
+ <div>
+ <input type="radio" v-model="selectorVal.boolValue" value="false"/>
+ <label>False</label>
+ </div>
+ </div>
+ </div>
+</template>
+<script>
+
+ export default {
+ mounted:function(){
+ //console.log('Selctor Value: '+ this.selectorVal.boolValue);
+ this.selectorVal.boolValue=this.selectorVal.boolValue;
+ },
+ props:{
+ selectorVal:{
+ type:Object,
+ default:function () {
+ return {
+ 'boolValue':'false',
+ };
+ }
+ },
+ heading:{
+ type:String
+ },
+ selectorId:{
+ type:String,
+ default:'na'
+ }
+ }
+ }
+</script>
+<style>
+ .boolean-selector-main{
+ display: block;
+ }
+ .boolean-selector{
+ display: flex;
+ font-weight: 100;
+ }
+
+ .boolean-selector div{
+ display: flex;
+ margin-right: 25px;
+ }
+
+ .boolean-selector div label{
+ margin-left: 10px;
+ text-align: center;
+ font-weight: bold;
+ padding-top: 4px;
+ }
+
+ .boolean-selector-heading{
+ font-size:1.1em;
+ font-weight: 400;
+ margin-bottom: 10px;
+ color: black;
+ width: 100%;
+
+ }
+</style>
http://git-wip-us.apache.org/repos/asf/airavata-django-portal/blob/d8d7c37a/django_airavata/apps/admin/static/django_airavata_admin/js/components/admin/NewApplication.vue
----------------------------------------------------------------------
diff --git a/django_airavata/apps/admin/static/django_airavata_admin/js/components/admin/NewApplication.vue b/django_airavata/apps/admin/static/django_airavata_admin/js/components/admin/NewApplication.vue
new file mode 100644
index 0000000..73f52d0
--- /dev/null
+++ b/django_airavata/apps/admin/static/django_airavata_admin/js/components/admin/NewApplication.vue
@@ -0,0 +1,112 @@
+<template>
+ <div class="new_app">
+ <h3>Create A New Application</h3>
+ <div class="main">
+ <div class="tabs">
+ <div class="tab" v-bind:class="tabs['details']"><router-link class="link" :to="{name:'details'}"><label class="lbl">Details</label></router-link></div>
+ <div class="tab" v-bind:class="tabs['interface']" v-bind:obj="appInterfaceTabData"><router-link class="link" :to="{name:'interface'}"><label class="lbl">Interface</label></router-link></div>
+ <div class="tab" v-bind:class="tabs['deployments']"><router-link class="link" :to="{name:'deployments'}"><label class="lbl">Deployments</label></router-link></div>
+ <div class="tab" style="width: 100%"></div>
+ </div>
+ <transition mode="out-in">
+ <router-view :key="$route.path"></router-view>
+ </transition>
+ </div>
+ </div>
+</template>
+<script>
+ import ApplicationDetails from './ApplicationDetails.vue'
+ import ApplicationInterface from './ApplicationInterface.vue'
+ export default {
+ components: {
+ ApplicationDetails,ApplicationInterface
+ },
+ mounted:function () {
+ this.current_active_tab=this.$route.name;
+ this.previous_active_tab='';
+ },
+ data: function () {
+ return {
+ current_active_tab: 0,
+ previous_active_tab: -1,
+ appInterfaceTabData:{'inputFields':[]}
+ };
+ },
+ computed: {
+ tabs: function () {
+ var tabs_active = {
+ 'details':'',
+ 'interface':'',
+ 'deployments':''
+ };
+ tabs_active[this.current_active_tab] = 'active';
+ if (tabs_active.hasOwnProperty(this.previous_active_tab)) {
+ tabs_active[this.previous_active_tab] = '';
+ }
+ return tabs_active;
+ }
+ },
+ watch:{
+ '$route' (to, from) {
+ this.previous_active_tab=from.name
+ this.current_active_tab=to.name
+
+ }
+ }
+ }
+</script>
+<style>
+ .new_app {
+ margin: 45px;
+ width: 70%;
+ }
+
+ .main {
+ width: 100%;
+ margin-top: 50px;
+ }
+
+ .tab {
+ text-align: center;
+ width: 120px;
+ margin-bottom: 15px;
+ border-bottom: solid #999999 1px;
+ color: #007BFF;
+ }
+
+ .tab .lbl:hover {
+ cursor: pointer;
+ }
+
+ .active .lbl:hover {
+ cursor: default;
+ }
+
+ .lbl {
+ margin: 10px;
+ color: inherit;
+ }
+
+ .link{
+ color: inherit;
+ }
+
+ .active {
+ color: #333333;
+ border-top: solid #999999 1px;
+ border-left: solid #999999 1px;
+ border-right: solid #999999 1px;
+ border-bottom: hidden;
+ border-top-right-radius: 3px;
+ border-top-left-radius: 3px;
+ }
+
+ .tabs {
+ display: flex;
+ width: 100%;
+ }
+
+
+
+
+</style>
http://git-wip-us.apache.org/repos/asf/airavata-django-portal/blob/d8d7c37a/django_airavata/apps/admin/static/django_airavata_admin/js/components/admin/NewApplicationButtons.vue
----------------------------------------------------------------------
diff --git a/django_airavata/apps/admin/static/django_airavata_admin/js/components/admin/NewApplicationButtons.vue b/django_airavata/apps/admin/static/django_airavata_admin/js/components/admin/NewApplicationButtons.vue
new file mode 100644
index 0000000..0bedc37
--- /dev/null
+++ b/django_airavata/apps/admin/static/django_airavata_admin/js/components/admin/NewApplicationButtons.vue
@@ -0,0 +1,42 @@
+<template>
+ <div class="btns">
+ <input class="cancel" type="button" value="Cancel"/>
+ <input class="save" type="button" value="Save"/>
+ </div>
+</template>
+<style>
+ .btns{
+ margin-top:50px;
+ display: inline-block;
+ width: 100%;
+ }
+
+ .btns input{
+ float: right;
+ margin-left: 20px;
+ text-align: center;
+ border-color: #007BFF;
+ border-style: solid;
+ border-radius: 3px;
+ padding-top: 5px;
+ padding-bottom:5px;
+ padding-left:15px;
+ padding-right: 15px;
+ }
+
+ .btns input:hover{
+ background-color: #3ca41a;
+ color: #f1fff3;
+ }
+
+ .save{
+ background-color: #007BFF;
+ color: white;
+ }
+
+ .cancel{
+ color: #007BFF;
+ background-color: white;
+ }
+
+</style>
http://git-wip-us.apache.org/repos/asf/airavata-django-portal/blob/d8d7c37a/django_airavata/apps/admin/static/django_airavata_admin/js/components/dashboards/AdminDashboard.vue
----------------------------------------------------------------------
diff --git a/django_airavata/apps/admin/static/django_airavata_admin/js/components/dashboards/AdminDashboard.vue b/django_airavata/apps/admin/static/django_airavata_admin/js/components/dashboards/AdminDashboard.vue
new file mode 100644
index 0000000..254dac1
--- /dev/null
+++ b/django_airavata/apps/admin/static/django_airavata_admin/js/components/dashboards/AdminDashboard.vue
@@ -0,0 +1,6 @@
+<template>
+<router-view>
+
+</router-view>
+</template>
+
http://git-wip-us.apache.org/repos/asf/airavata-django-portal/blob/d8d7c37a/django_airavata/apps/admin/static/django_airavata_admin/js/components/dashboards/AdminDashboardHome.vue
----------------------------------------------------------------------
diff --git a/django_airavata/apps/admin/static/django_airavata_admin/js/components/dashboards/AdminDashboardHome.vue b/django_airavata/apps/admin/static/django_airavata_admin/js/components/dashboards/AdminDashboardHome.vue
new file mode 100644
index 0000000..be1b768
--- /dev/null
+++ b/django_airavata/apps/admin/static/django_airavata_admin/js/components/dashboards/AdminDashboardHome.vue
@@ -0,0 +1,90 @@
+<template>
+ <div class="new_app">
+ <div class="new_app_header">
+ <h4 style="display: inline-block">Application Catalog</h4>
+ <router-link :to="{name:'details'}"><button v-on="this.$emit('new_application')">New Application <span>+</span></button></router-link>
+ </div>
+ <div class="applications">
+ <h6 style="color: #666666;">APPLICATIONS</h6>
+ <div class="container-fluid">
+ <div class="row">
+ <DashboardItem
+ v-for="item in applications" v-bind:dashboard_item="item" v-bind:key="item.title">
+ </DashboardItem>
+ </div>
+ </div>
+
+ </div>
+ </div>
+</template>
+<script>
+ import DashboardItem from '../DashboardItem.vue'
+ import NewApplication from '../admin/NewApplication.vue'
+ export default {
+ data:function () {
+ return {
+ "applications":[]
+ };
+ },
+ components:{
+ DashboardItem,NewApplication
+ },
+ mounted:function () {
+ this.fetchApplications();
+ },
+ methods:{
+ fetchApplications:function () {
+ var convert=function (applications) {
+
+ };
+ this.$http.get('/api/applications').then(response => {
+ this.applications=response.body;
+ }, response => {
+ this.applications=[{
+ "appModuleId": "",
+ "appModuleName": "No Applications Found",
+ "appModuleDescription": "",
+ "appModuleVersion": ""
+ }]
+ });
+ },
+
+ }
+ }
+</script>
+<style>
+ .new_app {
+ margin: 45px;
+ width: 100%;
+ }
+
+ .new_app_header{
+ width: 100%;
+ display: inline;
+ }
+
+ .new_app_header button{
+ background-color: #2e73bc;
+ color: white;
+ border: solid #2e73bc 1px ;
+ border-radius: 3px;
+ float: right;
+ padding-right: 15px;
+ padding-left: 15px;
+ padding-bottom: 8px;
+ padding-top: 3px;
+ }
+
+ .new_app_header button:hover{
+ cursor: pointer;
+ }
+
+ .new_app_header button span{
+ font-weight: 900;
+ font-size: larger;
+ }
+
+ .applications{
+ margin-top: 50px;
+ }
+</style>
http://git-wip-us.apache.org/repos/asf/airavata-django-portal/blob/d8d7c37a/django_airavata/apps/admin/static/django_airavata_admin/js/components/dashboards/ExperimentDashboard.vue
----------------------------------------------------------------------
diff --git a/django_airavata/apps/admin/static/django_airavata_admin/js/components/dashboards/ExperimentDashboard.vue b/django_airavata/apps/admin/static/django_airavata_admin/js/components/dashboards/ExperimentDashboard.vue
new file mode 100644
index 0000000..2898745
--- /dev/null
+++ b/django_airavata/apps/admin/static/django_airavata_admin/js/components/dashboards/ExperimentDashboard.vue
@@ -0,0 +1,104 @@
+<template>
+ <div class="stage">
+ <main class="main-content">
+ <div class="container-fluid">
+ <h1 class="h4 mb-4">Dashboard</h1>
+ </div>
+ <div class="container-fluid">
+ <div class="row">
+ <DashboardItem
+ v-for="item in applications" v-bind:dashboard_item="item" v-bind:key="item.title" v-bind:height="height">
+ </DashboardItem>
+ </div>
+ </div>
+ </main>
+ <aside class="sidebar">
+ <header class="sidebar-header">
+ <h1 class="sidebar-header__title">Recent Experiments</h1>
+ <a href="#0" class="sidebar-header__action" v-on:click="views_all_click_handler">View all</a>
+ </header>
+
+ <ol class="feed">
+ <RecentExperiment v-for="experiment in experiments"
+ v-if="experiment.index <default_experiment_count || view_all" v-bind:experiment="experiment"
+ v-bind:key="experiment.name"></RecentExperiment>
+ </ol>
+ </aside>
+ </div>
+</template>
+<script>
+ import DashboardItem from '../DashboardItem.vue'
+ import RecentExperiment from '../RecentExperiment.vue'
+ import {addIndex} from '../../utils.js'
+
+ export default{
+ 'name':'main-section',
+ components: {
+ DashboardItem, RecentExperiment
+ },
+ data:function () {
+
+ var data_returned={
+ "view_all": false,
+ "default_experiment_count": 3,
+ "height":180,
+ "applications":
+ [
+
+ ]
+ , "experiments": [
+ {
+ "name": "Gaussian",
+ "description": "My very first test experiment",
+ "status": "Failed",
+ "updated": "14 minutes ago"
+ },
+ {
+ "name": "Lampps",
+ "description": "A really BIG experiment That Has a Really Long Title",
+ "status": "Completed",
+ "updated": "20 hours ago"
+ },
+ {
+ "name": "Gromacs",
+ "description": "exp_4a56w4892s23r6p9y_1",
+ "status": "Created",
+ "updated": "2 days ago"
+ },
+ {
+ "name": "RandExpr",
+ "description": "exp_4a56w4892s23r6p9y_1",
+ "status": "Failed",
+ "updated": "5 days ago"
+ }
+ ]
+ };
+ addIndex(data_returned["experiments"]);
+ return data_returned;
+ },
+ mounted:function () {
+ this.fetchApplications();
+ },
+ methods: {
+ "views_all_click_handler": function () {
+ this.view_all = !this.view_all;
+ },
+ fetchApplications:function () {
+ var convert=function (applications) {
+
+ };
+ this.$http.get('/api/applications').then(response => {
+ this.applications=response.body;
+ }, response => {
+ this.applications=[{
+ "appModuleId": "",
+ "appModuleName": "No Applications Found",
+ "appModuleDescription": "",
+ "appModuleVersion": ""
+ }]
+ });
+ }
+
+ }
+ }
+</script>
http://git-wip-us.apache.org/repos/asf/airavata-django-portal/blob/d8d7c37a/django_airavata/apps/admin/static/django_airavata_admin/js/main.js
----------------------------------------------------------------------
diff --git a/django_airavata/apps/admin/static/django_airavata_admin/js/main.js b/django_airavata/apps/admin/static/django_airavata_admin/js/main.js
new file mode 100644
index 0000000..35b0f10
--- /dev/null
+++ b/django_airavata/apps/admin/static/django_airavata_admin/js/main.js
@@ -0,0 +1,31 @@
+import Vue from 'vue';
+import VueResource from 'vue-resource';
+import VueRouter from 'vue-router';
+import Vuex from 'vuex';
+
+import ExperimentsDashboard from './components/dashboards/ExperimentDashboard.vue';
+import AdminDashboard from './components/dashboards/AdminDashboard.vue';
+
+import router from './router';
+import storeParams from './store';
+
+Vue.config.productionTip = false;
+
+Vue.use(VueResource);
+Vue.use(VueRouter);
+Vue.use(Vuex);
+
+var store=new Vuex.Store(storeParams);
+
+export function initializeApacheAiravataDashboard(dashboardName) {
+ return new Vue({
+ el: '#app',
+ router,
+ store,
+ template: '<' + dashboardName + '/>',
+ components: {ExperimentsDashboard, AdminDashboard}
+
+ })
+};
+
+
http://git-wip-us.apache.org/repos/asf/airavata-django-portal/blob/d8d7c37a/django_airavata/apps/admin/static/django_airavata_admin/js/router.js
----------------------------------------------------------------------
diff --git a/django_airavata/apps/admin/static/django_airavata_admin/js/router.js b/django_airavata/apps/admin/static/django_airavata_admin/js/router.js
new file mode 100644
index 0000000..291151b
--- /dev/null
+++ b/django_airavata/apps/admin/static/django_airavata_admin/js/router.js
@@ -0,0 +1,34 @@
+import AdminDashboardHome from './components/dashboards/AdminDashboardHome.vue'
+import NewApplication from './components/admin/NewApplication.vue'
+import ExperimentsDashboard from './components/dashboards/ExperimentDashboard.vue'
+import ApplicationDetails from'./components/admin/ApplicationDetails.vue'
+import ApplicationInterface from './components/admin/ApplicationInterface.vue'
+import ApplicationDeployments from './components/admin/ApplicationDeployments.vue'
+import VueRouter from 'vue-router'
+
+
+const routes=[
+ { path: '/new/application', component: NewApplication,name:'newapp',
+ children:[
+ {
+ path:'details',
+ component:ApplicationDetails,
+ name:'details',
+
+ },{
+ path:'interface',
+ component:ApplicationInterface,
+ name:'interface'
+ },{
+ path:'deployments',
+ component:ApplicationDeployments,
+ name:'deployments'
+
+ }
+ ]},
+ { path: '/', component: AdminDashboardHome },
+ {path:'/experiments',component:ExperimentsDashboard}
+];
+export default new VueRouter({
+ routes:routes
+});
http://git-wip-us.apache.org/repos/asf/airavata-django-portal/blob/d8d7c37a/django_airavata/apps/admin/static/django_airavata_admin/js/store.js
----------------------------------------------------------------------
diff --git a/django_airavata/apps/admin/static/django_airavata_admin/js/store.js b/django_airavata/apps/admin/static/django_airavata_admin/js/store.js
new file mode 100644
index 0000000..fbabdd0
--- /dev/null
+++ b/django_airavata/apps/admin/static/django_airavata_admin/js/store.js
@@ -0,0 +1,67 @@
+
+const store={
+ modules:{
+ appInterfaceTab:{
+ state:{
+ inputFields:[],
+ counter:0
+ },
+ mutations:{
+ createAppInterfaceInputField:function (state) {
+ state.inputFields.push(
+ {
+ input_id:state.counter++,
+ name:'',
+ value:'',
+ type:'',
+ appArg:'',
+ dataStaged:false,
+ requiredId:false,
+ requiredOnCmdId:false
+ }
+ );
+ }
+ },
+ getters:{
+ getAppInterface:state=>{
+ return state.data;
+ }
+ }
+ },
+ appDetailsTab:{
+ state:{
+ data:{},
+ },
+ mutations:{
+ addAppDetails:function (state,data) {
+ state.data=data;
+ }
+ },
+ getters:{
+ getAppDetails:(state,getters)=>{
+ return state.data;
+ }
+ }
+ },
+ appDeploymentsTab:{
+ state:{
+ data:{},
+ },
+ mutations:{
+ addAppDeployments:function (state,data) {
+ state.data=data;
+ }
+ },
+ getters:{
+ getAppDeployments:(state,getters)=>{
+ return state.data;
+ }
+ }
+ }
+ }
+};
+
+export default {
+ 'store':store
+}
+
http://git-wip-us.apache.org/repos/asf/airavata-django-portal/blob/d8d7c37a/django_airavata/apps/admin/static/django_airavata_admin/js/utils.js
----------------------------------------------------------------------
diff --git a/django_airavata/apps/admin/static/django_airavata_admin/js/utils.js b/django_airavata/apps/admin/static/django_airavata_admin/js/utils.js
new file mode 100644
index 0000000..076a033
--- /dev/null
+++ b/django_airavata/apps/admin/static/django_airavata_admin/js/utils.js
@@ -0,0 +1,8 @@
+
+
+export function addIndex(list){
+ for(var i=0;i<list.length;i++){
+ list[i].index=i;
+ }
+ return list;
+}
http://git-wip-us.apache.org/repos/asf/airavata-django-portal/blob/d8d7c37a/django_airavata/apps/admin/templates/admin/admin.html
----------------------------------------------------------------------
diff --git a/django_airavata/apps/admin/templates/admin/admin.html b/django_airavata/apps/admin/templates/admin/admin.html
new file mode 100644
index 0000000..4084afe
--- /dev/null
+++ b/django_airavata/apps/admin/templates/admin/admin.html
@@ -0,0 +1,19 @@
+{% extends "main_base.html" %}
+{% load static %}
+{% block content %}
+ <div id=app></div>
+{% endblock %}
+{% block css %}
+<link rel=stylesheet type=text/css href={% static 'css/app.css' %}>
+ {% endblock %}
+{% block scripts %}
+ {{ block.super }}
+ <script type=text/javascript src="{% static 'js/manifest.js' %}"></script>
+ <script type=text/javascript src="{% static 'js/vendor.js' %}"></script>
+ <script type=text/javascript src="{% static 'js/app.js' %}"></script>
+ <script>
+ if(AiravataApp){
+ AiravataApp.initializeApacheAiravataDashboard('AdminDashboard');
+ }
+ </script>
+{% endblock %}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/airavata-django-portal/blob/d8d7c37a/django_airavata/apps/admin/tests.py
----------------------------------------------------------------------
diff --git a/django_airavata/apps/admin/tests.py b/django_airavata/apps/admin/tests.py
new file mode 100644
index 0000000..7ce503c
--- /dev/null
+++ b/django_airavata/apps/admin/tests.py
@@ -0,0 +1,3 @@
+from django.test import TestCase
+
+# Create your tests here.
http://git-wip-us.apache.org/repos/asf/airavata-django-portal/blob/d8d7c37a/django_airavata/apps/admin/urls.py
----------------------------------------------------------------------
diff --git a/django_airavata/apps/admin/urls.py b/django_airavata/apps/admin/urls.py
new file mode 100644
index 0000000..49c002a
--- /dev/null
+++ b/django_airavata/apps/admin/urls.py
@@ -0,0 +1,9 @@
+
+from django.conf.urls import url
+
+from . import views
+
+app_name = 'admin'
+urlpatterns = [
+ url(r'^$', views.experiments, name='admin'),
+]
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/airavata-django-portal/blob/d8d7c37a/django_airavata/apps/admin/views.py
----------------------------------------------------------------------
diff --git a/django_airavata/apps/admin/views.py b/django_airavata/apps/admin/views.py
new file mode 100644
index 0000000..447c17e
--- /dev/null
+++ b/django_airavata/apps/admin/views.py
@@ -0,0 +1,10 @@
+from django.shortcuts import render
+
+# Create your views here.
+
+from django.contrib.auth.decorators import login_required
+from django.shortcuts import render
+
+@login_required
+def experiments(request):
+ return render(request, 'admin/admin.html')
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/airavata-django-portal/blob/d8d7c37a/django_airavata/apps/api/__init__.py
----------------------------------------------------------------------
diff --git a/django_airavata/apps/api/__init__.py b/django_airavata/apps/api/__init__.py
new file mode 100644
index 0000000..e69de29
http://git-wip-us.apache.org/repos/asf/airavata-django-portal/blob/d8d7c37a/django_airavata/apps/api/admin.py
----------------------------------------------------------------------
diff --git a/django_airavata/apps/api/admin.py b/django_airavata/apps/api/admin.py
new file mode 100644
index 0000000..8c38f3f
--- /dev/null
+++ b/django_airavata/apps/api/admin.py
@@ -0,0 +1,3 @@
+from django.contrib import admin
+
+# Register your models here.
http://git-wip-us.apache.org/repos/asf/airavata-django-portal/blob/d8d7c37a/django_airavata/apps/api/apps.py
----------------------------------------------------------------------
diff --git a/django_airavata/apps/api/apps.py b/django_airavata/apps/api/apps.py
new file mode 100644
index 0000000..32e1767
--- /dev/null
+++ b/django_airavata/apps/api/apps.py
@@ -0,0 +1,5 @@
+from django.apps import AppConfig
+
+
+class ApiConfig(AppConfig):
+ name = 'django_airavata.apps.api'
http://git-wip-us.apache.org/repos/asf/airavata-django-portal/blob/d8d7c37a/django_airavata/apps/api/migrations/__init__.py
----------------------------------------------------------------------
diff --git a/django_airavata/apps/api/migrations/__init__.py b/django_airavata/apps/api/migrations/__init__.py
new file mode 100644
index 0000000..e69de29
http://git-wip-us.apache.org/repos/asf/airavata-django-portal/blob/d8d7c37a/django_airavata/apps/api/models.py
----------------------------------------------------------------------
diff --git a/django_airavata/apps/api/models.py b/django_airavata/apps/api/models.py
new file mode 100644
index 0000000..71a8362
--- /dev/null
+++ b/django_airavata/apps/api/models.py
@@ -0,0 +1,3 @@
+from django.db import models
+
+# Create your models here.
http://git-wip-us.apache.org/repos/asf/airavata-django-portal/blob/d8d7c37a/django_airavata/apps/api/serializers.py
----------------------------------------------------------------------
diff --git a/django_airavata/apps/api/serializers.py b/django_airavata/apps/api/serializers.py
new file mode 100644
index 0000000..e6dc921
--- /dev/null
+++ b/django_airavata/apps/api/serializers.py
@@ -0,0 +1,91 @@
+from apache.airavata.model.experiment.ttypes import ExperimentModel
+from apache.airavata.model.workspace.ttypes import Project
+from apache.airavata.model.appcatalog.appdeployment.ttypes import ApplicationModule
+from django.conf import settings
+
+from rest_framework import serializers
+
+from urllib.parse import quote
+
+
+class FullyEncodedHyperlinkedIdentityField(serializers.HyperlinkedIdentityField):
+ def get_url(self, obj, view_name, request, format):
+ lookup_value = getattr(obj, self.lookup_field)
+ encoded_lookup_value = quote(lookup_value, safe="")
+ # Bit of a hack. Django's URL reversing does URL encoding but it doesn't
+ # encode all characters including some like '/' that are used in URL
+ # mappings.
+ kwargs = {self.lookup_url_kwarg: "__PLACEHOLDER__"}
+ url = self.reverse(view_name, kwargs=kwargs, request=request, format=format)
+ return url.replace("__PLACEHOLDER__", encoded_lookup_value)
+
+class GetGatewayUsername(object):
+
+ def __call__(self):
+ return self.field.context['request'].user.username
+
+ def set_context(self, field):
+ self.field = field
+
+class GatewayUsernameDefaultField(serializers.CharField):
+
+ def __init__(self, *args, **kwargs):
+ super().__init__(*args, **kwargs)
+ self.read_only = True
+ self.default = GetGatewayUsername()
+
+class GatewayIdDefaultField(serializers.CharField):
+
+ def __init__(self, *args, **kwargs):
+ super().__init__(*args, **kwargs)
+ self.read_only = True
+ self.default = settings.GATEWAY_ID
+
+class ProjectSerializer(serializers.Serializer):
+ url = FullyEncodedHyperlinkedIdentityField(view_name='project-detail', lookup_field='projectID', lookup_url_kwarg='pk')
+ projectID = serializers.CharField(read_only=True)
+ name = serializers.CharField(required=True)
+ description = serializers.CharField(required=False)
+ owner = GatewayUsernameDefaultField()
+ gatewayId = GatewayIdDefaultField()
+ experiments = FullyEncodedHyperlinkedIdentityField(view_name='api_project_experiments_list', lookup_field='projectID', lookup_url_kwarg='project_id')
+
+ def create(self, validated_data):
+ return Project(**validated_data)
+
+ def update(self, instance, validated_data):
+ instance.name = validated_data.get('name', instance.name)
+ instance.description = validated_data.get('description', instance.description)
+ return instance
+
+ def get_username(self):
+ return self.context.request.user.username
+
+class ExperimentSerializer(serializers.Serializer):
+
+ experimentId = serializers.CharField(read_only=True)
+ projectId = serializers.CharField(required=True)
+ project = FullyEncodedHyperlinkedIdentityField(view_name='project-detail', lookup_field='projectId', lookup_url_kwarg='project_id')
+ gatewayId = GatewayIdDefaultField()
+ experimentType = serializers.CharField(required=True)
+ userName = GatewayUsernameDefaultField()
+ experimentName = serializers.CharField(required=True)
+
+ def create(self, validated_data):
+ return ExperimentModel(**validated_data)
+
+ def update(self, instance, validated_data):
+ raise Exception("Not implemented")
+
+
+class ApplicationModuleSerializer(serializers.Serializer):
+ appModuleId=serializers.CharField(required=True)
+ appModuleName=serializers.CharField(required=True)
+ appModuleDescription = serializers.CharField()
+ appModuleVersion=serializers.CharField()
+
+ def create(self, validated_data):
+ return ApplicationModule(**validated_data)
+
+ def update(self, instance, validated_data):
+ raise Exception("Not implemented")
http://git-wip-us.apache.org/repos/asf/airavata-django-portal/blob/d8d7c37a/django_airavata/apps/api/tests.py
----------------------------------------------------------------------
diff --git a/django_airavata/apps/api/tests.py b/django_airavata/apps/api/tests.py
new file mode 100644
index 0000000..7ce503c
--- /dev/null
+++ b/django_airavata/apps/api/tests.py
@@ -0,0 +1,3 @@
+from django.test import TestCase
+
+# Create your tests here.
http://git-wip-us.apache.org/repos/asf/airavata-django-portal/blob/d8d7c37a/django_airavata/apps/api/urls.py
----------------------------------------------------------------------
diff --git a/django_airavata/apps/api/urls.py b/django_airavata/apps/api/urls.py
new file mode 100644
index 0000000..8fa12ac
--- /dev/null
+++ b/django_airavata/apps/api/urls.py
@@ -0,0 +1,23 @@
+
+from . import views
+
+from django.conf.urls import include, url
+from rest_framework import routers
+from rest_framework.urlpatterns import format_suffix_patterns
+
+router = routers.SimpleRouter()
+router.register(r'projects', views.ProjectViewSet, base_name='project')
+
+urlpatterns = [
+ url(r'^$', views.api_root),
+ # url(r'^projects/$', views.ProjectList.as_view(), name='api_project_list'),
+ # More specific, longer URLs should come before less specific, shorter ones
+ # since the regular expression for project_id allows any character, even '/'
+ url(r'^projects/(?P<project_id>.+)/experiments/$', views.ProjectExperimentList.as_view(), name='api_project_experiments_list'),
+ # url(r'^projects/(?P<project_id>.+)/$', views.ProjectDetail.as_view(), name='api_project_detail'),
+ url(r'^experiments/$', views.ExperimentList.as_view(), name='api_experiment_list'),
+ url(r'^', include(router.urls)),
+ url(r'^applications/$', views.ApplicationList.as_view(), name='application_module_list')
+]
+
+urlpatterns = format_suffix_patterns(urlpatterns)
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/airavata-django-portal/blob/d8d7c37a/django_airavata/apps/api/views.py
----------------------------------------------------------------------
diff --git a/django_airavata/apps/api/views.py b/django_airavata/apps/api/views.py
new file mode 100644
index 0000000..7a7be35
--- /dev/null
+++ b/django_airavata/apps/api/views.py
@@ -0,0 +1,127 @@
+
+from . import serializers
+
+from rest_framework import status, mixins
+from rest_framework.decorators import api_view
+from rest_framework.views import APIView
+from rest_framework.viewsets import GenericViewSet
+from rest_framework.response import Response
+from rest_framework.reverse import reverse
+
+from django.conf import settings
+from django.http import JsonResponse, Http404
+from django.shortcuts import render
+from django.views.decorators.csrf import csrf_exempt
+
+# Create your views here.
+@api_view(['GET'])
+def api_root(request, format=None):
+ return Response({
+ 'projects': reverse('project-list', request=request, format=format),
+ 'admin': reverse('api_experiment_list', request=request, format=format)
+ })
+
+class GenericAPIBackedViewSet(GenericViewSet):
+
+ def get_list(self):
+ """
+ Subclasses must implement.
+ """
+ raise NotImplementedError()
+
+ def get_instance(self, lookup_value):
+ """
+ Subclasses must implement.
+ """
+ raise NotImplementedError()
+
+ def get_queryset(self):
+ return self.get_list()
+
+ def get_object(self):
+ lookup_url_kwarg = self.lookup_url_kwarg or self.lookup_field
+ lookup_value = self.kwargs[lookup_url_kwarg]
+ inst = self.get_instance(lookup_value)
+ if inst is None:
+ raise Http404
+ self.check_object_permissions(self.request, inst)
+ return inst
+
+ @property
+ def username(self):
+ return self.request.user.username
+
+ @property
+ def gateway_id(self):
+ return settings.GATEWAY_ID
+
+ @property
+ def authz_token(self):
+ return self.request.authz_token
+
+class CreateUpdateRetrieveListViewSet(mixins.CreateModelMixin,
+ mixins.RetrieveModelMixin,
+ mixins.UpdateModelMixin,
+ mixins.DestroyModelMixin,
+ mixins.ListModelMixin,
+ GenericAPIBackedViewSet):
+ """
+ A viewset that provides default `create()`, `retrieve()`, `update()`,
+ `partial_update()` and `list()` actions.
+
+ Subclasses must implement the following:
+ * get_list(self)
+ * get_instance(self, lookup_value)
+ * perform_create(self, serializer) - should return instance with id populated
+ * perform_update(self, serializer)
+ """
+ pass
+
+
+class ProjectViewSet(CreateUpdateRetrieveListViewSet):
+
+ serializer_class = serializers.ProjectSerializer
+
+ def get_list(self):
+ # TODO: support pagination
+ return self.request.airavata_client.getUserProjects(self.authz_token, self.gateway_id, self.username, -1, 0)
+
+ def get_instance(self, lookup_value):
+ return self.request.airavata_client.getProject(self.authz_token, lookup_value)
+
+ def perform_create(self, serializer):
+ project = serializer.save()
+ project_id = self.request.airavata_client.createProject(self.authz_token, self.gateway_id, project)
+ project.projectID = project_id
+
+ def perform_update(self, serializer):
+ project = serializer.save()
+ self.request.airavata_client.updateProject(self.authz_token, project.projectID, project)
+
+
+class ExperimentList(APIView):
+ def get(self, request, format=None):
+ gateway_id = settings.GATEWAY_ID
+ username = request.user.username
+
+ experiments = request.airavata_client.getUserExperiments(request.authz_token, gateway_id, username, -1, 0)
+ serializer = serializers.ExperimentSerializer(experiments, many=True, context={'request': request})
+ return Response(serializer.data)
+
+class ProjectExperimentList(APIView):
+ def get(self, request, project_id, format=None):
+ gateway_id = settings.GATEWAY_ID
+ username = request.user.username
+
+ experiments = request.airavata_client.getExperimentsInProject(request.authz_token, project_id, -1, 0)
+ serializer = serializers.ExperimentSerializer(experiments, many=True, context={'request': request})
+ return Response(serializer.data)
+
+
+class ApplicationList(APIView):
+
+ def get(self,request,format=None):
+ gateway_id = settings.GATEWAY_ID
+ app_modules=request.airavata_client.getAllAppModules(request.authz_token,gateway_id)
+ serializer=serializers.ApplicationModuleSerializer(app_modules,many=True,context={'request':request})
+ return Response(serializer.data)
http://git-wip-us.apache.org/repos/asf/airavata-django-portal/blob/d8d7c37a/django_airavata/apps/auth/__init__.py
----------------------------------------------------------------------
diff --git a/django_airavata/apps/auth/__init__.py b/django_airavata/apps/auth/__init__.py
new file mode 100644
index 0000000..e69de29
http://git-wip-us.apache.org/repos/asf/airavata-django-portal/blob/d8d7c37a/django_airavata/apps/auth/admin.py
----------------------------------------------------------------------
diff --git a/django_airavata/apps/auth/admin.py b/django_airavata/apps/auth/admin.py
new file mode 100644
index 0000000..8c38f3f
--- /dev/null
+++ b/django_airavata/apps/auth/admin.py
@@ -0,0 +1,3 @@
+from django.contrib import admin
+
+# Register your models here.
http://git-wip-us.apache.org/repos/asf/airavata-django-portal/blob/d8d7c37a/django_airavata/apps/auth/apps.py
----------------------------------------------------------------------
diff --git a/django_airavata/apps/auth/apps.py b/django_airavata/apps/auth/apps.py
new file mode 100644
index 0000000..1e103a4
--- /dev/null
+++ b/django_airavata/apps/auth/apps.py
@@ -0,0 +1,6 @@
+from django.apps import AppConfig
+
+
+class AuthConfig(AppConfig):
+ name = 'django_airavata.apps.auth'
+ label = 'django_airavata_auth'
http://git-wip-us.apache.org/repos/asf/airavata-django-portal/blob/d8d7c37a/django_airavata/apps/auth/backends.py
----------------------------------------------------------------------
diff --git a/django_airavata/apps/auth/backends.py b/django_airavata/apps/auth/backends.py
new file mode 100644
index 0000000..c198123
--- /dev/null
+++ b/django_airavata/apps/auth/backends.py
@@ -0,0 +1,73 @@
+
+from django.conf import settings
+from django.contrib.auth.models import User
+from django.urls import reverse
+
+from oauthlib.oauth2 import LegacyApplicationClient
+from requests_oauthlib import OAuth2Session
+
+import logging
+
+logger = logging.getLogger(__name__)
+
+class KeycloakBackend(object):
+ def authenticate(self, username=None, password=None, request=None):
+ token = None
+ userinfo = None
+ if username and password:
+ token, userinfo = self._get_token_and_userinfo_password_flow(username, password)
+ else:
+ token, userinfo = self._get_token_and_userinfo_redirect_flow(request)
+ # TODO validate the JWS signature
+ logger.debug("token: {}".format(token))
+ access_token = token['access_token']
+ logger.debug("userinfo: {}".format(userinfo))
+ username = userinfo['preferred_username']
+ # TODO load user roles too
+ try:
+ user = User.objects.get(username=username)
+ except User.DoesNotExist:
+ user = User(username=username)
+ user.save()
+ # Put access_token into session to be used for authenticating with API server
+ request.session['ACCESS_TOKEN'] = access_token
+ request.session['USERINFO'] = userinfo
+ return user
+
+ def get_user(self, user_id):
+ try:
+ return User.objects.get(pk=user_id)
+ except User.DoesNotExist:
+ return None
+
+ def _get_token_and_userinfo_password_flow(self, username, password):
+ client_id = settings.KEYCLOAK_CLIENT_ID
+ client_secret = settings.KEYCLOAK_CLIENT_SECRET
+ token_url = settings.KEYCLOAK_TOKEN_URL
+ userinfo_url = settings.KEYCLOAK_USERINFO_URL
+ verify_ssl = settings.KEYCLOAK_VERIFY_SSL
+ oauth2_session = OAuth2Session(client=LegacyApplicationClient(client_id=client_id))
+ if hasattr(settings, 'KEYCLOAK_CA_CERTFILE'):
+ oauth2_session.verify = settings.KEYCLOAK_CA_CERTFILE
+ token = oauth2_session.fetch_token(token_url=token_url, username=username,
+ password=password, client_id=client_id, client_secret=client_secret, verify=verify_ssl)
+ userinfo = oauth2_session.get(userinfo_url).json()
+ return token, userinfo
+
+ def _get_token_and_userinfo_redirect_flow(self, request):
+ authorization_code_url=request.build_absolute_uri()
+ redirect_url=request.build_absolute_uri(reverse('django_airavata_auth:callback'))
+ client_id = settings.KEYCLOAK_CLIENT_ID
+ client_secret = settings.KEYCLOAK_CLIENT_SECRET
+ token_url = settings.KEYCLOAK_TOKEN_URL
+ userinfo_url = settings.KEYCLOAK_USERINFO_URL
+ verify_ssl = settings.KEYCLOAK_VERIFY_SSL
+ state = request.session['OAUTH2_STATE']
+ logger.debug("state={}".format(state))
+ oauth2_session = OAuth2Session(client_id, scope='openid', redirect_uri=redirect_url, state=state)
+ if hasattr(settings, 'KEYCLOAK_CA_CERTFILE'):
+ oauth2_session.verify = settings.KEYCLOAK_CA_CERTFILE
+ token = oauth2_session.fetch_token(token_url, client_secret=client_secret,
+ authorization_response=authorization_code_url, verify=verify_ssl)
+ userinfo = oauth2_session.get(userinfo_url).json()
+ return token, userinfo
http://git-wip-us.apache.org/repos/asf/airavata-django-portal/blob/d8d7c37a/django_airavata/apps/auth/middleware.py
----------------------------------------------------------------------
diff --git a/django_airavata/apps/auth/middleware.py b/django_airavata/apps/auth/middleware.py
new file mode 100644
index 0000000..2ee937d
--- /dev/null
+++ b/django_airavata/apps/auth/middleware.py
@@ -0,0 +1,16 @@
+from . import utils
+
+def authz_token_middleware(get_response):
+ "Automatically add the 'authz_token' to the request"
+
+ def middleware(request):
+
+ authz_token = None
+ if request.user.is_authenticated:
+ authz_token = utils.get_authz_token(request)
+
+ request.authz_token = authz_token
+
+ return get_response(request)
+
+ return middleware
http://git-wip-us.apache.org/repos/asf/airavata-django-portal/blob/d8d7c37a/django_airavata/apps/auth/migrations/__init__.py
----------------------------------------------------------------------
diff --git a/django_airavata/apps/auth/migrations/__init__.py b/django_airavata/apps/auth/migrations/__init__.py
new file mode 100644
index 0000000..e69de29