flood-for-transmission icon indicating copy to clipboard operation
flood-for-transmission copied to clipboard

Add support for exporting and importing UI configuration

Open johman10 opened this issue 2 years ago • 9 comments

There is quite a bit of config stored in the browser now. And @realivanjx suggested here to add support for exporting and importing that configuration somehow.

johman10 avatar May 19 '22 19:05 johman10

what are config (non server config) that are stored in the browser besides the common paths? i believe currently it is everything under the User Interface menu?

ivanjx avatar May 20 '22 04:05 ivanjx

just to keep it simple i think it is good to store everything into a .json file for export/import. when an export button is clicked just merge the localstorage settings into a single json object then convert to json string and then trigger a browser download dialog somehow? importing can simply be a button that open file browser dialog like the ones under Add Torrents by file. this way #427 can be mitigated while waiting for a fix.

ivanjx avatar May 20 '22 04:05 ivanjx

if i am not mistaken the download thing can be done with window.URL.createObjectURL as explained here

ivanjx avatar May 20 '22 04:05 ivanjx

what are config (non server config) that are stored in the browser besides the common paths? i believe currently it is everything under the User Interface menu?

Enabled and disabled columns, their width and order are also stored in LocalStorage. So that can also be part of the export.

johman10 avatar May 20 '22 07:05 johman10

Hi and thanks for this great UI, I'm using it with transmission-openvpn as a docker container and I'd like to know if the exported json file could be mounted as a volume in docker so it could be easy to store these configs on the server. I'm using Flood on different browsers (mobile and desktop) and it's a PITA to configure all.

niawag avatar Jun 08 '22 12:06 niawag

@niawag thanks for your input!

I don't think that will be possible since the docker container won't be accessible from the browser, where the data is stored, and the browser won't be accessible from the docker container. However, if you know of some way to write to localStorage from a docker container, I'm all ears! :D

If support should be added for such a case we would have to add a feature into Transmission Daemon to support loading some UI config file from the file system. Otherwise the UI is completely blind to what is present in the OS.

edit: that's actually not entirely true! 🤔 I think Transmission serves all files within a folder, so the UI can make a request to a file on the file system and read from there. Writing could perhaps be done via the FileSystem API.

That would an interesting thing to attempt at least, but I'm not sure if it will work! :D

johman10 avatar Jun 08 '22 14:06 johman10

@johman10 thanks for your detailled answer! I'm not a js connoisseur so I asked! I thought that what is done here https://github.com/vasyl-bhd/flood-for-transmission/commit/aef7e0b24d89f705d9287700dafe032da200331e#diff-4b049ea196f984c5efdff949c671572127f627d6a5addaf069f19f5924b1cc8cL8-R13 could be added from a file instead of hardcoded. Maybe with something like this: https://stackoverflow.com/questions/19706046/how-to-read-an-external-local-json-file-in-javascript (but, as I said, I'm no js expert...)

niawag avatar Jun 15 '22 09:06 niawag

@niawag you're right something like that could be done as well! An interesting suggestion to also consider while implementing this.

In general I would want to make this quite diverse though, not to force the user to deal with the file system etc, but rather to allow at least some kind of UI to export and import the data. However that doesn't take away the option to also support a file system approach.

johman10 avatar Jun 15 '22 10:06 johman10

I think my mind is docker-oriented now, too much playing with it ! In any case, if you need some testing I'll be glad to help!

niawag avatar Jun 15 '22 12:06 niawag

I'm using it with transmission-openvpn as a docker container and I'd like to know if the exported json file could be mounted as a volume in docker so it could be easy to store these configs on the server.

@niawag same, this is my workaround

#!/bin/bash

# save user interface settings in flood
# type "localStorage" into console, right click and copy object
# paste object below into "const obj"

# https://haugene.github.io/docker-transmission-openvpn/config-options/#custom_scripts
# volume /path/transmission/scripts:/scripts
# chmod +x scripts/transmission-pre-start.sh

