You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@airavata.apache.org by sm...@apache.org on 2020/04/12 04:21:34 UTC

[airavata-mft-portal] 13/16: configure vue js settings for the app

This is an automated email from the ASF dual-hosted git repository.

smarru pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/airavata-mft-portal.git

commit 0a8a84f7eed6ce2ffae1238c963ca8b8f39d07a6
Author: Aarushi Bisht <aa...@gmail.com>
AuthorDate: Sat Apr 11 06:44:16 2020 -0400

    configure vue js settings for the app
---
 airavata_mft/apps/workspace/package-lock.json      |  88 +++++++++
 airavata_mft/apps/workspace/package.json           |   6 +-
 airavata_mft/apps/workspace/public/favicon.ico     | Bin 4286 -> 0 bytes
 airavata_mft/apps/workspace/public/index.html      |  17 --
 airavata_mft/apps/workspace/src/App.vue            |  28 ---
 airavata_mft/apps/workspace/src/assets/logo.png    | Bin 6849 -> 0 bytes
 .../apps/workspace/src/components/HelloWorld.vue   |  58 ------
 airavata_mft/apps/workspace/src/main.js            |   8 -
 .../js/containers/Storage.vue                      |  92 ++++++++++
 .../js/entry-view-storage.js                       |  11 ++
 airavata_mft/apps/workspace/templates/storage.html |  21 ++-
 airavata_mft/apps/workspace/views.py               |   2 -
 airavata_mft/apps/workspace/vue.config.js          |  45 +++++
 airavata_mft/settings.py                           |  24 ++-
 airavata_mft/static/common/.gitignore              |  21 +++
 airavata_mft/static/common/README.md               |  24 +++
 airavata_mft/static/common/babel.config.js         |   5 +
 airavata_mft/static/common/js/cms.js               |  13 ++
 airavata_mft/static/common/js/main.js              |  10 +
 .../common/js/notices.js}                          |   0
 airavata_mft/static/common/main.js                 |  17 ++
 .../workspace => static/common}/package-lock.json  | 203 ++++++++++++++++-----
 .../{apps/workspace => static/common}/package.json |  15 +-
 airavata_mft/static/common/vue.config.js           |  19 ++
 airavata_mft/templates/base.html                   |   6 +-
 requirements.txt                                   |   1 +
 26 files changed, 566 insertions(+), 168 deletions(-)

diff --git a/airavata_mft/apps/workspace/package-lock.json b/airavata_mft/apps/workspace/package-lock.json
index b56ef55..0ff4570 100644
--- a/airavata_mft/apps/workspace/package-lock.json
+++ b/airavata_mft/apps/workspace/package-lock.json
@@ -1039,6 +1039,17 @@
       "integrity": "sha512-shAmDyaQC4H92APFoIaVDHCx5bStIocgvbwQyxPRrbUY20V1EYTbSDchWbuwlMG3V17cprZhA6+78JfB+3DTPw==",
       "dev": true
     },
+    "@nuxt/opencollective": {
+      "version": "0.3.0",
+      "resolved": "https://registry.npmjs.org/@nuxt/opencollective/-/opencollective-0.3.0.tgz",
+      "integrity": "sha512-Vf09BxCdj1iT2IRqVwX5snaY2WCTkvM0O4cWWSO1ThCFuc4if0Q/nNwAgCxRU0FeYHJ7DdyMUNSdswCLKlVqeg==",
+      "dev": true,
+      "requires": {
+        "chalk": "^2.4.2",
+        "consola": "^2.10.1",
+        "node-fetch": "^2.6.0"
+      }
+    },
     "@soda/friendly-errors-webpack-plugin": {
       "version": "1.7.1",
       "resolved": "https://registry.npmjs.org/@soda/friendly-errors-webpack-plugin/-/friendly-errors-webpack-plugin-1.7.1.tgz",
@@ -2382,6 +2393,25 @@
       "integrity": "sha1-aN/1++YMUes3cl6p4+0xDcwed24=",
       "dev": true
     },
+    "bootstrap": {
+      "version": "4.4.1",
+      "resolved": "https://registry.npmjs.org/bootstrap/-/bootstrap-4.4.1.tgz",
+      "integrity": "sha512-tbx5cHubwE6e2ZG7nqM3g/FZ5PQEDMWmMGNrCUBVRPHXTJaH7CBDdsLeu3eCh3B1tzAxTnAbtmrzvWEvT2NNEA==",
+      "dev": true
+    },
+    "bootstrap-vue": {
+      "version": "2.11.0",
+      "resolved": "https://registry.npmjs.org/bootstrap-vue/-/bootstrap-vue-2.11.0.tgz",
+      "integrity": "sha512-T23+aVVSDifX1SsI5y69bYZzbm8iQHlmgiBUw9XxY1KTw/fb4xvUq4+Y01Tsaul04+zmrUah/5zvUGKLwTcH7A==",
+      "dev": true,
+      "requires": {
+        "@nuxt/opencollective": "^0.3.0",
+        "bootstrap": ">=4.4.1 <5.0.0",
+        "popper.js": "^1.16.1",
+        "portal-vue": "^2.1.7",
+        "vue-functional-data-merge": "^3.1.0"
+      }
+    },
     "brace-expansion": {
       "version": "1.1.11",
       "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
@@ -3176,6 +3206,12 @@
       "integrity": "sha512-e54B99q/OUoH64zYYRf3HBP5z24G38h5D3qXu23JGRoigpX5Ss4r9ZnDk3g0Z8uQC2x2lPaJ+UlWBc1ZWBWdLg==",
       "dev": true
     },
+    "consola": {
+      "version": "2.11.3",
+      "resolved": "https://registry.npmjs.org/consola/-/consola-2.11.3.tgz",
+      "integrity": "sha512-aoW0YIIAmeftGR8GSpw6CGQluNdkWMWh3yEFjH/hmynTYnMtibXszii3lxCXmk8YxJtI3FAK5aTiquA5VH68Gw==",
+      "dev": true
+    },
     "console-browserify": {
       "version": "1.2.0",
       "resolved": "https://registry.npmjs.org/console-browserify/-/console-browserify-1.2.0.tgz",
@@ -3714,6 +3750,12 @@
         "regexp.prototype.flags": "^1.2.0"
       }
     },
+    "deep-extend": {
+      "version": "0.6.0",
+      "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz",
+      "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==",
+      "dev": true
+    },
     "deep-is": {
       "version": "0.1.3",
       "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz",
@@ -7613,6 +7655,12 @@
         "lower-case": "^1.1.1"
       }
     },
+    "node-fetch": {
+      "version": "2.6.0",
+      "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.0.tgz",
+      "integrity": "sha512-8dG4H5ujfvFiqDmVu9fQ5bOHUC15JMjMY/Zumv26oOvvVJjM67KF8koCWIabKQ1GJIa9r2mMZscBq/TbdOcmNA==",
+      "dev": true
+    },
     "node-forge": {
       "version": "0.9.0",
       "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-0.9.0.tgz",
@@ -8321,6 +8369,18 @@
         "ts-pnp": "^1.1.6"
       }
     },
