Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

feat(settings): add settings page #63

Merged
merged 7 commits into from
Dec 17, 2020
Merged

feat(settings): add settings page #63

merged 7 commits into from
Dec 17, 2020

Conversation

heyhippari
Copy link
Contributor

@heyhippari heyhippari commented Sep 7, 2020

Desktop
image
Mobile
image

@heyhippari heyhippari force-pushed the feat/settings branch 2 times, most recently from b3cb5ca to 40ac8a5 Compare September 20, 2020 01:49
@sonarcloud
Copy link

sonarcloud bot commented Sep 20, 2020

SonarCloud Quality Gate failed.

Bug B 5 Bugs
Vulnerability A 0 Vulnerabilities (and Security Hotspot 0 Security Hotspots to review)
Code Smell A 0 Code Smells

No Coverage information No Coverage information
0.0% 0.0% Duplication

@heyhippari heyhippari mentioned this pull request Sep 25, 2020
90 tasks
@heyhippari heyhippari added this to the Preview Release 1 milestone Dec 6, 2020
@heyhippari heyhippari marked this pull request as ready for review December 6, 2020 17:34
Copy link
Contributor

@camc314 camc314 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks Great! Only a couple of things...

Something weird is happening here for non-admins:
image

pages/settings/index.vue Outdated Show resolved Hide resolved
pages/settings/index.vue Outdated Show resolved Hide resolved
pages/settings/index.vue Show resolved Hide resolved
pages/settings/index.vue Outdated Show resolved Hide resolved
"noResultsFound": "There is nothing here",
"numberTracks": "{number} tracks",
"operatingSystem": "Operating system",
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
"operatingSystem": "Operating system",
"operatingSystem": "OS",

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here's an option that would fit on a single line on mobile devices.

pages/settings/index.vue Outdated Show resolved Hide resolved
pages/settings/index.vue Outdated Show resolved Hide resolved
Copy link
Member

@ferferga ferferga left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also, I think that we should move the assets from assets folder to static (or merge static with assets). Static already contains the images for the PWA manifest so I think it makes sense to move them there.

<v-row>
<v-col>
<p class="mb-0">
<span
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why in v-html and not inside the tag? Just like you do in the system version strings. Do we need to keep formatting or something?

This can lead to XSS attacks.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The issue is that we need to translate the link and the text around it. The place of the linked word can change depending on the language, though, which means we need to translate the entire thing, link included.

Of course, the issue is that this opens us to potential issues, but I don't really see another way to do this :/

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@mrtimscampi Didn't think about the links, good point.

Not sure if it's worth it, given that no data should be inputted by any users anywhere (but I'm not by any means an XSS expert) but I just had the following idea:

Create a new component that handles this exact situation. We pass it the translation's key string and the component, based on separators, can determine what's a link and what not in the value. For instance:

"Check [Jellyfin](jellyfin.org) docs for more information"

With a computed property, we generate two arrays, one to be used with a for that generates tags and another one for . The tags will be generated from the array ["Check", "docs for more information"] and the from ["[Jellyfin](jellyfin.org)"].

We should be able to cover all the possible cases with a component that parses texts like this while keeping Vetur's complaints away.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do note that there is sanitation performed on the entire translated chain, using dompurify.

It's explicitly for these kind of cases that I added it to the source.

Vetur's warning is just that: a warning to let you know you need to sanitize whatever you pass to it, which we do already.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@mrtimscampi Fair enough.

The only remnant is the question about the images location 😄

pages/settings/index.vue Show resolved Hide resolved
</p>
</v-col>
<v-col cols="3" class="d-flex justify-end">
<v-img src="/icon.png" width="100%" :alt="$t('jellyfinLogo')" />
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
<v-img src="/icon.png" width="100%" :alt="$t('jellyfinLogo')" />
<v-img
contain
src="/icon.png"
width="100%"
:alt="$t('jellyfinLogo')"
/>

Sometimes logo is cut off. Containing it should fix it

Comment on lines 165 to 166
target="_blank"
>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
target="_blank"
>
rel="noopener"
target="_blank"
>

Comment on lines 42 to 48
"helpTranslateLink": "Help <a href=\"{link}\">translate Jellyfin</a> in your language",
"poweredByJellyfin": "This server is powered by Jellyfin",
"poweredByJellyfinLink": "This server is powered by <a href=\"{link}\">Jellyfin</a>",
"readTheDocumentation": "Read the documentation",
"readTheDocumentationLink": "Read the <a href=\"{link}\">documentation</a>",
"reportAnIssue": "Report an issue with the Vue client",
"reportAnIssueLink": "<a href=\"{link}\">Report an issue</a> with the Vue client"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it would be better if these links were opened in new tabs

Copy link
Member

@ferferga ferferga left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unrelated to my review (and you will hate me for not mentioning this before you did all the design), but:

I think we should make another page for the server settings entirely, so we leave in the main settings page the user options (as is right now) and the bottom section (with a title like Administration) with the first Server button that it's in your screenshots, removing everything else.

That button would route us to another page exclusive for server settings, where the main tab displays the card with server info and the settings that are under General in web. From there, we can switch between the many options that the server has.

This solves the overwhelming feel of the actual design, while also easing configuration (with its own page, we can make two columns, left for pages and right for the settings) without the need of going back and forth for reaching every setting.

