client/routes/workflow/query.vue (179 lines of code) (raw):

<script> // Copyright (c) 2017-2024 Uber Technologies Inc. // Portions of the Software are attributed to Copyright (c) 2020-2024 Temporal Technologies Inc. // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. import { getQueryResult } from './helpers'; import { SelectInput } from '~components'; import { httpService } from '~services'; export default { components: { 'select-input': SelectInput, }, data() { return { error: undefined, loading: false, queryName: undefined, queryInput: undefined, queries: [], queryResult: undefined, running: false, }; }, props: ['baseAPIURL', 'clusterName', 'taskListName', 'isWorkerRunning'], created() { if (!this.isWorkerRunning) { return; } this.fetchQueries(); }, methods: { setQuery(queryName) { this.queryResult = undefined; this.error = undefined; this.queryName = queryName; }, run() { this.running = true; httpService .post(`${this.baseAPIURL}/query/${this.queryName}`) .then( ({ queryResult }) => { this.queryResult = getQueryResult(queryResult); }, e => { this.error = (e.json && e.json.message) || e.status || e.message; } ) .finally(() => { this.running = false; }); }, fetchQueries() { this.loading = true; return httpService .get(`${this.baseAPIURL}/query`) .then( queries => { this.queries = queries.filter(query => query !== '__stack_trace'); if (!this.queryName) { [this.queryName] = this.queries; } }, error => { this.error = (error.json && error.json.message) || error.status || error.message; } ) .finally(() => { this.loading = false; }); }, }, watch: { isWorkerRunning: function(newVal, oldVal) { if (newVal == false) { this.queries = []; return; } this.fetchQueries(); }, }, }; </script> <template> <section class="query" :class="{ loading }" data-cy="query"> <header v-if="queries && queries.length"> <div class="query-name"> <select-input label="Query" :options="queries" :value="queryName" @change="setQuery" /> </div> <a :href="queryName && !running ? '#' : undefined" :class="{ run: true, running }" @click.prevent="run" > Run </a> </header> <pre v-if="queryResult && queryResult.payloads !== undefined">{{ queryResult.payloads }}</pre> <span class="error" v-if="error">{{ error }}</span> <span v-if="!isWorkerRunning" class="no-queries"> There are no Workers currently listening to the Task List: <router-link :to="{ name: 'task-list', params: { clusterName, taskList: taskListName, }, }" >{{ taskListName }} </router-link> </span> <span class="no-queries" v-else-if="queries && queries.length === 0"> No queries registered </span> </section> </template> <style lang="stylus"> @require "../../styles/definitions.styl" section.query { padding: layout-spacing-small; header { display: flex; padding-top: layout-spacing-small; margin-bottom: layout-spacing-medium; align-items: center; .query-name { flex: 0 0 auto; min-width: 350px; superlabel(); } a.run { flex: 0 0 auto; margin: 0 1em; action-button(); icon-play(); &:not([href="#"]) { opacity: 0.7; } &.running { icon-refresh(); } } } span.no-queries { display: block; width: 100%; text-align: center; font-size: 20px; color: uber-black-60; } } </style>