Skip to content
This repository was archived by the owner on Dec 24, 2025. It is now read-only.
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
278 changes: 255 additions & 23 deletions app/javascript/components/spreadsheet/spreadsheet.vue
Original file line number Diff line number Diff line change
Expand Up @@ -40,15 +40,37 @@
rows: null,
column: null,
columns: [],
minDimensions: [32,32]
minDimensions: [32,32],
headers: [],
},
isReset: false,
userList: [],
isEditing: false,
saveElement: true,
changeRequest: 1,
addColumnReq: false,
showPiviotTable: false
showPiviotTable: false,
lastSavedSheet: {
data: [[]],
style: {},
width: [],
rows: null,
column: null,
columns: [],
minDimensions: [32,32],
headers: [],
},
intermittentSave: {
data: [[]],
style: {},
width: [],
rows: null,
column: null,
columns: [],
minDimensions: [32,32],
headers: [],
},
dataChangeRequest: 0,
}
},
components: {},
Expand Down Expand Up @@ -96,21 +118,166 @@
this.currentMindMap = data.mindmap
this.sheetData = JSON.parse(data.mindmap.canvas)


if(this.temporaryUser != this.$store.getters.getUser){
this.table.destroy()
this.createSheet(data.mindmap.canvas)

let tableHeaders = this.table.getHeaders(true)
if(this.sheetData.data != null && (tableHeaders.length != this.sheetData.headers.length || this.sheetData.data[0].length != this.table.getData()[0].length)){
//Change in grid size requires the table to be recreated
this.table.destroy()
this.createSheet(data.mindmap.canvas)
}else {
this.updateSheet()
//Update the headers
for(let i = 0; i < Math.min(tableHeaders.length, this.sheetData.headers.length); i++){
if(this.sheetData.headers == null || this.sheetData.headers.length == 0){
break
}
if(this.sheetData.headers[i] != tableHeaders[i]){
this.table.setHeader(i, this.sheetData.headers[i])
}
}
}

if(this.currentSelection != null){
let x = Number(this.currentSelection[0])
let y = Number(this.currentSelection[1])
let x1 = Number(this.currentSelection[2])||x
let y1 = Number(this.currentSelection[3])||y
this.table.updateSelectionFromCoords(x,y,x1,y1)
jexcel.current = this.table
}
this.lastSavedSheet = JSON.parse(JSON.stringify(this.sheetData))
this.intermittentSave = JSON.parse(JSON.stringify(this.lastSavedSheet))
//console.log('SavedSheet updated')
//console.log(this.lastSavedSheet.data)
} else {
setTimeout(() => {
this.lastSavedSheet = JSON.parse(JSON.stringify(this.sheetData))
this.intermittentSave = JSON.parse(JSON.stringify(this.lastSavedSheet))
//console.log('SavedSheet updated')
//console.log(this.lastSavedSheet.data)
}, 500);
}
this.changeRequest = this.changeRequest + 1
this.sheetStyles()

}
else {}
}
}
},
methods: {
updateSheet(){
if(this.table == null)
{
this.createSheet(this.currentMindMap.canvas)
return
}
if(this.lastSavedSheet.data == null || this.lastSavedSheet.style == null) {
//console.log('Last saved sheet is null')
this.table.setData(this.sheetData.data)
this.table.setStyle(this.sheetData.style)
return
}
//console.log('Update Sheet - Start')
let tableData = this.table.getData()
let tableStyle = this.getTableStyle()
let currLastSaved = JSON.parse(JSON.stringify(this.lastSavedSheet))
let lastSavedData = JSON.parse(JSON.stringify(currLastSaved.data))
let lastSavedStyle = JSON.parse(JSON.stringify(currLastSaved.style))

//console.log('Table Data')
//console.log(tableData)
//console.log('Last Saved Data')
//console.log(lastSavedData)
//console.log('Websocket Sheet Data')
//console.log(this.sheetData.data)
//console.log('Table Style')
//console.log(tableStyle)
//console.log('Last Saved Style')
//console.log(lastSavedStyle)
//console.log('Websocket Sheet Style')
//console.log(this.sheetData.style)

//console.log('Update table - data comparison')

//check the difference of data between the last saved data and the current data, if there is a difference, put tableData in that cell, if none, put sheetData in that cell
for(let i = 0; i < lastSavedData.length && i < tableData.length; i++){
for(let j = 0; j < lastSavedData[i].length && j < tableData[i].length; j++){
if(lastSavedData[i][j] != tableData[i][j]){
this.sheetData.data[i][j] = tableData[i][j]
this.$nextTick(() => {
this.dataChange()
})
}
}
}
//console.log('Style comparison start')
//check the difference of style between the last saved style and the current style, if there is a difference, put tableStyle in that cell, if none, put sheetData in that cell
for(const [cell, style] of Object.entries(lastSavedStyle)){
if(style != tableStyle[cell]){
this.sheetData.style[cell] = tableStyle[cell]
this.$nextTick(() => {
this.changeStyle()
})
}
}
//console.log('Update table - set data and style')
//console.log(this.sheetData.data)
try{
this.table.setData(this.sheetData.data)
this.table.setStyle(this.sheetData.style)
} catch(e){
this.table.destroy()
this.createSheet(JSON.stringify(this.sheetData))
}

},
compareRow(gridExtenstion, lastSavedData, otherData){
//loop through and see if any rows data has been moved up or down
for(let i = 0; i < lastSavedData.length && i < otherData.length; i++){
if(lastSavedData[i] != otherData[i]){
gridExtenstion.y = i
gridExtenstion.type = lastSavedData[i].length < otherData[i].length
return true
}
}
gridExtenstion.y = 1
gridExtenstion.type = true
return true
},
compareColumn(gridExtenstion, lastSavedData, otherData){
//loop through and see if any column data has been moved up or down
for(let i = 0; i < lastSavedData[0].length && i < otherData[0].length; i++){
//create a new array of the column data
let savedColumnData = []
for(let j = 0; j < lastSavedData.length; j++){
savedColumnData.push(lastSavedData[j][i])
}
let tableColumnData = []
for(let j = 0; j < otherData.length; j++){
tableColumnData.push(otherData[j][i])
}
if(savedColumnData != tableColumnData){
gridExtenstion.x = i
gridExtenstion.type = savedColumnData.length < tableColumnData.length
return true
}
}
gridExtenstion.x = 1
gridExtenstion.type = true
return true
},
createSheet(sheetData){
let _this = this
if(_this.currentMindMap.canvas != null) _this.sheetData = JSON.parse(sheetData)
if(_this.currentMindMap.canvas != null) {
_this.sheetData = JSON.parse(sheetData)
}
if(_this.lastSavedSheet.data == null || _this.lastSavedSheet.style == null) {
_this.lastSavedSheet = JSON.parse(sheetData)
_this.intermittentSave = JSON.parse(sheetData)
}
if(this.currentMindMap.canvas && this.sheetData.data.length > 0 && this.sheetData.columns.length > 0) this.sheetData.minDimensions = [_this.sheetData.columns.length, _this.sheetData.data.length]
else{
this.sheetData.minDimensions = [32,32]
Expand All @@ -126,6 +293,7 @@
minDimensions: _this.sheetData.minDimensions,
allowRenameColumn: true,
onchange: _this.dataChange,
onbeforechange: _this.saveSheet,
onchangestyle: _this.changeStyle,
onresizecolumn: _this.changeSizeColmun,
onselection: _this.selectionCreated,
Expand All @@ -136,6 +304,8 @@
oninsertcolumn: _this.dataChange,
ondeletecolumn: _this.dataChange,
onchangeheader: _this.dataChange,
onundo: _this.dataChange,
onredo: _this.dataChange,
csvFileName: `${_this.currentMindMap.unique_key}`,
toolbar:[
{
Expand All @@ -149,14 +319,14 @@
type: 'i',
content: 'undo',
onclick: function() {
table.undo();
_this.undoTable()
}
},
{
type: 'i',
content: 'redo',
onclick: function() {
table.redo();
_this.redoTable()
}
},
{
Expand Down Expand Up @@ -219,22 +389,46 @@
$('#mytable')[0].style.height = heightVal
},200)
},
async dataChange(){
let _this = this
_this.sheetData.data = _this.table.getData()
_this.sheetData.columns = _this.table.options.columns
if(_this.table.getStyle()) _this.sheetData.style = _this.table.getStyle()
_this.sheetData.user = this.$store.getters.getUser
let mindmap = { mindmap: { canvas: JSON.stringify(_this.sheetData) } }
let id = _this.currentMindMap.unique_key
if(!_this.isReset){
let response = await http.patch(`/msuite/${id}.json`,mindmap)
if (response) {
_this.saveElement = true
_this.sendLocals(false)
saveSheet(){
this.lastSavedSheet.data = this.intermittentSave.data
this.lastSavedSheet.style = this.intermittentSave.style
this.$nextTick(() => {
this.intermittentSave.data = this.table.getData()
this.intermittentSave.style = this.getTableStyle()
//console.log('Sheet saved')
//console.log(this.lastSavedSheet.data)
})

},
dataChange(){
setTimeout(() => {
if(this.dataChangeRequest > 0) return
let _this = this
_this.sheetData.data = _this.table.getData()
_this.sheetData.columns = _this.table.options.columns
_this.sheetData.headers = _this.table.getHeaders(true)
_this.sheetData.style = _this.getTableStyle()
_this.sheetData.user = this.$store.getters.getUser
let mindmap = { mindmap: { canvas: JSON.stringify(_this.sheetData) } }
let id = _this.currentMindMap.unique_key
if(!_this.isReset){
//console.log('Data send start')
//console.log(_this.sheetData.data)
let response = http.patch(`/msuite/${id}.json`,mindmap)
if (response) {
_this.dataChangeRequest = _this.dataChangeRequest + 1
//console.log(_this.dataChangeRequest)
//console.log('Data change saved')
_this.saveElement = true
_this.sendLocals(false)
setTimeout(() => {
_this.dataChangeRequest = 0
//console.log(_this.dataChangeRequest)
}, 25);
}
}
}
else this.isReset = false
else this.isReset = false
}, 100);
},
editStart(){
this.sendLocals(true)
Expand All @@ -248,9 +442,23 @@
});
this.changeStyle()
},
getTableStyle(){
let out = {}
//When a new column or row is added from another user, the style of the table is lost, so we need to catch the error and set the style again
try {
out = this.table.getStyle()
} catch (e) {
this.changeRequest = this.changeRequest + 1
this.table.setStyle(this.sheetData.style)
//console.log(this.sheetData.style)
out = this.table.getStyle()
}
return out
},
changeStyle(){
if(this.changeRequest < 1){
if(this.table) this.sheetData.style = this.table.getStyle()
this.changeRequest = this.changeRequest + 1
this.sheetData.style = this.getTableStyle()
this.sheetData.user = this.$store.getters.getUser
let mindmap = { mindmap: { canvas: JSON.stringify(this.sheetData) } }
let id = this.currentMindMap.unique_key
Expand All @@ -264,6 +472,30 @@
},
selectionCreated(){
this.changeRequest = 0
let tempSelection = this.table.getHighlighted()||null
if(tempSelection == null || tempSelection == undefined || tempSelection[0] == undefined) return
if(tempSelection.length == 1){
this.currentSelection = new Array(4)
this.currentSelection[0] = tempSelection[0].dataset['x']
this.currentSelection[1] = tempSelection[0].dataset['y']
}
else if(tempSelection[0].dataset['x'] == tempSelection[tempSelection.length - 1].dataset['x'] || tempSelection[0].dataset['y'] == tempSelection[tempSelection.length - 1].dataset['y']){
//if the user selects a column or row, the selection will be a thin line
this.currentSelection = new Array(4)
this.currentSelection[0] = tempSelection[0].dataset['x']
this.currentSelection[1] = tempSelection[0].dataset['y']
this.currentSelection[2] = tempSelection[tempSelection.length - 1].dataset['x']
this.currentSelection[3] = tempSelection[tempSelection.length - 1].dataset['y']
}
else if(tempSelection.length > 1){
//get the opposite corner of the selection considering currentSelection 0 and 1 is the starting point
let x = this.currentSelection[0]
let y = this.currentSelection[1]
let lastElData = tempSelection[tempSelection.length - 1].dataset
this.currentSelection[2] = tempSelection[0].dataset['x'] == x ? lastElData['x'] : tempSelection[0].dataset['x'];
this.currentSelection[3] = tempSelection[0].dataset['y'] == y ? lastElData['y'] : tempSelection[0].dataset['y'];
}
//console.log(this.currentSelection)
},
exportXLS(option){
if(option === 1){
Expand Down