Netlify CMS nested YAML using Middleman - middleman

I'm trying to get my Middleman page set up with Netlify CMS. I'm using have the following file structure:
data
> pages
> page1.yml
> page2.yml
Each page has this content:
de:
title: Title in German
en:
title: Title in English
Now I'd like to be able to edit these pages in Netlify CMS and basically have two text fields per page ("Title (DE)" and "Title (EN)").
I tried it with this config:
collections:
- label: Pages
name: pages
folder: data/pages/
fields:
- { label: Title (DE), name: de.title, widget: string, required: true }
- { label: Title (EN), name: en.title, widget: string, required: true }
But nothing shows up in the Netlify CMS backend:
What am I doing wrong?

I'm guessing your files aren't markdown with frontmatter? If you're using data files, eg. json/yaml/toml, you'll need to set the extension for the collection: https://www.netlifycms.org/docs/configuration-options/#extension-and-format
Also, you need a field named title, or else set identifier_field to the name of the field you'd like to use as the identifier (otherwise your files will show as blank tiles in the UI): https://www.netlifycms.org/docs/configuration-options/#identifier_field

Related

How do I get Watch Mode with Sanity.io and Gatsby to refresh content when referenced documents are edited in the CMS / Studio?

I'm using Sanity.io, GatsbyJS 3.x
Watch mode works great when you update content in the CMS, except for when the content you edit is part of a referenced schema of type 'document'.
Put another way, changes made to a document referenced by another document will not re-render the page despite having watch mode on and configured properly.
For example, here is a snippet from my Page schema.
...
{
name: "content",
type: "array",
title: "Page Sections",
description: "Add, edit, and reorder sections",
of: [
{
type: 'reference',
to: [
{ type: 'nav' },
{ type: 'section' },
{ type: 'footer' }
]
}
],
},
...
The above schema references a
nav schema
section schema
footer schema
Each of these are type 'document'.
See the example below.
export default {
type: 'document',
name: 'section',
title: 'Page Sections',
fields: [
{
name: 'meta',
title: 'Section Meta Data',
type: 'meta'
},
...
I want to reference a document, rather than an object, because I need to use the content created based on these schemas to be re-used in throughout the application.
Finally, I've configured the source plugin correctly for watch mode.
Gatsby Config is set properly
{
resolve: `gatsby-source-sanity`,
options: {
projectId: `asdfasdf`,
dataset: `template`,
watchMode: true,
overlayDrafts: true,
token: process.env.MY_SANITY_TOKEN,
},
},
In the CMS / Studio, when you edit one of the fields, you can see Gatsby re-compile in dev mode from the terminal. However, the page does not auto reload and display the changes made to the referenced document.
I've tried reloading the page with the reload button and via hard refresh, the changes do not render.
The only way to render the changes is to go back to the CMS and edit a field on the main “Page” document. Then it refreshes immediately.
Am I doing something wrong? Is this expected behavior? Is there a way to get this to work?
For those that run across this issue, I was able to answer my own question. I hope this saves you the day's it took me to find a solution.
Solution TLDR
You need to explicitly query the referenced document in order for watch mode to work properly.
Details with Examples
Summary
The gatsby-source-sanity plugin provides convenience queries that start with _raw for array types. When you use the _raw query in your GraphQL query, it will not trigger watch mode to reload the data. You need to explicitly query the referenced document in order for watch mode to work properly. This may have to do with how the plugin sets up listeners and I don't know if this is a bug or a feature.
Example
My Page Document has the following schema
{
name: "content",
type: "array",
title: "Page Sections",
description: "Add, edit, and reorder sections",
of: [
{
type: "reference",
to: [
{ type: "nav" },
{ type: 'section' },
],
},
],
},
The section is a reference to a section document.
{ type: 'section' }
The reason I'm not using an object is because I want the page sections to be re-usable on multiple pages.
Assuming you have watch mode enabled properly in your gatsby-config.js file, watch mode, like so...
// gatsby-config.js
{
resolve: `gatsby-source-sanity`,
options: {
projectId: `asdf123sg`,
dataset: `datasetname`,
watchMode: true,
overlayDrafts: true,
token: process.env.SANITY_TOKEN,
},
},
Then you should see the following behavior:
listen for document/content updates
re-run queries, update the data, hot-reload the page
You'll see the following scroll in your terminal window.
success Re-building development bundle - 1.371s
success building schema - 0.420s
success createPages - 0.020s
info Total nodes: 64, SitePage nodes: 9 (use --verbose for breakdown)
success Checking for changed pages - 0.001s
success update schema - 0.081s
success onPreExtractQueries - 0.006s
success extract queries from components - 0.223s
success write out requires - 0.002s
success run page queries - 0.010s - 1/1 99.82/s
This works great if you are querying the main document or any referenced objects. However, if you are querying any references to another document then there is one gotcha you need to be aware of.
The Gotcha
When you use the _raw query in your GraphQL query, it will not trigger watch mode to reload the data. You need to explicitly query the referenced document in order for watch mode to work properly.
Example: This Query will NOT work
export const PageQuery = graphql`
fragment PageInfo on SanityPage {
_id
_key
_updatedAt
_rawContent(resolveReferences: {maxDepth: 10})
}
`
Example: This query WILL Work
export const PageQuery = graphql`
fragment PageInfo on SanityPage {
_id
_key
_updatedAt
_rawContent(resolveReferences: {maxDepth: 10})
content {
... on SanitySection {
id
}
}
}
`
This additional query is the key
Here is where I am explicitly querying the document that is being referenced in the 'content' array.
content {
... on SanitySection {
id
}
}
You don't actually need to use the data that results from that query, you simply need to include this in your query.
My guess is that this informs the gatsby-source-sanity plugin to set up a listener, whereas the _rawContent fragment does not.
Not sure if this is a feature, bug, or just expected behavior. At the time of writing the versions were as follows.
"gatsby": "3.5.1",
"gatsby-source-sanity": "^7.0.0",

TYPO3 - tx_news Speaking URL route if storage out of root page lead to error "The requested page does not exist"

There are existing websites with page tree
Root Website 1
Folder: News Storage 1
Page: News List/Detail 1
Root Website 2
Folder: News Storage 2
Page: News List/Detail 2
When I try to show on "News List/Detail 2" Entity form "News Storage 1" its work for the list view. But in detail view, I have Error "The requested page does not exist" And the opposite.
If place Storage folder in the same level root page - don't work.
Also, if delete routeEnhancers From Site configuration - all works. It's simple:
News:
type: Extbase
extension: News
plugin: Pi1
routes:
-
routePath: '/{news-title}'
_controller: 'News::detail'
_arguments:
news-title: news
defaultController: 'News::list'
aspects:
news-title:
type: PersistedAliasMapper
tableName: tx_news_domain_model_news
routeFieldName: path_segment
Looks like a problem with URL route. But how fix?
I use TYPO3 9.5.22, tx_news 7.3.1.
Question. How allow show entity in detail view from other root pages and use URL routing? Thx for the advice :)
Update: Same problem for another routing like Extbase. If skip SLUG from routing configuration all works). Like, use title instead of the slug. Should be a problem in slug prefix or suffix logic.
So config like that
News:
type: Extbase
extension: News
plugin: Pi1
routes:
-
routePath: '/{news-title}'
_controller: 'News::detail'
_arguments:
news-title: news
defaultController: 'News::list'
aspects:
news-title:
type: PersistedAliasMapper
tableName: tx_news_domain_model_news
routeFieldName: uid
Works but URLs are not the best looking (. Why slug is buggy?
I found the answer in other case here https://stackoverflow.com/a/61673990/4796923. I pretty sure that this case will appear for other developers.
The problem in slug configuration:
Original configuration
$GLOBALS['TCA']['tx_news_domain_model_news']['columns']['path_segment']['config'] = [
'type' => 'slug',
'size' => 50,
'generatorOptions' => [
'fields' => ['title'],
'replacements' => [
'/' => '-'
],
],
'fallbackCharacter' => '-',
'eval' => 'uniqueInSite',
'default' => ''
];
option eval' => 'uniqueInSite' don't work if you need use Entitties over cross website, so you need replace to eval' => 'unique'
And all works. Im my case also was needed add routeValuePrefix: '' in routing config like
aspects:
fund_slug:
type: PersistedAliasMapper
tableName: tx_lloyd_domain_model_fund
routeFieldName: slug
routeValuePrefix: ''
But for tx_news firs fix works

Nuxt dynamic url param for application

I'm quite new to Vue and Nuxt and I built a web app. I need to show url based on city, but don't know what kind of routing is this.
I have web app under domain mydomain.com and there are pages like:
/ - for home page (mydomain.com)
/list - for list of items (mydomain.com/list)
/list/123 - item page, where 123 is id of item (mydomain.com/list/123)
What I want it is to get user's location and write it to vuex store and show urls with city prefix always, so it will look like:
/paris/ - for home page (mydomain.com/paris)
/paris/list - for list of items (mydomain.com/paris/list)
/paris/list/123 - item page, where 123 is id of item (mydomain.com/paris/list/123)
User will be able to change city using dropdown. I'm using nuxt and all url parts are used from pages, but in this case city is not the page it is kind of param. Please advice where to look.
It's achievable using vue-router. You can setup paths there like:
{
path: '/:city',
name: 'City',
component: City
},
{
path: '/:city/list',
name: 'List',
component: ListCmp
},
{
path: '/:city/list/:id',
name: 'ItemPage',
component: ItemPageCmp
},
Your template link for the ListCmp would be:
<router-link :to="{name: 'List', params: {city: 'Paris'}}">Paris</router-link>
And in your component you would access your param:
this.$route.params.city

using vue-head with prerender-spa-plugin is causing title and meta tags to be displayed twice on netlify

This issue only happens when live on netlify ( despite their prerender option turned off ), not while being served locally.
the live site shows :
<title>about | anonplayer about | anonplayer</title>
title and meta tags are set using the vue-head package like so
head: {
title: {
inner: "about | anonplayer",
separator: ' ',
}, ...
and this happens for all routes of my single page app and also to meta tags where there are two sets of the tags I intended to have.
looks like this
I used the default prerender settings like so:
config.plugins.push(new PrerenderSPAPlugin({
// Required - The path to the webpack-outputted app to prerender.
staticDir: path.join(__dirname, 'dist'),
// Required - Routes to render.
routes: ['/', '/about'].concat(contracts.map(each => `/${each.abi}/${each.contract}`)),
}))
was the same, but with Angular
in my case helped replacing function this.meta.addTag() with this.meta.updateTag()
so think it's not hosting issue)

Using Frontmatter with Dynamic Pages in Middleman 4

I have spent ample time researching this without finding a solution that worked. I would love it if someone could help me figure this out.
I’m trying to use Dynamic Pages in my setup, but need to include dynamic Frontmatter with this. But I can’t use Frontmatter in the template file, so I was thinking I could use a YAML data file instead? I tried various approaches, but none were successful. The dynamic pages load just fine, but every one of them will use the same Frontmatter unless I can pull in dynamic data instead.
My config includes:
["england", "france"].each do |team|
proxy "/teams/#{team}/index.html", "/teams/team.html", :locals => { :team_name => team }, :ignore => true
end
And my directory structure in this section looks like this:
teams
- index.html.erb
- team.html.erb
I began a YAML data file that includes:
england:
title: "Teams/England"
description: "England"
headline: "England"
addclass: "england cols"
france:
title: "Teams/France"
description: "France"
headline: "France"
addclass: "france cols"
When I use the aforementioned data in the template file as Frontmatter, it works just fine:
---
title: Teams/France
description: France
headline: France
addclass: france cols
---
One example of how I am using the data:
<%= current_page.data.addclass %>
My questions are as follows:
How can I use a YAML data file to serve unique data to each Dynamic Page?
Can I use the final URI segment ( “england” from /teams/england/, “france” from /teams/france/, etc.) to define which data set to use?
Can I do this without impacting other non-dynamic-pages (/matches/, /groups/, etc.) on the site?
Thank you so very much in advance.
I'd suggest changing your data format slightly. It'll allow you to pass the entire local data item to the template so you can use the data without needing to first "load it" into Frontmatter.
Adjust your teams.yml file (I've added the 'slug' value here):
items:
- title: "England"
slug: "england"
description: "England"
headline: "England"
addclass: "england cols"
- title: "France"
slug: "france"
description: "France"
headline: "France"
addclass: "france cols"
Change your config.rb block to (assuming teams.yml is at /data/teams.yml) - note the check to prevent errors if data is missing:
if File.exist?("data/teams.yml")
data.teams.items.each do |item|
p = item
proxy "teams/#{p.slug}.html", "teams/team.html", locals: { item: p }, ignore: true
end
end
This will pass all the data from the team item into the template. You won't have to "define which data set to use", since the template context will refer just to that data item.
Now, in your team.html.erb template, you can reference the data like this (in the template body, not in the Frontmatter):
<h1 class="<%= item.addclass %>"><%= item.title %></h1>
<h2><%= item.description %></h2>
<h3><%= item.headline %></h3>
This should give you two separate pages for England and France with their own unique data.
Unfortunately, Frontmatter doesn't like to be overwritten after a dynamic page is generated in Middleman. For overwriting Frontmatter that you use for metadata, specifically "title", I've had success with gem 'middleman-meta-tags' [ https://github.com/tiste/middleman-meta-tags ] which allows you to override page titles in the template body after it's been defined, sourced from the YAML data.