<template> <div> <div v-if="settings.disableAuth" class="mt-5 d-flex align-items-center justify-content-center my-3" > {{ $t("apiKeysDisabledMsg") }} </div> <div v-else> <div class="add-btn"> <button class="btn btn-primary me-2" type="button" @click="$refs.apiKeyDialog.show()"> <font-awesome-icon icon="plus" /> {{ $t("Add API Key") }} </button> </div> <div> <span v-if="Object.keys(keyList).length === 0" class="d-flex align-items-center justify-content-center my-3" > {{ $t("No API Keys") }} </span> <div v-for="(item, index) in keyList" :key="index" class="item" :class="item.status" > <div class="left-part"> <div class="circle"></div> <div class="info"> <div class="title">{{ item.name }}</div> <div class="status"> {{ $t("apiKey-" + item.status) }} </div> <div class="date"> {{ $t("Created") }}: {{ item.createdDate }} </div> <div class="date"> {{ $t("Expires") }}: {{ item.expires || $t("Never") }} </div> </div> </div> <div class="buttons"> <div class="btn-group" role="group"> <button v-if="item.active" class="btn btn-normal" @click="disableDialog(item.id)"> <font-awesome-icon icon="pause" /> {{ $t("Disable") }} </button> <button v-if="!item.active" class="btn btn-primary" @click="enableKey(item.id)"> <font-awesome-icon icon="play" /> {{ $t("Enable") }} </button> <button class="btn btn-danger" @click="deleteDialog(item.id)"> <font-awesome-icon icon="trash" /> {{ $t("Delete") }} </button> </div> </div> </div> </div> </div> <div class="text-center mt-3" style="font-size: 13px;"> <a href="https://github.com/louislam/uptime-kuma/wiki/API-Keys" target="_blank">{{ $t("Learn More") }}</a> </div> <Confirm ref="confirmPause" :yes-text="$t('Yes')" :no-text="$t('No')" @yes="disableKey"> {{ $t("disableAPIKeyMsg") }} </Confirm> <Confirm ref="confirmDelete" btn-style="btn-danger" :yes-text="$t('Yes')" :no-text="$t('No')" @yes="deleteKey"> {{ $t("deleteAPIKeyMsg") }} </Confirm> <APIKeyDialog ref="apiKeyDialog" /> </div> </template> <script> import APIKeyDialog from "../../components/APIKeyDialog.vue"; import Confirm from "../Confirm.vue"; export default { components: { APIKeyDialog, Confirm, }, data() { return { selectedKeyID: null, }; }, computed: { keyList() { let result = Object.values(this.$root.apiKeyList); return result; }, settings() { return this.$parent.$parent.$parent.settings; }, }, methods: { /** * Show dialog to confirm deletion * @param {number} keyID ID of monitor that is being deleted * @returns {void} */ deleteDialog(keyID) { this.selectedKeyID = keyID; this.$refs.confirmDelete.show(); }, /** * Delete a key * @returns {void} */ deleteKey() { this.$root.deleteAPIKey(this.selectedKeyID, (res) => { this.$root.toastRes(res); }); }, /** * Show dialog to confirm pause * @param {number} keyID ID of key to pause * @returns {void} */ disableDialog(keyID) { this.selectedKeyID = keyID; this.$refs.confirmPause.show(); }, /** * Pause API key * @returns {void} */ disableKey() { this.$root .getSocket() .emit("disableAPIKey", this.selectedKeyID, (res) => { this.$root.toastRes(res); }); }, /** * Resume API key * @param {number} id Key to resume * @returns {void} */ enableKey(id) { this.$root.getSocket().emit("enableAPIKey", id, (res) => { this.$root.toastRes(res); }); }, }, }; </script> <style lang="scss" scoped> @import "../../assets/vars.scss"; .mobile { .item { flex-direction: column; align-items: flex-start; margin-bottom: 20px; } } .add-btn { padding-top: 20px; padding-bottom: 20px; } .item { display: flex; align-items: center; gap: 10px; text-decoration: none; border-radius: 10px; transition: all ease-in-out 0.15s; justify-content: space-between; padding: 10px; min-height: 90px; margin-bottom: 5px; &:hover { background-color: $highlight-white; } &.active { .circle { background-color: $primary; } } &.inactive { .circle { background-color: $danger; } } &.expired { .left-part { opacity: 0.3; } .circle { background-color: $dark-font-color; } } .left-part { display: flex; gap: 12px; align-items: center; .circle { width: 25px; height: 25px; border-radius: 50rem; } .info { .title { font-weight: bold; font-size: 20px; } .status { font-size: 14px; } } } .buttons { display: flex; gap: 8px; flex-direction: row-reverse; .btn-group { width: 310px; } } } .date { margin-top: 5px; display: block; font-size: 14px; background-color: rgba(255, 255, 255, 0.5); border-radius: 20px; padding: 0 10px; width: fit-content; .dark & { color: white; background-color: rgba(255, 255, 255, 0.1); } } .dark { .item { &:hover { background-color: $dark-bg2; } } } </style>