John-sCC / jcc_frontend

Apache License 2.0
0 stars 0 forks source link

Frontend: Table Generator #41

Open aidenhuynh opened 7 months ago

aidenhuynh commented 7 months ago

Wireframe

First, Drew and I worked on a wireframe to get an idea of what it would look like, which we then edited to its current form

Version 1:

Image

Version 2:

Image

Initial Testing

Started out by testing the functionality on a markdown page, linked here. This page splits the input by line, then randomly assigns them to groups, divided by rows.

Image

In this image, the groups are [3, 4], [2, 1], and [5]

Conversion to real page

I started with styling with SCSS and HTML, then adding script functionality while tweaking some of the styling at the same time.

Image

You can mess with it here

Future needs

Currently this is mostly completed, but it runs with localstorage, and will be fully finished after integration with user accounts and the backend.

We will also need somewhere to link this to, such as a resources tab or under the classes page

aidenhuynh commented 7 months ago

Drag and drop (3/6)

Started out by implementing jQuery UI and testing its draggable and droppable methods, and learned to use different headers to achieve different results.

<!-- Link jQuery -->
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.7.1/jquery.min.js"></script>

<!-- Link jQueryUI -->
<script src="https://ajax.googleapis.com/ajax/libs/jqueryui/1.13.2/jquery-ui.min.js" type="text/javascript"></script>

In the following code block, we have the headers "revert", "scroll", and "containment", which I use to make the boxes return to their original positions after being dropped so that I can swap the content of the boxes rather than the boxes' positions. The scroll and containment make sure that they can not be dragged out of bounds.

const table = $(`#${tableId}`)

    table.draggable({
        revert: true,
        scroll: true,
        containment: $("#table-div")
    })

Eventually got to fully implement swapping functionality between tables by swapping the content of the table divs.

function dragDrop(nameId) {
    console.log("run")
    const table = $(`#${tableId}`)

    table.draggable({
        revert: true,
        scroll: true,
        containment: $("#table-div")
    })

    table.droppable({
        drop: function(event, ui) {
            var draggable = ui.draggable
            var droppable = $(this)

            var parent1 = draggable.parent()
            var parent2 = droppable.parent()

            temp = draggable

            parent1.children()[1].remove()
            parent1.append(droppable)

            parent2.append(temp)
        }
    })
}

For the next steps, I realized that I'm supposed to make MEMBERS swappable, not WHOLE TABLES, so I will change the code a little to fix that. Also, there is a weird animation thing that happens with the jQuery methods so I will work on making that looks smoother as well.

aidenhuynh commented 6 months ago

Drag and Drop Update (3/14)

Summary

Styling

We now have different hover effects that cause the dropzone to darken and the draggable object to stay on the top layer and lower opacity to make lower elements still visible.

.droppable-hover {
    @include basic-hover(dark);
}

.ui-draggable-dragging {
    z-index: 1;
    background-color: rgba(239, 239, 239, .9) !important // grayish color with half opacity
}

.ui-droppable-hover {
    filter: brightness(80%);
    transition: filter(.2s)
}

Image

Functionality

The code has been updated to be able to swap students between different tables and to different positions within the same table.

function dragDrop(studentId) {
    const student = $(`#${studentId}`)

    student.draggable({
        revert: true,
        scroll: true,
        containment: $("#table-div"),
        revertDuration: 0
    })

    student.droppable({
        drop: function(event, ui) {
            // define starting row and ending row
            var draggable = ui.draggable
            var droppable = $(this)

            // get parent objects and indexes of each element
            var parent1 = draggable.parent()
            var parent2 = droppable.parent()

            var index = draggable.index()

            draggable.insertBefore(droppable)
            temp = droppable.detach()
            console.log(index)
            console.log(parent1.children().length)

            if (parent1.children().length == index) {
                droppable.insertAfter(parent1.children().eq(index - 1))
            }

            else {
                droppable.insertBefore(parent1.children().eq(index))
            }

            // renumber
            for (parent of [parent1, parent2]) {
                const rows = parent.children()
                for (let i = 0; i < rows.length; i ++) {
                    rows[i].children[0].innerHTML = i + 1
                }
            }
        }
    })
}

Improvements

aidenhuynh commented 5 months ago

Backend integration

Functionality

Here is an example of how the code works: just a basic fetch with the delete method.

fetch(`${url}/api/class_period/delete/${id.slice(6)}`, {
        method: 'DELETE',
        mode: 'cors', // no-cors, *cors, same-origin
        cache: 'no-cache', // *default, no-cache, reload, force-cache, only-if-cached
        credentials: 'include', // include, *same-origin, omit
        headers: {
            "Content-Type": "application/json",
            "Authorization": `Bearer ${localStorage.getItem("jwtToken")}`
        },
    })
    .then(response => {
        if (!response.ok) {
            throw new Error(`HTTP error: ${response.status} ${response.statusText}`);
        }
        if (response.status === 204) return 'No content'; // Common for DELETE
        return response.json();
    })
    .catch(error => {
        console.error('There was a problem with the fetch operation:', error);
    });

Next Steps

Main problem is that I can't create or edit classes because they are tied to entire objects for each person in the backend, so the frontend would need to create entire new people.

Image