import { defineStore } from "pinia"; import axios from "axios"; import moment from 'moment'; import apiError from '@/module/apiError.js'; import Swal from 'sweetalert2'; import { uploadFailedFirst, uploadFailedSecond, uploadloader, uploadSuccess, deleteSuccess } from '@/module/alertModal.js'; import pinia from '@/stores/main.ts'; import loadingStore from '@/stores/loading.js'; const loading = loadingStore(pinia); export default defineStore('filesStore', { state: () => ({ allEventFiles: [ { parentLog: '', fileType: '', ownerName: '', } ], switchFilesTagData: { ALL: ['Log', 'Filter', 'Rule', 'Design'], DISCOVER: ['Log', 'Filter', 'Rule'], COMPARE: ['Log','Filter'], DESIGN: ['Log', 'Design'], }, filesTag: 'ALL', httpStatus: 200, uploadId: null, allUploadDetail: null, uploadLogId: null, uploadFileName: null, allDependentsData: null, }), getters: { /** * Get allFiles and switch files tag */ allFiles: state => { let result = state.allEventFiles; let data = state.switchFilesTagData; let filesTag = state.filesTag; result = result.filter(file => data[filesTag].includes(file.fileType)); return result; }, /** * Get upload preview */ uploadDetail: state => { return state.allUploadDetail; }, /** * Get dependents of files data */ dependentsData: state => { return state.allDependentsData; } }, actions: { /** * Fetch All Files api */ async fetchAllFiles() { const api = '/api/files'; let icon = ''; let fileType = ''; let parentLog = ''; try { const response = await axios.get(api); this.allEventFiles = response.data; this.allEventFiles.map(o => { switch (o.type) { case 'log': icon = 'work_history'; fileType = 'Log'; parentLog = o.name; break; case 'filter': icon = 'tornado'; fileType = 'Filter'; parentLog = o.parent.name; break; case 'log-check': case 'filter-check': icon = 'local_police'; fileType = 'Rule'; parentLog = o.parent.name; break; case 'design': icon = 'shape_line'; break; } o.icon = icon; o.parentLog = parentLog; o.fileType = fileType; o.ownerName = o.owner.name; o.updated_base = o.updated_at; o.accessed_base = o.accessed_at; o.updated_at = moment(o.updated_at).utcOffset('+08:00').format('YYYY-MM-DD HH:mm'); o.accessed_at = o.accessed_at ? moment(o.accessed_at).utcOffset('+08:00').format('YYYY-MM-DD HH:mm') : null; }); } catch(error) { apiError(error, 'Failed to load the files.'); }; }, /** * Uploads a CSV log file. 第一階段上傳 * @param {Object} fromData 傳給後端的 Data */ async upload(fromData) { const api = '/api/logs/csv-uploads'; const config = { data: true, headers: { 'Content-Type': 'multipart/form-data', }, }; uploadloader(); // 進度條 try { const response = await axios.post(api, fromData, config); this.uploadId = response.data.id; this.$router.push({name: 'Upload'}); Swal.close(); // 關閉進度條 } catch(error) { if(error.response.status === 422) { // msg: 'not in UTF-8' | 'insufficient columns' | 'the csv file is empty' | 'the filename does not ends with .csv' // type: 'encoding' | 'insufficient_columns' | 'empty' | 'name_suffix' let detail = error.response.data.detail; uploadFailedFirst(detail[0].type, detail[0].msg, detail[0].loc[2]); } else { Swal.close(); // 關閉進度條 apiError(error, 'Failed to upload the files.'); } } }, /** * Fetch upload detail */ async getUploadDetail() { const uploadId = this.uploadId; const api = `/api/logs/csv-uploads/${uploadId}`; try { const response = await axios.get(api); this.allUploadDetail = response.data.preview; } catch(error) { apiError(error, 'Failed to get upload detail.'); } }, /** * Add a Log from an Uploaded CSV Log File. 第二階段上傳 * @param {Object} data 傳給後端的 Data */ async uploadLog(data) { const uploadId = this.uploadId; const api = `/api/logs/csv-uploads/${uploadId}`; uploadloader(); // 進度條 try { const response = await axios.post(api, data); this.uploadLogId = await response.data.id; await Swal.close(); // 關閉進度條 await this.rename(); // 改檔名 await uploadSuccess(); this.$router.push({name: 'Files'}); } catch(error) { if(error.response.status === 422) { let detail = [...error.response.data.detail]; uploadFailedSecond(detail); } else { Swal.close(); // 關閉進度條 apiError(error, 'Failed to upload the log files.'); } } }, /** * Rename a Log * @param { string } type log | filter | log-check | filter-check,傳入以上任一個。 * @param { number } id 檔案 ID * @param { string } name file's name */ async rename(type, id, fileName) { // 先判斷有沒有 uploadLogId,有就設定 id 和 type;再判斷檔案型別。 if(this.uploadId && this.uploadFileName) { type = 'log'; id = this.uploadLogId; fileName = this.uploadFileName; } let api; let data = {"name": fileName}; switch (type) { case 'log': api = `/api/logs/${id}/name`; break; case 'filter': api = `/api/filters/${id}/name`; break; case 'log-check': api = `/api/log-checks/${id}/name`; break; case 'filter-check': api = `/api/filter-checks/${id}/name`; break; } try { await axios.put(api, data); this.uploadFileName = null; await this.fetchAllFiles(); } catch(error) { apiError(error, 'Failed to rename.'); } }, /** * Get the Dependents of the files * @param { string } type log | filter | log-check | filter-check * @param { number } id 檔案 ID */ async getDependents(type, id) { let api; switch (type) { case 'log': api = `/api/logs/${id}/dependents`; break; case 'filter': api = `/api/filters/${id}/dependents`; break; case 'log-check': api = `/api/log-checks/${id}/dependents`; break; case 'filter-check': api = `/api/filter-checks/${id}/dependents`; break; } try { const response = await axios.get(api); this.allDependentsData = response.data; } catch(error) { apiError(error, 'Failed to get Dependents of the files.'); } }, /** * Delete file * @param { string } type log | filter | log-check | filter-check * @param { number } id 檔案 ID */ async deleteFile(type, id) { let api; if(id == null || isNaN(id)) { return $toast.default('Delete File API Error.', {position: 'bottom'}); }; loading.isLoading = true; switch (type) { case 'log': api = `/api/logs/${id}`; break; case 'filter': api = `/api/filters/${id}`; break; case 'log-check': api = `/api/log-checks/${id}`; break; case 'filter-check': api = `/api/filter-checks/${id}`; break; } try { await this.fetchAllFiles(); await deleteSuccess(); } catch(error) { apiError(error, 'Failed to delete.'); } finally { loading.isLoading = false; } }, /** * Remove a Deletion Record,真刪除被 Admin 或被其他帳號刪除的檔案 * @param {number} id 檔案 ID */ async deletionRecord(id) { let api = ''; loading.isLoading = true; api = `/api/deletion/${id}`; try { } catch(error) { apiError(error, 'Failed to Remove a Deletion Record.') } finally { loading.isLoading = false; } }, /** * Download file as CSV * @param { string } type log | filter | log-check | filter-check * @param { number } id 檔案 ID * @param { string } fileName file's name */ async downloadFileCSV(type, id, fileName) { let api; switch (type) { case 'log': api = `/api/logs/${id}/csv`; break; case 'filter': api = `/api/filters/${id}/csv`; break; // case 'log-check': // api = `/api/log-checks/${id}/csv`; // break; // case 'filter-check': // api = `/api/filter-checks/${id}/csv`; // break; default: return; } try { const response = await axios.get(api); const csvData = response.data; const blob = new Blob([csvData], { type: 'text/csv' }); const url = window.URL.createObjectURL(blob); const link = document.createElement('a'); link.href = url; link.download = `${fileName}.csv`; link.click(); window.URL.revokeObjectURL(url); } catch(error) { apiError(error, 'Failed to delete.'); } }, }, })