admin_core 0.0.2 → 0.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (129) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +7 -1
  3. data/admin_core.gemspec +1 -1
  4. data/lib/admin_core.rb +34 -1
  5. data/lib/admin_core/errors.rb +6 -0
  6. data/lib/admin_core/resource_field_builder.rb +1 -11
  7. data/lib/admin_core/resource_filter/boolean.rb +2 -0
  8. data/lib/admin_core/resource_filter/number.rb +2 -0
  9. data/lib/admin_core/resource_filter/string.rb +2 -0
  10. data/lib/admin_core/resource_filter_builder.rb +1 -1
  11. data/lib/admin_core/version.rb +1 -1
  12. data/lib/generators/admin_core/resource_manager_generator.rb +4 -1
  13. data/lib/generators/admin_core/templates/admin-core.js +1047 -629
  14. metadata +2 -117
  15. data/client/.babelrc +0 -19
  16. data/client/.eslintignore +0 -3
  17. data/client/.eslintrc.yml +0 -20
  18. data/client/.flowconfig +0 -7
  19. data/client/.gitignore +0 -64
  20. data/client/.npmignore +0 -10
  21. data/client/README.md +0 -3
  22. data/client/admin-core.scss +0 -8
  23. data/client/flow-typed/npm/axios_v0.16.x.js +0 -120
  24. data/client/flow-typed/npm/classnames_v2.x.x.js +0 -16
  25. data/client/flow-typed/npm/lodash_v4.x.x.js +0 -514
  26. data/client/flow-typed/npm/react-router-dom_v4.x.x.js +0 -166
  27. data/client/flow-typed/npm/reactstrap_vx.x.x.js +0 -536
  28. data/client/package.json +0 -60
  29. data/client/src/.eslintrc.yml +0 -23
  30. data/client/src/AdminCore.jsx +0 -44
  31. data/client/src/components/Breadcrumb.jsx +0 -18
  32. data/client/src/components/Header.jsx +0 -45
  33. data/client/src/components/Pagination.jsx +0 -72
  34. data/client/src/components/ResourceFilters.jsx +0 -87
  35. data/client/src/components/ResourceForm.jsx +0 -103
  36. data/client/src/components/ResourcesCollection.jsx +0 -41
  37. data/client/src/components/Sidebar.jsx +0 -90
  38. data/client/src/decls.js +0 -119
  39. data/client/src/http-client.js +0 -18
  40. data/client/src/main.js +0 -9
  41. data/client/src/resource-field-renderer.js +0 -45
  42. data/client/src/resource-field/BelongsTo.jsx +0 -26
  43. data/client/src/resource-field/Boolean.jsx +0 -43
  44. data/client/src/resource-field/Date.jsx +0 -29
  45. data/client/src/resource-field/DateTime.jsx +0 -29
  46. data/client/src/resource-field/Enum.jsx +0 -34
  47. data/client/src/resource-field/Number.jsx +0 -28
  48. data/client/src/resource-field/String.jsx +0 -28
  49. data/client/src/resource-field/Text.jsx +0 -27
  50. data/client/src/resource-filter-renderer.js +0 -17
  51. data/client/src/resource-filter/Boolean.jsx +0 -22
  52. data/client/src/resource-filter/Number.jsx +0 -45
  53. data/client/src/resource-filter/String.jsx +0 -46
  54. data/client/src/resource-page/Base.js +0 -36
  55. data/client/src/resource-page/Edit.jsx +0 -48
  56. data/client/src/resource-page/Index.jsx +0 -141
  57. data/client/src/resource-page/New.jsx +0 -48
  58. data/client/src/resource-page/Show.jsx +0 -116
  59. data/client/webpack.config.js +0 -26
  60. data/client/yarn.lock +0 -3816
  61. data/sample/.gitignore +0 -21
  62. data/sample/Gemfile +0 -35
  63. data/sample/Gemfile.lock +0 -147
  64. data/sample/README.md +0 -24
  65. data/sample/Rakefile +0 -6
  66. data/sample/app/assets/config/manifest.js +0 -2
  67. data/sample/app/assets/images/.keep +0 -0
  68. data/sample/app/assets/stylesheets/application.css +0 -15
  69. data/sample/app/controllers/admin/application_controller.rb +0 -4
  70. data/sample/app/controllers/admin/tweets_controller.rb +0 -4
  71. data/sample/app/controllers/admin/users_controller.rb +0 -4
  72. data/sample/app/controllers/application_controller.rb +0 -3
  73. data/sample/app/controllers/concerns/.keep +0 -0
  74. data/sample/app/helpers/application_helper.rb +0 -2
  75. data/sample/app/jobs/application_job.rb +0 -2
  76. data/sample/app/models/admin/tweet.rb +0 -35
  77. data/sample/app/models/admin/user.rb +0 -41
  78. data/sample/app/models/application_record.rb +0 -3
  79. data/sample/app/models/concerns/.keep +0 -0
  80. data/sample/app/models/tweet.rb +0 -3
  81. data/sample/app/models/user.rb +0 -3
  82. data/sample/app/views/admin/application.html.erb +0 -64
  83. data/sample/app/views/layouts/application.html.erb +0 -13
  84. data/sample/bin/bundle +0 -3
  85. data/sample/bin/rails +0 -4
  86. data/sample/bin/rake +0 -4
  87. data/sample/bin/setup +0 -34
  88. data/sample/bin/update +0 -29
  89. data/sample/config.ru +0 -5
  90. data/sample/config/application.rb +0 -25
  91. data/sample/config/boot.rb +0 -3
  92. data/sample/config/database.yml +0 -25
  93. data/sample/config/environment.rb +0 -5
  94. data/sample/config/environments/development.rb +0 -42
  95. data/sample/config/environments/production.rb +0 -69
  96. data/sample/config/environments/test.rb +0 -36
  97. data/sample/config/initializers/admin_core.rb +0 -8
  98. data/sample/config/initializers/application_controller_renderer.rb +0 -6
  99. data/sample/config/initializers/backtrace_silencers.rb +0 -7
  100. data/sample/config/initializers/cookies_serializer.rb +0 -5
  101. data/sample/config/initializers/filter_parameter_logging.rb +0 -4
  102. data/sample/config/initializers/inflections.rb +0 -16
  103. data/sample/config/initializers/mime_types.rb +0 -4
  104. data/sample/config/initializers/new_framework_defaults.rb +0 -24
  105. data/sample/config/initializers/session_store.rb +0 -3
  106. data/sample/config/initializers/wrap_parameters.rb +0 -14
  107. data/sample/config/locales/en.yml +0 -23
  108. data/sample/config/routes.rb +0 -6
  109. data/sample/config/secrets.yml +0 -22
  110. data/sample/db/migrate/20170417055257_create_users.rb +0 -10
  111. data/sample/db/migrate/20170417055412_create_tweets.rb +0 -9
  112. data/sample/db/schema.rb +0 -31
  113. data/sample/db/seeds.rb +0 -7
  114. data/sample/lib/assets/.keep +0 -0
  115. data/sample/lib/tasks/.keep +0 -0
  116. data/sample/log/.keep +0 -0
  117. data/sample/public/404.html +0 -67
  118. data/sample/public/422.html +0 -67
  119. data/sample/public/500.html +0 -66
  120. data/sample/public/apple-touch-icon-precomposed.png +0 -0
  121. data/sample/public/apple-touch-icon.png +0 -0
  122. data/sample/public/bundle.min.js +0 -27
  123. data/sample/public/bundle.min.js.map +0 -1
  124. data/sample/public/favicon.ico +0 -0
  125. data/sample/public/javascripts/admin-core.js +0 -38196
  126. data/sample/public/robots.txt +0 -5
  127. data/sample/public/stylesheets/admin-core.css +0 -1
  128. data/sample/tmp/.keep +0 -0
  129. data/sample/vendor/assets/stylesheets/.keep +0 -0
