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

Adds multiple pages based on different config files #177

Merged
merged 2 commits into from
Mar 7, 2021
Merged

Adds multiple pages based on different config files #177

merged 2 commits into from
Mar 7, 2021

Conversation

luixal
Copy link
Contributor

@luixal luixal commented Jan 7, 2021

Description

As proposed in the related issue, this PR allows to have multiple pages based on different config files.

How does this work?

In the links section, you can add a page with a related path, for example (look at the "Second page"):

links:
  - name: "Contribute"
    icon: "fab fa-github"
    url: "https://github.com/bastienwirtz/homer"
    target: "_blank" # optional html a tag target attribute
  - name: "Second Page"
    icon: "fas fa-file-alt"
    url: "/page2"

When you navigate to this link, Homer will load the assets/config.yml file and the assets/page2.yml file; then it overwrites the fields present on the second config over the first one. This way you can keep the config presets from the main config and only include the ones you want to be different in the second.

For example, if your page2.yml file is like this:

# this config is used by a page linked in the navbar
# this pages will use the same configuration from config.yml, but will overwrite fields present here

# this overwrites title and subtitle:
title: "Page2"
subtitle: "this is the second page"

# this overwrites message config. Setting it to empty to remove message from this page and keep it only in the main one:
message:

# as we want to include a differente link here (so we can get back to home page), we need to replicate all links or they will be revome when overwriting the links field:
links:
  - name: "Home"
    icon: "fas fa-home"
    url: "/"
  - name: "Contribute"
    icon: "fab fa-github"
    url: "https://github.com/bastienwirtz/homer"
    target: "_blank" # optional html a tag target attribute
  - name: "Wiki"
    icon: "fas fa-book"
    url: "https://www.wikipedia.org/"

# we keep the first group from the main page, but remove the second group. We need to replicate that first group or it will be removed:
services:
  - name: "NEW"
    icon: "fas fa-cloud"
    items:
      - name: "Awesome app"
        logo: "assets/tools/sample.png"
        subtitle: "Bookmark example"
        tag: "app"
        url: "https://www.reddit.com/r/selfhosted/"
        target: "_blank"
      - name: "Another one"
        logo: "assets/tools/sample2.png"
        subtitle: "Another application"
        tag: "app"
        url: "#"

It will overwrite fields title, subtitle, message(gets removed as it's empty), linksand services with config from this file, but kill keep other fields from the default config.yml file.

Considerations

For this to work without errors, I had to change line (36@ConnectivityChecker.vue)[https://github.com/bastienwirtz/homer/blob/3786f80dae2df7780d19ba8ffd9374ef3c2fc30f/src/components/ConnectivityChecker.vue#L36] so it refers to window.location.origin instead of window.location.href' or it would try to use /page2?alive` for checking connectivity. Seems to work fine this way.

Fixes #152

Type of change

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to not work as expected)

Checklist:

  • I've read & comply with the contributing guidelines
  • I have tested my code for new features & regressions on both mobile & desktop devices, using the latest version of major browsers.
  • I have made corresponding changes the documentation (README.md).
  • I've checked my modifications for any breaking changes, especially in the config.yml file

@bastienwirtz
Copy link
Owner

Hi @luixal!

Thanks for your contribution! Same here, that sounds great, I will look more closely into it soon!

Copy link
Contributor

@pdevq pdevq left a comment

Choose a reason for hiding this comment

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

This introduces a breaking change for #8 (subdir hosting). The quickest fix I could think of is using a query string instead of a path for additional pages. I've added the corresponding suggestions in the review.

Personally using #page2 instead of ?page2 in the config seems more visually pleasing (and intuitive) to me, but as anchor links don't reload the page an additional mechanism would be needed.

On a side note and please correct me if I'm wrong, even ignoring the breaking change, doesn't a path like /page2 require additional configuration on the server? This would than also not work on the current docker image. For this to work on nginx I had to configure:

location /page2 {
    alias /usr/share/nginx/html;
    try_files $uri $uri/index.html $uri/ =404;
}

More importantly one has to be careful that the server does not add a trailing slash, which breaks the config file retrieval.

@@ -33,7 +33,7 @@ export default {
methods: {
checkOffline: function () {
let that = this;
return fetch(window.location.href + "?alive", {
return fetch(window.location.origin + "?alive", {
Copy link
Contributor

Choose a reason for hiding this comment

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

This will break #8 as window.location.origin only returns http://localhost if the website is located in a subdirectory; eg: http://localhost/homer.

Copy link
Contributor

Choose a reason for hiding this comment

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

With a query string this can reverted back to href.

Suggested change
return fetch(window.location.origin + "?alive", {
return fetch(window.location.href + "?alive", {

src/App.vue Outdated
@@ -13,7 +13,7 @@
<section v-if="config.header" class="first-line">
<div v-cloak class="container">
<div class="logo">
<img v-if="config.logo" :src="config.logo" alt="dashboard logo" />
<a href="/"><img v-if="config.logo" :src="config.logo" alt="dashboard logo" /></a>
Copy link
Contributor

Choose a reason for hiding this comment

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

Again breaks #8 as this will return to http://localhost and not the subdirectory the page is hosted on (http://localhost/homer).

Copy link
Contributor

Choose a reason for hiding this comment

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

If using a query string, just clear it.

Suggested change
<a href="/"><img v-if="config.logo" :src="config.logo" alt="dashboard logo" /></a>
<a href="?"><img v-if="config.logo" :src="config.logo" alt="dashboard logo" /></a>

src/App.vue Outdated
@@ -153,6 +153,13 @@ export default {
let config;
try {
config = await this.getConfig();
const path = (window.location.pathname != '/') ? window.location.pathname : null;
Copy link
Contributor

Choose a reason for hiding this comment

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

Instead of using a path, maybe use a query string instead, which allows for subdirectory hosting.

Suggested change
const path = (window.location.pathname != '/') ? window.location.pathname : null;
const path = (window.location.search.substring(1) != '') ? window.location.search.substring(1) : null;

src/App.vue Outdated
@@ -153,6 +153,13 @@ export default {
let config;
try {
config = await this.getConfig();
const path = (window.location.pathname != '/') ? window.location.pathname : null;
if (path) {
let pathConfig = await this.getConfig(`assets${path}.yml`); // the slash (/) is included in the pathname
Copy link
Contributor

Choose a reason for hiding this comment

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

When using a query string the slash is no longer part of the pathname and needs to be added.

Suggested change
let pathConfig = await this.getConfig(`assets${path}.yml`); // the slash (/) is included in the pathname
let pathConfig = await this.getConfig(`assets/${path}.yml`);

# see url field and assets/page.yml used in this example:
- name: "Second Page"
icon: "fas fa-file-alt"
url: "/page2"
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
url: "/page2"
url: "?page2"

@luixal
Copy link
Contributor Author

luixal commented Jan 30, 2021

Changes sound good to me. Didn't notice the #8 feature. Maybe a doc with all features will be nice to have :)

Copy link
Contributor

@pdevq pdevq left a comment

Choose a reason for hiding this comment

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

To be fair, I only checked for the feature after the fact. Still running an old fork locally that does not support it. I've just had my fair share of fights with applications that don't play well with relative paths and noticed that this change may be problematic in a subdir deployment. Some features are listed under Features in the README.md, maybe hosting in a subdir could be added?

I'm still more fond of using #page2 rather than ?page2. Not just visually, but also because using the query string could block or make it harder for future additions to make use of it. I've added another review with changes for using #page2.

# see url field and assets/page.yml used in this example:
- name: "Second Page"
icon: "fas fa-file-alt"
url: "/page2"
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
url: "/page2"
url: "#page2"

src/App.vue Outdated
@@ -13,7 +13,7 @@
<section v-if="config.header" class="first-line">
<div v-cloak class="container">
<div class="logo">
<img v-if="config.logo" :src="config.logo" alt="dashboard logo" />
<a href="/"><img v-if="config.logo" :src="config.logo" alt="dashboard logo" /></a>
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
<a href="/"><img v-if="config.logo" :src="config.logo" alt="dashboard logo" /></a>
<a href="#"><img v-if="config.logo" :src="config.logo" alt="dashboard logo" /></a>

src/App.vue Outdated
@@ -153,6 +153,13 @@ export default {
let config;
try {
config = await this.getConfig();
const path = (window.location.pathname != '/') ? window.location.pathname : null;
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
const path = (window.location.pathname != '/') ? window.location.pathname : null;
const path = (window.location.hash.substring(1) != '') ? window.location.hash.substring(1) : null;

src/App.vue Outdated
@@ -153,6 +153,13 @@ export default {
let config;
try {
config = await this.getConfig();
const path = (window.location.pathname != '/') ? window.location.pathname : null;
if (path) {
let pathConfig = await this.getConfig(`assets${path}.yml`); // the slash (/) is included in the pathname
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
let pathConfig = await this.getConfig(`assets${path}.yml`); // the slash (/) is included in the pathname
let pathConfig = await this.getConfig(`assets/${path}.yml`);

@@ -33,7 +33,7 @@ export default {
methods: {
checkOffline: function () {
let that = this;
return fetch(window.location.href + "?alive", {
return fetch(window.location.origin + "?alive", {
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
return fetch(window.location.origin + "?alive", {
return fetch(window.location.href + "?alive", {

src/App.vue Show resolved Hide resolved
@luixal
Copy link
Contributor Author

luixal commented Feb 23, 2021

Just tested your suggested changes and it works great. Just cleanning up and will push for merge. Thanks! :)

@bastienwirtz bastienwirtz merged commit 00b46a6 into bastienwirtz:main Mar 7, 2021
@bastienwirtz
Copy link
Owner

Thanks for the great work @luixal & @pdevq !

I merged that as is to just modified a few thing:

  • Little clean (commented code, lint, ...)
  • Renamed page2.yml to another-page.yml.dist (important thing is the .dist, all "templates" config in this repo follows this convention) & added a bit more description.
  • Made possible to switch page without a full reload!

Hope that sounds good to you!

btw, I updated the demo to show the second page feature.
Thanks again!

@pdevq
Copy link
Contributor

pdevq commented Mar 7, 2021

Awesome work! The 'no full reload' is a lot better. Guess I'll have to finally update my local copy, don't know yet what I need the multipages for, but I really like them.

@luixal
Copy link
Contributor Author

luixal commented Mar 7, 2021

Great! Avoiding full reload was a next stage I had on mind but I didn't found the moment to do it, awesome you could!

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.

Feature Request: Enable different 'pages' via multiple configs?
3 participants