python3 << EOF
PATH = "/opt/transmission-ui/flood-for-transmission/index.html"

SCRIPT = r"""
  <script id="inject">

    const obj = {
      "tableHeaderConfig": "false",
      "darkMode": "enabled",
      "paths": "[]",
      "timeConfig": "true",
      "switchSpeedColors": "false",
      "ui-columns": "[{\"id\":13,\"enabled\":true,\"width\":369},{\"id\":27,\"enabled\":true,\"width\":64},{\"id\":15,\"enabled\":true,\"width\":263},{\"id\":9,\"enabled\":true,\"width\":84},{\"id\":6,\"enabled\":true,\"width\":85},{\"id\":22,\"enabled\":true,\"width\":89},{\"id\":10,\"enabled\":true,\"width\":91},{\"id\":1,\"enabled\":true,\"width\":135},{\"id\":7,\"enabled\":false,\"width\":100},{\"id\":23,\"enabled\":false,\"width\":100},{\"id\":14,\"enabled\":false,\"width\":100},{\"id\":19,\"enabled\":false,\"width\":100},{\"id\":2,\"enabled\":true,\"width\":234},{\"id\":3,\"enabled\":false,\"width\":100},{\"id\":4,\"enabled\":false,\"width\":100},{\"id\":11,\"enabled\":false,\"width\":100},{\"id\":16,\"enabled\":false,\"width\":100},{\"id\":12,\"enabled\":false,\"width\":100},{\"id\":8,\"enabled\":false,\"width\":100},{\"id\":21,\"enabled\":false,\"width\":100},{\"id\":18,\"enabled\":false,\"width\":100},{\"id\":5,\"enabled\":false,\"width\":100},{\"id\":20,\"enabled\":false,\"width\":100},{\"id\":17,\"enabled\":false,\"width\":100},{\"id\":24,\"enabled\":false,\"width\":100},{\"id\":25,\"enabled\":false,\"width\":100},{\"id\":26,\"enabled\":false,\"width\":100}]",
      "torrent-sorting": "{\"id\":15,\"direction\":\"asc\"}"
    }

    for (const [key, value] of Object.entries(obj)) {
        localStorage.setItem(key, value);
    }

  </script>
"""

with open(PATH, "r", encoding="utf-8") as file:
    html = file.read()

# Check if the script with the ID "inject" is already in the file
if '<script id="inject">' in html:
    # Replace existing script
    html = html.split('<script id="inject">')[0] + SCRIPT + html.split('</script>', 1)[1]
else:
    # Inject new script before </head>
    html = html.replace("</head>", SCRIPT + "</head>")

with open(PATH, "w", encoding="utf-8") as file:
    file.write(html)

EOF

matt8707 avatar Dec 31 '22 09:12 matt8707

@ivanjx @niawag @matt8707 as you might have noticed I have released a new version with at least some kind of server side configuration. This means you can effectively overwrite the default configuration.

So the order of importance is like this: Client configuration > config.json configuration > original default configuration

PR for reference can be found here: https://github.com/johman10/flood-for-transmission/pull/540.

I hope that resolves the needs which were raised with this issue, so I will close this. Please open another issue if you have more specific needs.

johman10 avatar Nov 16 '23 23:11 johman10

Thanks a lot for this release, I've tried it and I can see that my settings are propagated, great! I'm having an issue with the common paths setting, I can see they are set well in the webui setting but, when I click on the magnifier icon to choose one, the webui get stuck, only a refresh works to get it back. I opened chrome console and here is the error:

Paths.svelte:18 Uncaught (in promise) TypeError: Pl.init is not a function
    at ic (Paths.svelte:18:15)
    at We (Component.js:148:34)
    at new ac (Paths.svelte:14:17)
    at ne (dom.js:1198:9)
    at Wa (ContextMenu.svelte:120:32)
    at Object.p (ContextMenu.svelte:102:20)
    at Ee (scheduler.js:119:30)
    at Se (scheduler.js:79:5)