@@ -1,60 +0,0 @@
1
- {
2
- "name": "admin-core-js",
3
- "version": "0.0.2",
4
- "engines": {
5
- "node": "~6.10",
6
- "npm": "~3.10",
7
- "yarn": "~0.21"
8
- },
9
- "description": "Flexible admin framework for Rails",
10
- "main": "lib/AdminCore.js",
11
- "author": "Yuku Takahashi <yuku@qiita.com>",
12
- "scripts": {
13
- "build": "yarn run clean && run-p build:*",
14
- "build:dist": "run-p build:dist:*",
15
- "build:dist:js": "webpack && uglifyjs dist/admin-core.js -o dist/admin-core.min.js --source-map dist/admin-core.min.js.map --source-map-url admin-core.min.js.map",
16
- "build:dist:css": "mkdir -p dist && node-sass --output-style compressed admin-core.scss > dist/admin-core.css",
17
- "build:lib": "babel src -d lib -s && rm -fr lib/main.*",
18
- "clean": "rm -fr dist lib",
19
- "test": "flow"
20
- },
21
- "repository": {
22
- "type": "git",
23
- "url": "git+https://github.com/increments/admin_core.git"
24
- },
25
- "bugs": {
26
- "url": "https://github.com/increments/admin_core/issues"
27
- },
28
- "homepage": "https://github.com/increments/admin_core#readme",
29
- "dependencies": {
30
- "axios": "^0.16.1",
31
- "classnames": "^2.2.5",
32
- "coreui.io": "^1.0.0-alpha.4",
33
- "lodash.omit": "^4.5.0",
34
- "lodash.reduce": "^4.6.0",
35
- "lodash.topairs": "^4.3.0",
36
- "react": "^15.5.4",
37
- "react-addons-css-transition-group": "^15.5.2",
38
- "react-addons-transition-group": "^15.5.2",
39
- "react-dom": "^15.5.4",
40
- "react-router-dom": "^4.1.1",
41
- "reactstrap": "^4.5.0"
42
- },
43
- "devDependencies": {
44
- "babel-cli": "^6.24.1",
45
- "babel-core": "^6.24.1",
46
- "babel-eslint": "^7.2.2",
47
- "babel-loader": "^6.4.1",
48
- "babel-preset-env": "^1.4.0",
49
- "babel-preset-react": "^6.24.1",
50
- "eslint": "^3.19.0",
51
- "eslint-plugin-flowtype": "^2.30.4",
52
- "eslint-plugin-react": "^6.10.3",
53
- "flow-bin": "^0.44.0",
54
- "flow-typed": "^2.0.0",
55
- "node-sass": "^4.5.2",
56
- "npm-run-all": "^4.0.2",
57
- "uglify-js": "^2.8.22",
58
- "webpack": "^2.4.1"
59
- }
60
- }
@@ -1,23 +0,0 @@
1
- ---
2
- env:
3
- browser: true
4
-
5
- plugins:
6
- - flowtype
7
- - react
8
-
9
- rules:
10
- flowtype/boolean-style: error
11
- flowtype/define-flow-type: error
12
- flowtype/delimiter-dangle: [error, always]
13
- flowtype/generic-spacing: [error, never]
14
- flowtype/no-dupe-keys: error
15
- flowtype/no-primitive-constructor-types: error
16
- flowtype/object-type-delimiter: [error, semicolon]
17
- flowtype/space-after-type-colon: error
18
- flowtype/space-before-generic-bracket: [error, never]
19
- flowtype/space-before-type-colon: [error, never]
20
- flowtype/union-intersection-spacing: error
21
- flowtype/use-flow-type: error
22
- react/jsx-uses-react: error
23
- react/jsx-uses-vars: error
@@ -1,44 +0,0 @@
1
- // @flow
2
- import React from "react";
3
- import {BrowserRouter, Route, Switch} from "react-router-dom";
4
-
5
- import EditPage from "./resource-page/edit";
6
- import Header from "./components/header";
7
- import IndexPage from "./resource-page/index";
8
- import NewPage from "./resource-page/new";
9
- import ShowPage from "./resource-page/show";
10
- import Sidebar from "./components/sidebar";
11
- import type {ResourceManager, SidebarItem} from "./decls";
12
-
13
- export default class App extends React.Component {
14
- props: {
15
- sidebar: SidebarItem[];
16
- resourceManagers: ResourceManager[];
17
- children?: any;
18
- siteName: string;
19
- }
20
-
21
- render() {
22
- return (
23
- <BrowserRouter>
24
- <div className="app">
25
- <Header siteName={this.props.siteName} />
26
- <div className="app-body">
27
- <Sidebar items={this.props.sidebar} />
28
- <Switch>
29
- {this.props.children}
30
- {this.props.resourceManagers.map((resourceManager, i) => [
31
- <Route exact path={resourceManager.indexPath} component={IndexPage(resourceManager)} key={`index-${i}`} />,
32
- resourceManager.newPath && <Route exact path={resourceManager.newPath} component={NewPage(resourceManager)} key={`new-${i}`} />,
33
- <Route exact path={resourceManager.showPath} component={ShowPage(resourceManager)} key={`show-${i}`} />,
34
- resourceManager.editPath && <Route exact path={resourceManager.editPath} component={EditPage(resourceManager)} key={`edit-${i}`} />,
35
- ].filter(route => route))}
36
- </Switch>
37
- </div>
38
- </div>
39
- </BrowserRouter>
40
- );
41
- }
42
- }
43
-
44
- App.displayName = "AdminCore";
@@ -1,18 +0,0 @@
1
- // @flow
2
- import React from "react";
3
- import {Link} from "react-router-dom";
4
-
5
- const Breadcrumb = ({ links, current }: { links: string[][]; current: ?string; }) => (
6
- <ol className="breadcrumb">
7
- {links.map(([text, path], i) =>
8
- <span className="breadcrumb-item" key={i}>
9
- <Link to={path}>{text}</Link>
10
- </span>
11
- )}
12
- <span className="breadcrumb-item">
13
- {current || "..."}
14
- </span>
15
- </ol>
16
- );
17
-
18
- export default Breadcrumb;
@@ -1,45 +0,0 @@
1
- // @flow
2
- import React from "react";
3
- import {Link} from "react-router-dom";
4
-
5
- export default class Header extends React.Component {
6
- props: {
7
- siteName: string;
8
- }
9
-
10
- sidebarToggle(e: SyntheticEvent) {
11
- e.preventDefault();
12
- this.toggle("sidebar-hidden");
13
- }
14
-
15
- mobileSidebarToggle(e: SyntheticEvent) {
16
- e.preventDefault();
17
- this.toggle("sidebar-mobile-show");
18
- }
19
-
20
- asideToggle(e: SyntheticEvent) {
21
- e.preventDefault();
22
- this.toggle("aside-menu-hidden");
23
- }
24
-
25
- toggle(name: string) {
26
- const body = document.body;
27
- if (body) {
28
- body.classList.toggle(name);
29
- }
30
- }
31
-
32
- render() {
33
- return (
34
- <header className="app-header navbar">
35
- <button className="navbar-toggler mobile-sidebar-toggler hidden-lg-up" onClick={this.mobileSidebarToggle.bind(this)} type="button">&#9776;</button>
36
- <Link to="/" className="navbar-brand">{this.props.siteName}</Link>
37
- <ul className="nav navbar-nav hidden-md-down">
38
- <li className="nav-item">
39
- <a className="nav-link navbar-toggler sidebar-toggler" onClick={this.sidebarToggle.bind(this)} href="#">&#9776;</a>
40
- </li>
41
- </ul>
42
- </header>
43
- );
44
- }
45
- }
@@ -1,72 +0,0 @@
1
- // @flow
2
- import React from "react";
3
- import {Link} from "react-router-dom";
4
-
5
- export default class Pagination extends React.Component {
6
- props: {
7
- total: number;
8
- current: number;
9
- location: {
10
- pathname: string;
11
- search: string;
12
- hash: string;
13
- };
14
- }
15
-
16
- link(page: number) {
17
- const queries = this.props.location.search.substring(1).split("&")
18
- .filter(query => query && !query.startsWith("page="));
19
- return {
20
- pathname: this.props.location.pathname,
21
- search: `?${queries.concat([`page=${page}`]).join("&")}`,
22
- hash: this.props.location.hash,
23
- };
24
- }
25
-
26
- renderPrev() {
27
- return (
28
- this.props.current === 1 ?
29
- <li className="page-item disabled">
30
- <a className="page-link" href="#">‹</a>
31
- </li>
32
- :
33
- <li className="page-item">
34
- <Link to={this.link(this.props.current - 1)} className="page-link">‹</Link>
35
- </li>
36
- );
37
- }
38
-
39
- renderNext() {
40
- return (
41
- this.props.current === this.props.total ?
42
- <li className="page-item disabled">
43
- <a className="page-link" href="#">›</a>
44
- </li>
45
- :
46
- <li className="page-item">
47
- <Link to={this.link(this.props.total)} className="page-link">›</Link>
48
- </li>
49
- );
50
- }
51
-
52
- render() {
53
- const pages = [];
54
- for (let i = 1; i <= this.props.total; i++) { pages.push(i); }
55
- return (
56
- <ul className="pagination">
57
- {this.renderPrev()}
58
- { pages.map(page =>
59
- page === this.props.current ?
60
- <li className="page-item active" key={page}>
61
- <a className="page-link" href="#">{page}</a>
62
- </li>
63
- :
64
- <li className="page-item" key={page}>
65
- <Link to={this.link(page)} className="page-link">{page}</Link>
66
- </li>
67
- )}
68
- {this.renderNext()}
69
- </ul>
70
- );
71
- }
72
- }
@@ -1,87 +0,0 @@
1
- // @flow
2
- import React from "react";
3
- import {Link} from "react-router-dom";
4
- import type {Location} from "react-router-dom";
5
- import {Card, CardBlock, CardHeader, CardFooter} from "reactstrap";
6
-
7
- import type {ResourceFilter} from "../decls";
8
- import {renderFilter} from "../resource-filter-renderer";
9
-
10
- const REGEXP = /\Afilter\[[^]*]\]=/;
11
-
12
- export default class ResourceFilters extends React.Component {
13
- props: {
14
- filters: ResourceFilter[];
15
- location: Location;
16
- };
17
-
18
- state: {
19
- [string]: { operator: string; value: string; };
20
- };
21
-
22
- constructor(props: any) {
23
- super(props);
24
- const state = {};
25
- this.props.filters.forEach(filter => {
26
- state[filter.name] = {
27
- operator: filter.query.operator,
28
- value: filter.query.value,
29
- };
30
- });
31
- this.state = state;
32
- }
33
-
34
- handleChange(name: string, operator: string, value: string) {
35
- const state = {};
36
- state[name] = { operator, value };
37
- this.setState(state);
38
- }
39
-
40
- renderApply() {
41
- const queries = this.props.location.search.substring(1).split("&").filter(kv => REGEXP.test(kv));
42
- Object.keys(this.state).forEach(name => {
43
- if (this.state[name].value) {
44
- queries.push(`filter[${name}:${this.state[name].operator}]=${this.state[name].value}`);
45
- }
46
- });
47
- const search = queries.join("&");
48
- return (
49
- <Link
50
- to={{
51
- pathname: this.props.location.pathname,
52
- search: search ? `?${search}` : "",
53
- hash: this.props.location.hash,
54
- }}
55
- className="btn btn-primary"
56
- >
57
- Apply
58
- </Link>
59
- );
60
- }
61
-
62
- render() {
63
- return (
64
- <Card>
65
- <CardHeader>
66
- <i className="fa fa-filter"/>
67
- Filters
68
- </CardHeader>
69
- <CardBlock>
70
- {this.props.filters.map((filter, i) =>
71
- <div className="row" key={i}>
72
- <div className="col-md-3 col-lg-12">
73
- {filter.displayName}
74
- </div>
75
- <div className="col-md-9 col-lg-12">
76
- {renderFilter(filter, this.handleChange.bind(this))}
77
- </div>
78
- </div>
79
- )}
80
- </CardBlock>
81
- <CardFooter>
82
- {this.renderApply()}
83
- </CardFooter>
84
- </Card>
85
- );
86
- }
87
- }
@@ -1,103 +0,0 @@
1
- // @flow
2
- import React from "react";
3
- import classNames from "classnames";
4
- import {Redirect} from "react-router-dom";
5
- import type {RouterHistory} from "react-router-dom";
6
-
7
- import httpClient from "../http-client";
8
- import type {Resource, ResourceField} from "../decls";
9
- import {getValue, renderNew, renderEdit} from "../resource-field-renderer";
10
-
11
- export default class ResourceForm extends React.Component {
12
- props: {
13
- action: string;
14
- resource: Resource;
15
- history: RouterHistory;
16
- };
17
-
18
- state: {
19
- redirectTo?: string;
20
- errors: {
21
- [string]: string[];
22
- };
23
- values: {
24
- [string]: any;
25
- };
26
- }
27
-
28
- constructor(props: any) {
29
- super(props);
30
- this.state = {
31
- errors: {},
32
- values: {},
33
- };
34
- props.resource.fields.forEach(field => {
35
- this.state.values[field.name] = getValue(field);
36
- });
37
- }
38
-
39
- request(data: any) {
40
- return this.props.resource.showPath ? httpClient.put(this.props.action, data) : httpClient.post(this.props.action, data);
41
- }
42
-
43
- handleSubmit(e: SyntheticEvent) {
44
- e.preventDefault();
45
- const data = {};
46
- data[this.props.resource.name] = this.state.values;
47
- this.request(data)
48
- .then(r => this.setState({ redirectTo: r.data.redirectTo }))
49
- .catch(e => this.setState({ errors: e.response.data.errors }));
50
- }
51
-
52
- handleChange(name: string, value: any) {
53
- const values = this.state.values;
54
- values[name] = value;
55
- this.setState({ values });
56
- }
57
-
58
- handleClickCancel() {
59
- this.props.history.goBack();
60
- }
61
-
62
- shouldComponentUpdate(_: any, prevState: $PropertyType<ResourceForm, "state">) {
63
- return this.state.errors !== prevState.errors ||
64
- this.state.redirectTo !== prevState.redirectTo;
65
- }
66
-
67
- renderField(field: ResourceField) {
68
- const renderer = this.props.resource.showPath ? renderEdit : renderNew;
69
- return renderer(field, this.handleChange.bind(this));
70
- }
71
-
72
- render() {
73
- if (this.state.redirectTo) {
74
- return <Redirect to={this.state.redirectTo} />;
75
- }
76
- return (
77
- <form onSubmit={this.handleSubmit.bind(this)} className="form-horizontal">
78
- {this.props.resource.fields.map((field, i) =>
79
- <div
80
- className={classNames("form-group", "row", { "has-danger": this.state.errors[field.name] })}
81
- key={i}
82
- >
83
- <label className="col-md-3 form-control-label" htmlFor={field.name}>
84
- {field.displayName}
85
- </label>
86
- <div className="col-md-9">
87
- {this.renderField(field)}
88
- {this.state.errors[field.name] && this.state.errors[field.name].map((error, i) =>
89
- <div className="form-control-feedback" key={i}>
90
- {error}
91
- </div>
92
- )}
93
- </div>
94
- </div>
95
- )}
96
- <button type="submit" className="btn btn-primary">Submit</button>
97
- <span className="btn btn-secondary" onClick={this.handleClickCancel.bind(this)}>
98
- Cancel
99
- </span>
100
- </form>
101
- );
102
- }
103
- }