Open rriemann opened 7 years ago
Thanks for opening this - it's definitely something folks have needed.
I think the most straightforward approach would be to accept a boolean root
config value on the list widget (this doesn't make much sense for any other widget type). If root
is true
, the resulting data is a list rather than an object. We would need validation to ensure that no other fields are defined if a "root" field is provided, and we would need to start handling frontmatter and data that are lists and not just objects as we do currently.
This probably conflicts with https://github.com/netlify/netlify-cms/pull/468 as well, where I believe we're outmoding the list widget in favor of a "repeatable" flag for all fields, in which case any "repeatable" field could have a "root" field (but still only one field defined if there's a root).
Would you be up for taking a swing at this?
Would you be up for taking a swing at this?
Unfortunately I'm super busy with university. :(
No problem! I'm sure someone will take it on.
I would be happy to implement this - currently it is not possible to use gatsby-transformer-yaml
with netlify since the transformer only supports lists.
Any pointers on where to look in the code to get started? I'm pretty new to netlify.
I have solved this on the gatsby side with a custom yaml transformer. I would still like to support it here for maximum flexibility :)
Forget the boolean thing I said before, we should apply the field
/fields
approach from the list widget to the collection config.
fields
vs. field
Here's the list widget using fields
:
# list field config using `fields`
- name: my-list
label: My List
widget: list
fields: [{ name: title, label: title, widget: string }]
# output:
# list: [{ title: 'a title' }, { title: 'another title' }]
Here's the same widget config using field
:
# list field config using `field`
- name: my-list
label: My List
widget: list
field: [{ name: title, label: title, widget: string }]
# output
# list: ['a title', 'another title']
field
on collections
Note: this is a proposal, doesn't actually work!
- name: posts
label: Posts
file: data/list.json # this only makes sense for file collections
field: [{ name: name, label: Name, widget: string }]
# output
['item', 'another item']
The UI and certain config options (like allowAdd
) from the list widget would be reused for at the collection level for this.
I can't think of any downsides or issues with this approach, personally. Thoughts?
Are there any updates regarding the proposals mentioned above? This is a deal-breaker for Gatsby users, please see #1282.
@kripod I believe this is a feature the CMS should support, Until then, it is NOT a deal-breaker for Gatsby users when it is still able to map to a structure the CMS does support at the moment.
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.
This is still happening.
I've just patched this locally in netlify-cms-core/src/backend.ts
functions entryToRaw
and entryWithFormat
. Around the calls to either format.toFile
or format.fromFile
I'm just doing a wrap/unwrap with a special key rootArray
.
entryWithFormat(collectionOrEntity: unknown) {
return (entry: EntryValue): EntryValue => {
const format = resolveFormat(collectionOrEntity, entry);
if (entry && entry.raw !== undefined) {
let data = (format && attempt(format.fromFile.bind(format, entry.raw))) || {};
let data = Array.isArray(data) ? { rootArray: data } : data; //Added wrapper for root arrays
if (isError(data)) console.error(data);
return Object.assign(entry, { data: isError(data) ? {} : data });
}
let data = format.fromFile(entry);
return Array.isArray(data) ? { rootArray: data } : data; //Added wrapper for root arrays
};
}
entryToRaw(collection: Collection, entry: EntryMap): string {
const format = resolveFormat(collection, entry.toJS());
const fieldsOrder = this.fieldsOrder(collection, entry);
let data = entry.get('data').toJS();
let data = data.rootArray || data; // Unwrap root array (this should probably check the fields.length == 1 too)
return format && format.toFile(data, fieldsOrder);
}
Not as clever as the approach mentioned above - but if you think of it as normalising files to always be a map instead of sometimes passing arrays around then it feels a bit less hacky.
No fix on this since 2017? )=
Hi @cyonder, we try to get to the most up voted features first. You can see the sorted list here https://github.com/netlify/netlify-cms/issues?q=is%3Aissue+is%3Aopen+sort%3Areactions-%2B1-desc. Regardless, we would love a contribution for this.
I just tried to see if I could get the ball rolling on this issue.
Doing edits / adding new content would be similar to above but in reversed order.
But the assumptions of content being in separate files made it very complicated straight away but maybe my idea was overly complicated?
Would love to get some help / discussion with main contributors to the project. <3
Hi @reimertz, thanks for pushing this forward. What do you think about putting a draft PR for it? We can use it for the discussion.
Another option is our #contributing channel on Slack https://www.netlifycms.org/chat.
Hi everyone, any update on this ? This seems blocking for Eleventy global data files too, if anyone has a workaround for this I'm interested :sweat_smile:
Hi @vnourdin this would make a great contribution to the CMS if anyone would like to pick it up
Just to said this is also an issue for @nuxt/content with array at the root level of a json. Like here.
+1 would love to see support for .json files with array at root level to mimic a MongoDB collection
would love to see support for this
Still needed :)
NEEEEED
Need it....
Here is a workaround:
CMS.registerCustomFormat('flat-json', 'json', {
fromFile: text => {
const body = JSON.parse(text) as Record<string, Record<string, string>>;
// Now we want to transform this object into a flat object with a 'key' field
const value = { items: Object.entries(body).reduce((acc, [key, value] : [
string,
Record<string, string>
]) => {
acc.push({ key, ...value });
return acc;
}, [] as Record<string, string>[]) };
return value;
},
toFile: (value : { items: Record<string, string>[] }) => {
const body = value.items.reduce((acc, { key, ...rest }) => {
acc[key] = rest;
return acc;
}, {} as Record<string, Record<string, string>>);
return JSON.stringify(body, null, 2);
}
});
- name: 'redirects-collection'
label: 'Redirects'
format: 'flat-json'
files:
- label: 'All Redirects'
file: 'sigpwny.com/src/redirects.json'
name: 'redirects'
fields:
- {label: 'Links', name: 'items', widget: 'list', fields: [
# must be named 'key' for our custom formatter to work
{label: 'From', name: 'key', widget: 'string', hint: 'Example: "/qrcode"'},
{label: 'To', name: 'destination', widget: 'string', hint: 'Example: "myurl.com/foo"'},
{label: 'Status Code', name: 'status', widget: 'hidden', default: 302}
]}
If you have a folder collection, you need a title field, and then your fromFile
should add one.
- Do you want to request a feature or report a bug?
Feature
- What is the current behavior?
it seems to be impossible to create data files with a list at root level:
The current work-around is to use
However, this may require a change of the template that may be part of libraries (jekyll theme gems).
- What is the expected behavior?
I can just create lists also on root level.