Skip to content

Commit

Permalink
Implement autosave for guest and authenticated users
Browse files Browse the repository at this point in the history
  • Loading branch information
simosathan9 committed Sep 4, 2024
1 parent 545c8c3 commit d34f9bc
Show file tree
Hide file tree
Showing 3 changed files with 206 additions and 20 deletions.
Binary file modified blockly_unix_database.db
Binary file not shown.
172 changes: 153 additions & 19 deletions public/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,137 @@ window.onload = function () {
};

function initBlockly() {
loadWorkspace(); // Load the workspace after initialization
//loadWorkspace(); // Load the workspace after initialization

fetch('/auth-token')
.then((response) => response.json())
.then((data) => {
const token = data.authToken;
if (token) {
loadAutoSavedWorkspace();
} else {
loadWorkspace();
}
});
}

const state = Blockly.serialization.workspaces.save(workspace);

function autoSaveWorkspace() {
fetch('/auth-token')
.then((response) => response.json())
.then((data) => {
const token = data.authToken;
const user = data.user;
if (token) {
document.getElementById('savedWorkspaces').style.display =
'inline-block';

// Serialize the current workspace state
const state = Blockly.serialization.workspaces.save(workspace);
const jsonState = JSON.stringify(state);

// Assuming you have a global 'user' object with the current user ID
if (jsonState && user.id) {
// Send the workspace data to the server to update __autosave__ workspace
fetch('/autoSaveWorkspace', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
workspaceData: jsonState,
userId: user.id
})
})
.then((response) => response.json())
.then((result) => {
if (result.error) {
console.error('Error auto-saving workspace:', result.error);
} else {
console.log('Workspace auto-saved successfully.');
}
})
.catch((error) => {
console.error('Error auto-saving workspace:', error);
});
}
}
})
.catch((error) => {
console.error('Error fetching the token:', error);
});
}

function loadAutoSavedWorkspace() {
// Fetch the authentication token and user information
fetch('/auth-token')
.then((response) => response.json())
.then((data) => {
const token = data.authToken;
const user = data.user;

if (token && user && user.id) {
// Construct the query to find the autosaved workspace ID for the user
fetch(`/getUserWorkspaces?userId=${user.id}`)
.then((response) => response.json())
.then((data) => {
const workspaces = data.workspaces;
const autoSaveWorkspace = workspaces.find(
(ws) => ws.workspaceName === '__autosave__'
);

if (autoSaveWorkspace) {
// Fetch the autosaved workspace data using its ID
fetch(`/getWorkspace?workspaceId=${autoSaveWorkspace.id}`)
.then((response) => response.json())
.then((data) => {
if (data.workspaceData) {
try {
// Deserialize and load the workspace state
const workspaceState = JSON.parse(data.workspaceData);

// Clear the existing workspace and load the autosaved state
Blockly.serialization.workspaces.load(
workspaceState,
workspace
);

console.log('Autosaved workspace loaded successfully.');
} catch (error) {
console.error('Error parsing workspace data:', error);
alert(
'Failed to load autosaved workspace. Please try again.'
);
}
} else {
console.log('No autosaved workspace data found.');
}
})
.catch((error) => {
console.error('Error fetching autosaved workspace:', error);
alert(
'Failed to fetch autosaved workspace. Please try again.'
);
});
} else {
console.log('No autosaved workspace found for user ID:', user.id);
}
})
.catch((error) => {
console.error('Error fetching user workspaces:', error);
alert('Failed to fetch user workspaces. Please try again.');
});
} else {
loadWorkspace();
}
})
.catch((error) => {
console.error('Error fetching the token:', error);
alert('Failed to fetch authentication token. Please try again.');
});
}

