Browse Source

feat: message when don't have access to spreadsheet

Ahmad Kholid 3 years ago
parent
commit
5e7454f399

+ 79 - 76
src/components/newtab/logs/LogsHistory.vue

@@ -12,87 +12,90 @@
     class="p-4 rounded-lg flex items-start font-mono bg-gray-900 dark:bg-gray-800 text-gray-100 dark scroll overflow-auto"
     style="max-height: 600px"
   >
-    <ul class="text-sm flex-1 overflow-auto">
-      <li
+    <div class="text-sm flex-1 space-y-1 overflow-auto">
+      <ui-expand
         v-for="(item, index) in history"
         :key="item.id || index"
-        :class="{ 'bg-box-transparent': item.id === state.itemId }"
-        class="px-2 py-1 rounded-md hoverable group cursor-default flex items-start"
+        :disabled="!ctxData[item.id]"
+        hide-header-icon
+        class="hoverable rounded-md"
+        active-class="bg-box-transparent"
+        header-class="px-2 w-full text-left focus:ring-0 py-1 rounded-md group cursor-default flex items-start"
         @click="state.itemId = item.id"
       >
-        <span
-          :title="t('log.duration')"
-          class="w-14 flex-shrink-0 text-overflow text-gray-400"
+        <template #header="{ show }">
+          <span class="w-6">
+            <v-remixicon
+              v-show="ctxData[item.id]"
+              :rotate="show ? 270 : 180"
+              size="20"
+              name="riArrowLeftSLine"
+              class="transition-transform text-gray-400 -ml-1 mr-2"
+            />
+          </span>
+          <span
+            :title="`${t('log.duration')}: ${Math.round(
+              item.duration / 1000
+            )}s`"
+            class="w-14 flex-shrink-0 text-overflow text-gray-400"
+          >
+            {{ countDuration(0, item.duration || 0) }}
+          </span>
+          <span
+            :class="logsType[item.type]?.color"
+            :title="item.type"
+            class="w-2/12 flex-shrink-0 text-overflow"
+          >
+            <v-remixicon
+              :name="logsType[item.type]?.icon"
+              size="18"
+              class="inline-block -mr-1 align-text-top"
+            />
+            {{ item.name }}
+          </span>
+          <span
+            :title="`${t('common.description')} (${item.description})`"
+            class="ml-2 w-2/12 text-overflow flex-shrink-0"
+          >
+            {{ item.description }}
+          </span>
+          <p
+            :title="item.message"
+            class="text-sm line-clamp ml-2 flex-1 leading-tight text-gray-600 dark:text-gray-200"
+          >
+            {{ item.message }}
+          </p>
+          <router-link
+            v-if="item.logId"
+            v-slot="{ navigate }"
+            :to="{ name: 'logs-details', params: { id: item.logId } }"
+            custom
+          >
+            <v-remixicon
+              title="Open log detail"
+              class="ml-2 text-gray-300 cursor-pointer"
+              size="20"
+              name="riFileTextLine"
+              @click.stop="navigate"
+            />
+          </router-link>
+          <router-link
+            v-show="currentLog.workflowId && item.blockId"
+            :to="`/workflows/${currentLog.workflowId}?blockId=${item.blockId}`"
+          >
+            <v-remixicon
+              name="riExternalLinkLine"
+              size="20"
+              title="Go to block"
+              class="text-gray-300 cursor-pointer ml-2 invisible group-hover:visible"
+            />
+          </router-link>
+        </template>
+        <pre
+          class="px-2 pb-2 text-gray-300 overflow-auto text-sm ml-6 scroll max-h-96"
+          >{{ ctxData[state.itemId] || 'EMPTY' }}</pre
         >
-          {{ countDuration(0, item.duration || 0) }}
-        </span>
-        <span
-          :class="logsType[item.type]?.color"
-          :title="item.type"
-          class="w-2/12 flex-shrink-0 text-overflow"
-        >
-          <v-remixicon
-            :name="logsType[item.type]?.icon"
-            size="18"
-            class="inline-block -mr-1 align-text-top"
-          />
-          {{ item.name }}
-        </span>
-        <span
-          :title="`${t('common.description')} (${item.description})`"
-          class="ml-2 w-2/12 text-overflow flex-shrink-0"
-        >
-          {{ item.description }}
-        </span>
-        <p
-          :title="item.message"
-          class="text-sm line-clamp ml-2 flex-1 leading-tight text-gray-600 dark:text-gray-200"
-        >
-          {{ item.message }}
-        </p>
-        <router-link
-          v-if="item.logId"
-          v-slot="{ navigate }"
-          :to="{ name: 'logs-details', params: { id: item.logId } }"
-          custom
-        >
-          <v-remixicon
-            title="Open log detail"
-            class="ml-2 text-gray-300 cursor-pointer"
-            size="20"
-            name="riFileTextLine"
-            @click.stop="navigate"
-          />
-        </router-link>
-        <router-link
-          v-show="currentLog.workflowId && item.blockId"
-          :to="`/workflows/${currentLog.workflowId}?blockId=${item.blockId}`"
-        >
-          <v-remixicon
-            name="riExternalLinkLine"
-            size="20"
-            title="Go to block"
-            class="text-gray-300 cursor-pointer ml-2 invisible group-hover:visible"
-          />
-        </router-link>
-      </li>
-    </ul>
-    <div
-      v-if="state.itemId"
-      class="w-4/12 ml-4 border-2 border-opacity-60 rounded-lg dark:text-gray-200 text-sm sticky top-4"
-    >
-      <div class="flex items-center p-2">
-        <p class="flex-1">Context Data</p>
-        <v-remixicon
-          name="riCloseLine"
-          class="cursor-pointer"
-          size="20"
-          @click="state.itemId = ''"
-        />
-      </div>
-      <pre class="px-2 pb-2 overflow-auto scroll max-h-96">{{
-        ctxData[state.itemId] || 'EMPTY'
-      }}</pre>
+      </ui-expand>
     </div>
   </div>
   <div

+ 32 - 3
src/components/newtab/workflow/edit/EditGoogleSheets.vue

@@ -20,7 +20,7 @@
         :model-value="data.spreadsheetId"
         class="w-full"
         placeholder="abcd123"
-        @change="updateData({ spreadsheetId: $event })"
+        @change="updateData({ spreadsheetId: $event }), checkPermission($event)"
       >
         <template #label>
           {{ t('workflow.blocks.google-sheets.spreadsheetId.label') }}*
@@ -35,6 +35,16 @@
         </template>
       </ui-input>
     </edit-autocomplete>
+    <a
+      v-if="!state.havePermission"
+      href="https://docs.automa.site/blocks/google-sheets.html#access-to-spreadsheet"
+      target="_blank"
+      rel="noopener"
+      class="text-sm leading-tight inline-block ml-1"
+    >
+      Automa doesn't have access to the spreadsheet
+      <v-remixicon name="riInformationLine" size="18" class="inline" />
+    </a>
     <edit-autocomplete>
       <ui-input
         :model-value="data.range"
@@ -195,8 +205,8 @@
 <script setup>
 import { shallowReactive, defineAsyncComponent } from 'vue';
 import { useI18n } from 'vue-i18n';
-import { googleSheets } from '@/utils/api';
-import { convert2DArrayToArrayObj } from '@/utils/helper';
+import { googleSheets, fetchApi } from '@/utils/api';
+import { convert2DArrayToArrayObj, debounce } from '@/utils/helper';
 import EditAutocomplete from './EditAutocomplete.vue';
 import InsertWorkflowData from './InsertWorkflowData.vue';
 
@@ -228,6 +238,25 @@ const customDataState = shallowReactive({
   showModal: false,
   data: props.data.customData,
 });
+const state = shallowReactive({
+  lastSheetId: null,
+  havePermission: true,
+});
+
+const checkPermission = debounce(async (value) => {
+  try {
+    if (state.lastSheetId === value) return;
+
+    const response = await fetchApi(
+      `/services/google-sheets/meta?spreadsheetId=${value}`
+    );
+
+    state.havePermission = response.status !== 403;
+    state.lastSheetId = value;
+  } catch (error) {
+    console.error(error);
+  }
+}, 1000);
 
 function updateData(value) {
   emit('update:data', { ...props.data, ...value });

+ 14 - 1
src/components/ui/UiExpand.vue

@@ -1,5 +1,5 @@
 <template>
-  <div :aria-expanded="show" class="ui-expand">
+  <div :aria-expanded="show" :class="{ [activeClass]: show }" class="ui-expand">
     <button
       :class="[headerClass, { [headerActiveClass]: show }]"
       @click="toggleExpand"
@@ -45,10 +45,15 @@ const props = defineProps({
     type: String,
     default: '',
   },
+  activeClass: {
+    type: String,
+    default: '',
+  },
   hideHeaderIcon: {
     type: Boolean,
     default: false,
   },
+  disabled: Boolean,
   appendIcon: Boolean,
 });
 const emit = defineEmits(['update:modelValue']);
@@ -56,6 +61,8 @@ const emit = defineEmits(['update:modelValue']);
 const show = ref(false);
 
 function toggleExpand() {
+  if (props.disabled) return;
+
   show.value = !show.value;
 
   emit('update:modelValue', show.value);
@@ -70,4 +77,10 @@ watch(
   },
   { immediate: true }
 );
+watch(
+  () => props.disabled,
+  () => {
+    show.value = false;
+  }
+);
 </script>

+ 2 - 0
src/newtab/App.vue

@@ -261,6 +261,8 @@ function autoDeleteLogs() {
       dbLogs.ctxData.where('logId').anyOf(ids).delete();
       dbLogs.logsData.where('logId').anyOf(ids).delete();
       dbLogs.histories.where('logId').anyOf(ids).delete();
+
+      localStorage.setItem('checkDeleteLogs', Date.now());
     });
 }
 function handleStorageChanged(change) {