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/configinlink #1146

Merged
merged 17 commits into from
Apr 10, 2018
Merged

Feat/configinlink #1146

merged 17 commits into from
Apr 10, 2018

Conversation

brianlmacdonald
Copy link
Contributor

@brianlmacdonald brianlmacdonald commented Feb 28, 2018

- Summary

Addressed issue #1132. The cms configuration file's URL had been hardcoded before. This PR allows the user to provide a <link> in <head> to direct to a config file elsewhere. We grab the link out of head using a query looking for rel="cms-config-url", then check to make sure the type is valid and supported. If the query finds a link and it's valid we grab the href provided, otherwise we use the default config.yml url.

- Test plan

Aside from creating tests, I ran the CMS example code with and without the <link> . Without the url defaults to config.yml and it works. To test the <link> url, I created a new folder and moved the config.yml file there and had the href pointing to it. It worked. I also added <link> s with incorrect type and it threw the expected error.

- Description for the changelog

Allows setting config URL with <link> in <head> .

- A picture of a cute animal (not mandatory but encouraged)
Behold, a slow loris!

slowloris

@verythorough
Copy link
Contributor

verythorough commented Feb 28, 2018

Deploy preview for cms-demo ready!

Built with commit 6348f0c

https://deploy-preview-1146--cms-demo.netlify.com

@verythorough
Copy link
Contributor

verythorough commented Feb 28, 2018

Deploy preview for netlify-cms-www ready!

Built with commit 6348f0c

https://deploy-preview-1146--netlify-cms-www.netlify.com

Copy link
Contributor

@erquhart erquhart left a comment

Choose a reason for hiding this comment

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

Thanks for this!

So the use case being covered is somewhat advanced, and also very simple. Therefore, I'm thinking:

  1. No need to provide error messaging.
  2. No need to export just for testing purposes.
  3. We can slim this whole thing down to something like:
configUrl = _.get(document.querySelector('link[rel="netlify-cms-config"]'), 'href') || 'config.yml'

Expanding the query a bit to ensure the type is set is fine too, but that's about it.

@tech4him1
Copy link
Contributor

tech4him1 commented Mar 2, 2018

@erquhart If we want to eventually expand this to support multiple formats, I'm not sure we want to "slim it down" too much -- we still want to check that the format is correct, for example. Thoughts?

@brianlmacdonald
Copy link
Contributor Author

@tech4him1 working on checking the type as we speak.

@@ -7,6 +7,12 @@ export const CONFIG_REQUEST = "CONFIG_REQUEST";
export const CONFIG_SUCCESS = "CONFIG_SUCCESS";
export const CONFIG_FAILURE = "CONFIG_FAILURE";

