github.com/e154/smart-home@v0.17.2-0.20240311175135-e530a6e5cd45/static_source/admin/src/views/Automation/components/Triggers.vue (about)

     1  <script setup lang="ts">
     2  import {useI18n} from '@/hooks/web/useI18n'
     3  import {Table} from '@/components/Table'
     4  import {PropType, reactive, ref, unref, watch} from 'vue'
     5  import {TableColumn} from '@/types/table'
     6  import {ElButton, ElTag, ElPopconfirm} from 'element-plus'
     7  import {ApiAttribute, ApiTrigger, ApiTypes} from "@/api/stub";
     8  import {useEmitt} from "@/hooks/web/useEmitt";
     9  import TriggerForm from "./TriggerForm.vue";
    10  import {Trigger} from "@/views/Automation/components/types";
    11  import {useRouter} from "vue-router";
    12  
    13  const {currentRoute, addRoute, push} = useRouter()
    14  const props = defineProps({
    15    triggers: {
    16      type: Array as PropType<ApiTrigger[]>,
    17      default: () => []
    18    }
    19  })
    20  
    21  const writeRef = ref<ComponentRef<typeof TriggerForm>>()
    22  let currentTrigger = reactive<Nullable<ApiTrigger>>(null)
    23  let currentTriggerIndex = ref(0)
    24  
    25  enum Mode {
    26    VIEW = 'VIEW',
    27    EDIT = 'EDIT',
    28    NEW = 'NEW'
    29  }
    30  
    31  const mode = ref<Mode>(Mode.VIEW)
    32  const {t} = useI18n()
    33  
    34  interface TableObject {
    35    tableList: ApiTrigger[]
    36  }
    37  
    38  const tableObject = reactive<TableObject>(
    39      {
    40        tableList: [],
    41      }
    42  );
    43  
    44  watch(
    45      () => props.triggers,
    46      (val: ApiTrigger[]) => {
    47        if (val == unref(tableObject.tableList)) return;
    48        tableObject.tableList = val
    49        if (val.length) {
    50          currentTrigger = val[0]
    51        }
    52      },
    53      {
    54        immediate: true
    55      }
    56  )
    57  
    58  const columns: TableColumn[] = [
    59    {
    60      field: 'name',
    61      label: t('triggers.name'),
    62    },
    63    {
    64      field: 'script',
    65      label: t('triggers.script'),
    66    },
    67    {
    68      field: 'entity',
    69      label: t('triggers.entity'),
    70    },
    71    {
    72      field: 'plugin',
    73      label: t('triggers.plugin'),
    74    },
    75    {
    76      field: 'operations',
    77      label: t('triggers.operations'),
    78      width: "200px",
    79      type: 'time',
    80  
    81    },
    82  ]
    83  
    84  const addNew = () => {
    85    currentTrigger = null
    86    mode.value = Mode.NEW
    87  }
    88  
    89  const {emitter} = useEmitt()
    90  const call = (trigger: ApiTrigger) => {
    91    emitter.emit('callTrigger', trigger.name)
    92  }
    93  
    94  const updateTriggers = () => {
    95    const triggers = unref(tableObject.tableList)
    96    emitter.emit('updateTriggers', triggers)
    97  }
    98  
    99  const edit = (trigger: ApiTrigger, $index) => {
   100    currentTriggerIndex.value = $index
   101    currentTrigger = unref(trigger)
   102    mode.value = Mode.EDIT
   103  }
   104  
   105  const save = async () => {
   106    const write = unref(writeRef)
   107    const validate = await write?.elFormRef?.validate()?.catch(() => {
   108    })
   109    const data = (await write?.getFormData()) as Trigger
   110    if (validate) {
   111      let attributes: { [key: string]: ApiAttribute } = {};
   112      if (data.timePluginOptions) {
   113        attributes.cron = {
   114          name: 'cron',
   115          type: ApiTypes.STRING,
   116          string: data.timePluginOptions
   117        };
   118      }
   119      if (data.alexaPluginOptions) {
   120        attributes.skillId = {
   121          name: 'skillId',
   122          type: ApiTypes.INT,
   123          int: data.alexaPluginOptions
   124        };
   125      }
   126      const trigger = {
   127        id: data?.id,
   128        name: data.name,
   129        pluginName: data.pluginName,
   130        entity: data.entity,
   131        entityId: data.entity?.id || null,
   132        script: data.script,
   133        scriptId: data.script?.id || null,
   134        attributes: attributes,
   135      } as ApiTrigger
   136      if (mode.value === Mode.NEW) {
   137        tableObject.tableList.push(trigger)
   138      } else {
   139        tableObject.tableList[currentTriggerIndex.value] = trigger
   140      }
   141      mode.value = Mode.VIEW
   142      updateTriggers()
   143    }
   144  }
   145  
   146  const resetForm = () => {
   147    mode.value = Mode.VIEW
   148    currentTrigger = null
   149  }
   150  
   151  const removeItem = () => {
   152    tableObject.tableList.splice(currentTriggerIndex.value, 1);
   153    mode.value = Mode.VIEW
   154  }
   155  
   156  const goToEntity = (trigger: ApiTrigger) => {
   157    if (!trigger.entity?.id) {
   158      return
   159    }
   160    push(`/entities/edit/${trigger.entity?.id}`)
   161  }
   162  
   163  const goToScript = (trigger: ApiTrigger) => {
   164    if (!trigger.script?.id) {
   165      return
   166    }
   167    push(`/scripts/edit/${trigger.script?.id}`)
   168  }
   169  
   170  </script>
   171  
   172  <template>
   173    <ElButton class="flex mb-20px items-left"  @click="addNew()" plain v-if="mode==='VIEW'">
   174      <Icon icon="ep:plus" class="mr-5px"/>
   175      {{ t('triggers.addNew') }}
   176    </ElButton>
   177  
   178    <Table
   179        v-if="mode==='VIEW'"
   180        :selection="false"
   181        :columns="columns"
   182        :data="tableObject.tableList"
   183        style="width: 100%"
   184    >
   185  
   186      <template #script="{row}">
   187        <ElButton v-if="row.script" :link="true" @click.prevent.stop="goToScript(row)">
   188          {{ row.script.name }}
   189        </ElButton>
   190        <span v-else>-</span>
   191      </template>
   192  
   193      <template #entity="{row}">
   194        <ElButton v-if="row.entity" :link="true" @click.prevent.stop="goToEntity(row)">
   195          {{ row.entity.id }}
   196        </ElButton>
   197        <span v-else>-</span>
   198      </template>
   199  
   200      <template #plugin="{row}">
   201        <ElTag type="info">
   202          {{ row.pluginName }}
   203        </ElTag>
   204      </template>
   205  
   206      <template #operations="{ row, $index }">
   207  
   208        <ElButton :link="true" @click.prevent.stop="call(row)">
   209          {{ $t('main.call') }}
   210        </ElButton>
   211  
   212        <ElButton :link="true" @click.prevent.stop="edit(row, $index)">
   213          {{ $t('main.edit') }}
   214        </ElButton>
   215  
   216      </template>
   217  
   218    </Table>
   219  
   220    <TriggerForm ref="writeRef" :trigger="currentTrigger" v-if="mode!=='VIEW'"/>
   221  
   222    <div style="text-align: right" v-if="mode!=='VIEW'">
   223  
   224      <ElButton v-if="mode === 'NEW'" type="primary" @click="save()">
   225        {{ t('triggers.addTrigger') }}
   226      </ElButton>
   227  
   228      <ElButton v-if="mode === 'EDIT'" type="primary" @click="save()">
   229        {{ t('main.update') }}
   230      </ElButton>
   231  
   232      <ElButton type="default" @click="resetForm()">
   233        {{ t('main.cancel') }}
   234      </ElButton>
   235  
   236      <ElPopconfirm
   237          v-if="mode === 'EDIT'"
   238          :confirm-button-text="$t('main.ok')"
   239          :cancel-button-text="$t('main.no')"
   240          width="250"
   241          style="margin-left: 10px;"
   242          :title="$t('main.are_you_sure_to_do_want_this?')"
   243          @confirm="removeItem"
   244      >
   245        <template #reference>
   246          <ElButton class="mr-10px" type="danger" plain>
   247            <Icon icon="ep:delete" class="mr-5px"/>
   248            {{ t('main.remove') }}
   249          </ElButton>
   250        </template>
   251      </ElPopconfirm>
   252  
   253    </div>
   254  </template>
   255  
   256  <style lang="less">
   257  
   258  </style>