+    "popper.js": {
+      "version": "1.16.1",
+      "resolved": "https://registry.npmjs.org/popper.js/-/popper.js-1.16.1.tgz",
+      "integrity": "sha512-Wb4p1J4zyFTbM+u6WuO4XstYx4Ky9Cewe4DWrel7B0w6VVICvPwdOpotjzcf6eD8TsckVnIMNONQyPIUFOUbCQ==",
+      "dev": true
+    },
+    "portal-vue": {
+      "version": "2.1.7",
+      "resolved": "https://registry.npmjs.org/portal-vue/-/portal-vue-2.1.7.tgz",
+      "integrity": "sha512-+yCno2oB3xA7irTt0EU5Ezw22L2J51uKAacE/6hMPMoO/mx3h4rXFkkBkT4GFsMDv/vEe8TNKC3ujJJ0PTwb6g==",
+      "dev": true
+    },
     "portfinder": {
       "version": "1.0.25",
       "resolved": "https://registry.npmjs.org/portfinder/-/portfinder-1.0.25.tgz",
@@ -11120,6 +11180,12 @@
         }
       }
     },
+    "vue-functional-data-merge": {
+      "version": "3.1.0",
+      "resolved": "https://registry.npmjs.org/vue-functional-data-merge/-/vue-functional-data-merge-3.1.0.tgz",
+      "integrity": "sha512-leT4kdJVQyeZNY1kmnS1xiUlQ9z1B/kdBFCILIjYYQDqZgLqCLa0UhjSSeRX6c3mUe6U5qYeM8LrEqkHJ1B4LA==",
+      "dev": true
+    },
     "vue-hot-reload-api": {
       "version": "2.3.4",
       "resolved": "https://registry.npmjs.org/vue-hot-reload-api/-/vue-hot-reload-api-2.3.4.tgz",
@@ -11283,6 +11349,28 @@
         }
       }
     },