const configUrl =
get(
get(document.querySelectorAll('head link[rel="cms-config-url"][type="text/yaml"], [type="application/x-yaml"]')[0],
Copy link
Contributor

Choose a reason for hiding this comment

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

I don't believe head link[rel="cms-config-url"][type="text/yaml"], [type="application/x-yaml"] is valid, since you are checking for either head link[rel="cms-config-url"][type="text/yaml"] or [type="application/x-yaml"].

Copy link
Contributor

Choose a reason for hiding this comment

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

Two thoughts:

  1. Just use querySelector and take the first one. I don't think we need robust handling here - it's an advanced use case, they should just make sure they don't add more than one.
  2. It's cool to check the type property of the retrieved element directly, a bit cleaner too.

@tech4him1
Copy link
Contributor

tech4him1 commented Mar 2, 2018

I think we should check the format separately from the selector, so that it is easier to add support for multiple formats later. Thoughts?

@talves
Copy link
Collaborator

talves commented Mar 3, 2018

Am I being too robust to ask we include support for json here?
I have some plans in the works for a configurator app for the cms config and would like to provide a json endpoint. If it is out of scope, I can always PR a change later.

@Benaiah and I were discussing this the other day and want to make sure he has reviewed this PR also. 😄

import { authenticateUser } from "Actions/auth";
import * as publishModes from "Constants/publishModes";

export const CONFIG_REQUEST = "CONFIG_REQUEST";
export const CONFIG_SUCCESS = "CONFIG_SUCCESS";
export const CONFIG_FAILURE = "CONFIG_FAILURE";

const validTypes = [ "text/yaml", "application/x-yaml" ];
const validTypes = { TEXT_YAML: "text/yaml", APPLICATION_X_YAML: "application/x-yaml" };
Copy link
Contributor

Choose a reason for hiding this comment

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

Why not just use an array of types?

Copy link
Contributor Author

@brianlmacdonald brianlmacdonald Mar 5, 2018

Choose a reason for hiding this comment

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

@tech4him1 I was looking through other files and saw types as an object in ListControl.js , so I figured I'd follow in previous footsteps. I can revert back to an array, if you'd like?

Copy link
Contributor

@tech4him1 tech4him1 Mar 5, 2018

Choose a reason for hiding this comment

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

Let me think a little about how this would best work with our formats.js for supporting multiple config formats in the future. (if you have any suggestions, that's great as well)

@tech4him1
Copy link
Contributor

tech4him1 commented Mar 15, 2018

@brianlmacdonald Sorry for the delay, I'm ready to get this merged! I'm thinking the easiest way we would have to send this into our formats.js, is to have the accepted MIME types as the key and the formatter "name" as the value. The keys/values could be switched too, if that is easier.

Example:

{
  "text/yaml": "yaml", 
  "application/x-yaml": "yaml",
  "application/toml": "toml",
}

@brianlmacdonald
Copy link
Contributor Author

@tech4him1 sounds good, I made the adjustments.

@@ -9,6 +9,11 @@ export const CONFIG_SUCCESS = "CONFIG_SUCCESS";
export const CONFIG_FAILURE = "CONFIG_FAILURE";
export const CONFIG_MERGE = "CONFIG_MERGE";

const validTypes = { 'text/yaml': 'yaml', 'application/x-yaml': 'yaml', 'application/toml': 'toml' };
Copy link
Contributor

Choose a reason for hiding this comment

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

Unless we add toml parsing for the config, we can only handle json or yaml.

const validTypes = { 'text/yaml': 'yaml', 'application/x-yaml': 'yaml', 'application/toml': 'toml' };
const configLink = document.querySelector('link[rel="cms-config-url"]');
const isValidType = link => link && validTypes[link.type];
const configUrl = isValidType(configLink) ? get(configLink, 'href') : 'config.yml';
Copy link
Contributor

Choose a reason for hiding this comment

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

It'd be nice to group all of the logic into a getConfigUrl function.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

You got it!


describe('getConfig', () => {
const validTypes = { 'text/yaml': 'yaml', 'application/x-yaml': 'yaml', 'application/toml': 'toml' };
Copy link
Contributor

Choose a reason for hiding this comment

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

Looks like TOML got left in the test accidently.

@tech4him1
Copy link
Contributor

tech4him1 commented Mar 16, 2018

We may need to add docs at some point as well, but that can probably wait until we get more real-world use cases.

@brianlmacdonald
Copy link
Contributor Author

@tech4him1 I can help with docs as soon as I finish battling the field vs fields bug.

@@ -107,8 +114,9 @@ export function loadConfig() {
dispatch(configLoading());

try {
const configUrl = getConfig();
Copy link
Contributor

@tech4him1 tech4him1 Mar 16, 2018

Choose a reason for hiding this comment

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

If you don't mind, I think it would be good to add something like:

console.log(`Netlify CMS using config file: "${ configURL }"`);

That way if a config file isn't being recognized and is defaulting to config.yml, at least the dev knows that is happening.

@tech4him1 tech4him1 requested a review from erquhart March 16, 2018 15:22
@tech4him1
Copy link
Contributor

Awesome, let's get it merged! Really appreciate all your work on this!

@tech4him1
Copy link
Contributor

Am I being too robust to ask we include support for json here?

@talves For now, our YAML parser works with JSON 😄:

<link rel="cms-config-url" type="text/yaml" href="config.json">

Copy link
Contributor

@erquhart erquhart left a comment

Choose a reason for hiding this comment

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

Couple more things here, one may cause the CMS to crash. We should also add some docs to this before merging.

const getConfig = () => {
const validTypes = { 'text/yaml': 'yaml', 'application/x-yaml': 'yaml' };
const configLink = document.querySelector('link[rel="cms-config-url"]');
const isValidType = link => link && validTypes[link.type];
Copy link
Contributor

Choose a reason for hiding this comment

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

Looks like we're going to crash if there's no matching link element by attempting to access property "type" of null.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@erquhart doesn't link && validTypes[link.type] short circuit to false when link is null?

Copy link
Contributor

Choose a reason for hiding this comment

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

🤦‍♂️🤦‍♂️🤦‍♂️

Disregard!

@@ -7,6 +7,9 @@

<link href='https://fonts.googleapis.com/css?family=Roboto:300,400,500' rel='stylesheet' type='text/css'>
<link rel="stylesheet" href="/cms.css"/>
<link href="config.yml" type="text/yaml" rel="cms-config-url">
Copy link
Contributor

Choose a reason for hiding this comment

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

We should remove this from the example project, only because it makes an optional feature seem necessary, and a lot of people treat this example as documentation. We could, however add a comment like:

<!--
  Netlify CMS will automatically look for a "config.yml" file in the same directory
  as this "index.html", but you can override this by providing a link tag like this
  one:
  
  <link href="path/to/config.yml" type="text/yaml" rel="cms-config-url">
-->

@tech4him1
Copy link
Contributor

tech4him1 commented Mar 28, 2018

@brianlmacdonald Would you mind rebasing onto master? Just makes the diff a bit nicer to review 😄.

@brianlmacdonald
Copy link
Contributor Author

@tech4him1 -- I know. It looks horrible. Lesson learned.

@erquhart
Copy link
Contributor

@talves if you have a sec can you test this against one of your local cases? Just want to be sure before merging.

@tech4him1
Copy link
Contributor

@talves Did you get a chance to test this yet?

@talves
Copy link
Collaborator

talves commented Apr 10, 2018

@tech4him1 not yet, sorry. I will try to see if I can get to it tomorrow, if you need it soon.

@tech4him1
Copy link
Contributor

tech4him1 commented Apr 10, 2018

@talves no rush on my part, just wanted to be sure you knew about it 😄

Copy link
Collaborator

@talves talves left a comment

Choose a reason for hiding this comment

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

We need to fix the default failure on a bad link path at a minimum. This is a great contribution btw!

@@ -130,7 +137,9 @@ export function loadConfig() {

try {
const preloadedConfig = getState().config;
const loadedConfig = await getConfig('config.yml', preloadedConfig && preloadedConfig.size > 1);
const configUrl = getConfigUrl();
console.log(`Netlify CMS using config file: "${configUrl}"`);
Copy link
Collaborator

Choose a reason for hiding this comment

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

I wonder if we should clarify this a little further. Also, maybe only show it if the link exists since the default behavior is already known. So, this console.log would move into the getConfigUrl function. That way when debugging we know the link was used rather than default. Not detrimental though, just a thought.

Using config file path: "${configUrl}"

Probably don't need to specify Netilify CMS since we already print a version on page load showing Netlify CMS

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@talves Awesome! Made the changes!

const validTypes = { 'text/yaml': 'yaml', 'application/x-yaml': 'yaml' };
const configLink = document.querySelector('link[rel="cms-config-url"]');
const isValidType = link => link && validTypes[link.type];
return isValidType(configLink) ? get(configLink, 'href') : 'config.yml';
Copy link
Collaborator

Choose a reason for hiding this comment

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

This returns an empty path for the default if the user supplies a link without an href. It really should return 'config.yml' on any invalid form of the link.

Copy link
Collaborator

@talves talves Apr 10, 2018

Choose a reason for hiding this comment

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

Proposed:

const getConfigUrl = () => {
  const validTypes = { 'text/yaml': 'yaml', 'application/x-yaml': 'yaml' };
  const configLinkEl = document.querySelector('link[rel="cms-config-url"]');
  const isValidLink = configLinkEl && validTypes[configLinkEl.type] && get(configLinkEl, 'href');
  if (isValidLink) {
    console.log(`Using config file path: "${configUrl}"`);
    return get(configLinkEl, 'href');
  }
  return 'config.yml';
}

const configLinkEl = document.querySelector('link[rel="cms-config-url"]');
const isValidLink = configLinkEl && validTypes[configLinkEl.type] && get(configLinkEl, 'href');
if (isValidLink) {
console.log(`Using config file path: "${configUrl}"`);
Copy link
Collaborator

@talves talves Apr 10, 2018

Choose a reason for hiding this comment

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

Sorry Brian, missed the configUrl value here. I will let you decide how to manage it 😄

With it fixed, things look good after that.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@talves done and done!

Copy link
Collaborator

@talves talves left a comment

Choose a reason for hiding this comment

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

All Looks good. Testing well in my use cases also!

@Benaiah
Copy link
Contributor

Benaiah commented Apr 10, 2018

Going to squash and merge this as soon as the Travis check completes. @brianlmacdonald thanks for the PR!

@Benaiah Benaiah merged commit 6b77aee into decaporg:master Apr 10, 2018
brianlmacdonald added a commit to brianlmacdonald/netlify-cms that referenced this pull request May 23, 2018
* fix: allows for valid config types expansion

* feat: config url can now come through link tag

* fix: lints added coded

* fix: slims down code per review

* fix: expands query to find supported type

* fix: removes typo in test copy

* fix: changes validTypes to object

* fix: groups config functions into one getConfig func

* adds console message for config url

* adds to docs

* update docs

* fix test

* fix merge conflicts

contributor addition moved to decaporg#1241

* avoids empty path with link without href. changes link console message

* removes additional console

* fixes link path in console

* fix: remove superfluous .allcontributorsrc change
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants