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 2018/09/25 23:27:40 UTC

[airavata-django-portal] 01/02: AIRAVATA-2840 Add copy ssh key link

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

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

commit f5328b968a71391212fb7e2c1b7dd6273cae388a
Author: Marcus Christie <ma...@iu.edu>
AuthorDate: Tue Sep 25 12:37:41 2018 -0400

    AIRAVATA-2840 Add copy ssh key link
---
 django_airavata/apps/admin/package-lock.json       | 41 ++++++++++++++
 django_airavata/apps/admin/package.json            |  2 +
 .../src/components/commons/ClipboardCopyLink.vue   | 43 ++++++++++++++
 .../dashboards/CredentialStoreDashboard.vue        |  7 ++-
 .../admin/static/django_airavata_admin/src/main.js | 65 +++++++++++-----------
 5 files changed, 122 insertions(+), 36 deletions(-)

diff --git a/django_airavata/apps/admin/package-lock.json b/django_airavata/apps/admin/package-lock.json
index 4559986..810624c 100644
--- a/django_airavata/apps/admin/package-lock.json
+++ b/django_airavata/apps/admin/package-lock.json
@@ -17,6 +17,14 @@
         "@fortawesome/fontawesome-common-types": "^0.2.4"
       }
     },
+    "@fortawesome/free-regular-svg-icons": {
+      "version": "5.3.1",
+      "resolved": "https://registry.npmjs.org/@fortawesome/free-regular-svg-icons/-/free-regular-svg-icons-5.3.1.tgz",
+      "integrity": "sha512-ZHMohHUxPSEUeqc7LOmO5jdeI3vlQLDgSCYR4MYk6oN7C3X59vUadLefnvctMTJyF5NWYxDbaj90ulvickDnsQ==",
+      "requires": {
+        "@fortawesome/fontawesome-common-types": "^0.2.4"
+      }
+    },
     "@fortawesome/free-solid-svg-icons": {
       "version": "5.3.1",
       "resolved": "https://registry.npmjs.org/@fortawesome/free-solid-svg-icons/-/free-solid-svg-icons-5.3.1.tgz",
@@ -2085,6 +2093,16 @@
       "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-2.2.0.tgz",
       "integrity": "sha1-/xnt6Kml5XkyQUewwR8PvLq+1jk="
     },
+    "clipboard": {
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/clipboard/-/clipboard-2.0.1.tgz",
+      "integrity": "sha512-7yhQBmtN+uYZmfRjjVjKa0dZdWuabzpSKGtyQZN+9C8xlC788SSJjOHWh7tzurfwTqTD5UDYAhIv5fRJg3sHjQ==",
+      "requires": {
+        "good-listener": "^1.2.2",
+        "select": "^1.1.2",
+        "tiny-emitter": "^2.0.0"
+      }
+    },
     "cliui": {
       "version": "2.1.0",
       "resolved": "https://registry.npmjs.org/cliui/-/cliui-2.1.0.tgz",
@@ -2817,6 +2835,11 @@
       "integrity": "sha1-yY2bzvdWdBiOEQlpFRGZ45sfppM=",
       "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",
@@ -13688,6 +13711,14 @@
         "slash": "^1.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"
+      }
+    },
     "got": {
       "version": "8.3.2",
       "resolved": "https://registry.npmjs.org/got/-/got-8.3.2.tgz",
@@ -18349,6 +18380,11 @@
         "ajv": "^5.0.0"
       }
     },
+    "select": {
+      "version": "1.1.2",
+      "resolved": "https://registry.npmjs.org/select/-/select-1.1.2.tgz",
+      "integrity": "sha1-DnNQrN7ICxEIUoeG7B1EGNEbOW0="
+    },
     "semver": {
       "version": "5.5.1",
       "resolved": "https://registry.npmjs.org/semver/-/semver-5.5.1.tgz",
@@ -18952,6 +18988,11 @@
         "setimmediate": "^1.0.4"
       }
     },