+    "webpack-bundle-tracker": {
+      "version": "0.4.3",
+      "resolved": "https://registry.npmjs.org/webpack-bundle-tracker/-/webpack-bundle-tracker-0.4.3.tgz",
+      "integrity": "sha512-Sl/+OsNhFAH3/c6XADupRu8jLvGojfXX0pZIIm3O5ZcJqkHHqlY4nLG+NVRcbDgM/jOeWimKDGQMVEa8FBeJ2g==",
+      "dev": true,
+      "requires": {
+        "deep-extend": "^0.6.0",
+        "mkdirp": "^0.5.1",
+        "strip-ansi": "^5.2.0"
+      },
+      "dependencies": {
+        "strip-ansi": {
+          "version": "5.2.0",
+          "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz",
+          "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==",
+          "dev": true,
+          "requires": {
+            "ansi-regex": "^4.1.0"
+          }
+        }
+      }
+    },
     "webpack-chain": {
       "version": "6.4.0",
       "resolved": "https://registry.npmjs.org/webpack-chain/-/webpack-chain-6.4.0.tgz",
diff --git a/airavata_mft/apps/workspace/package.json b/airavata_mft/apps/workspace/package.json
index a20305a..a52ef0e 100644
--- a/airavata_mft/apps/workspace/package.json
+++ b/airavata_mft/apps/workspace/package.json
@@ -18,7 +18,11 @@
     "babel-eslint": "^10.1.0",
     "eslint": "^6.7.2",
     "eslint-plugin-vue": "^6.2.2",
-    "vue-template-compiler": "^2.6.11"
+    "vue-loader": "^15.7.0",
+    "vue-template-compiler": "^2.6.11",
+    "webpack-bundle-tracker": "^0.4.3",
+    "bootstrap": "^4.3.1",
+    "bootstrap-vue": "^2.11.0"
   },
   "eslintConfig": {
     "root": true,
diff --git a/airavata_mft/apps/workspace/public/favicon.ico b/airavata_mft/apps/workspace/public/favicon.ico
deleted file mode 100644
index df36fcf..0000000
Binary files a/airavata_mft/apps/workspace/public/favicon.ico and /dev/null differ
diff --git a/airavata_mft/apps/workspace/public/index.html b/airavata_mft/apps/workspace/public/index.html
deleted file mode 100644
index 4123528..0000000
--- a/airavata_mft/apps/workspace/public/index.html
+++ /dev/null
@@ -1,17 +0,0 @@
-<!DOCTYPE html>
-<html lang="en">
-  <head>
-    <meta charset="utf-8">
-    <meta http-equiv="X-UA-Compatible" content="IE=edge">
-    <meta name="viewport" content="width=device-width,initial-scale=1.0">
-    <link rel="icon" href="<%= BASE_URL %>favicon.ico">
-    <title><%= htmlWebpackPlugin.options.title %></title>
-  </head>
-  <body>
-    <noscript>
-      <strong>We're sorry but <%= htmlWebpackPlugin.options.title %> doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
-    </noscript>
-    <div id="app"></div>
-    <!-- built files will be auto injected -->
-  </body>
-</html>
diff --git a/airavata_mft/apps/workspace/src/App.vue b/airavata_mft/apps/workspace/src/App.vue
deleted file mode 100644
index 55df315..0000000
--- a/airavata_mft/apps/workspace/src/App.vue
+++ /dev/null
@@ -1,28 +0,0 @@
-<template>
-  <div id="app">
-    <img alt="Vue logo" src="./assets/logo.png">
-    <HelloWorld msg="Welcome to Your Vue.js App"/>
-  </div>
-</template>
-
-<script>
-import HelloWorld from './components/HelloWorld.vue'
-
-export default {
-  name: 'App',
-  components: {
-    HelloWorld
-  }
-}
-</script>
-
-<style>
-#app {
-  font-family: Avenir, Helvetica, Arial, sans-serif;
-  -webkit-font-smoothing: antialiased;
-  -moz-osx-font-smoothing: grayscale;
-  text-align: center;
-  color: #2c3e50;
-  margin-top: 60px;
-}
-</style>
diff --git a/airavata_mft/apps/workspace/src/assets/logo.png b/airavata_mft/apps/workspace/src/assets/logo.png
deleted file mode 100644
index f3d2503..0000000
Binary files a/airavata_mft/apps/workspace/src/assets/logo.png and /dev/null differ
diff --git a/airavata_mft/apps/workspace/src/components/HelloWorld.vue b/airavata_mft/apps/workspace/src/components/HelloWorld.vue
deleted file mode 100644
index 879051a..0000000
--- a/airavata_mft/apps/workspace/src/components/HelloWorld.vue
+++ /dev/null
@@ -1,58 +0,0 @@
-<template>
-  <div class="hello">
-    <h1>{{ msg }}</h1>
-    <p>
-      For a guide and recipes on how to configure / customize this project,<br>
-      check out the
-      <a href="https://cli.vuejs.org" target="_blank" rel="noopener">vue-cli documentation</a>.
-    </p>
-    <h3>Installed CLI Plugins</h3>
-    <ul>
-      <li><a href="https://github.com/vuejs/vue-cli/tree/dev/packages/%40vue/cli-plugin-babel" target="_blank" rel="noopener">babel</a></li>
-      <li><a href="https://github.com/vuejs/vue-cli/tree/dev/packages/%40vue/cli-plugin-eslint" target="_blank" rel="noopener">eslint</a></li>
-    </ul>
-    <h3>Essential Links</h3>
-    <ul>
-      <li><a href="https://vuejs.org" target="_blank" rel="noopener">Core Docs</a></li>
-      <li><a href="https://forum.vuejs.org" target="_blank" rel="noopener">Forum</a></li>
-      <li><a href="https://chat.vuejs.org" target="_blank" rel="noopener">Community Chat</a></li>
-      <li><a href="https://twitter.com/vuejs" target="_blank" rel="noopener">Twitter</a></li>
-      <li><a href="https://news.vuejs.org" target="_blank" rel="noopener">News</a></li>
-    </ul>
-    <h3>Ecosystem</h3>
-    <ul>
-      <li><a href="https://router.vuejs.org" target="_blank" rel="noopener">vue-router</a></li>
-      <li><a href="https://vuex.vuejs.org" target="_blank" rel="noopener">vuex</a></li>
-      <li><a href="https://github.com/vuejs/vue-devtools#vue-devtools" target="_blank" rel="noopener">vue-devtools</a></li>
-      <li><a href="https://vue-loader.vuejs.org" target="_blank" rel="noopener">vue-loader</a></li>
-      <li><a href="https://github.com/vuejs/awesome-vue" target="_blank" rel="noopener">awesome-vue</a></li>
-    </ul>
-  </div>
-</template>
-
-<script>
-export default {
-  name: 'HelloWorld',
-  props: {
-    msg: String
-  }
-}
-</script>
-
-<!-- Add "scoped" attribute to limit CSS to this component only -->
-<style scoped>
-h3 {
-  margin: 40px 0 0;
-}
-ul {
-  list-style-type: none;
-  padding: 0;
-}
-li {
-  display: inline-block;
-  margin: 0 10px;
-}
-a {
-  color: #42b983;
-}
-</style>
diff --git a/airavata_mft/apps/workspace/src/main.js b/airavata_mft/apps/workspace/src/main.js
deleted file mode 100644
index 63eb05f..0000000
--- a/airavata_mft/apps/workspace/src/main.js
+++ /dev/null
@@ -1,8 +0,0 @@
-import Vue from 'vue'
-import App from './App.vue'
-
-Vue.config.productionTip = false
-
-new Vue({
-  render: h => h(App),
-}).$mount('#app')
diff --git a/airavata_mft/apps/workspace/static/airavata_mft_workspace/js/containers/Storage.vue b/airavata_mft/apps/workspace/static/airavata_mft_workspace/js/containers/Storage.vue
new file mode 100644
index 0000000..7048340
--- /dev/null
+++ b/airavata_mft/apps/workspace/static/airavata_mft_workspace/js/containers/Storage.vue
@@ -0,0 +1,92 @@
+<template>
+    <div id="storage">
+        <div class="container-fluid">
+        <div class="row">
+            <div class="col-8">
+                <h1 class="h4 mb-4">Storage Units</h1>
+            </div>
+            <div class="col-1">
+                 <div class="dropdown">
+                      <button class="btn btn-sm btn-secondary dropdown-toggle" style="background: white;color: grey" type="button" id="dropdownMenu2" data-toggle="dropdown" aria-haspopup="true" aria-expanded="true">
+                        Sort by
+                      </button>
+                      <div class="dropdown-menu" aria-labelledby="dropdownMenu2">
+                        <button class="dropdown-item" type="button">Action</button>
+                        <button class="dropdown-item" type="button">Another action</button>
+                        <button class="dropdown-item" type="button">Something else here</button>
+                      </div>
+                </div>
+            </div>
+           <div class="col-1">
+
+           </div>
+            <div class="col-2">
+                <button class="btn btn-sm"><span data-feather="plus"></span> Add new unit</button>
+            </div>
+        </div>
+              <!--
+                  <div class="btn-group btn-group-sm" role="group" aria-label="view">
+                      <button class="btn-sm btn-primary"></button>
+                       <button class="btn-sm btn-primary"></button>
+                  </div>
+                  <button class="btn-sm btn-primary"> Add new unit</button> -->
+
+          <table class="table table-hover">
+            <thead>
+                <tr>
+                  <th scope="col">Name</th>
+                  <th scope="col">Storage size</th>
+                  <th scope="col">Storage occupied</th>
+                  <th scope="col">Last modified</th>
+                </tr>
+            </thead>
+              <!--- This should be removed -->
+              <tbody>
+                <tr>
+                  <th scope="row">Box </th>
+                  <td>15 GB</td>
+                  <td>
+                      <div class="progress storage-progress" style="width: 20%">
+                          <div class="progress-bar bg-danger" role="progressbar" style="width: 15%" aria-valuenow="15" aria-valuemin="0" aria-valuemax="100"></div>
+                          <div class="progress-bar bg-success" role="progressbar" style="width: 85%" aria-valuenow="30" aria-valuemin="0" aria-valuemax="100"></div>
+                      </div>
+                  </td>
+                  <td>Jan 15, 2020</td>
+                </tr>
+                <tr>
+                  <th scope="row">Box </th>
+                  <td>15 GB</td>
+                  <td>
+                      <div class="progress storage-progress" style="width: 20%">
+                          <div class="progress-bar bg-danger" role="progressbar" style="width: 15%" aria-valuenow="15" aria-valuemin="0" aria-valuemax="100"></div>
+                          <div class="progress-bar bg-success" role="progressbar" style="width: 85%" aria-valuenow="30" aria-valuemin="0" aria-valuemax="100"></div>
+                      </div></td>
+                  <td>Jan 15, 2020</td>
+                </tr>
+                <tr>
+                  <th scope="row">Box </th>
+                  <td>15 GB</td>
+                  <td>
+                                            <div class="progress storage-progress" style="width: 20%">
+                          <div class="progress-bar bg-danger" role="progressbar" style="width: 15%" aria-valuenow="15" aria-valuemin="0" aria-valuemax="100"></div>
+                          <div class="progress-bar bg-success" role="progressbar" style="width: 85%" aria-valuenow="30" aria-valuemin="0" aria-valuemax="100"></div>
+                      </div>
+                  </td>
+                  <td>Jan 15, 2020</td>
+                </tr>
+
+              </tbody>
+            </table>
+      </div>
+    </div>
+</template>
+
+<script>
+export default {
+    name: 'storage',
+}
+</script>
+
+<style>
+
+</style>
\ No newline at end of file
diff --git a/airavata_mft/apps/workspace/static/airavata_mft_workspace/js/entry-view-storage.js b/airavata_mft/apps/workspace/static/airavata_mft_workspace/js/entry-view-storage.js
index e69de29..28fa928 100644
--- a/airavata_mft/apps/workspace/static/airavata_mft_workspace/js/entry-view-storage.js
+++ b/airavata_mft/apps/workspace/static/airavata_mft_workspace/js/entry-view-storage.js
@@ -0,0 +1,11 @@
+import Vue from 'vue'
+import storage from "./containers/Storage"
+import { BootstrapVue } from 'bootstrap-vue'
+
+// Install BootstrapVue
+Vue.use(BootstrapVue)
+
+import 'bootstrap/dist/css/bootstrap.css'
+import 'bootstrap-vue/dist/bootstrap-vue.css'
+
+new Vue ({render: h => h(storage, {})}).$mount("#storage")
\ No newline at end of file
diff --git a/airavata_mft/apps/workspace/templates/storage.html b/airavata_mft/apps/workspace/templates/storage.html
index 563f92c..8d3f607 100644
--- a/airavata_mft/apps/workspace/templates/storage.html
+++ b/airavata_mft/apps/workspace/templates/storage.html
@@ -1,3 +1,20 @@
-{% extends "base.html" %}
+{#{% extends "base.html" %}#}
+
+{% load render_bundle from webpack_loader %}
+<div id="storage"></div>
+
+{% render_bundle "chunk-vendors" %}
+{% render_bundle "storage" %}
+
 {% block app %}
-{% endblock app %}
\ No newline at end of file
+
+    <div id="storage"></div>
+
+{% endblock app %}
+
+<!--- This has to go to vue file--->
+<style>
+    .storage-progress {
+        width: 20%;
+    }
+</style>
\ No newline at end of file
diff --git a/airavata_mft/apps/workspace/views.py b/airavata_mft/apps/workspace/views.py
index de79c86..222f56d 100644
--- a/airavata_mft/apps/workspace/views.py
+++ b/airavata_mft/apps/workspace/views.py
@@ -1,7 +1,5 @@
 from django.shortcuts import render
 
 # Create your views here.
-
-
 def storage(request):
     return render(request, 'storage.html', {})
\ No newline at end of file
diff --git a/airavata_mft/apps/workspace/vue.config.js b/airavata_mft/apps/workspace/vue.config.js
new file mode 100644
index 0000000..9a67329
--- /dev/null
+++ b/airavata_mft/apps/workspace/vue.config.js
@@ -0,0 +1,45 @@
+const BundleTracker = require("webpack-bundle-tracker");
+const path = require("path");
+
+module.exports = {
+  publicPath:
+    process.env.NODE_ENV === "development"
+      ? "http://localhost:9000/static/airavata_mft_workspace/dist/"
+      : "/static/airavata_mft_workspace/dist/",
+  outputDir: "./static/airavata_mft_workspace/dist",
+  productionSourceMap: false,
+  pages: {
+      'storage': './static/airavata_mft_workspace/js/entry-view-storage',
+  },
+  configureWebpack: {
+    plugins: [
+      new BundleTracker({
+        filename: "webpack-stats.json",
+        path: "./static/airavata_mft_workspace/dist/"
+      })
+    ],
+  },
+  chainWebpack: config => {
+    /*
+     * Specify the eslint config file otherwise it complains of a missing
+     * config file for the ../api and ../../static/common packages
+     *
+     * See: https://github.com/vuejs/vue-cli/issues/2539#issuecomment-422295246
+     */
+    config.module
+      .rule("eslint")
+      .use("eslint-loader")
+      .tap(options => {
+        options.configFile = path.resolve(__dirname, "package.json");
+        return options;
+      });
+  },
+  devServer: {
+    port: 9000,
+    headers: {
+      "Access-Control-Allow-Origin": "*"
+    },
+    hot: true,
+    hotOnly: true
+  }
+};
\ No newline at end of file
diff --git a/airavata_mft/settings.py b/airavata_mft/settings.py
index 5bde881..1a53e67 100644
--- a/airavata_mft/settings.py
+++ b/airavata_mft/settings.py
@@ -14,7 +14,7 @@ import os
 
 # Build paths inside the project like this: os.path.join(BASE_DIR, ...)
 BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
-
+FRONTEND_DIR = os.path.join(BASE_DIR, 'airavata_mft', 'apps', 'workspace')
 
 # Quick-start development settings - unsuitable for production
 # See https://docs.djangoproject.com/en/3.0/howto/deployment/checklist/
@@ -38,7 +38,8 @@ INSTALLED_APPS = [
     'django.contrib.messages',
     'django.contrib.staticfiles',
     'rest_framework',
-    'airavata_mft.apps.workspace'
+    'airavata_mft.apps.workspace',
+    'webpack_loader',
 ]
 
 MIDDLEWARE = [
@@ -120,6 +121,23 @@ USE_TZ = True
 # https://docs.djangoproject.com/en/3.0/howto/static-files/
 
 STATICFILES_DIRS = [
-    os.path.join(BASE_DIR, "airavata_mft/static")
+    os.path.join(BASE_DIR, "airavata_mft", "static"),
+    os.path.join(BASE_DIR, "airavata_mft", "apps", "workspace", "static")
 ]
 STATIC_URL = '/static/'
+
+# Webpack loader
+WEBPACK_LOADER = {
+    'DEFAULT': {
+        'BUNDLE_DIR_NAME': 'airavata_mft_workspace/dist/',
+        'STATS_FILE': os.path.join(
+            BASE_DIR,
+            'airavata_mft',
+            'apps',
+            'workspace',
+            'static',
+            'airavata_mft_workspace',
+            'dist',
+            'webpack-stats.json'),
+    },
+}
diff --git a/airavata_mft/static/common/.gitignore b/airavata_mft/static/common/.gitignore
new file mode 100644
index 0000000..a0dddc6
--- /dev/null
+++ b/airavata_mft/static/common/.gitignore
@@ -0,0 +1,21 @@
+.DS_Store
+node_modules
+/dist
+
+# local env files
+.env.local
+.env.*.local
+
+# Log files
+npm-debug.log*
+yarn-debug.log*
+yarn-error.log*
+
+# Editor directories and files
+.idea
+.vscode
+*.suo
+*.ntvs*
+*.njsproj
+*.sln
+*.sw?
diff --git a/airavata_mft/static/common/README.md b/airavata_mft/static/common/README.md
new file mode 100644
index 0000000..15d4eff
--- /dev/null
+++ b/airavata_mft/static/common/README.md
@@ -0,0 +1,24 @@
+# common
+
+## Project setup
+```
+npm install
+```
+
+### Compiles and hot-reloads for development
+```
+npm run serve
+```
+
+### Compiles and minifies for production
+```
+npm run build
+```
+
+### Lints and fixes files
+```
+npm run lint
+```
+
+### Customize configuration
+See [Configuration Reference](https://cli.vuejs.org/config/).
diff --git a/airavata_mft/static/common/babel.config.js b/airavata_mft/static/common/babel.config.js
new file mode 100644
index 0000000..e955840
--- /dev/null
+++ b/airavata_mft/static/common/babel.config.js
@@ -0,0 +1,5 @@
+module.exports = {
+  presets: [
+    '@vue/cli-plugin-babel/preset'
+  ]
+}
diff --git a/airavata_mft/static/common/js/cms.js b/airavata_mft/static/common/js/cms.js
new file mode 100644
index 0000000..bd9d46f
--- /dev/null
+++ b/airavata_mft/static/common/js/cms.js
@@ -0,0 +1,13 @@
+import bootstrap from "bootstrap"; // eslint-disable-line no-unused-vars
+import $ from "jquery";
+
+import "bootstrap/dist/css/bootstrap.css";
+import "@fortawesome/fontawesome-free/css/all.css";
+
+$(function() {
+  $('[data-toggle="tooltip"]').tooltip();
+});
+
+$('.carousel').carousel({
+  interval: 2000
+})
\ No newline at end of file
diff --git a/airavata_mft/static/common/js/main.js b/airavata_mft/static/common/js/main.js
new file mode 100644
index 0000000..91576ce
--- /dev/null
+++ b/airavata_mft/static/common/js/main.js
@@ -0,0 +1,10 @@
+import bootstrap from "bootstrap"; // eslint-disable-line no-unused-vars
+import $ from "jquery";
+
+// Expose jQuery on the global object
+window.$ = window.jQuery = $;
+
+import "bootstrap/dist/css/bootstrap.css";
+$(function() {
+  $('[data-toggle="tooltip"]').tooltip();
+});
\ No newline at end of file
diff --git a/airavata_mft/apps/workspace/static/airavata_mft_workspace/js/containers/StorageUnitListContainer.vue b/airavata_mft/static/common/js/notices.js
similarity index 100%
rename from airavata_mft/apps/workspace/static/airavata_mft_workspace/js/containers/StorageUnitListContainer.vue
rename to airavata_mft/static/common/js/notices.js
diff --git a/airavata_mft/static/common/main.js b/airavata_mft/static/common/main.js
new file mode 100644
index 0000000..73999b9
--- /dev/null
+++ b/airavata_mft/static/common/main.js
@@ -0,0 +1,17 @@
+import bootstrap from "bootstrap"; // eslint-disable-line no-unused-vars
+import $ from "jquery";
+
+// Expose jQuery on the global object
+window.$ = window.jQuery = $;
+
+import "bootstrap/dist/css/bootstrap.css";
+import "@fortawesome/fontawesome-free/css/all.css";
+import "../scss/main.scss";
+$(function() {
+  $('[data-toggle="tooltip"]').tooltip();
+});
+
+// CMS integration
+// $('.carousel').carousel({
+//   interval: 2000
+// })
\ No newline at end of file
diff --git a/airavata_mft/apps/workspace/package-lock.json b/airavata_mft/static/common/package-lock.json
similarity index 98%
copy from airavata_mft/apps/workspace/package-lock.json
copy to airavata_mft/static/common/package-lock.json
index b56ef55..90a3092 100644
--- a/airavata_mft/apps/workspace/package-lock.json
+++ b/airavata_mft/static/common/package-lock.json
@@ -1,5 +1,5 @@
 {
-  "name": "workspace",
+  "name": "common",
   "version": "0.1.0",
   "lockfileVersion": 1,
   "requires": true,
@@ -973,6 +973,11 @@
         "to-fast-properties": "^2.0.0"
       }
     },
+    "@fortawesome/fontawesome-free": {
+      "version": "5.13.0",
+      "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-free/-/fontawesome-free-5.13.0.tgz",
+      "integrity": "sha512-xKOeQEl5O47GPZYIMToj6uuA2syyFlq9EMSl2ui0uytjY9xbe8XS0pexNWmxrdcCyNGyDmLyYw5FtKsalBUeOg=="
+    },
     "@hapi/address": {
       "version": "2.1.4",
       "resolved": "https://registry.npmjs.org/@hapi/address/-/address-2.1.4.tgz",
@@ -1039,6 +1044,16 @@
       "integrity": "sha512-shAmDyaQC4H92APFoIaVDHCx5bStIocgvbwQyxPRrbUY20V1EYTbSDchWbuwlMG3V17cprZhA6+78JfB+3DTPw==",
       "dev": true
     },
+    "@nuxt/opencollective": {
+      "version": "0.2.2",
+      "resolved": "https://registry.npmjs.org/@nuxt/opencollective/-/opencollective-0.2.2.tgz",
+      "integrity": "sha512-ie50SpS47L+0gLsW4yP23zI/PtjsDRglyozX2G09jeiUazC1AJlGPZo0JUs9iuCDUoIgsDEf66y7/bSfig0BpA==",
+      "requires": {
+        "chalk": "^2.4.1",
+        "consola": "^2.3.0",
+        "node-fetch": "^2.3.0"
+      }
+    },
     "@soda/friendly-errors-webpack-plugin": {
       "version": "1.7.1",
       "resolved": "https://registry.npmjs.org/@soda/friendly-errors-webpack-plugin/-/friendly-errors-webpack-plugin-1.7.1.tgz",
@@ -1161,9 +1176,9 @@
       "dev": true
     },
     "@types/node": {
-      "version": "13.11.0",
-      "resolved": "https://registry.npmjs.org/@types/node/-/node-13.11.0.tgz",
-      "integrity": "sha512-uM4mnmsIIPK/yeO+42F2RQhGUIs39K2RFmugcJANppXe6J1nvH87PvzPZYpza7Xhhs8Yn9yIAVdLZ84z61+0xQ==",
+      "version": "13.11.1",
+      "resolved": "https://registry.npmjs.org/@types/node/-/node-13.11.1.tgz",
+      "integrity": "sha512-eWQGP3qtxwL8FGneRrC5DwrJLGN4/dH1clNTuLfN81HCrxVtxRjygDTUoZJ5ASlDEeo0ppYFQjQIlXhtXpOn6g==",
       "dev": true
     },
     "@types/normalize-package-data": {
@@ -1568,9 +1583,9 @@
       }
     },
     "@vue/component-compiler-utils": {
-      "version": "3.1.1",
-      "resolved": "https://registry.npmjs.org/@vue/component-compiler-utils/-/component-compiler-utils-3.1.1.tgz",
-      "integrity": "sha512-+lN3nsfJJDGMNz7fCpcoYIORrXo0K3OTsdr8jCM7FuqdI4+70TY6gxY6viJ2Xi1clqyPg7LpeOWwjF31vSMmUw==",
+      "version": "3.1.2",
+      "resolved": "https://registry.npmjs.org/@vue/component-compiler-utils/-/component-compiler-utils-3.1.2.tgz",
+      "integrity": "sha512-QLq9z8m79mCinpaEeSURhnNCN6djxpHw0lpP/bodMlt5kALfONpryMthvnrQOlTcIKoF+VoPi+lPHUYeDFPXug==",
       "dev": true,
       "requires": {
         "consolidate": "^0.15.1",
@@ -1926,7 +1941,6 @@
       "version": "3.2.1",
       "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
       "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
-      "dev": true,
       "requires": {
         "color-convert": "^1.9.0"
       }
@@ -2382,6 +2396,23 @@
       "integrity": "sha1-aN/1++YMUes3cl6p4+0xDcwed24=",
       "dev": true
     },
+    "bootstrap": {
+      "version": "4.4.1",
+      "resolved": "https://registry.npmjs.org/bootstrap/-/bootstrap-4.4.1.tgz",
+      "integrity": "sha512-tbx5cHubwE6e2ZG7nqM3g/FZ5PQEDMWmMGNrCUBVRPHXTJaH7CBDdsLeu3eCh3B1tzAxTnAbtmrzvWEvT2NNEA=="
+    },
+    "bootstrap-vue": {
+      "version": "2.0.0-rc.26",
+      "resolved": "https://registry.npmjs.org/bootstrap-vue/-/bootstrap-vue-2.0.0-rc.26.tgz",
+      "integrity": "sha512-AzN+IRTmfR9rLFWNGt+v2XPmQjZiAlH4x5z2kStA3UoJ5LR91K34iZ8apaa6isDo+DfWDcwH4q7OwHM+VNxWwg==",
+      "requires": {
+        "@nuxt/opencollective": "^0.2.2",
+        "bootstrap": "^4.3.1",
+        "popper.js": "^1.15.0",
+        "portal-vue": "^2.1.5",
+        "vue-functional-data-merge": "^3.1.0"
+      }
+    },
     "brace-expansion": {
       "version": "1.1.11",
       "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
@@ -2756,9 +2787,9 @@
       }
     },
     "caniuse-lite": {
-      "version": "1.0.30001039",
-      "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001039.tgz",
-      "integrity": "sha512-SezbWCTT34eyFoWHgx8UWso7YtvtM7oosmFoXbCkdC6qJzRfBTeTgE9REtKtiuKXuMwWTZEvdnFNGAyVMorv8Q==",
+      "version": "1.0.30001040",
+      "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001040.tgz",
+      "integrity": "sha512-Ep0tEPeI5wCvmJNrXjE3etgfI+lkl1fTDU6Y3ZH1mhrjkPlVI9W4pcKbMo+BQLpEWKVYYp2EmYaRsqpPC3k7lQ==",
       "dev": true
     },
     "case-sensitive-paths-webpack-plugin": {
@@ -2777,7 +2808,6 @@
       "version": "2.4.2",
       "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
       "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
-      "dev": true,
       "requires": {
         "ansi-styles": "^3.2.1",
         "escape-string-regexp": "^1.0.5",
@@ -2980,6 +3010,16 @@
       "integrity": "sha1-/xnt6Kml5XkyQUewwR8PvLq+1jk=",
       "dev": true
     },
+    "clipboard": {
+      "version": "2.0.6",
+      "resolved": "https://registry.npmjs.org/clipboard/-/clipboard-2.0.6.tgz",
+      "integrity": "sha512-g5zbiixBRk/wyKakSwCKd7vQXDjFnAMGHoEyBogG/bw9kTD9GvdAvaoRR1ALcEzt3pVKxZR0pViekPMIS0QyGg==",
+      "requires": {
+        "good-listener": "^1.2.2",
+        "select": "^1.1.2",
+        "tiny-emitter": "^2.0.0"
+      }
+    },
     "clipboardy": {
       "version": "2.3.0",
       "resolved": "https://registry.npmjs.org/clipboardy/-/clipboardy-2.3.0.tgz",
@@ -3057,7 +3097,6 @@
       "version": "1.9.3",
       "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
       "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==",
-      "dev": true,
       "requires": {
         "color-name": "1.1.3"
       }
@@ -3065,8 +3104,7 @@
     "color-name": {
       "version": "1.1.3",
       "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
-      "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=",
-      "dev": true
+      "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU="
     },
     "color-string": {
       "version": "1.5.3",
@@ -3176,6 +3214,11 @@
       "integrity": "sha512-e54B99q/OUoH64zYYRf3HBP5z24G38h5D3qXu23JGRoigpX5Ss4r9ZnDk3g0Z8uQC2x2lPaJ+UlWBc1ZWBWdLg==",
       "dev": true
     },
+    "consola": {
+      "version": "2.11.3",
+      "resolved": "https://registry.npmjs.org/consola/-/consola-2.11.3.tgz",
+      "integrity": "sha512-aoW0YIIAmeftGR8GSpw6CGQluNdkWMWh3yEFjH/hmynTYnMtibXszii3lxCXmk8YxJtI3FAK5aTiquA5VH68Gw=="
+    },
     "console-browserify": {
       "version": "1.2.0",
       "resolved": "https://registry.npmjs.org/console-browserify/-/console-browserify-1.2.0.tgz",
@@ -3334,17 +3377,17 @@
       }
     },
     "core-js": {
-      "version": "3.6.4",
-      "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.6.4.tgz",
-      "integrity": "sha512-4paDGScNgZP2IXXilaffL9X7968RuvwlkK3xWtZRVqgd8SYNiVKRJvkFd1aqqEuPfN7E68ZHEp9hDj6lHj4Hyw=="
+      "version": "3.6.5",
+      "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.6.5.tgz",
+      "integrity": "sha512-vZVEEwZoIsI+vPEuoF9Iqf5H7/M3eeQqWlQnYa8FSKKePuYTf5MWnxb5SDAzCa60b3JBRS5g9b+Dq7b1y/RCrA=="
     },
     "core-js-compat": {
-      "version": "3.6.4",
-      "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.6.4.tgz",
-      "integrity": "sha512-zAa3IZPvsJ0slViBQ2z+vgyyTuhd3MFn1rBQjZSKVEgB0UMYhUkCj9jJUVPgGTGqWvsBVmfnruXgTcNyTlEiSA==",
+      "version": "3.6.5",
+      "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.6.5.tgz",
+      "integrity": "sha512-7ItTKOhOZbznhXAQ2g/slGg1PJV5zDO/WdkTwi7UEOJmkvsE32PWvx6mKtDjiMpjnR2CNf6BAD6sSxIlv7ptng==",
       "dev": true,
       "requires": {
-        "browserslist": "^4.8.3",
+        "browserslist": "^4.8.5",
         "semver": "7.0.0"
       },
       "dependencies": {
@@ -3472,9 +3515,9 @@
       }
     },
     "css-loader": {
-      "version": "3.5.1",
-      "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-3.5.1.tgz",
-      "integrity": "sha512-0G4CbcZzQ9D1Q6ndOfjFuMDo8uLYMu5vc9Abs5ztyHcKvmil6GJrMiNjzzi3tQvUF+mVRuDg7bE6Oc0Prolgig==",
+      "version": "3.5.2",
+      "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-3.5.2.tgz",
+      "integrity": "sha512-hDL0DPopg6zQQSRlZm0hyeaqIRnL0wbWjay9BZxoiJBpbfOW4WHfbaYQhwnDmEa0kZUc1CJ3IFo15ot1yULMIQ==",
       "dev": true,
       "requires": {
         "camelcase": "^5.3.1",
@@ -3714,6 +3757,12 @@
         "regexp.prototype.flags": "^1.2.0"
       }
     },
+    "deep-extend": {
+      "version": "0.6.0",
+      "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz",
+      "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==",
+      "dev": true
+    },
     "deep-is": {
       "version": "0.1.3",
       "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz",
@@ -3950,6 +3999,11 @@
       "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=",
       "dev": true
     },
+    "delegate": {
+      "version": "3.2.0",
+      "resolved": "https://registry.npmjs.org/delegate/-/delegate-3.2.0.tgz",
+      "integrity": "sha512-IofjkYBZaZivn0V8nnsMJGBr4jVLxHDheKSW88PyxS5QC4Vo9ZbZVvhzlSxY87fVq3STR6r+4cGepyHkcWOQSw=="
+    },
     "depd": {
       "version": "1.1.2",
       "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz",
@@ -4158,9 +4212,9 @@
       "dev": true
     },
     "electron-to-chromium": {
-      "version": "1.3.398",
-      "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.398.tgz",
-      "integrity": "sha512-BJjxuWLKFbM5axH3vES7HKMQgAknq9PZHBkMK/rEXUQG9i1Iw5R+6hGkm6GtsQSANjSUrh/a6m32nzCNDNo/+w==",
+      "version": "1.3.403",
+      "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.403.tgz",
+      "integrity": "sha512-JaoxV4RzdBAZOnsF4dAlZ2ijJW72MbqO5lNfOBHUWiBQl3Rwe+mk2RCUMrRI3rSClLJ8HSNQNqcry12H+0ZjFw==",
       "dev": true
     },
     "elliptic": {
@@ -4300,8 +4354,7 @@
     "escape-string-regexp": {
       "version": "1.0.5",
       "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
-      "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=",
-      "dev": true
+      "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ="
     },
     "eslint": {
       "version": "6.8.0",
@@ -5780,6 +5833,14 @@
         "slash": "^2.0.0"
       }
     },
+    "good-listener": {
+      "version": "1.2.2",
+      "resolved": "https://registry.npmjs.org/good-listener/-/good-listener-1.2.2.tgz",
+      "integrity": "sha1-1TswzfkxPf+33JoNR3CWqm0UXFA=",
+      "requires": {
+        "delegate": "^3.1.2"
+      }
+    },
     "graceful-fs": {
       "version": "4.2.3",
       "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.3.tgz",
@@ -5847,8 +5908,7 @@
     "has-flag": {
       "version": "3.0.0",
       "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
-      "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=",
-      "dev": true
+      "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0="
     },
     "has-symbols": {
       "version": "1.0.1",
@@ -6810,6 +6870,11 @@
         }
       }
     },
+    "jquery": {
+      "version": "3.5.0",
+      "resolved": "https://registry.npmjs.org/jquery/-/jquery-3.5.0.tgz",
+      "integrity": "sha512-Xb7SVYMvygPxbFMpTFQiHh1J7HClEaThguL15N/Gg37Lri/qKyhRGZYzHRyLH8Stq3Aow0LsHO2O2ci86fCrNQ=="
+    },
     "js-message": {
       "version": "1.0.5",
       "resolved": "https://registry.npmjs.org/js-message/-/js-message-1.0.5.tgz",
@@ -7613,6 +7678,11 @@
         "lower-case": "^1.1.1"
       }
     },
