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

Support editing data files in sub-directories #349

Merged
merged 42 commits into from
May 14, 2017

Conversation

ashmaroli
Copy link
Member

@ashmaroli ashmaroli commented Apr 21, 2017

Fixes #302

  • Update API to support data files in sub-dirs
  • Update Front End
  • Update documentation

API Breaking Changes

  • path, relative_path, absolute_path is now derived from data file id
  • 'path' != 'relative_path'
  • relative_path is now relative to data_dir and does not have a leading /
  • file id now has a .yml extension even if the assoc. file doesn't.

read from the `id` attribute for path generation

  - redefine `relative_path` from the `data_file_id` by stripping away
`data_dir` in the file id.
  - redefine `absolute_path` here to include subdirectories based on
`splat` params.
  - point `path` to the data file `id` instead of returning the same
data from `relative_path` as previously.
  - consistent `resource_path`
@ashmaroli
Copy link
Member Author

Front-end Changes

  • CRUD data files recursively
  • Added ability to rename data files. Rename their path to move a file from one directory to another.

@ashmaroli
Copy link
Member Author

@benbalter This is ready for your review.
The relative_path now outputs path relative to the data_dir and it doesn't have a leading / to easily join with directory paths that have a trailing / to differentiate itself from a path to an id without an extension.