Another little problem is that, once the webui is used on a client the following changes in config.json won't be propagated without clearing storage and autorisations (why are both needed ?) but I'm not sure this can be leveraged. Or is it possible to change the order of preference and always use config.json configuration?

niawag avatar Nov 17 '23 11:11 niawag

Regarding the error, I just pushed a fix for that. I should probably write some tests at some point. 😅

Another little problem is that, once the webui is used on a client the following changes in config.json won't be propagated without clearing storage and autorisations (why are both needed ?) but I'm not sure this can be leveraged. Or is it possible to change the order of preference and always use config.json configuration?

Yeah, that's a limitation of the current setup. Perhaps easiest would be to prevent changes if a config file is present. But I don't really want to force everyone to use a file to configure the UI, hence why it's currently supported. Changing the priority order is another option, but I would have to find another way to store the column width than I'm doing currently for that to work correctly.

johman10 avatar Nov 17 '23 12:11 johman10

Great, thanks for the fix! Would it be possible to store a hash of the file (or another way to check if the file changed) ? If yes, we could reload file and overwrite client config only if the file changed. The column width is a very good example of what should not be in the config file, maybe a part of the settings like this one should be in another file, not affected by the presence of a config file.

niawag avatar Nov 17 '23 14:11 niawag

How does this work with haugene/transmission-openvpn? Linking config.json has no effect, do i have to install flood manually?

transmission:
  image: haugene/transmission-openvpn
  environment:
    TRANSMISSION_WEB_UI: flood-for-transmission
  volumes:
    - /volume1/docker/transmission/config.json:/opt/transmission-ui/flood-for-transmission/public/config.json
    ...

matt8707 avatar Nov 24 '23 02:11 matt8707

@matt8707 I think that should work. Can you share the output of the next two commands after running it on the Docker host machine:

ls -al /volume1/docker/transmission/config.json
docker exec transmission ls -al /opt/transmission-ui/flood-for-transmission/public/config.json

johman10 avatar Nov 24 '23 09:11 johman10

-rwxrwxrwx+ 1 matte users 349 Nov 24 02:55 /volume1/docker/transmission/config.json
-rwxrwxr-x 1 abc abc 349 Nov 24 02:55 /opt/transmission-ui/flood-for-transmission/public/config.json

I also can't find a config.json.defaults file, which suggests that I might be on an older version? (haugene/transmission-openvpn is latest)

matt8707 avatar Nov 24 '23 09:11 matt8707

Right, that's probably it. You will have to wait for haugene/transmission-openvpn to upgrade to the latest version, but after that this mounting solution should work.

johman10 avatar Nov 24 '23 09:11 johman10

How does this work with haugene/transmission-openvpn? Linking config.json has no effect, do i have to install flood manually?

transmission:
  image: haugene/transmission-openvpn
  environment:
    TRANSMISSION_WEB_UI: flood-for-transmission
  volumes:
    - /volume1/docker/transmission/config.json:/opt/transmission-ui/flood-for-transmission/public/config.json
    ...

I think you should install this webui as an alternate webui, not messing with the flood installed by default. You just have to mount a volume with this webui file and change the TRANSMISSION_WEB_HOME to this path. This issue should help you do so: https://github.com/haugene/docker-transmission-openvpn/discussions/2271 (same problem for a different webui) And that would allow you to keep flood up to date (but you'll have to take care of it)

niawag avatar Nov 24 '23 09:11 niawag

Can confirm that new docker-transmission-openvpn release has the config.json.defaults

Using public folder, linking config file still has no effect. I did clear localStorage, console says

No config.json found, using default values: See https://github.com/johman10/flood-for-transmission#beta-customization

What did fix it was to remove public in the path 👍🏻

volumes:
  - /volume1/docker/transmission/config.json:/opt/transmission-ui/flood-for-transmission/config.json

matt8707 avatar Dec 13 '23 02:12 matt8707