+    "node-fetch": {
+      "version": "2.6.0",
+      "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.0.tgz",
+      "integrity": "sha512-8dG4H5ujfvFiqDmVu9fQ5bOHUC15JMjMY/Zumv26oOvvVJjM67KF8koCWIabKQ1GJIa9r2mMZscBq/TbdOcmNA=="
+    },
     "node-forge": {
       "version": "0.9.0",
       "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-0.9.0.tgz",
@@ -8321,6 +8391,16 @@
         "ts-pnp": "^1.1.6"
       }
     },
+    "popper.js": {
+      "version": "1.16.1",
+      "resolved": "https://registry.npmjs.org/popper.js/-/popper.js-1.16.1.tgz",
+      "integrity": "sha512-Wb4p1J4zyFTbM+u6WuO4XstYx4Ky9Cewe4DWrel7B0w6VVICvPwdOpotjzcf6eD8TsckVnIMNONQyPIUFOUbCQ=="
+    },
+    "portal-vue": {
+      "version": "2.1.7",
+      "resolved": "https://registry.npmjs.org/portal-vue/-/portal-vue-2.1.7.tgz",
+      "integrity": "sha512-+yCno2oB3xA7irTt0EU5Ezw22L2J51uKAacE/6hMPMoO/mx3h4rXFkkBkT4GFsMDv/vEe8TNKC3ujJJ0PTwb6g=="
+    },
     "portfinder": {
       "version": "1.0.25",
       "resolved": "https://registry.npmjs.org/portfinder/-/portfinder-1.0.25.tgz",
@@ -8949,7 +9029,8 @@
       "version": "1.19.1",
       "resolved": "https://registry.npmjs.org/prettier/-/prettier-1.19.1.tgz",
       "integrity": "sha512-s7PoyDv/II1ObgQunCbB9PdLmUcBZcnWOcxDh7O0N/UwDEsHyqkW+Qh28jW+mVuCdx7gLB0BotYI1Y6uI9iyew==",
-      "dev": true
+      "dev": true,
+      "optional": true
     },
     "pretty-error": {
       "version": "2.1.1",
@@ -9576,6 +9657,11 @@
         "ajv-keywords": "^3.4.1"
       }
     },
