Skip to content
New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

Switch to select multiple for editing permissions #24

Closed
simonw opened this issue Sep 2, 2024 · 7 comments
Closed

Switch to select multiple for editing permissions #24

simonw opened this issue Sep 2, 2024 · 7 comments
Labels
enhancement New feature or request

Comments

@simonw
Copy link
Contributor

simonw commented Sep 2, 2024

Claude artifact showing what it could look like if I use this rather than the table of checkboxes:

https://claude.site/artifacts/3b83782b-74d3-4759-ac68-523fe2a905eb

CleanShot 2024-09-02 at 16 14 09@2x

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Group Permissions UI</title>
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/choices.js/10.2.0/choices.min.css">
    <style>
        body {
            font-family: Arial, sans-serif;
            margin: 20px;
            background-color: #f0f0f0;
        }
        .container {
            background-color: white;
            padding: 20px;
            border-radius: 8px;
            box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
        }
        h1 {
            color: #333;
        }
        .group-row {
            display: flex;
            align-items: center;
            margin-bottom: 10px;
            padding: 10px;
            background-color: #f9f9f9;
            border-radius: 4px;
        }
        .group-name {
            width: 150px;
            font-weight: bold;
            color: #4a4a4a;
        }
        select[multiple] {
            min-width: 200px;
        }
        /* Choices.js custom styles */
        .choices__inner {
            min-height: 30px;
            padding: 4px 7.5px 4px 3.75px;
        }
        .choices__list--multiple .choices__item {
            font-size: 12px;
            padding: 2px 5px;
            margin-bottom: 0;
        }
    </style>
</head>
<body>
    <div class="container">
        <h1>Group Permissions</h1>
        <div id="groups-container">
            <div class="group-row">
                <span class="group-name">staff (1)</span>
                <select multiple id="select-staff">
                    <option value="insert-row">insert-row</option>
                    <option value="delete-row">delete-row</option>
                    <option value="update-row">update-row</option>
                    <option value="alter-table" selected>alter-table</option>
                    <option value="drop-table">drop-table</option>
                </select>
            </div>
            <div class="group-row">
                <span class="group-name">devs (5)</span>
                <select multiple id="select-devs">
                    <option value="insert-row" selected>insert-row</option>
                    <option value="delete-row" selected>delete-row</option>
                    <option value="update-row" selected>update-row</option>
                    <option value="alter-table" selected>alter-table</option>
                    <option value="drop-table">drop-table</option>
                </select>
            </div>
            <div class="group-row">
                <span class="group-name">newgroup (0)</span>
                <select multiple id="select-newgroup">
                    <option value="insert-row">insert-row</option>
                    <option value="delete-row">delete-row</option>
                    <option value="update-row">update-row</option>
                    <option value="alter-table" selected>alter-table</option>
                    <option value="drop-table">drop-table</option>
                </select>
            </div>
            <div class="group-row">
                <span class="group-name">muppets (5)</span>
                <select multiple id="select-muppets">
                    <option value="insert-row">insert-row</option>
                    <option value="delete-row">delete-row</option>
                    <option value="update-row">update-row</option>
                    <option value="alter-table">alter-table</option>
                    <option value="drop-table">drop-table</option>
                </select>
            </div>
        </div>
    </div>

    <script src="https://cdnjs.cloudflare.com/ajax/libs/choices.js/10.2.0/choices.min.js"></script>
    <script>
        document.addEventListener('DOMContentLoaded', function() {
            const selects = document.querySelectorAll('select[multiple]');
            selects.forEach(select => {
                new Choices(select, {
                    removeItemButton: true,
                    classNames: {
                        containerOuter: 'choices custom-choices',
                    }
                });
            });
        });
    </script>
</body>
</html>

Conversation transcript: https://gist.github.com/simonw/7b87b24cd53daf8ea05170c3c8013e3c

I started with this screenshot:

image

Originally posted by @simonw in #23 (comment)

@simonw simonw added the enhancement New feature or request label Sep 2, 2024
@simonw simonw added this to the Feature complete milestone Sep 2, 2024
@simonw
Copy link
Contributor Author

simonw commented Sep 2, 2024

I think this UI will work better on narrow screens and will expand to handle more permissions.

@datasette datasette deleted a comment Sep 2, 2024
@simonw
Copy link
Contributor Author

simonw commented Sep 3, 2024

Here's an annoying problem:

CleanShot 2024-09-03 at 07 23 33@2x

Those look weird because the Datasette default CSS targets form button[type="button"] with a bunch of styles that don't work with Choices.

@simonw
Copy link
Contributor Author

simonw commented Sep 3, 2024

Similar visual glitches for the inputs themselves, thanks to default Datasette styles:

CleanShot 2024-09-03 at 07 25 35@2x

Disabling that all fixes it:

CleanShot 2024-09-03 at 07 26 29@2x

@simonw
Copy link
Contributor Author

simonw commented Sep 3, 2024

I think I need to introduce an opt-in mechanism to Datasette core classes, maybe a class of core - which can be used directly on the button or can be put on a wrapper element, such as a form.

@simonw
Copy link
Contributor Author

simonw commented Sep 9, 2024

I'm tempted to get Playwright tests working here, as seen in https://github.com/simonw/datasette-search-all/blob/main/tests/test_playwright.py

@simonw
Copy link
Contributor Author

simonw commented Sep 9, 2024

Another problem: https://github.com/simonw/datasette/blob/832f76ce26ffb2f3e27a006ff90254374bd90e61/datasette/utils/asgi.py#L138-L140

    async def post_vars(self):
        body = await self.post_body()
        return dict(parse_qsl(body.decode("utf-8"), keep_blank_values=True))

That means that a ` will only return the first selected item at the moment. need to work around that (and then fix it in Datasette core).

@simonw
Copy link
Contributor Author

simonw commented Sep 9, 2024

For the moment I'll work around that problem like so:

from datasette.utils import MultiParams

body = await self.post_body()
post_vars = MultiParams(parse_qs(qs=body, keep_blank_values=True))

# for free to join this conversation on GitHub. Already have an account? # to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

1 participant