document.addEventListener('DOMContentLoaded', () => {
fetch('/auth-token')
.then((response) => response.json())
Expand Down Expand Up @@ -40,10 +166,12 @@ document.addEventListener('DOMContentLoaded', () => {

// Populate dropdown with the user's saved workspaces
workspaces.forEach((workspace) => {
const option = document.createElement('option');
option.value = workspace.id; // use the ID as the option value
option.text = workspace.workspaceName; // display the workspace name
savedWorkspacesSelect.appendChild(option);
if (workspace.workspaceName !== '__autosave__') {
const option = document.createElement('option');
option.value = workspace.id; // use the ID as the option value
option.text = workspace.workspaceName; // display the workspace name
savedWorkspacesSelect.appendChild(option);
}
});

savedWorkspacesSelect.addEventListener('change', () => {
Expand Down Expand Up @@ -197,19 +325,15 @@ loadInitialLanguage();
handleLanguageChange();

function loadWorkspace() {
var xml_text = localStorage.getItem('blocklyWorkspace');
if (xml_text) {
var jsonState = localStorage.getItem('blocklyWorkspace');
if (jsonState) {
console.log('blocklyWorkspace found in local storage.');
try {
var parser = new DOMParser();
var xml = parser.parseFromString(xml_text, 'text/xml');
Blockly.Xml.domToWorkspace(
xml.documentElement,
Blockly.getMainWorkspace()
);
var state = JSON.parse(jsonState);
Blockly.serialization.workspaces.load(state, workspace);
console.log('Blockly workspace loaded successfully.');
} catch (e) {
console.error('Error parsing XML from local storage:', e);
console.error('Error parsing JSON from local storage:', e);
}
} else {
console.log('No saved blocklyWorkspace found in local storage.');
Expand All @@ -218,16 +342,26 @@ function loadWorkspace() {

function onWorkspaceChange(event) {
console.log('Saving Workspace...');
saveWorkspace();
fetch('/auth-token')
.then((response) => response.json())
.then((data) => {
const token = data.authToken;
if (token) {
autoSaveWorkspace();
} else {
saveWorkspace();
}
});
}
Blockly.getMainWorkspace().addChangeListener(onWorkspaceChange);

function saveWorkspace() {
var xml = Blockly.Xml.workspaceToDom(Blockly.getMainWorkspace());
var xmlText = Blockly.Xml.domToText(xml);
localStorage.setItem('blocklyWorkspace', xmlText);
const state = Blockly.serialization.workspaces.save(workspace);
const jsonState = JSON.stringify(state);
localStorage.setItem('blocklyWorkspace', jsonState);
}
window.addEventListener('beforeunload', saveWorkspace);
//window.addEventListener('beforeunload', saveWorkspace);
//window.addEventListener('beforeunload', autoSaveWorkspace);

// Global replacement map
const replacementMap = new Map([
Expand Down
54 changes: 53 additions & 1 deletion server.js
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,17 @@ app.post(
});
}
);
db.run(
`INSERT INTO workspaces (workspaceData, userId, workspaceName) VALUES (?, ?, ?)`,
['{}', newUser.id, '__autosave__'],
function (err) {
if (err) {
console.log(err.message);
req.flash('error', 'Registration failed.');
return res.redirect('/register');
}
}
);
} catch (e) {
console.log(e);
req.flash('error', 'Registration failed.');
Expand Down Expand Up @@ -207,7 +218,11 @@ app.get('/auth-token', addAuthToken, (req, res) => {
}
});
} else {
res.status(401).json({ authToken: null, user: null });
res.json({
message: 'User is not authenticated',
authToken: null,
user: null
});
}
});

Expand Down Expand Up @@ -266,6 +281,43 @@ app.post('/saveWorkspace', (req, res) => {
});
});

app.post('/autoSaveWorkspace', (req, res) => {
const { workspaceData, userId } = req.body;

if (!workspaceData || !userId) {
return res
.status(400)
.json({ error: 'Missing workspace data or user ID.' });
}

// Query to update the __autosave__ workspace
const query = `UPDATE workspaces SET workspaceData = ? WHERE userId = ? AND workspaceName = '__autosave__'`;

db.run(query, [workspaceData, userId], function (err) {
if (err) {
console.error('Error auto-saving workspace:', err.message);
return res.status(500).json({ error: 'Failed to auto-save workspace.' });
}

// If no rows were updated, it means the __autosave__ entry doesn't exist. Insert a new one.
if (this.changes === 0) {
const insertQuery = `INSERT INTO workspaces (workspaceData, userId, workspaceName) VALUES (?, ?, '__autosave__')`;
db.run(insertQuery, [workspaceData, userId], function (err) {
if (err) {
console.error('Error inserting __autosave__ workspace:', err.message);
return res
.status(500)
.json({ error: 'Failed to auto-save workspace.' });
}

res.status(200).json({ message: 'Workspace auto-saved successfully.' });
});
} else {
res.status(200).json({ message: 'Workspace auto-saved successfully.' });
}
});
});

app.get('/getUserWorkspaces', (req, res) => {
// Assume that userId is passed as a query parameter or extracted from session
const userId = req.query.userId;
Expand Down

0 comments on commit d34f9bc

Please sign in to comment.