HEX
Server: Microsoft-IIS/10.0
System: Windows NT ITPWINWEBSVR22 10.0 build 20348 (Windows Server 2022) AMD64
User: www.conferencesearch.co.uk (0)
PHP: 8.3.30
Disabled: NONE
Upload Files
File: D:/web/matomo.vdk/plugins/UsersManager/vue/src/CapabilitiesEdit/CapabilitiesEdit.vue
<!--
  Matomo - free/libre analytics platform

  @link    https://matomo.org
  @license https://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
-->

<template>
  <div
    class="capabilitiesEdit"
    :class="{busy: isBusy}"
  >
    <div
      v-for="capability in actualCapabilities"
      :key="capability.id"
      class="chip"
    >
      <span
        class="capability-name"
        :title="`${capability.description} ${
          isIncludedInRole(capability)
            ? `<br/><br/>${translate('UsersManager_IncludedInUsersRole')}`
            : ''
        }`"
      >
        {{ capability.category }}: {{ capability.name }}
      </span>
      <span
        class="icon-close"
        v-if="!isIncludedInRole(capability)"
        @click="capabilityToRemoveId = capability.id; onToggleCapability(false)"
      />
    </div>
    <div
      class="addCapability"
      v-if="availableCapabilitiesGrouped.length"
    >
      <Field
        :model-value="capabilityToAddId"
        @update:model-value="capabilityToAddId = $event; onToggleCapability(true)"
        :disabled="isBusy"
        uicontrol="expandable-select"
        name="add_capability"
        :full-width="true"
        v-if="userRole !== 'noaccess'"
        :options="availableCapabilitiesGrouped"
      >
      </Field>
    </div>
    <div class="ui-confirm confirmCapabilityToggle modal" ref="confirmCapabilityToggleModal">
      <div class="modal-content">
        <h2
          v-if="isAddingCapability"
          v-html="$sanitize(confirmAddCapabilityToggleContent)"
        ></h2>
        <h2
          v-if="!isAddingCapability"
          v-html="$sanitize(confirmCapabilityToggleContent)"
        ></h2>
      </div>
      <div class="modal-footer">
        <a
          href=""
          class="modal-action modal-close btn"
          @click.prevent="toggleCapability()"
        >{{ translate('General_Yes') }}</a>
        <a
          href=""
          class="modal-action modal-close modal-no"
          @click.prevent="
            capabilityToAddOrRemove = null;
            capabilityToAddId = null;
            capabilityToRemoveId = null;"
        >
          {{ translate('General_No') }}
        </a>
      </div>
    </div>
  </div>
</template>

<script lang="ts">
import { defineComponent, DeepReadonly } from 'vue';
import { translate, AjaxHelper, Matomo } from 'CoreHome';
import { Field } from 'CorePluginsAdmin';
import CapabilitiesStore from '../CapabilitiesStore/CapabilitiesStore';
import Capability from '../CapabilitiesStore/Capability';
import ModalOptions = M.ModalOptions;

interface CapabilitiesEditState {
  isBusy: boolean;
  theCapabilities: string[];
  isAddingCapability: boolean;
  capabilityToAddId: string|null;
  capabilityToRemoveId: string|null;
  capabilityToAddOrRemove: DeepReadonly<Capability>|null;
}

const { $ } = window;

export default defineComponent({
  props: {
    idsite: [String, Number],
    siteName: {
      type: String,
      required: true,
    },
    userLogin: {
      type: String,
      required: true,
    },
    userRole: {
      type: String,
      required: true,
    },
    capabilities: Array,
  },
  components: {
    Field,
  },
  data(): CapabilitiesEditState {
    return {
      theCapabilities: (this.capabilities as string[]) || [],
      isBusy: false,
      isAddingCapability: false,
      capabilityToAddId: null,
      capabilityToRemoveId: null,
      capabilityToAddOrRemove: null,
    };
  },
  emits: ['change'],
  watch: {
    capabilities(newValue) {
      if (newValue) {
        this.theCapabilities = newValue as string[];
      }
    },
  },
  created() {
    CapabilitiesStore.init();

    if (!this.capabilities) {
      this.isBusy = true;

      AjaxHelper.fetch<{ capabilities: string[] }>({
        method: 'UsersManager.getUsersPlusRole',
        limit: '1',
        filter_search: this.userLogin,
      }).then((user) => {
        if (!user || !user.capabilities) {
          return [];
        }

        return user.capabilities;
      }).then((capabilities) => {
        this.theCapabilities = capabilities;
      }).finally(() => {
        this.isBusy = false;
      });
    } else {
      this.theCapabilities = this.capabilities as string[];
    }
  },
  methods: {
    onToggleCapability(isAdd: boolean) {
      this.isAddingCapability = isAdd;

      const capabilityToAddOrRemoveId = isAdd ? this.capabilityToAddId : this.capabilityToRemoveId;

      this.capabilityToAddOrRemove = null;
      this.availableCapabilities.forEach((capability) => {
        if (capability.id === capabilityToAddOrRemoveId) {
          this.capabilityToAddOrRemove = capability;
        }
      });

      if (this.$refs.confirmCapabilityToggleModal) {
        $(this.$refs.confirmCapabilityToggleModal as HTMLElement).modal({
          dismissible: false,
          yes: () => null,
        } as unknown as ModalOptions).modal('open');
      }
    },
    toggleCapability() {
      if (this.isAddingCapability) {
        this.addCapability(this.capabilityToAddOrRemove!);
      } else {
        this.removeCapability(this.capabilityToAddOrRemove!);
      }
    },
    isIncludedInRole(capability: DeepReadonly<Capability>) {
      return (capability.includedInRoles || []).indexOf(this.userRole) !== -1;
    },
    getCapabilitiesList() {
      const result: string[] = [];
      this.availableCapabilities.forEach((capability) => {
        if (this.isIncludedInRole(capability)) {
          return;
        }

        if (this.capabilitiesSet[capability.id]) {
          result.push(capability.id);
        }
      });
      return result;
    },
    addCapability(capability: DeepReadonly<Capability>) {
      this.isBusy = true;
      AjaxHelper.post(
        {
          method: 'UsersManager.addCapabilities',
        },
        {
          userLogin: this.userLogin,
          capabilities: capability.id,
          idSites: this.idsite,
        },
      ).then(() => {
        this.$emit('change', this.getCapabilitiesList());
      }).finally(() => {
        this.isBusy = false;
        this.capabilityToAddOrRemove = null;
        this.capabilityToAddId = null;
        this.capabilityToRemoveId = null;
      });
    },
    removeCapability(capability: DeepReadonly<Capability>) {
      this.isBusy = true;
      AjaxHelper.post(
        {
          method: 'UsersManager.removeCapabilities',
        },
        {
          userLogin: this.userLogin,
          capabilities: capability.id,
          idSites: this.idsite,
        },
      ).then(() => {
        this.$emit('change', this.getCapabilitiesList());
      }).finally(() => {
        this.isBusy = false;
        this.capabilityToAddOrRemove = null;
        this.capabilityToAddId = null;
        this.capabilityToRemoveId = null;
      });
    },
  },
  computed: {
    availableCapabilities() {
      return CapabilitiesStore.capabilities.value;
    },
    confirmAddCapabilityToggleContent() {
      return translate(
        'UsersManager_AreYouSureAddCapability',
        `<strong>${this.userLogin}</strong>`,
        `<strong>${this.capabilityToAddOrRemove ? this.capabilityToAddOrRemove.name : ''}</strong>`,
        `<strong>${this.siteNameText}</strong>`,
      );
    },
    confirmCapabilityToggleContent() {
      return translate(
        'UsersManager_AreYouSureRemoveCapability',
        `<strong>${this.capabilityToAddOrRemove ? this.capabilityToAddOrRemove.name : ''}</strong>`,
        `<strong>${this.userLogin}</strong>`,
        `<strong>${this.siteNameText}</strong>`,
      );
    },
    siteNameText() {
      return Matomo.helper.htmlEntities(this.siteName);
    },
    availableCapabilitiesGrouped() {
      const availableCapabilitiesGrouped = this.availableCapabilities.filter(
        (c) => !this.capabilitiesSet[c.id],
      ).map((c) => ({
        group: c.category,
        key: c.id,
        value: c.name,
        tooltip: c.description,
      }));

      availableCapabilitiesGrouped.sort((lhs, rhs) => {
        if (lhs.group === rhs.group) {
          if (lhs.value === rhs.value) {
            return 0;
          }
          return lhs.value < rhs.value ? -1 : 1;
        }
        return lhs.group < rhs.group ? -1 : 1;
      });

      return availableCapabilitiesGrouped;
    },
    capabilitiesSet() {
      const capabilitiesSet: Record<string, boolean> = {};
      const capabilities = this.theCapabilities as string[];

      (capabilities || []).forEach((capability) => {
        capabilitiesSet[capability] = true;
      });

      (this.availableCapabilities || []).forEach((capability) => {
        if (this.isIncludedInRole(capability)) {
          capabilitiesSet[capability.id] = true;
        }
      });

      return capabilitiesSet;
    },
    actualCapabilities() {
      const { capabilitiesSet } = this;
      return this.availableCapabilities.filter((c) => !!capabilitiesSet[c.id]);
    },
  },
});
</script>