Source: management-system/src/frontend/components/processes/editor/SubprocessSelection.vue

<template>
  <!-- we use the process form for its layout when we select and for its process creation functionality when we want a new subprocess -->
  <add-process-form
    :show="show"
    :type="process.type"
    @cancel="$emit('cancel')"
    @process="emitProcess"
  >
    <template #title>Set Subprocess</template>
    <template #title-action>
      <v-switch v-model="createNewProcess" :label="'New Subprocess'"></v-switch>
    </template>
    <!-- Override the main area of the process form with our subprocess selection when we are in select mode -->
    <template v-if="!createNewProcess" #main>
      <!-- To select a process, e.g. a subprocess -->
      <v-container class="pa-0">
        <v-row>
          <v-col class="py-0" cols="12" sm="12" md="12">
            <v-autocomplete
              label="Select Process"
              color="primary"
              v-model="selectedProcess"
              :filter="filterProcesses"
              :items="selectableProcesses"
              item-text="name"
              return-object
              clearable
            >
            </v-autocomplete>
          </v-col>
        </v-row>
        <v-row v-if="selectedProcess">
          <v-col cols="12" sm="12" md="12">
            <BpmnPreview viewerMode="navigated-viewer" :process="selectedProcess"></BpmnPreview>
          </v-col>
        </v-row>
      </v-container>
    </template>
    <!-- override the buttons in the footer with custom functionality but trigger the forms functionality when we want to create a process -->
    <template v-if="!createNewProcess" #actions="{ confirm, cancel, isFormValid, isSubmitting }">
      <v-btn @click="cancel">Cancel</v-btn>
      <v-btn :loading="isSubmitting" color="primary" @click="emitProcess(selectedProcess)"
        >Set Subprocess</v-btn
      >
    </template>
  </add-process-form>
</template>
<script>
import AddProcessForm from '../processForm/AddProcessForm.vue';
import BpmnPreview from '@/frontend/components/bpmn/BpmnPreview.vue';

import { getAllSubprocesses } from '@/frontend/helpers/process-export/export-preparation.js';

/**
 * @module components
 */
/**
 * @memberof module:components
 * @module processes
 */
/**
 * This is a dialog used to select a process to be used in a callActivity
 *
 * @memberof module:components.module:processes
 * @module Vue:SubprocessSelection
 *
 * @vue-prop {Process} process - the process containing the callActivity
 * @vue-prop {String} currentlySelectedId - the definitions id of the currently selected subprocess
 *
 * @vue-event {undefined} done - signals that we are done selecting
 * @vue-event {(Object<Process>|null)} process - the process that was selected
 * @vue-event {undefined} cancel - if the form should be closed without the intention of doing anything (abort)
 */
export default {
  components: { AddProcessForm, BpmnPreview },

  props: {
    process: { type: Object, required: true },
    currentlySelectedId: { type: String, required: false },
    show: { type: Boolean, required: true },
  },
  data() {
    return {
      /**
       * if a new process is created instead of selecting a process
       * @type {boolean}
       */
      createNewProcess: false,
      /** The process that was newly selected */
      selectedProcess: null,
      /** Processes that can be selected for a callActivity */
      selectableProcesses: [],
    };
  },
  methods: {
    /** filter processes based on current user input in autocomplete component  */
    filterProcesses(item, queryText) {
      return item.name.includes(queryText);
    },
    /**
     * Emits the selected process and the done signal
     *
     * @param {Object} process the selected process
     */
    emitProcess(process) {
      this.$emit('process', process);
      this.selectedProcess = null;
      this.createNewProcess = false;
      this.$emit('done');
    },
    /**
     * Remove the process and processes (indirectly) referencing it from the list of selectable processes
     * (cycle protection)
     **/
    async filterSelectableSubprocesses() {
      let processes = this.$store.getters['processStore/processes'].map(async (process) => ({
        ...process,
        bpmn: await this.$store.getters['processStore/xmlById'](process.id),
      }));

      processes = await Promise.all(processes);

      // hide local subprocesses to avoid problems on deployment down the line
      // local processes are not deployable since they are unknown to the backend
      processes = processes.filter((process) => process.shared);

      let deepSubprocesses = processes.map((process) =>
        getAllSubprocesses(processes, { ...process }, [process])
      );

      deepSubprocesses = await Promise.all(deepSubprocesses);

      if (this.process) {
        this.selectableProcesses = processes.filter(
          (_, index) =>
            !deepSubprocesses[index].some((subProcess) => subProcess.id === this.process.id)
        );
      }
    },
    async selectCurrentSubprocess() {
      // don't allow user to select processes that would result in cyclic calls
      await this.filterSelectableSubprocesses();

      if (this.currentlySelectedId) {
        // preselect the process currently used in the callActivity if in select mode
        this.selectedProcess = this.selectableProcesses.find(
          (process) => process.id === this.currentlySelectedId
        );
      }
    },
  },
  watch: {
    show: {
      handler(isShown) {
        if (isShown) {
          this.selectCurrentSubprocess();
        }
      },
      immediate: true,
    },
  },
};
</script>