+    "select": {
+      "version": "1.1.2",
+      "resolved": "https://registry.npmjs.org/select/-/select-1.1.2.tgz",
+      "integrity": "sha1-DnNQrN7ICxEIUoeG7B1EGNEbOW0="
+    },
     "select-hose": {
       "version": "2.0.0",
       "resolved": "https://registry.npmjs.org/select-hose/-/select-hose-2.0.0.tgz",
@@ -10282,9 +10368,9 @@
       }
     },
     "string.prototype.trimend": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.0.tgz",
-      "integrity": "sha512-EEJnGqa/xNfIg05SxiPSqRS7S9qwDhYts1TSLR1BQfYUfPe1stofgGKvwERK9+9yf+PpfBMlpBaCHucXGPQfUA==",
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.1.tgz",
+      "integrity": "sha512-LRPxFUaTtpqYsTeNKaFOw3R4bxIzWOnbQ837QfBylo8jIxtcbK/A/sMV7Q+OAV/vWo+7s25pOE10KYSjaSO06g==",
       "dev": true,
       "requires": {
         "define-properties": "^1.1.3",
@@ -10314,9 +10400,9 @@
       }
     },
     "string.prototype.trimstart": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.0.tgz",
-      "integrity": "sha512-iCP8g01NFYiiBOnwG1Xc3WZLyoo+RuBymwIlWncShXDDJYWN6DbnM3odslBJdgCdRlq94B5s63NWAZlcn2CS4w==",
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.1.tgz",
+      "integrity": "sha512-XxZn+QpvrBI1FOcg6dIpxUPgWCPuNXvMD72aaRaUQv1eD4e/Qy8i/hFTe0BUmD60p/QA6bh1avmuPTfNjqVWRw==",
       "dev": true,
       "requires": {
         "define-properties": "^1.1.3",
@@ -10401,7 +10487,6 @@
       "version": "5.5.0",
       "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
       "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
-      "dev": true,
       "requires": {
         "has-flag": "^3.0.0"
       }
@@ -10486,9 +10571,9 @@
       "dev": true
     },
     "terser": {
-      "version": "4.6.10",
-      "resolved": "https://registry.npmjs.org/terser/-/terser-4.6.10.tgz",
-      "integrity": "sha512-qbF/3UOo11Hggsbsqm2hPa6+L4w7bkr+09FNseEe8xrcVD3APGLFqE+Oz1ZKAxjYnFsj80rLOfgAtJ0LNJjtTA==",
+      "version": "4.6.11",
+      "resolved": "https://registry.npmjs.org/terser/-/terser-4.6.11.tgz",
+      "integrity": "sha512-76Ynm7OXUG5xhOpblhytE7X58oeNSmC8xnNhjWVo8CksHit0U0kO4hfNbPrrYwowLWFgM2n9L176VNx2QaHmtA==",
       "dev": true,
       "requires": {
         "commander": "^2.20.0",
@@ -10612,6 +10697,11 @@
       "integrity": "sha1-QFQRqOfmM5/mTbmiNN4R3DHgK9Q=",
       "dev": true
     },
+    "tiny-emitter": {
+      "version": "2.1.0",
+      "resolved": "https://registry.npmjs.org/tiny-emitter/-/tiny-emitter-2.1.0.tgz",
+      "integrity": "sha512-NB6Dk1A9xgQPMoGqC5CVXn123gWyte215ONT5Pp5a0yt4nlEoO1ZWeCwpncaekPHXO60i47ihFnZPiRPjRMq4Q=="
+    },
     "tmp": {
       "version": "0.0.33",
       "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz",
@@ -11120,6 +11210,11 @@
         }
       }
     },