href: `${base}/${before}${path}`,
label: path
};
if (type == "data files") {
Copy link
Member

Choose a reason for hiding this comment

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

Can't we include the trailing slash in path variable like we do with other types?

Copy link
Member Author

Choose a reason for hiding this comment

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

are you referring to the pre-API variable or path within Breadcrumbs? If its the latter, the reason is that variable before uses path to generate its value and I get the following:

Data Files / movies/ / genres/ /

Copy link
Member

Choose a reason for hiding this comment

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

Trailing slash should be optional for the API. For example while /_api/data/movies/ returns a result , /_api/data/movies doesn't.

Copy link
Member Author

Choose a reason for hiding this comment

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

Actually, /_api/data/movies/ returns result for the /movies/ folder and /_api/data/movies returns for movies.yml file, both being valid data source in their own context and both resulting in site.data.movies

Copy link
Member

Choose a reason for hiding this comment

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

But we defined our routes so that individuals are called with their extensions.

get "/*?/?:path.:ext"

/_api/data/movies returning for movies.yml file doesn't make sense for me. IMO we need to be as specific as possible while calling the endpoints.

Copy link
Member Author

Choose a reason for hiding this comment

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

/_api/data/movies returning for movies.yml file doesn't make sense for me.

It didn't make sense to me too till I read the spec files.

Copy link
Member

Choose a reason for hiding this comment

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

I'm suggesting to fix it since we are proposing sub-directory support now.
@benbalter What do you think?

Copy link
Member Author

Choose a reason for hiding this comment

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

But we defined our routes so that individuals are called with their extensions.

Its not so according to master

get "/:path.?:ext?" do

(I vote for the more sensible resolution too)

Copy link
Member

Choose a reason for hiding this comment

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

Yeah, I just noticed that :face_palm: :trollface:

Copy link
Member

Choose a reason for hiding this comment

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

I think it was a flexible solution at the time, props to @benbalter 🎉 Directories change everything 😄

@@ -12,7 +12,7 @@ export default class Breadcrumbs extends Component {
let base;
if (type == 'pages') {
base = `${ADMIN_PREFIX}/pages`;
} else if (type == 'datafiles') {
} else if (type == 'data files') {
Copy link
Member

Choose a reason for hiding this comment

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

Why rename?

Copy link
Member Author

Choose a reason for hiding this comment

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

I had included the explanation for this in the commit message:

[...] to render into 'Data Files' instead of 'Datafiles'

@@ -47,23 +63,36 @@ export class DataFileEdit extends Component {
}
}

getDirectoryfromPath(path) {
Copy link
Member

Choose a reason for hiding this comment

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

You can retrieve the directory via;

const [directory, ...rest] = params.splat;

Copy link
Member Author

Choose a reason for hiding this comment

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

yes I've used that in a few places elsewhere.

}else if (type == 'datafiles') {
placeholder = 'your-filename.yml';
}else if (type == 'data files') {
placeholder = '<directory/>your-filename.yml';
Copy link
Member

Choose a reason for hiding this comment

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

Typo here => <directory> / your-filename.yml

Copy link
Member Author

Choose a reason for hiding this comment

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

actually, it was intended to show that directory and / are optional. The / needed only if there was a directory param.

(directory/)?filename.yml
(directory/)filename.yml
[directory/]filename.yml
<directory/>filename.yml

Copy link
Member

Choose a reason for hiding this comment

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

I didn't get it. I don't think non-technical users will do 😬 HTML tag came to my mind directly.

Copy link
Member Author

Choose a reason for hiding this comment

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

Ah! I see. I'll settle for the your suggestion then <directory> / your-filename.yml

<InputPath
onChange={onDataFileChanged}
type="data files"
path={path} // TODO: Support using `relative_path` from API instead
Copy link
Member

Choose a reason for hiding this comment

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

For pages and documents, only filenames are passed to InputPath component. Relative paths are shown in the Breadcrumb component. We should be consistent with them. I'm testing locally and seeing /_data/data_file.yml instead for InputPath. Before the filename is already shown to users in the Breadcrumbs component. No need to repeat it. Let's abstract that.

Copy link
Member Author

Choose a reason for hiding this comment

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

/_data/data_file.yml is shown because that parameter (path) is required to be changed to rename the data file.

Copy link
Member Author

Choose a reason for hiding this comment

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

renaming /_data/data_file.yml to /_data/foo/data_file.yml will move the data file into a subdirectory named foo.

Copy link
Member

Choose a reason for hiding this comment

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

Yeah, that's expected. What I'm saying is just show data_file.yml like posts, for example. You can rename it to foo/data_file.yml and it will drop into /_data/foo/data_file.yml automagically 😄 Just check out other types, you will understand the difference.

Copy link
Member Author

Choose a reason for hiding this comment

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

I did check other types. Hence added the //TODO here for a future PR

Copy link
Member

Choose a reason for hiding this comment

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

That info is already exposed via path, relative_path and api_url. We just need to parse it.

Copy link
Member Author

@ashmaroli ashmaroli Apr 25, 2017

Choose a reason for hiding this comment

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

On master, path == relative_path for this resource.
In this PR, they are redefined.
So, do we parse it like below ?

const data_dir = path - relative_path

--
update: strings cannot be subtracted only concatenated

Copy link
Member

Choose a reason for hiding this comment

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

Yeah, that should work.

Copy link
Member Author

Choose a reason for hiding this comment

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

what do you think about enabling the tooltip for DataFileEdit? If yes, what should the message be?

Copy link
Member

Choose a reason for hiding this comment

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

I can't think of one.

@mertkahyaoglu
Copy link
Member

how would you move _data/movies/genres/fiction.yml to _data/books/favs/fiction.yml via the DataFileEdit container?

I intentionally disabled this functionality when I was implementing directory support for Pages and Collections. I don't think it's a good idea to give users too much flexibility/power in the front-end. They can mistakenly move a file to another directory or maybe another content type or even out of Jekyll site and it is really troublesome to move it back.

IMO, these type of operations should be done via OS, not via the GUI. And also I don't want to bring extra complexity to the codebase. This feature requires a bit too much validation to deal with for now. In the future, when Jekyll Admin can be hosted on the cloud, we may implement this or maybe drag-and-drop functionality for files.

Finishing off by quoting from Ben Balter: Sometimes removing/omitting a feature is a feature ☯️

@ashmaroli
Copy link
Member Author

Alrite then, I'll make the change.. funny, that field's label says Path: when it should rightly be Filename..

Regarding the other concerns, directory traversal is already delimited by the API. The put action will always be within JekyllAdmin::Datafile.data_dir, and other content-types are possible even at current master by simply changing the extension in the InputPath. That guard has been provided by the DataGUI though..

Sometimes removing/omitting a feature is a feature

Cool quote! But it doesn't send a clear answer: yes or no

@mertkahyaoglu
Copy link
Member

mertkahyaoglu commented May 12, 2017

funny, that field's label says Path: when it should rightly be Filename

Nope, you can go deeper from the current directory by passing test/othertest/page.md to InputPath, for example, but you can't go to the opposite direction. Therefore Path makes sense, I think..

@ashmaroli
Copy link
Member Author

@mertkahyaoglu addressed the two things that bothered you.. 😄

@mertkahyaoglu mertkahyaoglu added this to the v0.5.0 milestone May 13, 2017
end

get "/:path.?:ext?" do
get "/*?/?:path.?:ext?" do
Copy link
Member

Choose a reason for hiding this comment

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

Let's go with /*?/?:path.:ext 👍

Copy link
Member Author

Choose a reason for hiding this comment

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

so to confirm, we're dropping support for accessing extension-less data files?

Copy link
Member

Choose a reason for hiding this comment

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

Yeap.

Copy link
Member Author

Choose a reason for hiding this comment

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

k.. so change frontend to send requests to /data/foo-dir or leave it at /data/foo-dir/?

@@ -23,7 +24,7 @@ class Server < Sinatra::Base
json written_file.to_api(:include_content => true)
end

delete "/:path.?:ext?" do
delete "/*?/?:path.?:ext?" do
Copy link
Member

Choose a reason for hiding this comment

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

Same here.

@@ -117,7 +117,7 @@ export class DataFileNew extends Component {
datafileChanged, fieldChanged, onDataFileChanged, datafile, updated, errors, params
} = this.props;
const { path, raw_content } = datafile;
const initialPath = params.splat ? (params.splat + "/") : "";
const initialPath = params.splat ? (params.splat) : "";
Copy link
Member

Choose a reason for hiding this comment

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

This is easier.

const initialPath = params.splat || '';

Copy link
Member

Choose a reason for hiding this comment

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

Actually this is not used at all.

@@ -30,14 +30,13 @@ export class DataFiles extends Component {
handleClickDelete(path) {
const { deleteDataFile, params } = this.props;
const confirm = window.confirm(getDeleteMessage(path));
const directory = params.splat ? (params.splat.replace(/\/$/, "")) : "";
const goTo = params.splat ? (params.splat) : "";
const directory = params.splat ? (params.splat) : "";
Copy link
Member

Choose a reason for hiding this comment

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

Again.

const directory = params.splat || '';

Copy link
Member Author

Choose a reason for hiding this comment

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

Ah yes.. its a remnant from an earlier commit. One cant call replace on a nil entity..
will change..

const { deleteDataFile, params } = this.props;
const confirm = window.confirm(getDeleteMessage(path));
const directory = params.splat || "";
const dir = directory ? `/${directory}` : ""
Copy link
Member

Choose a reason for hiding this comment

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

Semicolon here 😄

Copy link
Member Author

Choose a reason for hiding this comment

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

aargh.. I hate it that the linter doesn't report this while running npm run test:watch

@mertkahyaoglu
Copy link
Member

@ashmaroli What do you think about type converting? Let's say I created a JSON data file first, then decided to switch to YAML using the selectbox. Currently it's not converting. Shall we support it or expect users to decide first then input their data accordingly? 😄

}

handleClickSave(e) {
const { datafile, datafileChanged, fieldChanged, putDataFile, params } = this.props;
const { path, relative_path } = datafile;
const data_dir = path.replace(relative_path, "");
Copy link
Member

Choose a reason for hiding this comment

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

Try to use single quote for convention please. I also do that 😄

Copy link
Member Author

Choose a reason for hiding this comment

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

the convention I saw used in all container/views/* is that single quotes are used at the top when importing components, and double quotes within the current component class body.
So I think its best to handle all those files in a separate dedicated PR..

Copy link
Member

Choose a reason for hiding this comment

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

Yeah. I also forget them sometimes 😬 Just a reminder for future commitments. Appreciate for the PR though 👍

Copy link
Member Author

Choose a reason for hiding this comment

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

Let me know if that PR will get merged.. I can then correct files here as part of resolving conflicts

Copy link
Member

Choose a reason for hiding this comment

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

I was planning to merge it last.

Copy link
Member Author

Choose a reason for hiding this comment

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

okay then..

@ashmaroli
Copy link
Member Author

ashmaroli commented May 14, 2017

What do you think about type converting? Let's say I created a JSON data file first, then decided to switch to YAML using the selectbox. Currently it's not converting. Shall we support it..

I had added support for it via the DataGUI.. but checking now, it seems like minor refactors I made to the putDatafile action across various PRs introduced an uncaught bug where the type conversion only takes place when altering the basename and ext for the said file. I'll fix it and extend support to the raw editor as well..

UPDATE: Raw Editor won't handle data type conversion as its output is WYSIWYG

@mertkahyaoglu
Copy link
Member

@ashmaroli One last thing. Could you move Create button above Switch button for DataFileNew?

Copy link
Member

@mertkahyaoglu mertkahyaoglu left a comment

Choose a reason for hiding this comment

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

Thanks @ashmaroli . This one is huge 😄

@mertkahyaoglu mertkahyaoglu merged commit 3813da4 into jekyll:master May 14, 2017
@ashmaroli
Copy link
Member Author

Sorry for the long list of commits 😇
Thank you @mertkahyaoglu for the time and patient review 😃

@mertkahyaoglu
Copy link
Member

@ashmaroli Glad to work with you 😄

Should've hit squash and merge 😬

@ashmaroli ashmaroli deleted the data-directories branch May 14, 2017 12:11
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.

None yet

2 participants