{"action":"created","comment":{"url":"https://api.github.com/repos/silverstripe/silverstripe-framework/pulls/comments/58853325","id":58853325,"diff_hunk":"@@ -0,0 +1,63 @@\n+/**\n+ * The register of Redux reducers.\n+ * @private\n+ */\n+const register = {};\n+\n+/**\n+ * The central register of Redux reducers for the CMS.","path":"admin/javascript/src/reducer-register.js","position":8,"original_position":8,"commit_id":"40069c4cfc0b0bfdc24b7b66f7d67ec45b3027b9","original_commit_id":"40069c4cfc0b0bfdc24b7b66f7d67ec45b3027b9","user":{"login":"chillu","id":111025,"avatar_url":"https://avatars.githubusercontent.com/u/111025?v=3","gravatar_id":"","url":"https://api.github.com/users/chillu","html_url":"https://github.com/chillu","followers_url":"https://api.github.com/users/chillu/followers","following_url":"https://api.github.com/users/chillu/following{/other_user}","gists_url":"https://api.github.com/users/chillu/gists{/gist_id}","starred_url":"https://api.github.com/users/chillu/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/chillu/subscriptions","organizations_url":"https://api.github.com/users/chillu/orgs","repos_url":"https://api.github.com/users/chillu/repos","events_url":"https://api.github.com/users/chillu/events{/privacy}","received_events_url":"https://api.github.com/users/chillu/received_events","type":"User","site_admin":false},"body":"Since there can only be one \"root reducer\" in Redux that's composed of other reducers, it makes sense to only have one central `ReducerRegister` for any admin code that wants to influence state changes, regardless of module. So the documentation is correct stating \"for the CMS\".","created_at":"2016-04-07T10:58:39Z","updated_at":"2016-04-07T10:58:39Z","html_url":"https://github.com/silverstripe/silverstripe-framework/pull/5278#discussion_r58853325","pull_request_url":"https://api.github.com/repos/silverstripe/silverstripe-framework/pulls/5278","_links":{"self":{"href":"https://api.github.com/repos/silverstripe/silverstripe-framework/pulls/comments/58853325"},"html":{"href":"https://github.com/silverstripe/silverstripe-framework/pull/5278#discussion_r58853325"},"pull_request":{"href":"https://api.github.com/repos/silverstripe/silverstripe-framework/pulls/5278"}}},"pull_request":{"url":"https://api.github.com/repos/silverstripe/silverstripe-framework/pulls/5278","id":65389447,"html_url":"https://github.com/silverstripe/silverstripe-framework/pull/5278","diff_url":"https://github.com/silverstripe/silverstripe-framework/pull/5278.diff","patch_url":"https://github.com/silverstripe/silverstripe-framework/pull/5278.patch","issue_url":"https://api.github.com/repos/silverstripe/silverstripe-framework/issues/5278","number":5278,"state":"open","locked":false,"title":"Campaigns Feature","user":{"login":"chillu","id":111025,"avatar_url":"https://avatars.githubusercontent.com/u/111025?v=3","gravatar_id":"","url":"https://api.github.com/users/chillu","html_url":"https://github.com/chillu","followers_url":"https://api.github.com/users/chillu/followers","following_url":"https://api.github.com/users/chillu/following{/other_user}","gists_url":"https://api.github.com/users/chillu/gists{/gist_id}","starred_url":"https://api.github.com/users/chillu/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/chillu/subscriptions","organizations_url":"https://api.github.com/users/chillu/orgs","repos_url":"https://api.github.com/users/chillu/repos","events_url":"https://api.github.com/users/chillu/events{/privacy}","received_events_url":"https://api.github.com/users/chillu/received_events","type":"User","site_admin":false},"body":"@silverstripe/core-team @unclecheese @stevie-mayhew This is the first significant piece of React work we want to merge, and would appreciate all your feedback :)\r\n\r\n# Overview\r\n\r\nFirst cut of a UI for the [Neo-Versioning RFC](https://github.com/silverstripe/silverstripe-framework/issues/4932) feature - note that the model is called `ChangeSet`, but the user-facing terminology is `Campaign`. From a UI perspective, it simply lists the available campaigns. You can't publish a campaign, add pages or files to a campaign - all of which will follow in subsequent pull requests. The UI is based on @clarkepaul's designs at https://projects.invisionapp.com/boards/9GX68PTXUQFH/.\r\n\r\n# Related Features\r\n\r\nIt's also the first implementation of the [Form Schema RFC](https://github.com/silverstripe/silverstripe-framework/issues/4938), with a stub implementation of a React-based `GridFieldComponent`. It's not meant to fully work with the PHP `GridField` yet, that's a whole different topic. It has just enough functionality to show the campaigns list through a hardcoded form schema JSON in `CampaignAdmin`. As the feature evolves, we'll have the schema generated by the PHP `GridField`. We'll also likely use a third party React component, so didn't spend too much time polishing the current `GridFieldComponent`.\r\n\r\nSimilarly, the `CampaignAdmin` PHP class creates the minimum API surface necessary to drive the feature. We'll need to have a discussion on how APIs work with GridField, how we can work towards a consolidated webservice approach in core, how we manage API state in the client (Relay+GraphQL?) - none of which will be solved by implementing this feature.\r\n\r\n# Background\r\n\r\nThis is a large pull request with a lot of React and build tooling groundwork for the feature. It's been an unnaturally long-lived feature branch because we tried to get the feature \"presentable\". But we're at a point now where keeping the code away from master is doing more harm than good. I've spent many hours squashing and rebasing this, it's getting a bit too time intensive to split it up further. Particularly the ESLint rewrite changes virtually every file, hence it's hard to separate out. I'd recommend going through each commit individually to review, rather than looking at the final diff in Github.\r\n\r\n# Remaining work\r\n\r\nThere's a bit of work left which Open Sourcerers are committing to addressing in the next weeks (before alpha1):\r\n- Better documentation for build tooling and the React base layer\r\n- Automatic ESLint on gulp builds (and via Travis)\r\n- [Inconsistent back button navigation](https://github.com/silverstripe/silverstripe-framework/issues/5276)\r\n\r\nAnd known bugs which we'll get around to before beta:\r\n- https://github.com/silverstripe/silverstripe-framework/issues/5265\r\n- https://github.com/silverstripe/silverstripe-framework/issues/5267\r\n- https://github.com/silverstripe/silverstripe-framework/issues/5268\r\n- https://github.com/silverstripe/silverstripe-framework/issues/5269\r\n- https://github.com/silverstripe/silverstripe-framework/issues/5270\r\n\r\n# How to run locally\r\n\r\nYou don't need to run an `npm install` or `npm run build` unless you want to change frontend code, but it'd be good to try and get it running anyway.\r\n\r\nSince there's no way to create a Campaign just yet, here's a snippet from @tractorcow to create one.\r\n\r\n```\r\nclass Page_Controller extends ContentController {\r\n\r\n\tprivate static $allowed_actions = array (\r\n\t\t'setup'\r\n\t);\r\n\r\n\tpublic function setup() {\r\n\t\t// You can include any CSS or JS required by your project here.\r\n\t\t// See: http://doc.silverstripe.org/framework/en/reference/requirements\r\n\r\n\t\t$set = ChangeSet::get()->filter('Name', 'Test')->first();\r\n\t\tif(!$set) {\r\n\t\t\t$set = new ChangeSet();\r\n\t\t}\r\n\t\t$set->Name = 'Test';\r\n\t\t$set->write();\r\n\t\tforeach(Page::get()->filter('ParentID', 0) as $page) {\r\n\t\t\t$set->addObject($page);\r\n\t\t}\r\n\t\t$set->write();\r\n\r\n\t}\r\n\r\n}\r\n```","created_at":"2016-04-05T23:39:26Z","updated_at":"2016-04-07T10:58:40Z","closed_at":null,"merged_at":null,"merge_commit_sha":"d5b1c36751ff7346291e4767fa53844b24e52d77","assignee":null,"milestone":null,"commits_url":"https://api.github.com/repos/silverstripe/silverstripe-framework/pulls/5278/commits","review_comments_url":"https://api.github.com/repos/silverstripe/silverstripe-framework/pulls/5278/comments","review_comment_url":"https://api.github.com/repos/silverstripe/silverstripe-framework/pulls/comments{/number}","comments_url":"https://api.github.com/repos/silverstripe/silverstripe-framework/issues/5278/comments","statuses_url":"https://api.github.com/repos/silverstripe/silverstripe-framework/statuses/40069c4cfc0b0bfdc24b7b66f7d67ec45b3027b9","head":{"label":"open-sausages:pulls/4.0/campaign-admin","ref":"pulls/4.0/campaign-admin","sha":"40069c4cfc0b0bfdc24b7b66f7d67ec45b3027b9","user":{"login":"open-sausages","id":12824172,"avatar_url":"https://avatars.githubusercontent.com/u/12824172?v=3","gravatar_id":"","url":"https://api.github.com/users/open-sausages","html_url":"https://github.com/open-sausages","followers_url":"https://api.github.com/users/open-sausages/followers","following_url":"https://api.github.com/users/open-sausages/following{/other_user}","gists_url":"https://api.github.com/users/open-sausages/gists{/gist_id}","starred_url":"https://api.github.com/users/open-sausages/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/open-sausages/subscriptions","organizations_url":"https://api.github.com/users/open-sausages/orgs","repos_url":"https://api.github.com/users/open-sausages/repos","events_url":"https://api.github.com/users/open-sausages/events{/privacy}","received_events_url":"https://api.github.com/users/open-sausages/received_events","type":"Organization","site_admin":false},"repo":{"id":37888247,"name":"silverstripe-framework","full_name":"open-sausages/silverstripe-framework","owner":{"login":"open-sausages","id":12824172,"avatar_url":"https://avatars.githubusercontent.com/u/12824172?v=3","gravatar_id":"","url":"https://api.github.com/users/open-sausages","html_url":"https://github.com/open-sausages","followers_url":"https://api.github.com/users/open-sausages/followers","following_url":"https://api.github.com/users/open-sausages/following{/other_user}","gists_url":"https://api.github.com/users/open-sausages/gists{/gist_id}","starred_url":"https://api.github.com/users/open-sausages/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/open-sausages/subscriptions","organizations_url":"https://api.github.com/users/open-sausages/orgs","repos_url":"https://api.github.com/users/open-sausages/repos","events_url":"https://api.github.com/users/open-sausages/events{/privacy}","received_events_url":"https://api.github.com/users/open-sausages/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/open-sausages/silverstripe-framework","description":"SilverStripe Framework, the MVC framework that powers SilverStripe CMS","fork":true,"url":"https://api.github.com/repos/open-sausages/silverstripe-framework","forks_url":"https://api.github.com/repos/open-sausages/silverstripe-framework/forks","keys_url":"https://api.github.com/repos/open-sausages/silverstripe-framework/keys{/key_id}","collaborators_url":"https://api.github.com/repos/open-sausages/silverstripe-framework/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/open-sausages/silverstripe-framework/teams","hooks_url":"https://api.github.com/repos/open-sausages/silverstripe-framework/hooks","issue_events_url":"https://api.github.com/repos/open-sausages/silverstripe-framework/issues/events{/number}","events_url":"https://api.github.com/repos/open-sausages/silverstripe-framework/events","assignees_url":"https://api.github.com/repos/open-sausages/silverstripe-framework/assignees{/user}","branches_url":"https://api.github.com/repos/open-sausages/silverstripe-framework/branches{/branch}","tags_url":"https://api.github.com/repos/open-sausages/silverstripe-framework/tags","blobs_url":"https://api.github.com/repos/open-sausages/silverstripe-framework/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/open-sausages/silverstripe-framework/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/open-sausages/silverstripe-framework/git/refs{/sha}","trees_url":"https://api.github.com/repos/open-sausages/silverstripe-framework/git/trees{/sha}","statuses_url":"https://api.github.com/repos/open-sausages/silverstripe-framework/statuses/{sha}","languages_url":"https://api.github.com/repos/open-sausages/silverstripe-framework/languages","stargazers_url":"https://api.github.com/repos/open-sausages/silverstripe-framework/stargazers","contributors_url":"https://api.github.com/repos/open-sausages/silverstripe-framework/contributors","subscribers_url":"https://api.github.com/repos/open-sausages/silverstripe-framework/subscribers","subscription_url":"https://api.github.com/repos/open-sausages/silverstripe-framework/subscription","commits_url":"https://api.github.com/repos/open-sausages/silverstripe-framework/commits{/sha}","git_commits_url":"https://api.github.com/repos/open-sausages/silverstripe-framework/git/commits{/sha}","comments_url":"https://api.github.com/repos/open-sausages/silverstripe-framework/comments{/number}","issue_comment_url":"https://api.github.com/repos/open-sausages/silverstripe-framework/issues/comments{/number}","contents_url":"https://api.github.com/repos/open-sausages/silverstripe-framework/contents/{+path}","compare_url":"https://api.github.com/repos/open-sausages/silverstripe-framework/compare/{base}...{head}","merges_url":"https://api.github.com/repos/open-sausages/silverstripe-framework/merges","archive_url":"https://api.github.com/repos/open-sausages/silverstripe-framework/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/open-sausages/silverstripe-framework/downloads","issues_url":"https://api.github.com/repos/open-sausages/silverstripe-framework/issues{/number}","pulls_url":"https://api.github.com/repos/open-sausages/silverstripe-framework/pulls{/number}","milestones_url":"https://api.github.com/repos/open-sausages/silverstripe-framework/milestones{/number}","notifications_url":"https://api.github.com/repos/open-sausages/silverstripe-framework/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/open-sausages/silverstripe-framework/labels{/name}","releases_url":"https://api.github.com/repos/open-sausages/silverstripe-framework/releases{/id}","deployments_url":"https://api.github.com/repos/open-sausages/silverstripe-framework/deployments","created_at":"2015-06-23T00:36:38Z","updated_at":"2015-06-23T00:36:43Z","pushed_at":"2016-04-07T06:10:17Z","git_url":"git://github.com/open-sausages/silverstripe-framework.git","ssh_url":"git@github.com:open-sausages/silverstripe-framework.git","clone_url":"https://github.com/open-sausages/silverstripe-framework.git","svn_url":"https://github.com/open-sausages/silverstripe-framework","homepage":"http://silverstripe.org/","size":69587,"stargazers_count":0,"watchers_count":0,"language":"PHP","has_issues":false,"has_downloads":true,"has_wiki":false,"has_pages":false,"forks_count":0,"mirror_url":null,"open_issues_count":1,"forks":0,"open_issues":1,"watchers":0,"default_branch":"3.2"}},"base":{"label":"silverstripe:master","ref":"master","sha":"7337f26d3ae877dbfee288f868da408a3720a8ae","user":{"login":"silverstripe","id":379348,"avatar_url":"https://avatars.githubusercontent.com/u/379348?v=3","gravatar_id":"","url":"https://api.github.com/users/silverstripe","html_url":"https://github.com/silverstripe","followers_url":"https://api.github.com/users/silverstripe/followers","following_url":"https://api.github.com/users/silverstripe/following{/other_user}","gists_url":"https://api.github.com/users/silverstripe/gists{/gist_id}","starred_url":"https://api.github.com/users/silverstripe/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/silverstripe/subscriptions","organizations_url":"https://api.github.com/users/silverstripe/orgs","repos_url":"https://api.github.com/users/silverstripe/repos","events_url":"https://api.github.com/users/silverstripe/events{/privacy}","received_events_url":"https://api.github.com/users/silverstripe/received_events","type":"Organization","site_admin":false},"repo":{"id":1318892,"name":"silverstripe-framework","full_name":"silverstripe/silverstripe-framework","owner":{"login":"silverstripe","id":379348,"avatar_url":"https://avatars.githubusercontent.com/u/379348?v=3","gravatar_id":"","url":"https://api.github.com/users/silverstripe","html_url":"https://github.com/silverstripe","followers_url":"https://api.github.com/users/silverstripe/followers","following_url":"https://api.github.com/users/silverstripe/following{/other_user}","gists_url":"https://api.github.com/users/silverstripe/gists{/gist_id}","starred_url":"https://api.github.com/users/silverstripe/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/silverstripe/subscriptions","organizations_url":"https://api.github.com/users/silverstripe/orgs","repos_url":"https://api.github.com/users/silverstripe/repos","events_url":"https://api.github.com/users/silverstripe/events{/privacy}","received_events_url":"https://api.github.com/users/silverstripe/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/silverstripe/silverstripe-framework","description":"SilverStripe Framework, the MVC framework that powers SilverStripe CMS","fork":false,"url":"https://api.github.com/repos/silverstripe/silverstripe-framework","forks_url":"https://api.github.com/repos/silverstripe/silverstripe-framework/forks","keys_url":"https://api.github.com/repos/silverstripe/silverstripe-framework/keys{/key_id}","collaborators_url":"https://api.github.com/repos/silverstripe/silverstripe-framework/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/silverstripe/silverstripe-framework/teams","hooks_url":"https://api.github.com/repos/silverstripe/silverstripe-framework/hooks","issue_events_url":"https://api.github.com/repos/silverstripe/silverstripe-framework/issues/events{/number}","events_url":"https://api.github.com/repos/silverstripe/silverstripe-framework/events","assignees_url":"https://api.github.com/repos/silverstripe/silverstripe-framework/assignees{/user}","branches_url":"https://api.github.com/repos/silverstripe/silverstripe-framework/branches{/branch}","tags_url":"https://api.github.com/repos/silverstripe/silverstripe-framework/tags","blobs_url":"https://api.github.com/repos/silverstripe/silverstripe-framework/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/silverstripe/silverstripe-framework/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/silverstripe/silverstripe-framework/git/refs{/sha}","trees_url":"https://api.github.com/repos/silverstripe/silverstripe-framework/git/trees{/sha}","statuses_url":"https://api.github.com/repos/silverstripe/silverstripe-framework/statuses/{sha}","languages_url":"https://api.github.com/repos/silverstripe/silverstripe-framework/languages","stargazers_url":"https://api.github.com/repos/silverstripe/silverstripe-framework/stargazers","contributors_url":"https://api.github.com/repos/silverstripe/silverstripe-framework/contributors","subscribers_url":"https://api.github.com/repos/silverstripe/silverstripe-framework/subscribers","subscription_url":"https://api.github.com/repos/silverstripe/silverstripe-framework/subscription","commits_url":"https://api.github.com/repos/silverstripe/silverstripe-framework/commits{/sha}","git_commits_url":"https://api.github.com/repos/silverstripe/silverstripe-framework/git/commits{/sha}","comments_url":"https://api.github.com/repos/silverstripe/silverstripe-framework/comments{/number}","issue_comment_url":"https://api.github.com/repos/silverstripe/silverstripe-framework/issues/comments{/number}","contents_url":"https://api.github.com/repos/silverstripe/silverstripe-framework/contents/{+path}","compare_url":"https://api.github.com/repos/silverstripe/silverstripe-framework/compare/{base}...{head}","merges_url":"https://api.github.com/repos/silverstripe/silverstripe-framework/merges","archive_url":"https://api.github.com/repos/silverstripe/silverstripe-framework/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/silverstripe/silverstripe-framework/downloads","issues_url":"https://api.github.com/repos/silverstripe/silverstripe-framework/issues{/number}","pulls_url":"https://api.github.com/repos/silverstripe/silverstripe-framework/pulls{/number}","milestones_url":"https://api.github.com/repos/silverstripe/silverstripe-framework/milestones{/number}","notifications_url":"https://api.github.com/repos/silverstripe/silverstripe-framework/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/silverstripe/silverstripe-framework/labels{/name}","releases_url":"https://api.github.com/repos/silverstripe/silverstripe-framework/releases{/id}","deployments_url":"https://api.github.com/repos/silverstripe/silverstripe-framework/deployments","created_at":"2011-02-02T02:04:13Z","updated_at":"2016-03-31T23:02:36Z","pushed_at":"2016-04-07T01:29:50Z","git_url":"git://github.com/silverstripe/silverstripe-framework.git","ssh_url":"git@github.com:silverstripe/silverstripe-framework.git","clone_url":"https://github.com/silverstripe/silverstripe-framework.git","svn_url":"https://github.com/silverstripe/silverstripe-framework","homepage":"http://silverstripe.org/","size":77828,"stargazers_count":501,"watchers_count":501,"language":"PHP","has_issues":true,"has_downloads":true,"has_wiki":false,"has_pages":false,"forks_count":580,"mirror_url":null,"open_issues_count":650,"forks":580,"open_issues":650,"watchers":501,"default_branch":"3"}},"_links":{"self":{"href":"https://api.github.com/repos/silverstripe/silverstripe-framework/pulls/5278"},"html":{"href":"https://github.com/silverstripe/silverstripe-framework/pull/5278"},"issue":{"href":"https://api.github.com/repos/silverstripe/silverstripe-framework/issues/5278"},"comments":{"href":"https://api.github.com/repos/silverstripe/silverstripe-framework/issues/5278/comments"},"review_comments":{"href":"https://api.github.com/repos/silverstripe/silverstripe-framework/pulls/5278/comments"},"review_comment":{"href":"https://api.github.com/repos/silverstripe/silverstripe-framework/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/silverstripe/silverstripe-framework/pulls/5278/commits"},"statuses":{"href":"https://api.github.com/repos/silverstripe/silverstripe-framework/statuses/40069c4cfc0b0bfdc24b7b66f7d67ec45b3027b9"}}}}