frap 0.2.0 → 0.2.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile.lock +1 -1
- data/README.md +24 -0
- data/lib/frap.rb +1 -0
- data/lib/frap/create_resource.rb +8 -7
- data/lib/frap/generators/flutter_config.rb +7 -3
- data/lib/frap/generators/flutter_resource.rb +117 -17
- data/lib/frap/generators/templates/dart/src/app.dart.erb +1 -2
- data/lib/frap/generators/templates/dart/src/blocs/base_block.dart.erb +21 -0
- data/lib/frap/generators/templates/dart/src/config/router.dart.erb +0 -1
- data/lib/frap/generators/templates/dart/src/constants/app_constants.dart.erb +1 -0
- data/lib/frap/generators/templates/dart/src/models/base_model.dart.erb +32 -0
- data/lib/frap/generators/templates/dart/src/resources/base_api_provider.dart.erb +18 -0
- data/lib/frap/generators/templates/dart/src/resources/repository.dart.erb +4 -0
- data/lib/frap/generators/templates/dart/src/screens/base.dart.erb +0 -1
- data/lib/frap/generators/templates/dart/src/screens/base_bottom_navigation.dart.erb +57 -0
- data/lib/frap/generators/templates/dart/src/screens/base_index.dart.erb +72 -0
- data/lib/frap/generators/templates/dart/src/screens/edit_class.dart.erb +0 -0
- data/lib/frap/generators/templates/dart/src/screens/index_class.dart.erb +0 -0
- data/lib/frap/generators/templates/dart/src/screens/show_class.dart.erb +0 -0
- data/lib/frap/generators/templates/dart/src/widgets/popup_menu_widget.dart.erb +1 -3
- data/lib/frap/version.rb +1 -1
- metadata +12 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 2113fe87e979c5dcc6f1068901f9addbb33398ef7bbc54d138d87c37b3813145
|
4
|
+
data.tar.gz: 75f07d7ef133da72c45d1086b28e3054020a6aadeb889a5dc06ad90a2598a9f5
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 2199c30717694e927e1275b0c4c661302b7e1e6f04db69ba06b05f4cee4486aaf440340f0ad7aa85b96a364944d9f193c63dc23fd3f6d350c482f2fd5bb77e92
|
7
|
+
data.tar.gz: 93bdd37d1101b04848a6bdcd86cf69c89c2806548c53f2c54c07f0546d2b5374cc798dab578ecb267741e3021da42eeda80570f5ddfdb7210939fda28623e72d
|
data/Gemfile.lock
CHANGED
data/README.md
CHANGED
@@ -32,6 +32,30 @@ This will create a new Parent directory for the Rails and Flutter App.
|
|
32
32
|
|__ my_app_server
|
33
33
|
|__ my_app_ui
|
34
34
|
```
|
35
|
+
Generate a Rails and Flutter Resource from the app route directory `/my_app`, **currently does NOT support references, please open an ISSUE for broken data types**
|
36
|
+
`frap generate resource post -a title:string body:text`
|
37
|
+
|
38
|
+
The next step is to implement your Rails controller method for index action and run the migrations:
|
39
|
+
```
|
40
|
+
cd my_app/my_app_server
|
41
|
+
rails db:migrate
|
42
|
+
```
|
43
|
+
You can then edit the `app/constrollers/posts_controller.rb`:
|
44
|
+
```ruby
|
45
|
+
class PostsController < ApplicationController
|
46
|
+
def index
|
47
|
+
render json: { posts: Post.all.as_json }, status: :ok
|
48
|
+
end
|
49
|
+
end
|
50
|
+
```
|
51
|
+
Next fire up Rails and Flutter (you may need to start up an emulator, just follow the terminal output:
|
52
|
+
```bash
|
53
|
+
cd my_app/my_app_server
|
54
|
+
rails s
|
55
|
+
|
56
|
+
cd my_app/my_app_ui
|
57
|
+
flutter run
|
58
|
+
```
|
35
59
|
|
36
60
|
|
37
61
|
## Motivation
|
data/lib/frap.rb
CHANGED
data/lib/frap/create_resource.rb
CHANGED
@@ -17,15 +17,16 @@ module Frap
|
|
17
17
|
private
|
18
18
|
|
19
19
|
def generate_rails_resource
|
20
|
-
Dir.chdir("#{working_dir}/#{
|
21
|
-
|
20
|
+
Dir.chdir("#{working_dir}/#{rails_app_dir}")
|
22
21
|
system("rails generate resource #{name} #{fields}")
|
22
|
+
Dir.chdir("#{working_dir}")
|
23
23
|
end
|
24
24
|
|
25
25
|
def generate_flutter_resource
|
26
|
-
|
27
|
-
|
28
|
-
|
26
|
+
flutter_fields = options[:attributes] || 'name:string'
|
27
|
+
Frap::Generators::FlutterResource.new(
|
28
|
+
[name.capitalize, flutter_app_dir, flutter_fields]
|
29
|
+
).invoke(:configure_directories)
|
29
30
|
end
|
30
31
|
|
31
32
|
def fields
|
@@ -51,11 +52,11 @@ module Frap
|
|
51
52
|
@config ||= YAML.load(File.read('config.yml'))
|
52
53
|
end
|
53
54
|
|
54
|
-
def
|
55
|
+
def flutter_app_dir
|
55
56
|
config['flutter_app']
|
56
57
|
end
|
57
58
|
|
58
|
-
def
|
59
|
+
def rails_app_dir
|
59
60
|
config['rails_app']
|
60
61
|
end
|
61
62
|
end
|
@@ -28,6 +28,8 @@ module Frap
|
|
28
28
|
|
29
29
|
def create_files
|
30
30
|
template('main.dart.erb', "#{lib_directory}/main.dart")
|
31
|
+
template('src/constants/app_constants.dart.erb', "#{src_directory}/constants/app_constants.dart")
|
32
|
+
template('src/resources/repository.dart.erb', "#{src_directory}/resources/repository.dart")
|
31
33
|
template('src/app.dart.erb', "#{src_directory}/app.dart")
|
32
34
|
template('src/animations/slide_right_route.dart.erb', "#{src_directory}/animations/slide_right_route.dart")
|
33
35
|
template('src/config/router.dart.erb', "#{src_directory}/config/router.dart")
|
@@ -44,7 +46,7 @@ module Frap
|
|
44
46
|
def setup_pages
|
45
47
|
inject_into_file("#{src_directory}/config/router.dart", home_router, after: /^.*switch \(settings.name\) \{$/)
|
46
48
|
inject_into_file("#{src_directory}/constants/pages_list.dart", home_route, after: /const List<Page> pages = const <Page>\[.*$/)
|
47
|
-
append_to_file("#{src_directory}/constants/routing.dart", "const String HomeScreenRoute = '/'
|
49
|
+
append_to_file("#{src_directory}/constants/routing.dart", "const String HomeScreenRoute = '/';\n")
|
48
50
|
end
|
49
51
|
|
50
52
|
private
|
@@ -65,7 +67,8 @@ module Frap
|
|
65
67
|
%Q(
|
66
68
|
dio: ^2.1.13
|
67
69
|
rxdart: ^0.22.0
|
68
|
-
bloc_pattern: ^2.2.3
|
70
|
+
bloc_pattern: ^2.2.3
|
71
|
+
http: ^0.12.0+2)
|
69
72
|
end
|
70
73
|
|
71
74
|
def home_router
|
@@ -76,7 +79,8 @@ module Frap
|
|
76
79
|
|
77
80
|
def home_route
|
78
81
|
%Q(
|
79
|
-
const Page(title: 'Home', icon: Icons.home, route: HomeScreenRoute),
|
82
|
+
const Page(title: 'Home', icon: Icons.home, route: HomeScreenRoute),
|
83
|
+
)
|
80
84
|
end
|
81
85
|
end
|
82
86
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
require 'active_support/inflector'
|
2
|
+
|
1
3
|
module Frap
|
2
4
|
module Generators
|
3
5
|
class FlutterResource < Thor::Group
|
@@ -5,37 +7,82 @@ module Frap
|
|
5
7
|
|
6
8
|
desc 'Generate Flutter Config files'
|
7
9
|
argument :name
|
8
|
-
argument :
|
9
|
-
|
10
|
+
argument :flutter_app_dir
|
11
|
+
argument :fields
|
10
12
|
def self.source_root
|
11
13
|
File.dirname(__FILE__) + '/templates/dart'
|
12
14
|
end
|
13
15
|
|
14
16
|
def configure_directories
|
15
|
-
inject_into_file("#{working_directory}/pubspec.yaml", pub_files, after: /^dependencies:.*$/)
|
16
|
-
remove_file("#{lib_directory}/main.dart")
|
17
17
|
invoke :create_directories
|
18
18
|
end
|
19
19
|
|
20
20
|
def create_directories
|
21
|
-
empty_directory("#{lib_directory}/src/
|
21
|
+
empty_directory("#{lib_directory}/src/screens/#{lower_name}")
|
22
|
+
|
22
23
|
invoke :create_files
|
23
24
|
end
|
24
25
|
|
25
26
|
def create_files
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
template('src/
|
27
|
+
@name_capitalized_plural = name_capitalize_pluralize
|
28
|
+
@name_capitalized_single = name_capitalized_single
|
29
|
+
@name_downcased_plural = name_downcase_pluralize
|
30
|
+
@lower_name = lower_name
|
31
|
+
@field_types = build_fields
|
32
|
+
@field_names = fields.keys
|
33
|
+
template('src/screens/base_index.dart.erb', "#{screen_path}/#{lower_name}_index_screen.dart")
|
34
|
+
template('src/screens/base_bottom_navigation.dart.erb', "#{screen_path}/#{lower_name}_show_screen.dart")
|
35
|
+
template('src/blocs/base_block.dart.erb', "#{src_directory}/blocs/#{@name_downcased_plural}_bloc.dart")
|
36
|
+
template('src/models/base_model.dart.erb', "#{src_directory}/models/#{@name_downcased_plural}.dart")
|
37
|
+
template('src/resources/base_api_provider.dart.erb', "#{src_directory}/resources/#{lower_name}_api_provider.dart")
|
38
|
+
invoke :connect_widgets
|
39
|
+
end
|
40
|
+
|
41
|
+
def connect_widgets
|
42
|
+
inject_into_file("#{src_directory}/config/router.dart", router_packages, after: /^import 'package:flutter\/material.dart';$/)
|
43
|
+
inject_into_file("#{src_directory}/config/router.dart", show_screen_router, after: /^.*switch \(settings.name\) \{$/)
|
44
|
+
inject_into_file("#{src_directory}/config/router.dart", index_screen_router, after: /^.*switch \(settings.name\) \{$/)
|
45
|
+
inject_into_file("#{src_directory}/constants/pages_list.dart", index_screen_route, after: /const List<Page> pages = const <Page>\[.*$/)
|
46
|
+
inject_into_file("#{src_directory}/resources/repository.dart", repository_packages, after: /^import 'dart:async';$/)
|
47
|
+
inject_into_file("#{src_directory}/resources/repository.dart", repository_body, after: /^class Repository \{$/)
|
48
|
+
append_to_file("#{src_directory}/constants/routing.dart", "const String #{name}IndexScreenRoute = '/#{lower_name.pluralize }'; \n")
|
49
|
+
append_to_file("#{src_directory}/constants/routing.dart", "const String #{name}ShowScreenRoute = '/#{lower_name.singularize}';\n")
|
50
|
+
# Here we will make sure all imports are handled:
|
51
|
+
# Import new resource into routes route and constants
|
52
|
+
# Index page with bottom floating button for adding
|
53
|
+
# build detail screen with bottom navigations
|
54
|
+
# Link navigation buttons to Edit and back to list and delete
|
33
55
|
end
|
34
56
|
|
35
57
|
private
|
36
58
|
|
59
|
+
def build_fields
|
60
|
+
return unless fields
|
61
|
+
|
62
|
+
fields.map do |key, value|
|
63
|
+
case value
|
64
|
+
when 'text'
|
65
|
+
"String #{key}"
|
66
|
+
when 'string'
|
67
|
+
"String #{key}"
|
68
|
+
when 'integer'
|
69
|
+
"int #{key}"
|
70
|
+
when 'float'
|
71
|
+
"double #{key}"
|
72
|
+
when 'bigint'
|
73
|
+
"BigInt #{key}"
|
74
|
+
when 'datetime'
|
75
|
+
"DateTime #{key}"
|
76
|
+
when 'boolean'
|
77
|
+
"bool #{key}"
|
78
|
+
else
|
79
|
+
"var #{key}"
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
37
84
|
def working_directory
|
38
|
-
"#{destination_root}/#{
|
85
|
+
"#{destination_root}/#{flutter_app_dir}"
|
39
86
|
end
|
40
87
|
|
41
88
|
def lib_directory
|
@@ -46,11 +93,64 @@ module Frap
|
|
46
93
|
"#{lib_directory}/src"
|
47
94
|
end
|
48
95
|
|
49
|
-
def
|
96
|
+
def screen_path
|
97
|
+
"#{src_directory}/screens/#{lower_name}"
|
98
|
+
end
|
99
|
+
|
100
|
+
def index_screen_router
|
101
|
+
%Q(
|
102
|
+
case #{name}IndexScreenRoute:
|
103
|
+
return SlideRightRoute(widget:#{name}IndexScreen());)
|
104
|
+
end
|
105
|
+
|
106
|
+
def index_screen_route
|
50
107
|
%Q(
|
51
|
-
|
52
|
-
|
53
|
-
|
108
|
+
const Page(title: '#{name.pluralize}', icon: Icons.home, route: #{name}IndexScreenRoute),)
|
109
|
+
end
|
110
|
+
|
111
|
+
def show_screen_router
|
112
|
+
%Q(
|
113
|
+
case #{name}ShowScreenRoute:
|
114
|
+
return SlideRightRoute(widget:#{name}ShowScreen());)
|
115
|
+
end
|
116
|
+
|
117
|
+
def show_screen_route
|
118
|
+
%Q(
|
119
|
+
const Page(title: '#{name}', icon: Icons.home, route: #{name}ShowScreenRoute),)
|
120
|
+
end
|
121
|
+
|
122
|
+
def lower_name
|
123
|
+
name.downcase.singularize
|
124
|
+
end
|
125
|
+
|
126
|
+
def name_capitalized_single
|
127
|
+
name.capitalize.singularize
|
128
|
+
end
|
129
|
+
|
130
|
+
def name_capitalize_pluralize
|
131
|
+
name.capitalize.pluralize
|
132
|
+
end
|
133
|
+
|
134
|
+
def name_downcase_pluralize
|
135
|
+
name.downcase.pluralize
|
136
|
+
end
|
137
|
+
|
138
|
+
def router_packages
|
139
|
+
%Q(
|
140
|
+
import 'package:#{flutter_app_dir}/src/screens/#{lower_name}/#{lower_name}_index_screen.dart';
|
141
|
+
import 'package:#{flutter_app_dir}/src/screens/#{lower_name}/#{lower_name}_show_screen.dart';)
|
142
|
+
end
|
143
|
+
|
144
|
+
def repository_body
|
145
|
+
%Q(
|
146
|
+
final #{lower_name}ApiProvider = #{name_capitalized_single}ApiProvider();
|
147
|
+
Future<#{name_capitalize_pluralize}> fetchAll#{name_capitalize_pluralize}() => #{lower_name}ApiProvider.fetchAll#{name_capitalize_pluralize}();)
|
148
|
+
end
|
149
|
+
|
150
|
+
def repository_packages
|
151
|
+
%Q(
|
152
|
+
import 'package:#{flutter_app_dir}/src/resources/#{lower_name}_api_provider.dart';
|
153
|
+
import 'package:#{flutter_app_dir}/src/models/#{name_downcase_pluralize}.dart';)
|
54
154
|
end
|
55
155
|
end
|
56
156
|
end
|
@@ -5,10 +5,9 @@ import 'package:<%= folder_name %>/src/config/router.dart' as router;
|
|
5
5
|
import 'package:<%= folder_name %>/src/constants/routing.dart';
|
6
6
|
|
7
7
|
class App extends StatelessWidget {
|
8
|
-
@override
|
9
|
-
|
10
8
|
static const String _title = '<%= folder_name %>';
|
11
9
|
|
10
|
+
@override
|
12
11
|
Widget build(BuildContext context) {
|
13
12
|
return MaterialApp(
|
14
13
|
title: _title,
|
@@ -0,0 +1,21 @@
|
|
1
|
+
import 'package:rxdart/rxdart.dart';
|
2
|
+
import 'package:<%= flutter_app_dir %>/src/resources/repository.dart';
|
3
|
+
import 'package:<%= flutter_app_dir %>/src/models/<%= @name_downcased_plural %>.dart';
|
4
|
+
|
5
|
+
class <%= @name_capitalized_plural %>Bloc {
|
6
|
+
final _repository = Repository();
|
7
|
+
final _<%= @name_downcased_plural %>Fetcher = PublishSubject<<%= @name_capitalized_plural %>>();
|
8
|
+
|
9
|
+
Observable<<%= @name_capitalized_plural %>> get all<%= @name_capitalized_plural %> => _<%= @name_downcased_plural %>Fetcher.stream;
|
10
|
+
|
11
|
+
fetchAll<%= @name_capitalized_plural %>() async {
|
12
|
+
<%= @name_capitalized_plural %> <%= @name_downcased_plural %> = await _repository.fetchAll<%= @name_capitalized_plural %>();
|
13
|
+
_<%= @name_downcased_plural%>Fetcher.sink.add(<%= @name_downcased_plural %>);
|
14
|
+
}
|
15
|
+
|
16
|
+
dispose() {
|
17
|
+
_<%= @name_downcased_plural %>Fetcher.close();
|
18
|
+
}
|
19
|
+
}
|
20
|
+
|
21
|
+
final bloc = <%= @name_capitalized_plural %>Bloc();
|
@@ -0,0 +1 @@
|
|
1
|
+
const String RootUrl = 'http://10.0.2.2:3000';
|
@@ -0,0 +1,32 @@
|
|
1
|
+
class <%= @name_capitalized_plural %> {
|
2
|
+
int _id;
|
3
|
+
List<<%= @name_capitalized_single %>> _results = [];
|
4
|
+
|
5
|
+
<%= @name_capitalized_plural %>.fromJson(Map<String, dynamic> parsedJson) {
|
6
|
+
List<<%= @name_capitalized_single %>> temp = [];
|
7
|
+
for (int i = 0; i < parsedJson['<%= @name_downcased_plural %>'].length; i++) {
|
8
|
+
<%= @name_capitalized_single %> result = <%= @name_capitalized_single %>.fromJson(parsedJson['<%= @name_downcased_plural %>'][i]);
|
9
|
+
temp.add(result);
|
10
|
+
}
|
11
|
+
_results = temp;
|
12
|
+
}
|
13
|
+
|
14
|
+
List<<%= @name_capitalized_single %>> get results => _results;
|
15
|
+
}
|
16
|
+
|
17
|
+
class <%= @name_capitalized_single %> {
|
18
|
+
<% @field_types.each do |field| %>final <%= field %>;
|
19
|
+
<% end %>
|
20
|
+
|
21
|
+
<%= @name_capitalized_single %>({
|
22
|
+
<% @field_names.each do |field| %>this.<%= field %>,
|
23
|
+
<% end %>
|
24
|
+
});
|
25
|
+
|
26
|
+
factory <%= @name_capitalized_single %>.fromJson(Map<String, dynamic> json) {
|
27
|
+
return <%= @name_capitalized_single %>(
|
28
|
+
<% @field_names.each do |field| %><%= field %>: json['<%= field %>'],
|
29
|
+
<% end %>
|
30
|
+
);
|
31
|
+
}
|
32
|
+
}
|
@@ -0,0 +1,18 @@
|
|
1
|
+
import 'dart:async';
|
2
|
+
import 'package:http/http.dart' as http;
|
3
|
+
import 'dart:convert';
|
4
|
+
import 'package:<%= flutter_app_dir %>/src/models/<%= @name_downcased_plural %>.dart';
|
5
|
+
import 'package:<%= flutter_app_dir %>/src/constants/app_constants.dart';
|
6
|
+
|
7
|
+
class <%= @name_capitalized_single %>ApiProvider {
|
8
|
+
Future<<%= @name_capitalized_plural %>> fetchAll<%= @name_capitalized_plural %>() async {
|
9
|
+
final response =
|
10
|
+
await http.get("${RootUrl}/<%= @name_downcased_plural %>");
|
11
|
+
|
12
|
+
if (response.statusCode == 200) {
|
13
|
+
return <%= @name_capitalized_plural %>.fromJson(json.decode(response.body));
|
14
|
+
} else {
|
15
|
+
throw Exception('Failed to load <%= @name_capitalized_plural %>');
|
16
|
+
}
|
17
|
+
}
|
18
|
+
}
|
@@ -0,0 +1,57 @@
|
|
1
|
+
import 'package:flutter/material.dart';
|
2
|
+
import 'package:<%= flutter_app_dir %>/src/widgets/base_app_bar.dart';
|
3
|
+
import 'package:<%= flutter_app_dir %>/src/widgets/popup_menu_widget.dart';
|
4
|
+
import 'package:<%= flutter_app_dir %>/src/screens/<%= name.downcase %>/<%= name.downcase %>_index_screen.dart';
|
5
|
+
|
6
|
+
class <%= name %>ShowScreen extends StatefulWidget {
|
7
|
+
<%= name %>ShowScreen({Key key}) : super(key: key);
|
8
|
+
|
9
|
+
@override
|
10
|
+
_<%= name %>ShowScreenState createState() => _<%= name %>ShowScreenState();
|
11
|
+
}
|
12
|
+
|
13
|
+
class _<%= name %>ShowScreenState extends State<<%= name %>ShowScreen> {
|
14
|
+
int _selectedIndex = 1;
|
15
|
+
|
16
|
+
final List<Widget> _widgets = <Widget>[
|
17
|
+
<%= name %>IndexScreen(),
|
18
|
+
];
|
19
|
+
|
20
|
+
void _onItemTapped(int index) {
|
21
|
+
setState(() {
|
22
|
+
_selectedIndex = index;
|
23
|
+
});
|
24
|
+
}
|
25
|
+
|
26
|
+
@override
|
27
|
+
|
28
|
+
Widget build(BuildContext context) {
|
29
|
+
return Scaffold(
|
30
|
+
appBar: BaseAppBar(
|
31
|
+
title: Text('<%= name %>'),
|
32
|
+
appBar: AppBar(),
|
33
|
+
widgets: <Widget>[
|
34
|
+
PopupMenuWidget(),
|
35
|
+
],
|
36
|
+
),
|
37
|
+
body: Center(
|
38
|
+
child: Text('<%= name %>'),
|
39
|
+
),
|
40
|
+
bottomNavigationBar: BottomNavigationBar(
|
41
|
+
items: const <BottomNavigationBarItem>[
|
42
|
+
BottomNavigationBarItem(
|
43
|
+
icon: Icon(Icons.dashboard),
|
44
|
+
title: Text('Back'),
|
45
|
+
),
|
46
|
+
BottomNavigationBarItem(
|
47
|
+
icon: Icon(Icons.monetization_on),
|
48
|
+
title: Text('Edit'),
|
49
|
+
),
|
50
|
+
],
|
51
|
+
currentIndex: _selectedIndex,
|
52
|
+
selectedItemColor: Colors.green,
|
53
|
+
onTap: _onItemTapped,
|
54
|
+
),
|
55
|
+
);
|
56
|
+
}
|
57
|
+
}
|
@@ -0,0 +1,72 @@
|
|
1
|
+
import 'package:flutter/material.dart';
|
2
|
+
import 'package:<%= flutter_app_dir %>/src/widgets/base_app_bar.dart';
|
3
|
+
import 'package:<%= flutter_app_dir %>/src/widgets/popup_menu_widget.dart';
|
4
|
+
import 'package:<%= flutter_app_dir %>/src/models/<%= @name_downcased_plural %>.dart';
|
5
|
+
import 'package:<%= flutter_app_dir %>/src/blocs/<%= @name_downcased_plural %>_bloc.dart';
|
6
|
+
|
7
|
+
class <%= @name_capitalized_single %>IndexScreen extends StatefulWidget {
|
8
|
+
@override
|
9
|
+
State<StatefulWidget> createState() {
|
10
|
+
return <%= @name_capitalized_single %>IndexScreenState();
|
11
|
+
}
|
12
|
+
}
|
13
|
+
|
14
|
+
class <%= @name_capitalized_single %>IndexScreenState extends State<<%= @name_capitalized_single %>IndexScreen> {
|
15
|
+
@override
|
16
|
+
void initState() {
|
17
|
+
super.initState();
|
18
|
+
bloc.fetchAll<%= @name_capitalized_plural %>();
|
19
|
+
}
|
20
|
+
|
21
|
+
// @override
|
22
|
+
// void dispose() {
|
23
|
+
// bloc.dispose();
|
24
|
+
// super.dispose();
|
25
|
+
// }
|
26
|
+
|
27
|
+
Widget build(BuildContext context) {
|
28
|
+
return Scaffold(
|
29
|
+
appBar: BaseAppBar(
|
30
|
+
title: Text('<%= @name_capitalized_single %>'),
|
31
|
+
appBar: AppBar(),
|
32
|
+
widgets: <Widget>[
|
33
|
+
PopupMenuWidget(),
|
34
|
+
],
|
35
|
+
),
|
36
|
+
body: StreamBuilder(
|
37
|
+
stream: bloc.all<%= @name_capitalized_plural %>,
|
38
|
+
builder: (context, AsyncSnapshot<<%= @name_capitalized_plural %>> snapshot) {
|
39
|
+
if (snapshot.hasData) {
|
40
|
+
return buildList(snapshot);
|
41
|
+
} else if (snapshot.hasError) {
|
42
|
+
return Text(snapshot.error.toString());
|
43
|
+
}
|
44
|
+
return Center(child: CircularProgressIndicator());
|
45
|
+
},
|
46
|
+
),
|
47
|
+
floatingActionButton: FloatingActionButton(
|
48
|
+
elevation: 0.0,
|
49
|
+
child: Icon(Icons.add),
|
50
|
+
onPressed: (){ }
|
51
|
+
),
|
52
|
+
);
|
53
|
+
}
|
54
|
+
|
55
|
+
Widget buildList(AsyncSnapshot<<%= @name_capitalized_plural %>> snapshot) {
|
56
|
+
return ListView.builder(
|
57
|
+
itemCount: snapshot.data.results.length,
|
58
|
+
itemBuilder: (BuildContext context, int index) {
|
59
|
+
return Card(
|
60
|
+
child: ListTile(
|
61
|
+
leading: Icon(Icons.map),
|
62
|
+
title: Text('TODO EDIT: snapshot.data.results[index].your_field_name'),
|
63
|
+
subtitle: Text('TODO EDIT: snapshot.data.results[index].your_field_name.toString()'),
|
64
|
+
trailing: Icon(Icons.more_vert),
|
65
|
+
onTap: () {},
|
66
|
+
)
|
67
|
+
);
|
68
|
+
},
|
69
|
+
);
|
70
|
+
}
|
71
|
+
}
|
72
|
+
|
File without changes
|
File without changes
|
File without changes
|
@@ -1,6 +1,5 @@
|
|
1
1
|
import 'package:flutter/material.dart';
|
2
2
|
import 'package:<%= folder_name %>/src/constants/pages_list.dart';
|
3
|
-
import 'package:<%= folder_name %>/src/constants/routing.dart';
|
4
3
|
|
5
4
|
class PopupMenuWidget extends StatefulWidget {
|
6
5
|
@override
|
@@ -8,12 +7,11 @@ class PopupMenuWidget extends StatefulWidget {
|
|
8
7
|
}
|
9
8
|
|
10
9
|
class _PopupMenuWidgetState extends State<PopupMenuWidget> {
|
11
|
-
@override
|
12
|
-
|
13
10
|
_onSelect(Page page) {
|
14
11
|
Navigator.pushNamed(context, page.route);
|
15
12
|
}
|
16
13
|
|
14
|
+
@override
|
17
15
|
Widget build(BuildContext context) {
|
18
16
|
return PopupMenuButton<Page>(
|
19
17
|
onSelected: _onSelect,
|
data/lib/frap/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: frap
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.2.
|
4
|
+
version: 0.2.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- James Gascoigne - Taylor
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2019-07
|
11
|
+
date: 2019-08-07 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: thor
|
@@ -115,10 +115,20 @@ files:
|
|
115
115
|
- lib/frap/generators/templates/dart/main.dart.erb
|
116
116
|
- lib/frap/generators/templates/dart/src/animations/slide_right_route.dart.erb
|
117
117
|
- lib/frap/generators/templates/dart/src/app.dart.erb
|
118
|
+
- lib/frap/generators/templates/dart/src/blocs/base_block.dart.erb
|
118
119
|
- lib/frap/generators/templates/dart/src/config/router.dart.erb
|
120
|
+
- lib/frap/generators/templates/dart/src/constants/app_constants.dart.erb
|
119
121
|
- lib/frap/generators/templates/dart/src/constants/pages_list.dart.erb
|
120
122
|
- lib/frap/generators/templates/dart/src/constants/routing.dart.erb
|
123
|
+
- lib/frap/generators/templates/dart/src/models/base_model.dart.erb
|
124
|
+
- lib/frap/generators/templates/dart/src/resources/base_api_provider.dart.erb
|
125
|
+
- lib/frap/generators/templates/dart/src/resources/repository.dart.erb
|
121
126
|
- lib/frap/generators/templates/dart/src/screens/base.dart.erb
|
127
|
+
- lib/frap/generators/templates/dart/src/screens/base_bottom_navigation.dart.erb
|
128
|
+
- lib/frap/generators/templates/dart/src/screens/base_index.dart.erb
|
129
|
+
- lib/frap/generators/templates/dart/src/screens/edit_class.dart.erb
|
130
|
+
- lib/frap/generators/templates/dart/src/screens/index_class.dart.erb
|
131
|
+
- lib/frap/generators/templates/dart/src/screens/show_class.dart.erb
|
122
132
|
- lib/frap/generators/templates/dart/src/screens/undefined_route_screen.dart.erb
|
123
133
|
- lib/frap/generators/templates/dart/src/widgets/base_app_bar.dart.erb
|
124
134
|
- lib/frap/generators/templates/dart/src/widgets/popup_menu_widget.dart.erb
|