+    "tiny-emitter": {
+      "version": "2.0.2",
+      "resolved": "https://registry.npmjs.org/tiny-emitter/-/tiny-emitter-2.0.2.tgz",
+      "integrity": "sha512-2NM0auVBGft5tee/OxP4PI3d8WItkDM+fPnaRAVo6xTDI2knbz9eC5ArWGqtGlYqiH3RU5yMpdyTTO7MguC4ow=="
+    },
     "tmp": {
       "version": "0.0.33",
       "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz",
diff --git a/django_airavata/apps/admin/package.json b/django_airavata/apps/admin/package.json
index dc6a771..fc3d00f 100644
--- a/django_airavata/apps/admin/package.json
+++ b/django_airavata/apps/admin/package.json
@@ -12,10 +12,12 @@
   },
   "dependencies": {
     "@fortawesome/fontawesome-svg-core": "^1.2.4",
+    "@fortawesome/free-regular-svg-icons": "^5.3.1",
     "@fortawesome/free-solid-svg-icons": "^5.3.1",
     "@fortawesome/vue-fontawesome": "^0.1.1",
     "bootstrap": "^4.0.0",
     "bootstrap-vue": "^2.0.0-rc.11",
+    "clipboard": "^2.0.1",
     "django-airavata-api": "file:../api",
     "django-airavata-common-ui": "file:../../static/common",
     "moment": "^2.22.2",
diff --git a/django_airavata/apps/admin/static/django_airavata_admin/src/components/commons/ClipboardCopyLink.vue b/django_airavata/apps/admin/static/django_airavata_admin/src/components/commons/ClipboardCopyLink.vue
new file mode 100644
index 0000000..0cf6946
--- /dev/null
+++ b/django_airavata/apps/admin/static/django_airavata_admin/src/components/commons/ClipboardCopyLink.vue
@@ -0,0 +1,43 @@
+<template>
+  <div style="display: inline-block">
+    <b-link ref="copyLink" :data-clipboard-text="text">
+      Copy Key
+      <font-awesome-icon :icon="['far','clipboard']"></font-awesome-icon>
+    </b-link>
+    <b-tooltip :show="show" :disabled="!show" :target="() => $refs.copyLink">Copied!</b-tooltip>
+  </div>
+</template>
+
+<script>
+import ClipboardJS from "clipboard";
+
+export default {
+  name: "clipboard-copy-link",
+  props: {
+    text: {
+      type: String,
+      required: true
+    }
+  },
+  data() {
+    return {
+      show: false
+    };
+  },
+  mounted() {
+    let clipboard = new ClipboardJS(this.$refs.copyLink);
+    clipboard.on("success", this.onCopySuccess);
+  },
+  destroyed() {
+    let clipboard = new ClipboardJS(this.$refs.copyLink);
+    clipboard.destroy();
+  },
+  methods: {
+    onCopySuccess(e) {
+      this.show = true;
+      setTimeout(() => (this.show = false), 2000);
+    }
+  }
+};
+</script>
+
diff --git a/django_airavata/apps/admin/static/django_airavata_admin/src/components/dashboards/CredentialStoreDashboard.vue b/django_airavata/apps/admin/static/django_airavata_admin/src/components/dashboards/CredentialStoreDashboard.vue
index 04ba927..7dca361 100644
--- a/django_airavata/apps/admin/static/django_airavata_admin/src/components/dashboards/CredentialStoreDashboard.vue
+++ b/django_airavata/apps/admin/static/django_airavata_admin/src/components/dashboards/CredentialStoreDashboard.vue
@@ -4,7 +4,8 @@
 
       <b-table striped hover :fields="fields" :items="slotProps.items">
         <template slot="action" slot-scope="data">
-          <delete-link @delete="deleteSSHCredential(data.item)">
+          <clipboard-copy-link :text="data.item.publicKey" class="mr-1" />
+          <delete-link v-if="data.item.userHasWriteAccess" @delete="deleteSSHCredential(data.item)">
             Are you sure you want to delete this SSH credential?
           </delete-link>
         </template>
@@ -17,11 +18,13 @@
 import { services } from "django-airavata-api";
 import { components, layouts } from "django-airavata-common-ui";
 import moment from "moment";
+import ClipboardCopyLink from "../commons/ClipboardCopyLink.vue";
 
 export default {
   components: {
     "delete-link": components.DeleteLink,
-    "list-layout": layouts.ListLayout
+    "list-layout": layouts.ListLayout,
+    ClipboardCopyLink
   },
   created: function() {
     this.fetchSSHKeys();
diff --git a/django_airavata/apps/admin/static/django_airavata_admin/src/main.js b/django_airavata/apps/admin/static/django_airavata_admin/src/main.js
index f327b95..78d1a81 100644
--- a/django_airavata/apps/admin/static/django_airavata_admin/src/main.js
+++ b/django_airavata/apps/admin/static/django_airavata_admin/src/main.js
@@ -1,39 +1,38 @@
-import Vue from 'vue';
-import VueResource from 'vue-resource';
-import VueRouter from 'vue-router';
-
-import ExperimentsDashboard from './components/dashboards/ExperimentDashboard.vue';
-import CredentialStore from './components/dashboards/CredentialStoreDashboard.vue'
-import Loading from './components/Loading.vue'
-import ComputeResourceDashboard from './components/dashboards/ComputeResourceDashboard'
-import ComputeResourcePreferenceDashboard from './components/dashboards/ComputeResourcePreferenceDashboard'
-import BootstrapVue from 'bootstrap-vue'
+import Vue from "vue";
+import VueResource from "vue-resource";
+import VueRouter from "vue-router";
+
+import ExperimentsDashboard from "./components/dashboards/ExperimentDashboard.vue";
+import CredentialStore from "./components/dashboards/CredentialStoreDashboard.vue";
+import Loading from "./components/Loading.vue";
+import ComputeResourceDashboard from "./components/dashboards/ComputeResourceDashboard";
+import ComputeResourcePreferenceDashboard from "./components/dashboards/ComputeResourcePreferenceDashboard";
+import BootstrapVue from "bootstrap-vue";
 // TODO: load the latest bootstrap css globally
-import 'bootstrap/dist/css/bootstrap.css'
-import 'bootstrap-vue/dist/bootstrap-vue.css'
-import { library as faLibrary } from '@fortawesome/fontawesome-svg-core'
-import { faGripVertical, faEquals } from '@fortawesome/free-solid-svg-icons'
-import { FontAwesomeIcon } from '@fortawesome/vue-fontawesome'
-
-faLibrary.add(faGripVertical, faEquals)
+import "bootstrap/dist/css/bootstrap.css";
+import "bootstrap-vue/dist/bootstrap-vue.css";
+import { library as faLibrary } from "@fortawesome/fontawesome-svg-core";
+import { faGripVertical, faEquals } from "@fortawesome/free-solid-svg-icons";
+import { faClipboard } from "@fortawesome/free-regular-svg-icons";
+import { FontAwesomeIcon } from "@fortawesome/vue-fontawesome";
 
-Vue.component('font-awesome-icon', FontAwesomeIcon)
+faLibrary.add(faGripVertical, faEquals, faClipboard);
 
+Vue.component("font-awesome-icon", FontAwesomeIcon);
 
-import { components, errors } from 'django-airavata-common-ui'
+import { components, errors } from "django-airavata-common-ui";
 
-import router from './router';
-import store from './store/store';
+import router from "./router";
+import store from "./store/store";
 
 errors.GlobalErrorHandler.init();
 
 Vue.config.productionTip = false;
 
-Vue.use(BootstrapVue)
+Vue.use(BootstrapVue);
 Vue.use(VueResource);
 Vue.use(VueRouter);
 
-
 export function initializeApacheAiravataDashboard(dashboardName) {
   var template = `
     <div class="vmain"><notifications-display/><Loading/>
@@ -41,9 +40,9 @@ export function initializeApacheAiravataDashboard(dashboardName) {
             <router-view>
             </router-view>
         </transition>
-    </div>`
+    </div>`;
   var vueApp = new Vue({
-    el: '#app',
+    el: "#app",
     router,
     store,
     template: template,
@@ -54,13 +53,11 @@ export function initializeApacheAiravataDashboard(dashboardName) {
       Loading,
       ComputeResourceDashboard,
       ComputeResourcePreferenceDashboard,
-      'notifications-display': components.NotificationsDisplay,
+      "notifications-display": components.NotificationsDisplay
     }
-  })
-  Vue.config.devtools = true
-  Vue.config.debug = true
-  Vue.config.silent = false
-  return vueApp
-};
-
-
+  });
+  Vue.config.devtools = true;
+  Vue.config.debug = true;
+  Vue.config.silent = false;
+  return vueApp;
+}