admin_core 0.0.2 → 0.0.3

Sign up to get free protection for your applications and to get access to all the features.
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,34 +0,0 @@
1
- // @flow
2
- import React from "react";
3
- import type {ResourceField$Enum} from "../decls";
4
-
5
- exports.getValue = function (field: ResourceField$Enum) {
6
- return field.value.value;
7
- };
8
-
9
- exports.Index = exports.Show = function (field: ResourceField$Enum) {
10
- if (field.value.values.indexOf(field.value.value) !== -1 && typeof field.value.value === "number") {
11
- return <span>{field.value.values[field.value.value]}</span>;
12
- } else {
13
- return <span>{field.value.value}</span>;
14
- }
15
- };
16
-
17
- exports.New = exports.Edit = function (field: ResourceField$Enum, onChange: (string, any) => void) {
18
- return (
19
- <select
20
- className="form-control"
21
- defaultValue={field.value.value}
22
- onChange={(e: SyntheticEvent) => {
23
- const el = e.target;
24
- if (el instanceof HTMLSelectElement) {
25
- onChange(field.name, el.value);
26
- }
27
- }}
28
- >
29
- {field.value.values.map((value, i) =>
30
- <option value={value} key={i}>{value}</option>
31
- )}
32
- </select>
33
- );
34
- };
@@ -1,28 +0,0 @@
1
- // @flow
2
- import React from "react";
3
- import type {ResourceField$Number} from "../decls";
4
-
5
- exports.getValue = function (field: ResourceField$Number) {
6
- return field.value;
7
- };
8
-
9
- exports.Index = exports.Show = function (field: ResourceField$Number) {
10
- return <span>{field.value}</span>;
11
- };
12
-
13
- exports.New = exports.Edit = function(field: ResourceField$Number, onChange: (string, any) => void) {
14
- return (
15
- <input
16
- className="form-control"
17
- defaultValue={field.value}
18
- name={field.name}
19
- onChange={(e: SyntheticEvent) => {
20
- const el = e.target;
21
- if (el instanceof HTMLInputElement) {
22
- onChange(field.name, el.value);
23
- }
24
- }}
25
- type="number"
26
- />
27
- );
28
- };
@@ -1,28 +0,0 @@
1
- // @flow
2
- import React from "react";
3
- import type {ResourceField$String} from "../decls";
4
-
5
- exports.getValue = function (field: ResourceField$String) {
6
- return field.value;
7
- };
8
-
9
- exports.Index = exports.Show = function (field: ResourceField$String) {
10
- return <span>{field.value}</span>;
11
- };
12
-
13
- exports.New = exports.Edit = function(field: ResourceField$String, onChange: (string, any) => void) {
14
- return (
15
- <input
16
- className="form-control"
17
- defaultValue={field.value}
18
- name={field.name}
19
- onChange={(e: SyntheticEvent) => {
20
- const el = e.target;
21
- if (el instanceof HTMLInputElement) {
22
- onChange(field.name, el.value);
23
- }
24
- }}
25
- type="text"
26
- />
27
- );
28
- };
@@ -1,27 +0,0 @@
1
- // @flow
2
- import React from "react";
3
- import type {ResourceField$Text} from "../decls";
4
-
5
- exports.getValue = function (field: ResourceField$Text) {
6
- return field.value;
7
- };
8
-
9
- exports.Index = exports.Show = function (field: ResourceField$Text) {
10
- return <span>{field.value}</span>;
11
- };
12
-
13
- exports.New = exports.Edit = function(field: ResourceField$Text, onChange: (string, any) => void) {
14
- return (
15
- <textarea
16
- className="form-control"
17
- defaultValue={field.value}
18
- name={field.name}
19
- onChange={(e: SyntheticEvent) => {
20
- const el = e.target;
21
- if (el instanceof HTMLTextAreaElement) {
22
- onChange(field.name, el.value);
23
- }
24
- }}
25
- />
26
- );
27
- };
@@ -1,17 +0,0 @@
1
- // @flow
2
- import type {ResourceFilter, ResourceFilterModule} from "./decls";
3
-
4
- const resourceFilters: { [string]: ResourceFilterModule; } = {};
5
-
6
- export function register(name: string, module: ResourceFilterModule) {
7
- resourceFilters[name] = module;
8
- }
9
-
10
- export function renderFilter(filter: ResourceFilter, onChange: (string, string, any) => void) {
11
- const module = resourceFilters[filter.type];
12
- return module.Filter(filter, onChange);
13
- }
14
-
15
- register("boolean", require("./resource-filter/Boolean"));
16
- register("number", require("./resource-filter/Number"));
17
- register("string", require("./resource-filter/String"));
@@ -1,22 +0,0 @@
1
- // @flow
2
- import React from "react";
3
- import type {ResourceFilter$Boolean} from "../decls";
4
-
5
- export function Filter(filter: ResourceFilter$Boolean, onChange: (string, string, string) => void) {
6
- return (
7
- <select
8
- className="form-control"
9
- defaultValue={filter.query.value == null ? null : filter.query.value ? "true" : "false"}
10
- onChange={(e: SyntheticEvent) => {
11
- const el = e.target;
12
- if (el instanceof HTMLSelectElement) {
13
- onChange(filter.name, "is", el.value);
14
- }
15
- }}
16
- >
17
- <option>Any</option>
18
- <option value="true">Yes</option>
19
- <option value="false">No</option>
20
- </select>
21
- );
22
- }
@@ -1,45 +0,0 @@
1
- // @flow
2
- import React from "react";
3
- import type {ResourceFilter$Number} from "../decls";
4
-
5
- class ResourceFilterNumber extends React.Component {
6
- props: {
7
- filter: ResourceFilter$Number;
8
- onChange: (string, string, string) => void;
9
- };
10
-
11
- handleChange() {
12
- this.props.onChange(
13
- this.props.filter.name,
14
- this.refs.select.value,
15
- this.refs.input.value
16
- );
17
- }
18
-
19
- render() {
20
- return (
21
- <div>
22
- <select
23
- ref="select"
24
- className="form-control"
25
- defaultValue={this.props.filter.query.operator}
26
- onChange={this.handleChange.bind(this)}
27
- >
28
- <option value="equals">Equals</option>
29
- <option value="greater_than">Greater than</option>
30
- <option value="less_than">Less than</option>
31
- </select>
32
- <input
33
- ref="input"
34
- className="form-control"
35
- defaultValue={this.props.filter.query.value}
36
- onChange={this.handleChange.bind(this)}
37
- />
38
- </div>
39
- );
40
- }
41
- }
42
-
43
- export function Filter(filter: ResourceFilter$Number, onChange: (string, string, string) => void) {
44
- return <ResourceFilterNumber filter={filter} onChange={onChange} />;
45
- }
@@ -1,46 +0,0 @@
1
- // @flow
2
- import React from "react";
3
- import type {ResourceFilter$String} from "../decls";
4
-
5
- class ResourceFilterString extends React.Component {
6
- props: {
7
- filter: ResourceFilter$String;
8
- onChange: (string, string, string) => void;
9
- };
10
-
11
- handleChange() {
12
- this.props.onChange(
13
- this.props.filter.name,
14
- this.refs.select.value,
15
- this.refs.input.value
16
- );
17
- }
18
-
19
- render() {
20
- return (
21
- <div>
22
- <select
23
- ref="select"
24
- className="form-control"
25
- defaultValue={this.props.filter.query.operator}
26
- onChange={this.handleChange.bind(this)}
27
- >
28
- <option value="contains">Contains</option>
29
- <option value="equals">Equals</option>
30
- <option value="starts_with">Starts with</option>
31
- <option value="ends_with">Ends with</option>
32
- </select>
33
- <input
34
- ref="input"
35
- className="form-control"
36
- defaultValue={this.props.filter.query.value}
37
- onChange={this.handleChange.bind(this)}
38
- />
39
- </div>
40
- );
41
- }
42
- }
43
-
44
- export function Filter(filter: ResourceFilter$String, onChange: (string, string, string) => void) {
45
- return <ResourceFilterString filter={filter} onChange={onChange} />;
46
- }
@@ -1,36 +0,0 @@
1
- // @flow
2
- import React from "react";
3
- import type {Location, RouterHistory} from "react-router-dom";
4
-
5
- import httpClient from "../http-client";
6
-
7
- export default class Base extends React.Component {
8
- props: {
9
- location: Location;
10
- history: RouterHistory;
11
- };
12
-
13
- state: any;
14
-
15
- constructor(props: any) {
16
- super(props);
17
- this.state = {};
18
- }
19
-
20
- componentDidMount() {
21
- this.loadPage();
22
- }
23
-
24
- componentDidUpdate(prevProps: { location: Location; }) {
25
- if (this.props.location.pathname !== prevProps.location.pathname ||
26
- this.props.location.search !== prevProps.location.search) {
27
- this.loadPage();
28
- }
29
- }
30
-
31
- loadPage() {
32
- const jsonPathname = this.props.location.pathname.replace(/\.[^/.]+$/, "") + ".json";
33
- httpClient.get(jsonPathname + this.props.location.search)
34
- .then(({ data }) => this.setState({ page: data.page }));
35
- }
36
- }
@@ -1,48 +0,0 @@
1
- // @flow
2
- import React from "react";
3
-
4
- import Base from "./Base";
5
- import ResourceForm from "../components/ResourceForm";
6
- import Breadcrumb from "../components/Breadcrumb";
7
- import type {ResourcePage$Edit, ResourceManager} from "../decls";
8
-
9
- export default function editPage(resourceManager: ResourceManager) {
10
- class EditPage extends Base {
11
- state: {
12
- page?: ResourcePage$Edit;
13
- }
14
-
15
- render() {
16
- const page = this.state.page;
17
- return (
18
- <main className="main">
19
- <Breadcrumb links={[["Home", "/"], [resourceManager.displayName, resourceManager.indexPath], page ? [page.resource.displayName, page.resource.showPath || "#"] : ["...", "#"]]} current="Edit"/>
20
- <div className="container-fluid">
21
- <div className="animated fadeIn">
22
- <div className="row">
23
- {page &&
24
- <div className="col-sm-12">
25
- <div className="card">
26
- <div className="card-block">
27
- <h3 className="card-title">
28
- New
29
- </h3>
30
- <ResourceForm
31
- action={page.resource.showPath || ""}
32
- history={this.props.history}
33
- resource={page.resource}
34
- />
35
- </div>
36
- </div>
37
- </div>
38
- }
39
- </div>
40
- </div>
41
- </div>
42
- </main>
43
- );
44
- }
45
- }
46
- EditPage.displayName = `EditPage(${resourceManager.displayName})`;
47
- return EditPage;
48
- }
@@ -1,141 +0,0 @@
1
- // @flow
2
- import React from "react";
3
- import classNames from "classnames";
4
- import omit from "lodash.omit";
5
- import reduce from "lodash.reduce";
6
- import toPairs from "lodash.topairs";
7
- import {Link} from "react-router-dom";
8
- import {ButtonGroup, Card, CardBlock, CardHeader, CardTitle} from "reactstrap";
9
-
10
- import Base from "./Base";
11
- import Breadcrumb from "../components/Breadcrumb";
12
- import ResourceFilters from "../components/ResourceFilters";
13
- import ResourcesCollection from "../components/ResourcesCollection";
14
- import Pagination from "../components/Pagination";
15
- import type {ResourceManager, ResourcePage$Index} from "../decls";
16
-
17
- export default function index(resourceManager: ResourceManager) {
18
- class IndexPage extends Base {
19
- queries: { [string]: string; };
20
-
21
- state: {
22
- page?: ResourcePage$Index;
23
- }
24
-
25
- componentDidMount(...args: any) {
26
- super.componentDidMount(...args);
27
- this.setQueries();
28
- }
29
-
30
- componentDidUpdate(...args: any) {
31
- super.componentDidUpdate(...args);
32
- this.setQueries();
33
- }
34
-
35
- setQueries() {
36
- this.queries = reduce(this.props.location.search.substring(1).split("&"), (acc, kv) => {
37
- const [key, value] = kv.split("=");
38
- if (key) {
39
- acc[key] = value;
40
- }
41
- return acc;
42
- }, {});
43
- }
44
-
45
- renderScopeButton(scope: { name: string; count: number; }, key: number) {
46
- const match = scope.name === this.queries.scope;
47
- const search = reduce(toPairs(omit(this.queries, "scope")), (acc, kv) => {
48
- acc.push(kv.join("="));
49
- return acc;
50
- }, match ? [] : [`scope=${scope.name}`]).join("&");
51
- return (
52
- <Link
53
- to={{
54
- pathname: this.props.location.pathname,
55
- search: search ? `?${search}` : "",
56
- hash: this.props.location.hash,
57
- }}
58
- className={classNames("btn", { "btn-primary": match, "btn-secondary": !match })}
59
- key={key}
60
- >
61
- {scope.name} ({scope.count})
62
- </Link>
63
- );
64
- }
65
-
66
- needFilter() {
67
- const page = this.state.page;
68
- return page && (page.scopes.length > 0 || page.filters.length > 0);
69
- }
70
-
71
- render() {
72
- const page = this.state.page;
73
- return (
74
- <main className="main">
75
- <Breadcrumb links={[["Home", "/"]]} current={resourceManager.displayName}/>
76
- <div className="container-fluid">
77
- <div className="animated fadeIn">
78
- <div className="row">
79
- {this.needFilter() &&
80
- <div className="col-sm-12 col-lg-3 push-lg-9">
81
- {page && page.scopes.length > 0 &&
82
- <Card>
83
- <CardHeader>
84
- Scopes
85
- </CardHeader>
86
- <CardBlock>
87
- <ButtonGroup vertical className="hidden-md-down d-block">
88
- {page.scopes.map((scope, i) =>
89
- this.renderScopeButton(scope, i)
90
- )}
91
- </ButtonGroup>
92
- <ButtonGroup className="hidden-lg-up">
93
- {page.scopes.map((scope, i) =>
94
- this.renderScopeButton(scope, i)
95
- )}
96
- </ButtonGroup>
97
- </CardBlock>
98
- </Card>
99
- }
100
- {page && page.filters.length > 0 &&
101
- <ResourceFilters location={this.props.location} filters={page.filters} />
102
- }
103
- </div>
104
- }
105
- { page &&
106
- <div className={classNames("col-sm-12", { "col-lg-9 pull-lg-3": this.needFilter() })}>
107
- <Card>
108
- <CardBlock>
109
- <div className="row">
110
- <div className="col-sm-5">
111
- <CardTitle>{resourceManager.displayName}</CardTitle>
112
- </div>
113
- <div className="col-sm-7">
114
- {resourceManager.newPath &&
115
- <Link to={resourceManager.newPath} className="btn btn-primary float-right">
116
- <i className="icon-plus" />
117
- </Link>
118
- }
119
- </div>
120
- </div>
121
- <ResourcesCollection {...page} />
122
- {page.pagination.total > 1 &&
123
- <Pagination
124
- {...page.pagination}
125
- location={this.props.location}
126
- />
127
- }
128
- </CardBlock>
129
- </Card>
130
- </div>
131
- }
132
- </div>
133
- </div>
134
- </div>
135
- </main>
136
- );
137
- }
138
- }
139
- IndexPage.displayName = `IndexPage(${resourceManager.displayName})`;
140
- return IndexPage;
141
- }