+    "vue-functional-data-merge": {
+      "version": "3.1.0",
+      "resolved": "https://registry.npmjs.org/vue-functional-data-merge/-/vue-functional-data-merge-3.1.0.tgz",
+      "integrity": "sha512-leT4kdJVQyeZNY1kmnS1xiUlQ9z1B/kdBFCILIjYYQDqZgLqCLa0UhjSSeRX6c3mUe6U5qYeM8LrEqkHJ1B4LA=="
+    },
     "vue-hot-reload-api": {
       "version": "2.3.4",
       "resolved": "https://registry.npmjs.org/vue-hot-reload-api/-/vue-hot-reload-api-2.3.4.tgz",
@@ -11283,6 +11378,28 @@
         }
       }
     },
+    "webpack-bundle-tracker": {
+      "version": "0.4.3",
+      "resolved": "https://registry.npmjs.org/webpack-bundle-tracker/-/webpack-bundle-tracker-0.4.3.tgz",
+      "integrity": "sha512-Sl/+OsNhFAH3/c6XADupRu8jLvGojfXX0pZIIm3O5ZcJqkHHqlY4nLG+NVRcbDgM/jOeWimKDGQMVEa8FBeJ2g==",
+      "dev": true,
+      "requires": {
+        "deep-extend": "^0.6.0",
+        "mkdirp": "^0.5.1",
+        "strip-ansi": "^5.2.0"
+      },
+      "dependencies": {
+        "strip-ansi": {
+          "version": "5.2.0",
+          "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz",
+          "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==",
+          "dev": true,
+          "requires": {
+            "ansi-regex": "^4.1.0"
+          }
+        }
+      }
+    },
     "webpack-chain": {
       "version": "6.4.0",
       "resolved": "https://registry.npmjs.org/webpack-chain/-/webpack-chain-6.4.0.tgz",
diff --git a/airavata_mft/apps/workspace/package.json b/airavata_mft/static/common/package.json
similarity index 66%
copy from airavata_mft/apps/workspace/package.json
copy to airavata_mft/static/common/package.json
index a20305a..b4b73e0 100644
--- a/airavata_mft/apps/workspace/package.json
+++ b/airavata_mft/static/common/package.json
@@ -1,5 +1,5 @@
 {
-  "name": "workspace",
+  "name": "common",
   "version": "0.1.0",
   "private": true,
   "scripts": {
@@ -9,7 +9,12 @@
   },
   "dependencies": {
     "core-js": "^3.6.4",
-    "vue": "^2.6.11"
+    "vue": "^2.6.11",
+    "@fortawesome/fontawesome-free": "^5.6.3",
+    "bootstrap": "^4.3.1",
+    "bootstrap-vue": "2.0.0-rc.26",
+    "clipboard": "^2.0.4",
+    "jquery": "^3.5.0"
   },
   "devDependencies": {
     "@vue/cli-plugin-babel": "~4.3.0",
@@ -18,7 +23,11 @@
     "babel-eslint": "^10.1.0",
     "eslint": "^6.7.2",
     "eslint-plugin-vue": "^6.2.2",
-    "vue-template-compiler": "^2.6.11"
+    "vue-template-compiler": "^2.6.11",
+    "webpack": "^4.28.4",
+    "webpack-bundle-tracker": "^0.4.2-beta",
+    "webpack-dev-middleware": "^3.5.1",
+    "webpack-dev-server": "^3.1.14"
   },
   "eslintConfig": {
     "root": true,
diff --git a/airavata_mft/static/common/vue.config.js b/airavata_mft/static/common/vue.config.js
new file mode 100644
index 0000000..e2fded0
--- /dev/null
+++ b/airavata_mft/static/common/vue.config.js
@@ -0,0 +1,19 @@
+const BundleTracker = require("webpack-bundle-tracker");
+
+module.exports = {
+  publicPath: "/static/common/dist/",
+  productionSourceMap: false,
+  pages: {
+    app: "./js/main.js",
+    cms: "./js/cms.js",
+    notices: "./js/notices.js"
+  },
+  configureWebpack: {
+    plugins: [
+      new BundleTracker({
+        filename: "webpack-stats.json",
+        path: "./dist/"
+      })
+    ]
+  }
+};
\ No newline at end of file
diff --git a/airavata_mft/templates/base.html b/airavata_mft/templates/base.html
index 59731c1..c951299 100644
--- a/airavata_mft/templates/base.html
+++ b/airavata_mft/templates/base.html
@@ -74,11 +74,11 @@
 
         <main role="main" class="col-md-9 ml-sm-auto col-lg-10 px-4">
           <div class="d-flex justify-content-between flex-wrap flex-md-nowrap align-items-center pt-3 pb-2 mb-3 border-bottom">
-            <h1 class="h2">{% block title %}Dashboard{% endblock title %}</h1>
+             {% block app %}
+             {% endblock app %}
           </div>
         </main>
-        {% block app %}
-        {% endblock app %}
+
 
     <!-- Icons -->
     <script src="https://unpkg.com/feather-icons/dist/feather.min.js"></script>
diff --git a/requirements.txt b/requirements.txt
index 11fef13..c095d88 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -2,3 +2,4 @@ Django==3.0.4
 djangorestframework==3.11.0
 grpcio==1.27.2
 googleapis-common-protos==1.51.0
+django-webpack-loader==0.7.0