cms/resources/js/utils/media-library.js

336 lines
14 KiB
JavaScript
Vendored
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import mediaLibrary from '../components/MediaLibrary';
import {
get as fetchMedia,
update as updateMediaDescription,
destroy as deleteMedia,
updateCategory as updateCategoryForMedia
} from '../apis/admin/media-file';
import {
index as fetchMediaCategories,
destroy as deleteMediaCategory,
add as addMediaCategory,
update as updateMediaCategory,
updateOrder as updateMediaCategoriesOrder
} from '../apis/admin/media-category';
export default function(param) {
// 如果有存在的媒體庫則先刪除
let previousElement = document.getElementById('media-library');
if (previousElement) {
previousElement.remove();
}
// new一個新的媒體庫結構
let mediaLibraryElement = document.createElement('media-library');
// 設定vue的子組件屬性映射
mediaLibraryElement.setAttribute(':_d', 'd')
// 媒體庫元件append進body
document.body.appendChild(mediaLibraryElement);
// 初始化Vue
let vue = new Vue({
el: mediaLibraryElement,
data: {
d: {
// 文字翻譯
text: param.translations,
// 上傳檔案的Url
formAction: param.url,
// csrf token
csrfToken: param.csrfToken,
// 是否為單選模式
single: param.single,
// 是否顯示選擇按鈕
selectMode: param.selectMode,
// 是否為上傳的頁面
isUploadingPage: false,
// 媒體列表
medias: [],
// 目前點選的媒體
currentSelectedMedia: false,
// 選中的媒體列表
selectedMedias: [],
// 最後一個取得的媒體ID
lastFetchedMediaId: null,
// 取得媒體請求的lock
fetchingLock: false,
// 已取的最後一個媒體
fetchingEnd: false,
// 正在取得分類
categoryFetching: false,
// 媒體資訊更新失敗訊息
infoErrorMessage: '',
// 媒體資訊更新成功訊息
infoSuccessMessage: '',
// 媒體分類
categories: [],
// 目前正在拖曳的媒體ID
currentDraggingMediaIds: null,
// 目前所在的媒體分類
currentCategory: 'uncategorized',
// 目前正在編輯的分類ID
currentEditingCategory: null,
// 目前正在編輯的分類輸入框文字
currentEditingCategoryText: '',
// 目前正在新增分類
addingNewCategory: false,
// 目前正在拖曳的媒體分類ID
currentDraggingCategoryId: null,
// 目前拖曳媒體分類的指示線
categoryDraggingIndicator: null,
// 目前拖曳媒體分類過的媒體分類
currentDraggingOverCategoryId: null,
// 分類更新成功訊息
categorySuccessMessage: '',
// 分類更新失敗訊息
categoryErrorMessage: '',
// 圖片更新成功訊息
imageSuccessMessage: '',
// 圖片更新失敗訊息
imageErrorMessage: '',
// 視窗高度
windowHeight: null,
// 視窗寬度
windowWidth: null,
// 手機板下用,只顯示分類
onlyShowCategory: false,
// 手機板下用,只顯示媒體資訊
onlyShowMediaInfo: false,
}
},
computed: {
component() {
return this.$children[0];
}
},
// Vue instance建立完後呼叫
created() {
this.$on('resize', (height, width) => {
this.d.windowHeight = height;
this.d.windowWidth = width;
});
// 預設先載入媒體資料
this.fetchMedia(35);
// 監聽fetch_medias事件載入媒體資料
this.$on('fetch_medias', (limit = null) => {
this.fetchMedia(limit);
});
// 媒體庫子組件觸發的事件,更新拖曳的媒體的分類
this.$on('update_category_for_medias', (mediaCategoryId, mediaIds, isUpdatingDraggingMedias = true) => {
// ajax更新媒體的分類
updateCategoryForMedia(mediaIds, mediaCategoryId)
.then(response => {
let responseBody = response.data;
// 被移動的媒體數量
let mediasMovedCount = responseBody.mediaIds.length;
// 如果不是在all的分類下
if(this.d.currentCategory != 'all' && responseBody.categoryId != this.d.currentCategory) {
// 將media從現有顯示的列表移除
responseBody.mediaIds.forEach((id, i) => {
this.component.removeMediaFromList(id);
});
} else {
responseBody.mediaIds.forEach((id, i) => {
this.component.updateCategoryForMedia(id, responseBody.categoryId);
});
}
for(let categoryId in responseBody.categorySources) {
// 從原本分類的數量減去
this.component.substractCategoryCount(categoryId, responseBody.categorySources[categoryId], false);
}
// 加上數量至目標分類
this.component.addCategoryCount(responseBody.categoryId, mediasMovedCount, false);
// 顯示訊息
if(isUpdatingDraggingMedias) {
this.showImageMessage(responseBody);
} else {
this.showInfoMessage(responseBody);
}
}).catch(error => {
// 顯示訊息
if(isUpdatingDraggingMedias) {
this.showImageErrorMessage(error);
} else {
this.showInfoErrorMessage(error)
}
});
})
// 媒體庫子組件觸發的click事件更新媒體的描述
this.$on('update_media_description', (e, media) => {
// disable按鈕
e.target.disabled = true;
// ajax更新媒體描述
updateMediaDescription(media.id, media.description)
.then(response => {
this.showInfoMessage(response.data);
})
.catch(error => {
this.showInfoErrorMessage(error);
})
.finally(() => {
// endable按鈕
e.target.disabled = false;
})
});
// 媒體庫子組件觸發的click事件刪除媒體
this.$on('delete_media', (e, media) => {
if(confirm(this.d.text.deleteConfirmation)) {
// disable按鈕
e.target.disabled = true;
// ajax刪除媒體
deleteMedia(media.id)
.then(response => {
this.showInfoMessage(response.data);
// 將媒體從列表移除
this.component.removeMediaFromList(response.data.id);
this.component.substractCategoryCount(response.data.categoryId, 1);
})
.catch(error => {
this.showInfoErrorMessage(error);
})
.finally(() => {
// endable按鈕
e.target.disabled = false;
})
}
});
// ajax載入媒體分類
this.d.categoryFetching = true;
fetchMediaCategories()
.then(response => {
this.d.categories = response.data.mediaCategories;
})
.finally(() => {
this.d.categoryFetching = false;
});
// ajax更新媒體分類名稱
this.$on('update_category_name', (categoryId, name) => {
if(name) {
updateMediaCategory(categoryId, name)
.then(response => {
this.showCategoryMessage(response.data);
// 更新列表分類名稱
this.component.updateListCategoryName(response.data.id, response.data.name);
this.component.cancelCategoryEditing();
})
.catch(error => {
this.showCategoryErrorMessage(error);
})
}
})
// ajax新增媒體分類
this.$on('add_category', name => {
if(name) {
addMediaCategory(name)
.then(response => {
this.showCategoryMessage(response.data);
this.component.addCategoryToList(response.data.mediaCategory.id, response.data.mediaCategory.name);
this.component.cancelCategoryEditing();
this.component.onCancelCategoryAdding();
})
.catch(error => {
this.showCategoryErrorMessage(error);
})
}
})
// ajax刪除媒體分類
this.$on('delete_category', id => {
deleteMediaCategory(id)
.then(response => {
this.showCategoryMessage(response.data);
this.component.addCategoryCount('uncategorized', response.data.count, false);
this.component.deleteCategoryFromList(response.data.id);
})
.catch(error => {
this.showCategoryErrorMessage(error)
})
});
// ajax更新媒體分類順序
this.$on('update_category_order', ids => {
updateMediaCategoriesOrder(ids)
.catch(error => {
this.showCategoryErrorMessage(error);
})
})
},
components: {
mediaLibrary
},
methods: {
// 載入媒體資料
fetchMedia(limit = null) {
// 載入動作的lock避免重複呼叫
this.d.fetchingLock = true;
// ajax載入媒體資料
fetchMedia(this.d.currentCategory, this.d.lastFetchedMediaId, limit)
.then(response => {
let medias = response.data.medias;
// 加入至原有列表
this.d.medias = this.d.medias.concat(medias);
if(medias.length) {
// 紀錄最後一筆媒體的id供下次使用
this.d.lastFetchedMediaId = medias[medias.length - 1].id;
} else {
// 已載入至最後的資料
this.d.fetchingEnd = true;
}
})
.finally(() => {
// 釋放載入動作的lock
this.d.fetchingLock = false;
});
},
// 根據response body顯示訊息
showInfoMessage(responseBody, success = true) {
if(responseBody.hasOwnProperty('message')) {
this.component.clearInfoMessages();
if(success) {
this.component.showInfoSuccessMessage(responseBody.message);
} else {
this.component.showInfoErrorMessage(responseBody.message);
}
}
},
// 根據error顯示訊息只顯示http error
showInfoErrorMessage(error) {
if(error.hasOwnProperty('response')) {
this.showInfoMessage(error.response.data, false);
}
},
// 根據response body顯示分類操作訊息
showCategoryMessage(responseBody, success = true) {
if(responseBody.hasOwnProperty('message')) {
this.component.clearCategoryMessages();
if(success) {
this.component.showCategorySuccessMessage(responseBody.message);
} else {
this.component.showCategoryErrorMessage(responseBody.message);
}
}
},
// 根據error顯示分類操作訊息只顯示http error
showCategoryErrorMessage(error) {
if(error.hasOwnProperty('response')) {
this.showCategoryMessage(error.response.data, false);
}
},
// 根據response body顯示圖片操作訊息
showImageMessage(responseBody, success = true) {
if(responseBody.hasOwnProperty('message')) {
this.component.clearImageMessages();
if(success) {
this.component.showImageSuccessMessage(responseBody.message);
} else {
this.component.showImageErrorMessage(responseBody.message);
}
}
},
// 根據error顯示圖片操作訊息只顯示http error
showImageErrorMessage(error) {
if(error.hasOwnProperty('response')) {
this.showImageMessage(error.response.data, false);
}
},
}
});
return vue;
}