Do note that this is based on the screenshots of the first post and I actually haven't checked this out locally, I will provide further comments if necessary once I do

},
methods: {
...mapActions('page', ['setPageTitle', 'setAppBarOpacity']),
isEmpty(object: any): boolean {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
isEmpty(object: any): boolean {
isEmpty(object: never): boolean {

Let's keep the happiness of the linter :)

@heyhippari
Copy link
Contributor Author

@ferferga This is actually the third or so design that this has had 😋

I've tried to have separate settings and admin settings and the main issue is that there just isn't a nice way to have a tab-based navigation for this.

I followed the Material guidelines as much as I could, because in my opinion, a tabbed navigation makes for a terrible experience on mobile (There's just too many tabs).

Replacing the navigation drawer, as is done on web currently, is also pretty terrible because it doesn't match what any other app does (Yes, Plex has a sidebar on their web client, but their web client isn't responsive and their mobile app is a completely different client, which doesn't allow administration of the server it's connected to).

Ultimately, if we want to be fully responsive, there's some patterns we'll have to follow in order to make the experience at least decent on both platforms. I think this achieves it way better than the current web does or than the other designs I've tried before do, while keeping the line count and complexity as low as possible :)

Copy link
Contributor

@camc314 camc314 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good to me. Left some comments wrt the translations

"name": "Plugins"
},
"scheduledTasks": {
"description": "Manage scheduled tasks running on your server",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
"description": "Manage scheduled tasks running on your server",
"description": "Manage scheduled tasks running on this server",

"name": "Transcoding & streaming"
},
"users": {
"description": "Manage your users and their permissions",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
"description": "Manage your users and their permissions",
"description": "Manage users and their permissions",

"name": "Playback"
},
"plugins": {
"description": "Add and configure new features for your server",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
"description": "Add and configure new features for your server",
"description": "Add and configure new features on this server",

"name": "Networking"
},
"notifications": {
"description": "Manage and configure notification sent by your server",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
"description": "Manage and configure notification sent by your server",
"description": "Manage and configure notification sent by this server",

"name": "Media players"
},
"networking": {
"description": "Manage the network settings of your server",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
"description": "Manage the network settings of your server",
"description": "Manage the network settings on this server",

@@ -99,8 +184,10 @@
"mustBeUrl": "This field must be a valid URL",
"required": "This field is required"
},
"version": "Version",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
"version": "Version",
"version": "Server version",

@ferferga
Copy link
Member

@MrTimscampi This is the concept I had in mind. Please bear in mind with the photoshop aberrations.

Desktop

This is how the main settings page looks:

main

On the left side, all the options organised by category and with a name (with the proper alignment, size and such, not like in my mockups :P= Whenever something is clicked, on the right side the options are shown, right where it's red. We can add a cool fade effect for that

That's for the user's settings. For server settings, it's all the same, but with one difference: when clicked, left side of the screen fades out and the new server options appear with a fade in effect. Clicking on each option changes what you see on the right side with a fade effect, just like the user options.

Mobile

Same flow, but dividing what's in the right and what's in the left in different pages:

For instance, to reach the server settings, user must follow this route:

  • Go to general settings (what's shown in the desktop design), which will have the same design as demoed in the first post's descriptions
  • Click on server: Transition starts and options from the first page are swapped with server options:

mobile

  • Click on API Keys: Transition starts and user will see exactly what you see on the right (red) side of the desktop layout.

Extra things

With this, I think we ensure good responsiveness across screen sizes while not wasting any space in both desktop and mobile. In desktop, we can even put the Jellyfin logo on the right side when there's no option chosen :)

Not demoed in the mockups, but ofc with this layout descriptions of the options will need to change a bit:

  • Server's button description should be something like "Manage your server", as we're now grouping everything behind that button (As can be seen on desktop mockup, but ofc applies to mobile as well)

  • While on server settings, first option (can be seen on mobile design) should be something like "Information and General settings", essentially adding there the Architecture, OS, etc + a few basic options (so we don't overcrowd settings page)

@heyhippari
Copy link
Contributor Author

Same flow, but dividing what's in the right and what's in the left in different pages:

That's also one of the things I tried at first, but there's one major blocker: you can't make this responsive. Remember, we have to be able to go from one flow to the other on a resize.

Going from one page to multiple ones isn't exactly resize-friendly.

@ferferga
Copy link
Member

@MrTimscampi Oh good point. Was thinking only on fixed sizes like mobile phones.

However, we can solve this with an v-show/v-if I think.

We need to make sure that when breakpoint is bigger, we show stuff in the second column. On small breakpoint, we render both the options and values in the first column and toggle it's visibility with v-show or v-if

@sonarcloud
Copy link

sonarcloud bot commented Dec 17, 2020

Kudos, SonarCloud Quality Gate passed!

Bug A 0 Bugs
Vulnerability A 0 Vulnerabilities
Security Hotspot A 0 Security Hotspots
Code Smell A 0 Code Smells

No Coverage information No Coverage information
0.0% 0.0% Duplication

@heyhippari heyhippari merged commit fad5f7f into master Dec 17, 2020
@heyhippari heyhippari deleted the feat/settings branch December 17, 2020 21:49
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants