@raketa-cloud/admin 0.0.3 → 0.0.5

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 (39) hide show
  1. package/babel.config.js +6 -0
  2. package/bin/tailwind +2 -0
  3. package/package.json +22 -30
  4. package/src/Adapter.js +160 -0
  5. package/src/HonoAdapter.js +248 -0
  6. package/src/RaketaContext.js +46 -0
  7. package/src/helpers/AuthHelper.js +44 -0
  8. package/src/helpers/FormBuilder.js +226 -0
  9. package/src/helpers/HTMLBuilder.js +38 -0
  10. package/src/helpers/Pagination.js +92 -0
  11. package/src/helpers/SortButton.js +102 -0
  12. package/src/helpers/form_for.js +6 -0
  13. package/src/helpers/pagination_helper.js +5 -0
  14. package/src/helpers/sort_button.js +5 -0
  15. package/src/index.js +7 -0
  16. package/src/routeCollection.js +90 -0
  17. package/src/routeMember.js +40 -0
  18. package/src/routeNestedCollection.js +90 -0
  19. package/src/routeNestedMember.js +40 -0
  20. package/src/setGlobalConfig.js +5 -0
  21. package/src/setGlobalContext.js +5 -0
  22. package/src/setupAuthentication.js +99 -0
  23. package/src/styles/application.css +479 -0
  24. package/src/tests/Adapter.test.js +39 -0
  25. package/src/tests/HonoAdapter.test.js +34 -0
  26. package/src/tests/helpers/Pagination.test.js +65 -0
  27. package/src/tests/helpers/SortButton.test.js +85 -0
  28. package/src/tests/routeCollection.test.js +150 -0
  29. package/src/tests/routeMember.test.js +91 -0
  30. package/src/tests/routeNestedCollection.test.js +176 -0
  31. package/src/tests/routeNestedMember.test.js +96 -0
  32. package/src/views/_auth/login.ejs +92 -0
  33. package/src/views/layouts/application.ejs +147 -0
  34. package/src/views/layouts/header.ejs +49 -0
  35. package/src/views/redirects/index.ejs +1 -0
  36. package/tailwind.config.js +39 -0
  37. package/tsconfig.json +15 -0
  38. package/tsconfig.lint.json +8 -0
  39. package/dist/index.js +0 -670
