import { AssetsTable } from './assetstable/Table' import { TasksTable } from './taskstable/Table' import { ShotsTable } from './shotstable/Table' import './detailedview/Viewer' const BrowserHistoryState = pillar.vuecomponents.mixins.BrowserHistoryState; const StateSaveMode = pillar.vuecomponents.mixins.StateSaveMode; const TEMPLATE =`
`; class ComponentState { /** * Serializable state of this component. * * @param {Object} tableState */ constructor(tableState) { this.tableState = tableState; } } /** * Component wrapping a table for selecting attract_task/asset/shot nodes, and a editor to edit the selected node(s). * Selected row filters and visible columns are stored in localStorage per project/context. This makes the settings * sticky between sessions in the same browser. * Selected nodes are stored in window.history. This makes it possible to move back/forward in browser and the selection * will change accordingly. */ Vue.component('attract-app', { template: TEMPLATE, mixins: [BrowserHistoryState], props: { projectId: String, selectedIds: { type: Array, default: [] }, contextType: { type: String, default: 'shots', } }, data() { return { selectedItems: [], isEditing: false, isTableInited: false, project: null } }, created() { pillar.api.thenGetProject(this.projectId) .then((project) =>{ this.project = project; }); }, computed: { selectedNames() { return this.selectedItems.map(it => it.name); }, tableComponentName() { if(!this.project) return ''; switch (this.contextType) { case 'assets': return AssetsTable.options.name; case 'tasks': return TasksTable.options.name; case 'shots': return ShotsTable.options.name; default: console.log('Unknown context type', this.contextType); return ShotsTable.$options.name; } }, /** * @override BrowserHistoryState */ browserHistoryState() { if(this.isTableInited) { return { 'selectedIds': this.selectedIds }; } else { return {}; } }, /** * @override BrowserHistoryState */ historyStateUrl() { let projectUrl = ProjectUtils.projectUrl(); if(this.selectedItems.length !== 1) { return `/attract/${projectUrl}/${this.contextType}/`; } else { let selected = this.selectedItems[0]; let node_type = selected.node_type; if (node_type === 'attract_task' && this.contextType !== 'tasks') { return `/attract/${projectUrl}/${this.contextType}/with-task/${selected._id}`; } else { return `/attract/${projectUrl}/${this.contextType}/${selected._id}`; } } }, stateStorageKey() { return `attract.${this.projectId}.${this.contextType}`; }, initialAppState() { let stateJsonStr; try { stateJsonStr = localStorage.getItem(this.stateStorageKey); } catch (error) { // Log and ignore. console.warn('Unable to restore state:', error); } return stateJsonStr ? JSON.parse(stateJsonStr) : undefined; }, initialTableState() { return this.initialAppState ? this.initialAppState.tableState : undefined; } }, watch: { selectedItems(newValue) { function equals(arrA, arrB) { if (arrA.length === arrB.length) { return arrA.every(it => arrB.includes(it)) && arrB.every(it => arrA.includes(it)) } return false; } let newSelectedIds = newValue.map(item => item._id); // They will be equal for instance when we pop browser history if (equals(newSelectedIds, this.selectedIds)) return; this.selectedIds = newSelectedIds; } }, methods: { onSelectItemsChanged(selectedItems) { this.selectedItems = selectedItems; }, onEditingObjects(isEditing) { this.isEditing = !!isEditing; }, onTableInitialized() { this.isTableInited = true; }, /** * Save table state to localStorage per project and context * @param {Object} newState */ onTableStateChanged(newState) { let appState = new ComponentState(newState); let stateJsonStr = JSON.stringify(appState); try { localStorage.setItem(this.stateStorageKey, stateJsonStr); } catch (error) { // Log and ignore. console.warn('Unable to save state:', error); } }, canChangeSelectionCB() { if(this.isEditing) { let retval = confirm("You have unsaved data. Do you want to discard it?"); return retval; } return true }, /** * @override BrowserHistoryState */ stateSaveMode(newState, oldState) { if (!this.isTableInited) { return StateSaveMode.IGNORE; } if (!oldState) { // Initial state. Replace what we have so we can go back to this state return StateSaveMode.REPLACE; } if (newState.selectedIds.length > 1 && oldState.selectedIds.length > 1) { // To not spam history when multiselecting items return StateSaveMode.REPLACE; } return StateSaveMode.PUSH; }, /** * @override BrowserHistoryState */ applyHistoryState(newState) { this.selectedIds = newState.selectedIds || this.selectedIds; } }, });