summaryrefslogtreecommitdiff
path: root/app/assets/javascripts/serverless
diff options
context:
space:
mode:
Diffstat (limited to 'app/assets/javascripts/serverless')
-rw-r--r--app/assets/javascripts/serverless/components/function_details.vue73
-rw-r--r--app/assets/javascripts/serverless/components/function_row.vue25
-rw-r--r--app/assets/javascripts/serverless/components/functions.vue7
-rw-r--r--app/assets/javascripts/serverless/components/pod_box.vue36
-rw-r--r--app/assets/javascripts/serverless/serverless_bundle.js67
-rw-r--r--app/assets/javascripts/serverless/stores/serverless_details_store.js11
6 files changed, 200 insertions, 19 deletions
diff --git a/app/assets/javascripts/serverless/components/function_details.vue b/app/assets/javascripts/serverless/components/function_details.vue
new file mode 100644
index 00000000000..2b1c21f041b
--- /dev/null
+++ b/app/assets/javascripts/serverless/components/function_details.vue
@@ -0,0 +1,73 @@
+<script>
+import PodBox from './pod_box.vue';
+import ClipboardButton from '../../vue_shared/components/clipboard_button.vue';
+import Icon from '~/vue_shared/components/icon.vue';
+
+export default {
+ components: {
+ Icon,
+ PodBox,
+ ClipboardButton,
+ },
+ props: {
+ func: {
+ type: Object,
+ required: true,
+ },
+ },
+ computed: {
+ name() {
+ return this.func.name;
+ },
+ description() {
+ return this.func.description;
+ },
+ funcUrl() {
+ return this.func.url;
+ },
+ podCount() {
+ return this.func.podcount || 0;
+ },
+ },
+};
+</script>
+
+<template>
+ <section id="serverless-function-details">
+ <h3>{{ name }}</h3>
+ <div class="append-bottom-default">
+ <div v-for="line in description.split('\n')" :key="line">{{ line }}<br /></div>
+ </div>
+ <div class="clipboard-group append-bottom-default">
+ <div class="label label-monospace">{{ funcUrl }}</div>
+ <clipboard-button
+ :text="String(funcUrl)"
+ :title="s__('ServerlessDetails|Copy URL to clipboard')"
+ class="input-group-text js-clipboard-btn"
+ />
+ <a
+ :href="funcUrl"
+ target="_blank"
+ rel="noopener noreferrer nofollow"
+ class="input-group-text btn btn-default"
+ >
+ <icon name="external-link" />
+ </a>
+ </div>
+
+ <h4>{{ s__('ServerlessDetails|Kubernetes Pods') }}</h4>
+ <div v-if="podCount > 0">
+ <p>
+ <b v-if="podCount == 1">{{ podCount }} {{ s__('ServerlessDetails|pod in use') }}</b>
+ <b v-else>{{ podCount }} {{ s__('ServerlessDetails|pods in use') }}</b>
+ </p>
+ <pod-box :count="podCount" />
+ <p>
+ {{
+ s__('ServerlessDetails|Number of Kubernetes pods in use over time based on necessity.')
+ }}
+ </p>
+ </div>
+ <div v-else><p>No pods loaded at this time.</p></div>
+ </section>
+</template>
diff --git a/app/assets/javascripts/serverless/components/function_row.vue b/app/assets/javascripts/serverless/components/function_row.vue
index 31f5427c771..44bfae388cb 100644
--- a/app/assets/javascripts/serverless/components/function_row.vue
+++ b/app/assets/javascripts/serverless/components/function_row.vue
@@ -15,8 +15,14 @@ export default {
name() {
return this.func.name;
},
- url() {
- return this.func.url;
+ description() {
+ return this.func.description;
+ },
+ detailUrl() {
+ return this.func.detail_url;
+ },
+ environment() {
+ return this.func.environment_scope;
},
image() {
return this.func.image;
@@ -30,11 +36,20 @@ export default {
<template>
<div class="gl-responsive-table-row">
- <div class="table-section section-20">{{ name }}</div>
- <div class="table-section section-50">
- <a :href="url">{{ url }}</a>
+ <div class="table-section section-20 section-wrap">
+ <a :href="detailUrl">{{ name }}</a>
+ </div>
+ <div class="table-section section-10">{{ environment }}</div>
+ <div class="table-section section-40 section-wrap">
+ <span class="line-break">{{ description }}</span>
</div>
<div class="table-section section-20">{{ image }}</div>
<div class="table-section section-10"><timeago :time="timestamp" /></div>
</div>
</template>
+
+<style>
+.line-break {
+ white-space: pre;
+}
+</style>
diff --git a/app/assets/javascripts/serverless/components/functions.vue b/app/assets/javascripts/serverless/components/functions.vue
index 349e14670b1..9606a78410e 100644
--- a/app/assets/javascripts/serverless/components/functions.vue
+++ b/app/assets/javascripts/serverless/components/functions.vue
@@ -50,8 +50,11 @@ export default {
<div class="table-section section-20" role="rowheader">
{{ s__('Serverless|Function') }}
</div>
- <div class="table-section section-50" role="rowheader">
- {{ s__('Serverless|Domain') }}
+ <div class="table-section section-10" role="rowheader">
+ {{ s__('Serverless|Cluster Env') }}
+ </div>
+ <div class="table-section section-40" role="rowheader">
+ {{ s__('Serverless|Description') }}
</div>
<div class="table-section section-20" role="rowheader">
{{ s__('Serverless|Runtime') }}
diff --git a/app/assets/javascripts/serverless/components/pod_box.vue b/app/assets/javascripts/serverless/components/pod_box.vue
new file mode 100644
index 00000000000..04d3641bce3
--- /dev/null
+++ b/app/assets/javascripts/serverless/components/pod_box.vue
@@ -0,0 +1,36 @@
+<script>
+export default {
+ props: {
+ count: {
+ type: Number,
+ required: true,
+ },
+ color: {
+ type: String,
+ required: false,
+ default: 'green',
+ },
+ },
+ methods: {
+ boxOffset(i) {
+ return 20 * (i - 1);
+ },
+ },
+};
+</script>
+
+<template>
+ <svg :width="boxOffset(count + 1)" :height="20">
+ <rect
+ v-for="i in count"
+ :key="i"
+ width="15"
+ height="15"
+ rx="5"
+ ry="5"
+ :fill="color"
+ :x="boxOffset(i)"
+ y="0"
+ />
+ </svg>
+</template>
diff --git a/app/assets/javascripts/serverless/serverless_bundle.js b/app/assets/javascripts/serverless/serverless_bundle.js
index 3e3b81ba247..47a510d5fb5 100644
--- a/app/assets/javascripts/serverless/serverless_bundle.js
+++ b/app/assets/javascripts/serverless/serverless_bundle.js
@@ -4,23 +4,65 @@ import { s__ } from '../locale';
import Flash from '../flash';
import Poll from '../lib/utils/poll';
import ServerlessStore from './stores/serverless_store';
+import ServerlessDetailsStore from './stores/serverless_details_store';
import GetFunctionsService from './services/get_functions_service';
import Functions from './components/functions.vue';
+import FunctionDetails from './components/function_details.vue';
export default class Serverless {
constructor() {
- const { statusPath, clustersPath, helpPath, installed } = document.querySelector(
- '.js-serverless-functions-page',
- ).dataset;
+ if (document.querySelector('.js-serverless-function-details-page') != null) {
+ const {
+ serviceName,
+ serviceDescription,
+ serviceEnvironment,
+ serviceUrl,
+ serviceNamespace,
+ servicePodcount,
+ } = document.querySelector('.js-serverless-function-details-page').dataset;
+ const el = document.querySelector('#js-serverless-function-details');
+ this.store = new ServerlessDetailsStore();
+ const { store } = this;
- this.service = new GetFunctionsService(statusPath);
- this.knativeInstalled = installed !== undefined;
- this.store = new ServerlessStore(this.knativeInstalled, clustersPath, helpPath);
- this.initServerless();
- this.functionLoadCount = 0;
+ const service = {
+ name: serviceName,
+ description: serviceDescription,
+ environment: serviceEnvironment,
+ url: serviceUrl,
+ namespace: serviceNamespace,
+ podcount: servicePodcount,
+ };
- if (statusPath && this.knativeInstalled) {
- this.initPolling();
+ this.store.updateDetailedFunction(service);
+ this.functionDetails = new Vue({
+ el,
+ data() {
+ return {
+ state: store.state,
+ };
+ },
+ render(createElement) {
+ return createElement(FunctionDetails, {
+ props: {
+ func: this.state.functionDetail,
+ },
+ });
+ },
+ });
+ } else {
+ const { statusPath, clustersPath, helpPath, installed } = document.querySelector(
+ '.js-serverless-functions-page',
+ ).dataset;
+
+ this.service = new GetFunctionsService(statusPath);
+ this.knativeInstalled = installed !== undefined;
+ this.store = new ServerlessStore(this.knativeInstalled, clustersPath, helpPath);
+ this.initServerless();
+ this.functionLoadCount = 0;
+
+ if (statusPath && this.knativeInstalled) {
+ this.initPolling();
+ }
}
}
@@ -55,7 +97,7 @@ export default class Serverless {
resource: this.service,
method: 'fetchData',
successCallback: data => this.handleSuccess(data),
- errorCallback: () => this.handleError(),
+ errorCallback: () => Serverless.handleError(),
});
if (!Visibility.hidden()) {
@@ -64,7 +106,7 @@ export default class Serverless {
this.service
.fetchData()
.then(data => this.handleSuccess(data))
- .catch(() => this.handleError());
+ .catch(() => Serverless.handleError());
}
Visibility.change(() => {
@@ -102,5 +144,6 @@ export default class Serverless {
}
this.functions.$destroy();
+ this.functionDetails.$destroy();
}
}
diff --git a/app/assets/javascripts/serverless/stores/serverless_details_store.js b/app/assets/javascripts/serverless/stores/serverless_details_store.js
new file mode 100644
index 00000000000..5394d2cded1
--- /dev/null
+++ b/app/assets/javascripts/serverless/stores/serverless_details_store.js
@@ -0,0 +1,11 @@
+export default class ServerlessDetailsStore {
+ constructor() {
+ this.state = {
+ functionDetail: {},
+ };
+ }
+
+ updateDetailedFunction(func) {
+ this.state.functionDetail = func;
+ }
+}