HGustavs / LenaSYS

Code Viewer and Course Organization System used in some courses at University of Skövde
57 stars 31 forks source link

[Documentation] Save (localstorage) #14244

Open b21phiro opened 1 year ago

b21phiro commented 1 year ago

Description

We have our saving system, in that it saves a diagram in the LocalStorage. Write a quick report in md (mardkown) how it's implemented and write about known issues and bugs. Code snippets are helpful too.

b21oscpe commented 1 year ago

loadsave_feature.md

Save & load feature

Description

Save

This feature lets you save and load diagrams from localstorage. If a change is made to the drawing area the user will be able to save a diagram to localstorage. The user will be prompted to write the name of the save and unless it matches another name this file will be saved. If the filename matches an already existing file the user will be asked if they want the save to be overridden. The file is saved as a JSON object containing the statemachine history and all its elements. The save also contains the time of saving. This feature also comes with an autosave for when you close the page. This will be seen as "Autosave" in the load-modal.

Load

If a save is found it will be displayed once the user presses the "Load" button in the toolbar. The user will have the option to load or delete saves from here. Note that you can save several diagrams at a time therefore all of your saves found from your browsers localstorage will be listed here.

diagram.js

saveDiagramAs

The following function shows how a diagram is saved:

function saveDiagramAs()
{
    let elem = document.getElementById("saveDiagramAs");
    let fileName = elem.value;
    const currentDate=new Date();
    const year = currentDate.getFullYear();
    const month = currentDate.getMonth() + 1; // Note: January is month 0
    const day = currentDate.getDate();
    const hours = currentDate.getHours();
    const minutes = currentDate.getMinutes();
    const seconds = currentDate.getSeconds();
    const formattedDate = year + "-" + month + "-" + day+' ';
    const formattedTime = hours + ":" + minutes + ":" + seconds;
    if (fileName.trim() == "") {
        fileName = "diagram "+formattedDate+formattedTime;
    }
    let names;
    let localDiagrams;

    let local = localStorage.getItem("diagrams");
    if (local != null) {
        local = (local[0] == "{") ? local : `{${local}}`;
        localDiagrams = JSON.parse(local);
     names = Object.keys(localDiagrams);
    }

    for(let i=0; i<names.length; i++)
    {
        if(names[i]==fileName)
        {
            hideSavePopout();
            showOverridePopout()
            return;
        }
    }
    storeDiagramInLocalStorage(fileName);
}

storeDiagramInLocalStorage

Once a file is created we store it with storeDiagramInLocalStorage()

function storeDiagramInLocalStorage(key){

    if (stateMachine.currentHistoryIndex == -1) {
        displayMessage(messageTypes.ERROR, "You don't have anything to save!");
    } else {
        // Remove all future states to the history
        stateMachine.removeFutureStates();
        // The content of the save file
        var objToSave = {
            historyLog: stateMachine.historyLog,
            initialState: stateMachine.initialState
        };

        // Sets the autosave diagram first, if it is not already set.
        if (!localStorage.getItem("diagrams")) {
            let s = `{"AutoSave": ${JSON.stringify(objToSave)}}`
            localStorage.setItem("diagrams", s);
        }
        // Gets the string thats contains all the local diagram saves and updates an existing entry or creates a new entry based on the value of 'key'.
        let local = localStorage.getItem("diagrams");
        local = (local[0] == "{") ? local : `{${local}}`;

        let localDiagrams = JSON.parse(local);
        localDiagrams[key] = objToSave;
        localStorage.setItem("diagrams", JSON.stringify(localDiagrams));

        displayMessage(messageTypes.SUCCESS, "You have saved the current diagram");
    }
}

diagram.css & blackTheme.css

The css files handle how the modals are displayed. Aswell as if they are displayed, by removing and adding class-attributed to their classlists.

diagram.php

The html code for the load-modal is initially hidden with the hiddenLoad attribute.

Load modal

<div class="loadModal hiddenLoad">
        <div id="loadHeader">
            <p id="loadTitle">Select a load:</p>
            <button id="closeLoadModal" onclick="closeModal();">&times;</button>
        </div>
        <div id="loadContainer"></div>
        <p id="amountOfLoads"><span id="loadCounter">0</span> saves found</p>
    </div>
    <div class="loadModalOverlay hiddenLoad"></div>

Save modal

<div id="overrideContainer" class="loginBoxContainer" style="display:none">
        <div class="loginBox">
            <div class="loginBoxheader">
                <h3>
                    Filename already exists
                </h3>
                <div class="cursorPointer" onclick="closeOverridePopout()">
                    x
                </div>
            </div>
            <div id="savePopout" style="margin-top:15px;display:block">
                <div>
                    <p>Do you want to overwrite the existing file?</p>
                </div>
                <div class="button-row">
                    <button class="submit-button" onclick="closeOverridePopout(), showSavePopout()">Cancel</button>
                    <button class="submit-button" onclick="    storeDiagramInLocalStorage(getCurrentFileName()), closeOverridePopout()">Overwrite</button>
                </div>
            </div>
        </div>
    </div>

Future development

(Optional) There have been discussions regarding migrating this feature to be server-sided instead as switching browser would delete all of your saved files due to it being saved in localstorage.


b21oscpe, g1-2023, 2023-05-25