Skip to content

Commit

Permalink
Merge pull request #46 from hmatsu47/development
Browse files Browse the repository at this point in the history
#38 ほか
  • Loading branch information
hmatsu47 authored Nov 20, 2021
2 parents 06dd9c9 + 76aa2c0 commit d9542ed
Show file tree
Hide file tree
Showing 15 changed files with 1,214 additions and 36 deletions.
77 changes: 77 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
**In development:**(開発中の機能など)

- Add external API call.(外部 API 呼び出し)
- Search sightseeing spots etc.(近隣の観光スポット等検索)

![画面例](map_image.png "画面例")

Expand Down Expand Up @@ -59,6 +60,7 @@ dependencies:
minio: ^3.0.0
font_awesome_flutter: ^9.2.0
connectivity: ^3.0.6
supabase: ^0.2.9
```

- **Edit '`android/build.gradle`'** ( for Android / in `allprojects` -> `repositories` )
Expand Down Expand Up @@ -415,3 +417,78 @@ amplify push
- Endpoint
- Stage
- API Gateway Key

- **Create Supabase account & Project**
- Project name : maptool
- Database Password
- Database Extensions
- PostGIS

- **Create Tables etc. on Supabase**

```sql:CREATE_TABLES
CREATE TABLE category (
id int GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
categoryname text NOT NULL
);
CREATE TABLE spot_opendata (
id bigint GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
category_id int REFERENCES category (id) NOT NULL,
title text NOT NULL,
describe text NOT NULL,
location geometry(point, 4326) NOT NULL,
prefecture text NOT NULL,
municipality text NOT NULL,
pref_muni text GENERATED ALWAYS AS (prefecture || municipality) STORED,
created_at timestamp with time zone DEFAULT timezone('utc'::text, now()) NOT NULL,
updated_at timestamp with time zone DEFAULT timezone('utc'::text, now()) NOT NULL
);
CREATE INDEX spot_location_idx ON spot_opendata USING GIST (location);
CREATE INDEX spot_pref_idx ON spot_opendata (prefecture);
CREATE INDEX spot_muni_idx ON spot_opendata (municipality);
CREATE INDEX spot_pref_muni_idx ON spot_opendata (pref_muni);
```

```sql:CREATE FUNCTION
CREATE OR REPLACE
FUNCTION get_spots(point_latitude double precision, point_longitude double precision, dist_limit int)
RETURNS TABLE (
distance double precision,
category_name text,
title text,
describe text,
latitude double precision,
longitude double precision,
prefecture text,
municipality text
) AS $$
BEGIN
RETURN QUERY
SELECT ((ST_Transform(ST_SetSRID(ST_POINT(point_longitude, point_latitude), 4326), 2163) <-> ST_Transform(spot_opendata.location, 2163)) / 1000),
category.category_name,
spot_opendata.title,
spot_opendata.describe,
ST_Y(spot_opendata.location),
ST_X(spot_opendata.location),
spot_opendata.prefecture,
spot_opendata.municipality
FROM spot_opendata
INNER JOIN category ON spot_opendata.category_id = category.id
WHERE
ST_Transform(ST_SetSRID(ST_POINT(point_longitude, point_latitude), 4326), 2163) <-> ST_Transform(spot_opendata.location, 2163) <= dist_limit
ORDER BY distance;
END;
$$ LANGUAGE plpgsql;
```


- **Insert sample data to Supabase (PostgreSQL DB)**

- [sampleData/supabase/insert_category.sql](sampleData/supabase/insert_category.sql)
- [sampleData/supabase/insert_spot_opendata.sql](sampleData/supabase/insert_spot_opendata.sql)
- Original data : '愛知県文化財マップ(ナビ愛知)' / Aichi prefecture / CC BY 2.1 JP
- このサンプルデータは、以下の著作物を改変して利用しています。
- 愛知県文化財マップ(ナビ愛知)、愛知県、【その他の著作権者】、クリエイティブ・コモンズ・ライセンス 表示2.1日本
- https://www.pref.aichi.jp/soshiki/joho/0000069385.html

4 changes: 2 additions & 2 deletions lib/aws_access.dart
Original file line number Diff line number Diff line change
Expand Up @@ -75,15 +75,15 @@ Future<int?> backupSymbolInfos(AmplifyClass amplify, String backupTitle) async {
final String describe = record.symbolInfo.describe;
final int dateTime = record.symbolInfo.dateTime.millisecondsSinceEpoch;
final double latitude = record.latLng.latitude;
final double longtitude = record.latLng.longitude;
final double longitude = record.latLng.longitude;
final String prefecture = record.symbolInfo.prefMuni.prefecture;
final String municipalities = record.symbolInfo.prefMuni.municipalities;
body += '{"backupTitle": ${jsonEncode(backupTitle)}'
', "id": ${jsonEncode(id)}, "title": ${jsonEncode(title)}'
', "describe": ${jsonEncode(describe)}'
', "dateTime": ${jsonEncode(dateTime)}'
', "latitude": ${jsonEncode(latitude)}'
', "longtitude": ${jsonEncode(longtitude)}'
', "longtitude": ${jsonEncode(longitude)}'
', "prefecture": ${jsonEncode(prefecture)}'
', "municipalities": ${jsonEncode(municipalities)}'
'}, ';
Expand Down
31 changes: 31 additions & 0 deletions lib/class_definition.dart
Original file line number Diff line number Diff line change
Expand Up @@ -132,3 +132,34 @@ class FullConfigExtStyleData {

FullConfigExtStyleData(this.extStyles, this.configureExtStyleSave);
}

// Supabase 設定管理画面に渡す内容一式
class FullConfigSupabaseData {
String supabaseUrl;
String supabaseKey;
Function configureSupabaseSave;

FullConfigSupabaseData(
this.supabaseUrl, this.supabaseKey, this.configureSupabaseSave);
}

// Supabase get_spots の内容
class SpotData {
num distance;
String categoryName;
String title;
String describe;
LatLng latLng;
PrefMuni prefMuni;

SpotData(this.distance, this.categoryName, this.title, this.describe,
this.latLng, this.prefMuni);
}

// 近隣スポット一覧表示画面に渡す内容一式
class NearSpotList {
List<SpotData> spotList;
Function formatLabel;

NearSpotList(this.spotList, this.formatLabel);
}
145 changes: 145 additions & 0 deletions lib/edit_config_supabase_page.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:font_awesome_flutter/font_awesome_flutter.dart';

import 'package:gap/gap.dart';

import 'package:maptool/class_definition.dart';

class EditConfigSupabasePage extends StatefulWidget {
const EditConfigSupabasePage({Key? key}) : super(key: key);

@override
_EditConfigSupabasePageState createState() => _EditConfigSupabasePageState();
}

class _EditConfigSupabasePageState extends State<EditConfigSupabasePage> {
String _supabaseUrl = '';
String _supabaseKey = '';
Function? _configureSupabaseSave;
bool _hidePassword = true;

@override
Widget build(BuildContext context) {
final args =
ModalRoute.of(context)!.settings.arguments as FullConfigSupabaseData;
_supabaseUrl = args.supabaseUrl;
_supabaseKey = args.supabaseKey;
_configureSupabaseSave = args.configureSupabaseSave;
return Scaffold(
appBar: AppBar(
title: const Text('Supabase設定管理'),
),
body: _makeInputForm(),
);
}

// 入力フォームウィジェット
Widget _makeInputForm() {
return Container(
padding: const EdgeInsets.symmetric(horizontal: 10.0),
child: Wrap(
children: <Widget>[
Align(
alignment: Alignment.topCenter,
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
TextFormField(
style: const TextStyle(fontSize: 12),
initialValue: _supabaseUrl,
autofocus: true,
maxLength: 60,
maxLengthEnforcement: MaxLengthEnforcement.none,
decoration: const InputDecoration(
hintText: 'SupabaseのURLがあれば入力してください',
),
maxLines: 1,
onChanged: (String text) => _supabaseUrl = text,
),
TextFormField(
obscureText: _hidePassword,
style: const TextStyle(fontSize: 12),
initialValue: _supabaseKey,
autofocus: true,
maxLength: 160,
maxLengthEnforcement: MaxLengthEnforcement.none,
decoration: InputDecoration(
suffixIcon: IconButton(
icon: Icon(
!_hidePassword
? FontAwesomeIcons.solidEye
: FontAwesomeIcons.solidEyeSlash,
size: 18,
color: Colors.blue),
onPressed: () {
setState(() {
_hidePassword = !_hidePassword;
});
}),
hintText: 'Supabaseのキーがあれば入力してください',
),
maxLines: 1,
onChanged: (String text) => _supabaseKey = text,
),
const Gap(8),
Row(
mainAxisAlignment: MainAxisAlignment.end,
children: <Widget>[
TextButton(
child: const Text('キャンセル'),
onPressed: () {
Navigator.pop(context);
},
),
TextButton(
child: const Text('保存'),
onPressed: () {
_saveConfigDialog(context);
},
),
],
),
],
),
),
],
),
);
}

// 保存(確認ダイアログ)
void _saveConfigDialog(BuildContext context) async {
showDialog(
context: context,
builder: (BuildContext context) => AlertDialog(
title: const Text('確認'),
content: const Text('''保存してもよろしいですか?
※再起動後に有効になります'''),
actions: <Widget>[
TextButton(
child: const Text('いいえ'),
onPressed: () {
Navigator.pop(context);
},
),
TextButton(
child: const Text('はい(保存)'),
onPressed: () {
_saveConfig(context);
},
),
],
),
);
}

// 保存
void _saveConfig(BuildContext context) async {
await _configureSupabaseSave!(
_supabaseUrl,
_supabaseKey,
);
Navigator.popUntil(context, ModalRoute.withName('/'));
}
}
2 changes: 1 addition & 1 deletion lib/list_symbol_page.dart
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ class _ListSymbolPageState extends State<ListSymbolPage> {
// 項目表示ウィジェット
Widget _symbolInfoItem(SymbolInfoWithLatLng symbolInfoWithLatLng) {
final String title =
_formatLabel!(symbolInfoWithLatLng.symbolInfo.title, 15);
_formatLabel!(symbolInfoWithLatLng.symbolInfo.title, 13);
final String prefMuniText =
'${symbolInfoWithLatLng.symbolInfo.prefMuni.prefecture}${symbolInfoWithLatLng.symbolInfo.prefMuni.municipalities}';
final String dateTimeText =
Expand Down
5 changes: 5 additions & 0 deletions lib/main.dart
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import 'package:flutter/material.dart';

import 'package:maptool/edit_config_page.dart';
import 'package:maptool/edit_config_supabase_page.dart';
import 'package:maptool/edit_ext_style_config_page.dart';
import 'package:maptool/edit_symbol_info_page.dart';
import 'package:maptool/display_picture_page.dart';
Expand All @@ -9,6 +10,7 @@ import 'package:maptool/list_symbol_page.dart';
import 'package:maptool/map_page.dart';
import 'package:maptool/restore_data_page.dart';
import 'package:maptool/search_keyword_page.dart';
import 'package:maptool/search_near_spot_page.dart';

final navigatorKey = GlobalKey<NavigatorState>();

Expand All @@ -27,8 +29,11 @@ MaterialApp _materialApp() {
'/displayPicture': (BuildContext context) => const DisplayPicturePage(),
'/listSymbol': (BuildContext context) => const ListSymbolPage(),
'/searchKeyword': (BuildContext context) => const SearchKeywordPage(),
'/searchNearSpot': (BuildContext context) => const SearchNearSpotPage(),
'/restoreData': (BuildContext context) => const RestoreDataPage(),
'/editConfig': (BuildContext context) => const EditConfigPage(),
'/editConfigSupabase': (BuildContext context) =>
const EditConfigSupabasePage(),
'/editExtConfig': (BuildContext context) =>
const EditExtStyleConfigPage(),
},
Expand Down
Loading

0 comments on commit d9542ed

Please sign in to comment.