@@ -0,0 +1,65 @@
1
+ import Pagination from "../../helpers/Pagination";
2
+
3
+ function buildPagination({ currentPage, pagesCount }) {
4
+ return new Pagination(
5
+ {
6
+ currentPage: currentPage,
7
+ pagesCount: pagesCount,
8
+ },
9
+ {
10
+ path: "/example",
11
+ query: {
12
+ page: currentPage,
13
+ },
14
+ }
15
+ );
16
+ }
17
+
18
+ describe("Pagination", () => {
19
+ test("build for a single page", () => {
20
+ const pagination = buildPagination({ currentPage: 1, pagesCount: 1 });
21
+
22
+ const result = pagination.build();
23
+
24
+ expect(result).toEqual("");
25
+ });
26
+
27
+ test("build for the first page", () => {
28
+ const pagination = buildPagination({ currentPage: 1, pagesCount: 10 });
29
+
30
+ const result = pagination.build();
31
+
32
+ expect(result)
33
+ .toEqual(`<div class=\"pagination\"><div ><span class=\"btn-text is-inactive\">First</span>
34
+ <span class=\"btn-text is-inactive\">Previous</span>
35
+ <form action=\"/example\" method=\"GET\"><input type=\"number\" value=\"1\" /> of 10</form>
36
+ <a class=\"btn-text\" href=\"/example?page=2\">Next</a>
37
+ <a class=\"btn-text\" href=\"/example?page=10\">Last</a></div></div>`);
38
+ });
39
+
40
+ test("build for the last page", () => {
41
+ const pagination = buildPagination({ currentPage: 10, pagesCount: 10 });
42
+
43
+ const result = pagination.build();
44
+
45
+ expect(result)
46
+ .toEqual(`<div class=\"pagination\"><div ><a class=\"btn-text\" href=\"/example?page=1\">First</a>
47
+ <a class=\"btn-text\" href=\"/example?page=9\">Previous</a>
48
+ <form action=\"/example\" method=\"GET\"><input type=\"number\" value=\"10\" /> of 10</form>
49
+ <span class=\"btn-text is-inactive\">Next</span>
50
+ <span class=\"btn-text is-inactive\">Last</span></div></div>`);
51
+ });
52
+
53
+ test("build for the a middle page", () => {
54
+ const pagination = buildPagination({ currentPage: 5, pagesCount: 10 });
55
+
56
+ const result = pagination.build();
57
+
58
+ expect(result)
59
+ .toEqual(`<div class=\"pagination\"><div ><a class=\"btn-text\" href=\"/example?page=1\">First</a>
60
+ <a class=\"btn-text\" href=\"/example?page=4\">Previous</a>
61
+ <form action=\"/example\" method=\"GET\"><input type=\"number\" value=\"5\" /> of 10</form>
62
+ <a class=\"btn-text\" href=\"/example?page=6\">Next</a>
63
+ <a class=\"btn-text\" href=\"/example?page=10\">Last</a></div></div>`);
64
+ });
65
+ });
@@ -0,0 +1,85 @@
1
+ import SortButton from "../../helpers/SortButton";
2
+
3
+ describe("SortButton", () => {
4
+ test("build for inactive button without order parameters", () => {
5
+ const button = new SortButton("Sort Button", "url", {
6
+ path: "/example",
7
+ query: {
8
+ "f:keyword": "test",
9
+ },
10
+ });
11
+
12
+ const result = button.build();
13
+
14
+ expect(result)
15
+ .toEqual(`<a href=\"/example?f%3Akeyword=test&order_direction=ASC&order_by=url\" class=\"btn-sort\"><svg
16
+ xmlns=\"http://www.w3.org/2000/svg\"
17
+ viewBox=\"0 0 20 20\"
18
+ fill=\"currentColor\"
19
+ class=\"size-4\"
20
+ >
21
+ <path
22
+ fill-rule=\"evenodd\"
23
+ d=\"M2.24 6.8a.75.75 0 0 0 1.06-.04l1.95-2.1v8.59a.75.75 0 0 0 1.5 0V4.66l1.95 2.1a.75.75 0 1 0 1.1-1.02l-3.25-3.5a.75.75 0 0 0-1.1 0L2.2 5.74a.75.75 0 0 0 .04 1.06Zm8 6.4a.75.75 0 0 0-.04 1.06l3.25 3.5a.75.75 0 0 0 1.1 0l3.25-3.5a.75.75 0 1 0-1.1-1.02l-1.95 2.1V6.75a.75.75 0 0 0-1.5 0v8.59l-1.95-2.1a.75.75 0 0 0-1.06-.04Z\"
24
+ clip-rule=\"evenodd\"
25
+ />
26
+ </svg>
27
+ Sort Button</a>`);
28
+ });
29
+
30
+ test("build for active button in ASC direction", () => {
31
+ const button = new SortButton("Sort Button", "url", {
32
+ path: "/example",
33
+ query: {
34
+ order_by: "url",
35
+ order_direction: "ASC",
36
+ "f:keyword": "test",
37
+ },
38
+ });
39
+
40
+ const result = button.build();
41
+
42
+ expect(result)
43
+ .toEqual(`<a href=\"/example?f%3Akeyword=test&order_direction=DESC&order_by=url\" class=\"btn-sort is-active\"><svg
44
+ xmlns=\"http://www.w3.org/2000/svg\"
45
+ viewBox=\"0 0 20 20\"
46
+ fill=\"currentColor\"
47
+ class=\"size-4\"
48
+ >
49
+ <path
50
+ fill-rule=\"evenodd\"
51
+ d=\"M10 17a.75.75 0 0 1-.75-.75V5.612L5.29 9.77a.75.75 0 0 1-1.08-1.04l5.25-5.5a.75.75 0 0 1 1.08 0l5.25 5.5a.75.75 0 1 1-1.08 1.04l-3.96-4.158V16.25A.75.75 0 0 1 10 17Z\"
52
+ clip-rule=\"evenodd\"
53
+ />
54
+ </svg>
55
+ Sort Button</a>`);
56
+ });
57
+
58
+ test("build for active button in DESC direction", () => {
59
+ const button = new SortButton("Sort Button", "url", {
60
+ path: "/example",
61
+ query: {
62
+ order_by: "url",
63
+ order_direction: "DESC",
64
+ "f:keyword": "test",
65
+ },
66
+ });
67
+
68
+ const result = button.build();
69
+
70
+ expect(result)
71
+ .toEqual(`<a href=\"/example?f%3Akeyword=test&order_direction=ASC&order_by=url\" class=\"btn-sort is-active\"><svg
72
+ xmlns=\"http://www.w3.org/2000/svg\"
73
+ viewBox=\"0 0 20 20\"
74
+ fill=\"currentColor\"
75
+ class=\"size-4\"
76
+ >
77
+ <path
78
+ fill-rule=\"evenodd\"
79
+ d=\"M10 3a.75.75 0 0 1 .75.75v10.638l3.96-4.158a.75.75 0 1 1 1.08 1.04l-5.25 5.5a.75.75 0 0 1-1.08 0l-5.25-5.5a.75.75 0 1 1 1.08-1.04l3.96 4.158V3.75A.75.75 0 0 1 10 3Z\"
80
+ clip-rule=\"evenodd\"
81
+ />
82
+ </svg>
83
+ Sort Button</a>`);
84
+ });
85
+ });
@@ -0,0 +1,150 @@
1
+ import routeCollection from "../routeCollection";
2
+
3
+ const UsersHandler = {
4
+ index: () => {},
5
+ show: () => {},
6
+ create_form: () => {},
7
+ edit_form: () => {},
8
+ create: () => {},
9
+ update: () => {},
10
+ destroy: () => {},
11
+ };
12
+
13
+ const UsersHandlerWithFilters = {
14
+ before_filter: () => {},
15
+ after_filter: () => {},
16
+ index: () => {},
17
+ show: () => {},
18
+ create_form: () => {},
19
+ edit_form: () => {},
20
+ create: () => {},
21
+ update: () => {},
22
+ destroy: () => {},
23
+ };
24
+
25
+ const honoAdapter = {
26
+ routeCollection: (_mapping) => {},
27
+ };
28
+
29
+ const adapterSpy = jest.spyOn(honoAdapter, "routeCollection");
30
+
31
+ describe("routeCollection", () => {
32
+ test("Valid handler mapping is passed to router", () => {
33
+ routeCollection(honoAdapter, "users", UsersHandler);
34
+
35
+ expect(adapterSpy).toHaveBeenCalledWith([
36
+ ["GET", "/users", "users", "users", "index", UsersHandler.index],
37
+ [
38
+ "GET",
39
+ "/users/new",
40
+ "users",
41
+ "users",
42
+ "create_form",
43
+ UsersHandler.create_form,
44
+ ],
45
+ ["GET", "/users/:id", "users", "users", "show", UsersHandler.show],
46
+ [
47
+ "GET",
48
+ "/users/:id/edit",
49
+ "users",
50
+ "users",
51
+ "edit_form",
52
+ UsersHandler.edit_form,
53
+ ],
54
+ ["POST", "/users", "users", "users", "create_form", UsersHandler.create],
55
+ [
56
+ "POST",
57
+ "/users/:id",
58
+ "users",
59
+ "users",
60
+ "edit_form",
61
+ UsersHandler.update,
62
+ ],
63
+ [
64
+ "DELETE",
65
+ "/users/:id",
66
+ "users",
67
+ "users",
68
+ "destroy",
69
+ UsersHandler.destroy,
70
+ ],
71
+ ]);
72
+ });
73
+
74
+ test("Valid handler mapping is passed to router with filters", () => {
75
+ routeCollection(honoAdapter, "users", UsersHandlerWithFilters);
76
+
77
+ expect(adapterSpy).toHaveBeenCalledWith([
78
+ [
79
+ "GET",
80
+ "/users",
81
+ "users",
82
+ "users",
83
+ "index",
84
+ UsersHandlerWithFilters.index,
85
+ UsersHandlerWithFilters.before_filter,
86
+ UsersHandlerWithFilters.after_filter,
87
+ ],
88
+ [
89
+ "GET",
90
+ "/users/new",
91
+ "users",
92
+ "users",
93
+ "create_form",
94
+ UsersHandlerWithFilters.create_form,
95
+ UsersHandlerWithFilters.before_filter,
96
+ UsersHandlerWithFilters.after_filter,
97
+ ],
98
+ [
99
+ "GET",
100
+ "/users/:id",
101
+ "users",
102
+ "users",
103
+ "show",
104
+ UsersHandlerWithFilters.show,
105
+ UsersHandlerWithFilters.before_filter,
106
+ UsersHandlerWithFilters.after_filter,
107
+ ],
108
+ [
109
+ "GET",
110
+ "/users/:id/edit",
111
+ "users",
112
+ "users",
113
+ "edit_form",
114
+ UsersHandlerWithFilters.edit_form,
115
+ UsersHandlerWithFilters.before_filter,
116
+ UsersHandlerWithFilters.after_filter,
117
+ ],
118
+ [
119
+ "POST",
120
+ "/users",
121
+ "users",
122
+ "users",
123
+ "create_form",
124
+ UsersHandlerWithFilters.create,
125
+ UsersHandlerWithFilters.before_filter,
126
+ UsersHandlerWithFilters.after_filter,
127
+ ],
128
+ [
129
+ "POST",
130
+ "/users/:id",
131
+ "users",
132
+ "users",
133
+ "edit_form",
134
+ UsersHandlerWithFilters.update,
135
+ UsersHandlerWithFilters.before_filter,
136
+ UsersHandlerWithFilters.after_filter,
137
+ ],
138
+ [
139
+ "DELETE",
140
+ "/users/:id",
141
+ "users",
142
+ "users",
143
+ "destroy",
144
+ UsersHandlerWithFilters.destroy,
145
+ UsersHandlerWithFilters.before_filter,
146
+ UsersHandlerWithFilters.after_filter,
147
+ ],
148
+ ]);
149
+ });
150
+ });
@@ -0,0 +1,91 @@
1
+ import routeMember from "../routeMember";
2
+
3
+ const ProfileHandWithFilters = {
4
+ show: () => {},
5
+ edit_form: () => {},
6
+ update: () => {},
7
+ };
8
+
9
+ const ProfileHandWithFiltersWithFilters = {
10
+ before_filter: () => {},
11
+ after_filter: () => {},
12
+ show: () => {},
13
+ edit_form: () => {},
14
+ update: () => {},
15
+ };
16
+
17
+ const honoAdapter = {
18
+ routeMember: (_mapping) => {},
19
+ };
20
+
21
+ const adapterSpy = jest.spyOn(honoAdapter, "routeMember");
22
+
23
+ describe("routeMember", () => {
24
+ test("Valid handler mapping is passed to router", () => {
25
+ routeMember(honoAdapter, "profile", ProfileHandWithFilters);
26
+
27
+ expect(adapterSpy).toHaveBeenCalledWith([
28
+ [
29
+ "GET",
30
+ "/profile",
31
+ "profile",
32
+ "profile",
33
+ "show",
34
+ ProfileHandWithFilters.show,
35
+ ],
36
+ [
37
+ "GET",
38
+ "/profile/edit",
39
+ "profile",
40
+ "profile",
41
+ "edit_form",
42
+ ProfileHandWithFilters.edit_form,
43
+ ],
44
+ [
45
+ "POST",
46
+ "/profile",
47
+ "profile",
48
+ "profile",
49
+ "edit_form",
50
+ ProfileHandWithFilters.update,
51
+ ],
52
+ ]);
53
+ });
54
+
55
+ test("Valid handler mapping is passed to router with filters", () => {
56
+ routeMember(honoAdapter, "profile", ProfileHandWithFiltersWithFilters);
57
+
58
+ expect(adapterSpy).toHaveBeenCalledWith([
59
+ [
60
+ "GET",
61
+ "/profile",
62
+ "profile",
63
+ "profile",
64
+ "show",
65
+ ProfileHandWithFiltersWithFilters.show,
66
+ ProfileHandWithFiltersWithFilters.before_filter,
67
+ ProfileHandWithFiltersWithFilters.after_filter,
68
+ ],
69
+ [
70
+ "GET",
71
+ "/profile/edit",
72
+ "profile",
73
+ "profile",
74
+ "edit_form",
75
+ ProfileHandWithFiltersWithFilters.edit_form,
76
+ ProfileHandWithFiltersWithFilters.before_filter,
77
+ ProfileHandWithFiltersWithFilters.after_filter,
78
+ ],
79
+ [
80
+ "POST",
81
+ "/profile",
82
+ "profile",
83
+ "profile",
84
+ "edit_form",
85
+ ProfileHandWithFiltersWithFilters.update,
86
+ ProfileHandWithFiltersWithFilters.before_filter,
87
+ ProfileHandWithFiltersWithFilters.after_filter,
88
+ ],
89
+ ]);
90
+ });
91
+ });
@@ -0,0 +1,176 @@
1
+ import routeNestedCollection from "../routeNestedCollection";
2
+
3
+ const OrdersHandler = {
4
+ index: () => {},
5
+ show: () => {},
6
+ create_form: () => {},
7
+ edit_form: () => {},
8
+ create: () => {},
9
+ update: () => {},
10
+ destroy: () => {},
11
+ };
12
+
13
+ const OrdersHandlerWithFilters = {
14
+ before_filter: () => {},
15
+ after_filter: () => {},
16
+ index: () => {},
17
+ show: () => {},
18
+ create_form: () => {},
19
+ edit_form: () => {},
20
+ create: () => {},
21
+ update: () => {},
22
+ destroy: () => {},
23
+ };
24
+
25
+ const honoAdapter = {
26
+ routeNestedCollection: (_mapping) => {},
27
+ };
28
+
29
+ const adapterSpy = jest.spyOn(honoAdapter, "routeNestedCollection");
30
+
31
+ describe("routeNestedCollection", () => {
32
+ test("Valid handler mapping is passed to router", () => {
33
+ routeNestedCollection(honoAdapter, "orders", "line_items", OrdersHandler);
34
+
35
+ expect(adapterSpy).toHaveBeenCalledWith([
36
+ [
37
+ "GET",
38
+ "/orders/:parent_id/line_items",
39
+ "line_items",
40
+ "line_items",
41
+ "index",
42
+ OrdersHandler.index,
43
+ ],
44
+ [
45
+ "GET",
46
+ "/orders/:parent_id/line_items/new",
47
+ "line_items",
48
+ "line_items",
49
+ "create_form",
50
+ OrdersHandler.create_form,
51
+ ],
52
+ [
53
+ "GET",
54
+ "/line_items/:id",
55
+ "line_items",
56
+ "line_items",
57
+ "show",
58
+ OrdersHandler.show,
59
+ ],
60
+ [
61
+ "GET",
62
+ "/line_items/:id/edit",
63
+ "line_items",
64
+ "line_items",
65
+ "edit_form",
66
+ OrdersHandler.edit_form,
67
+ ],
68
+ [
69
+ "POST",
70
+ "/orders/:parent_id/line_items",
71
+ "line_items",
72
+ "line_items",
73
+ "create_form",
74
+ OrdersHandler.create,
75
+ ],
76
+ [
77
+ "PUT",
78
+ "/line_items/:id",
79
+ "line_items",
80
+ "line_items",
81
+ "update",
82
+ OrdersHandler.update,
83
+ ],
84
+ [
85
+ "DELETE",
86
+ "/line_items/:id",
87
+ "line_items",
88
+ "line_items",
89
+ "destroy",
90
+ OrdersHandler.destroy,
91
+ ],
92
+ ]);
93
+ });
94
+
95
+ test("Valid handler mapping is passed to router with filters", () => {
96
+ routeNestedCollection(
97
+ honoAdapter,
98
+ "orders",
99
+ "line_items",
100
+ OrdersHandlerWithFilters
101
+ );
102
+
103
+ expect(adapterSpy).toHaveBeenCalledWith([
104
+ [
105
+ "GET",
106
+ "/orders/:parent_id/line_items",
107
+ "line_items",
108
+ "line_items",
109
+ "index",
110
+ OrdersHandlerWithFilters.index,
111
+ OrdersHandlerWithFilters.before_filter,
112
+ OrdersHandlerWithFilters.after_filter,
113
+ ],
114
+ [
115
+ "GET",
116
+ "/orders/:parent_id/line_items/new",
117
+ "line_items",
118
+ "line_items",
119
+ "create_form",
120
+ OrdersHandlerWithFilters.create_form,
121
+ OrdersHandlerWithFilters.before_filter,
122
+ OrdersHandlerWithFilters.after_filter,
123
+ ],
124
+ [
125
+ "GET",
126
+ "/line_items/:id",
127
+ "line_items",
128
+ "line_items",
129
+ "show",
130
+ OrdersHandlerWithFilters.show,
131
+ OrdersHandlerWithFilters.before_filter,
132
+ OrdersHandlerWithFilters.after_filter,
133
+ ],
134
+ [
135
+ "GET",
136
+ "/line_items/:id/edit",
137
+ "line_items",
138
+ "line_items",
139
+ "edit_form",
140
+ OrdersHandlerWithFilters.edit_form,
141
+ OrdersHandlerWithFilters.before_filter,
142
+ OrdersHandlerWithFilters.after_filter,
143
+ ],
144
+ [
145
+ "POST",
146
+ "/orders/:parent_id/line_items",
147
+ "line_items",
148
+ "line_items",
149
+ "create_form",
150
+ OrdersHandlerWithFilters.create,
151
+ OrdersHandlerWithFilters.before_filter,
152
+ OrdersHandlerWithFilters.after_filter,
153
+ ],
154
+ [
155
+ "PUT",
156
+ "/line_items/:id",
157
+ "line_items",
158
+ "line_items",
159
+ "update",
160
+ OrdersHandlerWithFilters.update,
161
+ OrdersHandlerWithFilters.before_filter,
162
+ OrdersHandlerWithFilters.after_filter,
163
+ ],
164
+ [
165
+ "DELETE",
166
+ "/line_items/:id",
167
+ "line_items",
168
+ "line_items",
169
+ "destroy",
170
+ OrdersHandlerWithFilters.destroy,
171
+ OrdersHandlerWithFilters.before_filter,
172
+ OrdersHandlerWithFilters.after_filter,
173
+ ],
174
+ ]);
175
+ });
176
+ });
@@ -0,0 +1,96 @@
1
+ import routeNestedMember from "../routeNestedMember";
2
+
3
+ const ArtistHandWithFilters = {
4
+ show: () => {},
5
+ edit_form: () => {},
6
+ update: () => {},
7
+ };
8
+
9
+ const ArtistHandWithFiltersWithFilters = {
10
+ before_filter: () => {},
11
+ after_filter: () => {},
12
+ show: () => {},
13
+ edit_form: () => {},
14
+ update: () => {},
15
+ };
16
+
17
+ const honoAdapter = {
18
+ routeNestedMember: (_mapping) => {},
19
+ };
20
+
21
+ const adapterSpy = jest.spyOn(honoAdapter, "routeNestedMember");
22
+
23
+ describe("routeNestedMember", () => {
24
+ test("Valid handler mapping is passed to router", () => {
25
+ routeNestedMember(honoAdapter, "artist", "bio", ArtistHandWithFilters);
26
+
27
+ expect(adapterSpy).toHaveBeenCalledWith([
28
+ [
29
+ "GET",
30
+ "/artist/:parent_id/bio",
31
+ "bio",
32
+ "artist/bio",
33
+ "show",
34
+ ArtistHandWithFilters.show,
35
+ ],
36
+ [
37
+ "GET",
38
+ "/artist/:parent_id/bio/edit",
39
+ "bio",
40
+ "artist/bio",
41
+ "edit_form",
42
+ ArtistHandWithFilters.edit_form,
43
+ ],
44
+ [
45
+ "POST",
46
+ "/artist/:parent_id/bio",
47
+ "bio",
48
+ "artist/bio",
49
+ "edit_form",
50
+ ArtistHandWithFilters.update,
51
+ ],
52
+ ]);
53
+ });
54
+
55
+ test("Valid handler mapping is passed to router with filters", () => {
56
+ routeNestedMember(
57
+ honoAdapter,
58
+ "artist",
59
+ "bio",
60
+ ArtistHandWithFiltersWithFilters
61
+ );
62
+
63
+ expect(adapterSpy).toHaveBeenCalledWith([
64
+ [
65
+ "GET",
66
+ "/artist/:parent_id/bio",
67
+ "bio",
68
+ "artist/bio",
69
+ "show",
70
+ ArtistHandWithFiltersWithFilters.show,
71
+ ArtistHandWithFiltersWithFilters.before_filter,
72
+ ArtistHandWithFiltersWithFilters.after_filter,
73
+ ],
74
+ [
75
+ "GET",
76
+ "/artist/:parent_id/bio/edit",
77
+ "bio",
78
+ "artist/bio",
79
+ "edit_form",
80
+ ArtistHandWithFiltersWithFilters.edit_form,
81
+ ArtistHandWithFiltersWithFilters.before_filter,
82
+ ArtistHandWithFiltersWithFilters.after_filter,
83
+ ],
84
+ [
85
+ "POST",
86
+ "/artist/:parent_id/bio",
87
+ "bio",
88
+ "artist/bio",
89
+ "edit_form",
90
+ ArtistHandWithFiltersWithFilters.update,
91
+ ArtistHandWithFiltersWithFilters.before_filter,
92
+ ArtistHandWithFiltersWithFilters.after_filter,
93
+ ],
94
+ ]);
95
+ });
96
+ });