import Vue from "vue/dist/vue.esm.js"; import _ from "lodash"; import { getData } from "../utilities"; import axios from "axios"; // This is binding to a class name, so elem is actually a DOM object export default function (elem) { let data = getData(elem, ["communities", "servers", "aliases", "user-id"]); const userID = data["user-id"]; const app = new Vue({ el: elem, data: { communities: data.communities, servers: data.servers, alias: { all: data.aliases, original: {}, current: {} }, modal: {}, selectedServer: null, selectedCommunity: null }, created: function () { this.reset(); }, mounted: function () { $("#alias-modal").on("hidden", () => { this.reset(); }); }, computed: { targets: function () { let targets = _.concat(this.communities, this.servers.flatMap((s) => s.servers)); return _.sortBy(targets, "id"); }, aliases: function () { let aliases = _.filter(this.alias.all, (a) => a.state != "deleted"); return _.sortBy(aliases, "value"); }, hasAliases: function () { return !_.isEmpty(this.aliases); }, hasChanges: function () { return _.some(this.aliases, (a) => a.state != "unchanged") }, validAlias: function () { let currentAlias = this.alias.current; // let originalAlias = this.alias.original; let existingAlias = _.find(this.alias.all, (alias) => { let validAlias = alias.value === currentAlias.value; let validType = alias.type === currentAlias.type; let validID = true; // New alias do not have an ID if (!_.isEmpty(currentAlias.id)) { validID = alias.id !== currentAlias.id } return validAlias && validType && validID; }) || null; let aliasSize = _.size(currentAlias.value); let hasValidSize = aliasSize > 0 && aliasSize < 64; let hasTarget = !_.isNull(currentAlias.target); let hasExistingAlias = !_.isNull(existingAlias); if (hasExistingAlias) { Vue.set(this.modal, "error", `This alias already exists for ${existingAlias.target.name}`); } else { Vue.set(this.modal, "error", ""); } return hasValidSize && hasTarget && !hasExistingAlias; }, submitButtonEnabled: function () { return this.validAlias; } }, methods: { reset: function () { this.modal = { title: "Add a new alias", error: "", submitButton: "Add alias", onSubmitClick: this.addAlias, }; Vue.set(this.alias, "original", {}); Vue.set(this.alias, "current", { id: null, type: "community", value: "", target: null, state: "new" }); this.resetSelected(); }, resetSelected: function () { this.selectedServer = null; this.selectedCommunity = null; Vue.set(this.alias.current, "target", null); }, // Force a scroll so the UI is in the correct spot for the first change. // Allows the user to change the position without forcing them back again scrollToSection: function () { if (this.hasChanges) return; let section = $("#aliases-section"); UIkit.scroll(section).scrollTo(section); }, onSelectedType: function () { Vue.set(this.alias.current, "target", this.selectedCommunity || this.selectedServer); }, addAlias: function () { this.scrollToSection(); this.alias.current.target = this.selectedCommunity || this.selectedServer; let { state: _s, id: _i, ...alias } = this.alias.current; // Add the alias to the UI. Since it doesn't have an ID, a spinner will show where the icons are this.alias.all.push(alias); UIkit.modal($("#alias-modal")).hide(); axios.post(`/users/${userID}/aliases`, { user_alias: alias }) .then((response) => { Vue.set(alias, "id", response.data.id) }).catch((e) => { console.error(e); Toaster.error(`Failed to add a new alias - ${e.response?.data?.message}`); }); }, editAlias: function (alias) { this.scrollToSection(); Vue.set(this.alias, "original", alias); Vue.set(this.alias, "current", _.clone(alias)); // Find the target community/server let target = _.find(this.targets, ["id", alias.target.id]); if (alias.type === "community") { this.selectedCommunity = target; } else { this.selectedServer = target; } this.modal = { title: "Editing alias", submitButton: "Save changes", onSubmitClick: this.updateAlias, }; Vue.nextTick(() => { UIkit.modal($("#alias-modal")).show(); }); }, updateAlias: function () { let originalAlias = this.alias.original; let editedAlias = this.alias.current; Vue.set(originalAlias, "value", editedAlias.value); Vue.set(originalAlias, "target", editedAlias.target); Vue.set(originalAlias, "type", editedAlias.type); Vue.set(originalAlias, "state", "changed"); UIkit.modal($("#alias-modal")).hide(); axios.patch(`/users/${userID}/aliases/${originalAlias.id}`, { user_alias: originalAlias }) .then((_response) => { }) .catch((e) => { console.error(e); Toaster.error(`Failed to update the alias - ${e.response?.data?.message}`); }); }, deleteAlias: function (alias) { this.scrollToSection(); let confirmation = confirm( `Are you sure you want to delete the alias "${alias.value}" that represents "${alias.target.name}"?` ); if (!confirmation) return; // Hides the alias Vue.set(alias, "state", "deleted"); axios.delete(`/users/${userID}/aliases/${alias.id}`) .then(() => { Vue.delete(this.alias.all, _.indexOf(this.alias.all, alias)); }).catch((e) => { console.error(e); // Reset hiding the alias Vue.set(alias, "state", "unchanged"); Toaster.error(`Failed to delete alias - ${e.response?.data?.message}`); }).finally(() => { UIkit.modal($("#alias-modal")).hide(); }); }, }, }); }