346 lines
9.6 KiB
JavaScript
346 lines
9.6 KiB
JavaScript
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.');
|
||
}
|
||
},
|
||
},
|
||
})
|