Fakultas Ilmu Komputer UI

Commit 497b1135 authored by Jovi Handono Hutama's avatar Jovi Handono Hutama
Browse files

Merge branch 'dev-jovi' into 'PBI-9-info_kegiatan'

Pull from development

See merge request !33
parents 6e2f4d27 c6457f94
Pipeline #76880 failed with stages
in 1 minute and 52 seconds
...@@ -10,7 +10,7 @@ stages: ...@@ -10,7 +10,7 @@ stages:
mv $FLUTTER_ENV .env mv $FLUTTER_ENV .env
flutter pub get flutter pub get
image: poipole/bisago-be:latest image: poipole/bisago-be:2.0.5-4.6.0.2311
before_script: before_script:
- *flutter_before_script - *flutter_before_script
......
FROM cirrusci/flutter:latest FROM cirrusci/flutter:2.0.5
ENV SONARSCANNER="https://binaries.sonarsource.com/Distribution/sonar-scanner-cli/sonar-scanner-cli-4.2.0.1873-linux.zip" \
SONAR_SCANNER_CLI_VERSION=4.2.0.1873
ENV SONAR_SCANNER_CLI_VERSION=4.6.0.2311
RUN wget -qO sonar-scanner-cli.zip https://binaries.sonarsource.com/Distribution/sonar-scanner-cli/sonar-scanner-cli-${SONAR_SCANNER_CLI_VERSION}-linux.zip && \ RUN wget -qO sonar-scanner-cli.zip https://binaries.sonarsource.com/Distribution/sonar-scanner-cli/sonar-scanner-cli-${SONAR_SCANNER_CLI_VERSION}-linux.zip && \
unzip sonar-scanner-cli.zip -d /opt && \ unzip sonar-scanner-cli.zip -d /opt && \
rm sonar-scanner-cli.zip && \ rm sonar-scanner-cli.zip && \
chmod +x /opt/sonar-scanner-${SONAR_SCANNER_CLI_VERSION}-linux/bin/sonar-scanner && \ chmod +x /opt/sonar-scanner-${SONAR_SCANNER_CLI_VERSION}-linux/bin/sonar-scanner && \
ln -s /opt/sonar-scanner-${SONAR_SCANNER_CLI_VERSION}-linux/bin/sonar-scanner /usr/local/bin/sonar-scanner ln -s /opt/sonar-scanner-${SONAR_SCANNER_CLI_VERSION}-linux/bin/sonar-scanner /usr/local/bin/sonar-scanner
Add dialog to turn on Location services upon starting the app 3.2.1:
New feature for layanan search - Fix cant update fasilitas
Add feature to upload image for a fasilitas straight from the camera
Add default image for facilities 3.2.0:
Add search history feature - New feature share fasilitas as a link
Now all fields are required in edit profile
\ No newline at end of file 3.1.2:
- Fix google oauth
3.1.1:
- Add dialog to turn on Location services upon starting the app
- New feature for layanan search
- Add feature to upload image for a fasilitas straight from the camera
- Add default image for facilities
- Add search history feature
- Now all fields are required in edit profile
...@@ -23,6 +23,15 @@ class KomentarBloc { ...@@ -23,6 +23,15 @@ class KomentarBloc {
fetchKomentarList(placeId); fetchKomentarList(placeId);
} }
Future<KomentarModel> fetchDetailFasilitas(String placeId, int id) async {
try {
return await _komentarRepository.fetchDetailFasilitas(
placeId, id);
} catch (e) {
return KomentarModel();
}
}
Future<dynamic> addNewKomentar( Future<dynamic> addNewKomentar(
Map<String, dynamic> newKomentarData, String namaLokasi) async { Map<String, dynamic> newKomentarData, String namaLokasi) async {
try { try {
...@@ -33,13 +42,13 @@ class KomentarBloc { ...@@ -33,13 +42,13 @@ class KomentarBloc {
} }
} }
Future<Response> updateKomentar(Map<String, dynamic> newKomentarData, Future<dynamic> updateKomentar(Map<String, dynamic> newKomentarData,
String namaLokasi, int id, String token) async { String placeId, int id) async {
try { try {
return await _komentarRepository.updateKomentar( return await _komentarRepository.updateKomentar(
newKomentarData, namaLokasi, id, token); newKomentarData, placeId, id);
} catch (e) { } catch (e) {
return Response('Failed to update komentar', 400); return {'response': 'FAILED'};
} }
} }
......
...@@ -90,6 +90,12 @@ class BisaGoDrawer extends StatelessWidget { ...@@ -90,6 +90,12 @@ class BisaGoDrawer extends StatelessWidget {
if (snapshot.hasData && if (snapshot.hasData &&
snapshot.data != 'Selamat datang ke BisaGo!') { snapshot.data != 'Selamat datang ke BisaGo!') {
return Container( return Container(
decoration: BoxDecoration(
color: greenPrimary,
border: Border(
bottom: BorderSide(color: Colors.white),
),
),
child: ListTile( child: ListTile(
key: Key(title), key: Key(title),
leading: Icon( leading: Icon(
...@@ -107,18 +113,12 @@ class BisaGoDrawer extends StatelessWidget { ...@@ -107,18 +113,12 @@ class BisaGoDrawer extends StatelessWidget {
), ),
onTap: () async { onTap: () async {
if (title == 'Login') { if (title == 'Login') {
await checkLoginStatus(context); checkLoginStatus(context);
} else if (title == 'Profile') { } else if (title == 'Profile') {
_navigateToProfilePage(context, snapshot.data); _navigateToProfilePage(context, snapshot.data);
} }
}, },
), ),
decoration: BoxDecoration(
color: greenPrimary,
border: Border(
bottom: BorderSide(color: Colors.white),
),
),
); );
} }
return Container(); return Container();
...@@ -126,6 +126,12 @@ class BisaGoDrawer extends StatelessWidget { ...@@ -126,6 +126,12 @@ class BisaGoDrawer extends StatelessWidget {
); );
} }
return Container( return Container(
decoration: BoxDecoration(
color: greenPrimary,
border: Border(
bottom: BorderSide(color: Colors.white),
),
),
child: ListTile( child: ListTile(
key: Key(title), key: Key(title),
leading: Icon( leading: Icon(
...@@ -145,12 +151,6 @@ class BisaGoDrawer extends StatelessWidget { ...@@ -145,12 +151,6 @@ class BisaGoDrawer extends StatelessWidget {
_navigateToPage(context, title); _navigateToPage(context, title);
}, },
), ),
decoration: BoxDecoration(
color: greenPrimary,
border: Border(
bottom: BorderSide(color: Colors.white),
),
),
); );
} }
......
...@@ -39,9 +39,8 @@ class _ImagePreviewHolderState extends State<ImagePreviewHolder> { ...@@ -39,9 +39,8 @@ class _ImagePreviewHolderState extends State<ImagePreviewHolder> {
child: widget.image, child: widget.image,
), ),
const SizedBox(height: regularSpace), const SizedBox(height: regularSpace),
FlatButton( TextButton(
key: const Key('Button Hapus Foto'), key: const Key('Button Hapus Foto'),
padding: EdgeInsets.zero,
onPressed: widget.onPressed, onPressed: widget.onPressed,
child: Container( child: Container(
width: MediaQuery.of(context).size.width * 0.3, width: MediaQuery.of(context).size.width * 0.3,
......
import 'package:bisaGo/repository/kegiatan_repository.dart'; import 'package:bisaGo/repository/kegiatan_repository.dart';
import 'package:bisaGo/repository/komentar_posting_kegiatan_repository.dart'; import 'package:bisaGo/repository/komentar_posting_kegiatan_repository.dart';
import 'package:bisaGo/repository/dynamic_links_service_repository.dart';
import 'package:bisaGo/repository/komentar_posting_repository.dart'; import 'package:bisaGo/repository/komentar_posting_repository.dart';
import 'package:bisaGo/repository/komentar_repository.dart'; import 'package:bisaGo/repository/komentar_repository.dart';
import 'package:bisaGo/repository/komunitas_repository.dart'; import 'package:bisaGo/repository/komunitas_repository.dart';
...@@ -30,5 +31,7 @@ class AppGetIt { ...@@ -30,5 +31,7 @@ class AppGetIt {
() => LayananRepository()); () => LayananRepository());
_getIt.registerLazySingleton<BaseKegiatanRepository>( _getIt.registerLazySingleton<BaseKegiatanRepository>(
() => KegiatanRepository()); () => KegiatanRepository());
_getIt.registerLazySingleton<BaseDynamicLinksServiceRepository>(
() => DynamicLinksServiceRepository());
} }
} }
...@@ -32,16 +32,25 @@ class NetworkInterface { ...@@ -32,16 +32,25 @@ class NetworkInterface {
return responseJson; return responseJson;
} }
Future<dynamic> put({String url}) async { Future<dynamic> put({
String url,
Map<String, dynamic> bodyParams,
bool isLogin,
bool formData = true,
}) async {
var responseJson; var responseJson;
try { try {
final sharedPreferences = await SharedPreferences.getInstance(); if (isLogin) {
dio.options.headers['Authorization'] = final sharedPreferences = await SharedPreferences.getInstance();
dio.options.headers['Authorization'] =
'Token ${sharedPreferences.getString('token')}'; 'Token ${sharedPreferences.getString('token')}';
}
dio.options.headers['content-type'] = 'application/json';
final response = await dio.put( final response = await dio.put(
'${ApiFlavor.getBaseUrl()}$url', '${ApiFlavor.getBaseUrl()}$url',
data: formData ? FormData.fromMap(bodyParams) : json.encode(bodyParams),
); );
responseJson = response.data; responseJson = _response(response);
} on SocketException { } on SocketException {
throw FetchDataException('No Internet Connection'); throw FetchDataException('No Internet Connection');
} on DioError catch (e) { } on DioError catch (e) {
...@@ -77,6 +86,8 @@ class NetworkInterface { ...@@ -77,6 +86,8 @@ class NetworkInterface {
return response.data; return response.data;
case 201: case 201:
return response.data; return response.data;
case 202:
return response.data;
case 400: case 400:
throw BadRequestException(response.data.toString()); throw BadRequestException(response.data.toString());
break; break;
......
...@@ -56,81 +56,82 @@ class _AddLokasiState extends State<AddLokasi> { ...@@ -56,81 +56,82 @@ class _AddLokasiState extends State<AddLokasi> {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return WillPopScope( return WillPopScope(
child: Scaffold( onWillPop: () => Navigator.of(context).pushReplacement(MaterialPageRoute(
resizeToAvoidBottomInset: true, builder: (BuildContext context) => const Pencarian())),
appBar: BisaGoAppBar( child: Scaffold(
title: 'Tambah Lokasi', resizeToAvoidBottomInset: true,
leading: InkWell( appBar: BisaGoAppBar(
child: const Icon(Icons.arrow_back_ios), title: 'Tambah Lokasi',
onTap: () => Navigator.of(context).pushReplacement( leading: InkWell(
MaterialPageRoute( onTap: () => Navigator.of(context).pushReplacement(
builder: (BuildContext context) => const Pencarian()))), MaterialPageRoute(
builder: (BuildContext context) => const Pencarian())),
child: const Icon(Icons.arrow_back_ios),
), ),
body: Stack( ),
children: <Widget>[ body: Stack(
checkAvailabilityofUserLocation(), children: <Widget>[
InkWell( checkAvailabilityofUserLocation(),
key: const Key('InkWell'), InkWell(
onTap: () async { key: const Key('InkWell'),
resetData(); onTap: () async {
final locationPrediction = await PlacesAutocomplete.show( resetData();
final locationPrediction = await PlacesAutocomplete.show(
context: context,
apiKey: DotEnv().env['API_KEY'],
mode: Mode.overlay);
if (locationPrediction != null) {
final placemark = await Geolocator()
.placemarkFromAddress(locationPrediction.description);
final latitude = placemark[0].position.latitude;
final longitude = placemark[0].position.longitude;
final position = LatLng(latitude, longitude);
setState(() {
data['latitude'] = latitude;
data['longitude'] = longitude;
alamatController.text = locationPrediction.description
.split(',')
.sublist(1)
.join();
namaLokasitController.text =
locationPrediction.description.split(',')[0];
markers.add(Marker(
markerId: MarkerId('Selected Location'),
position: position));
});
await mapController.animateCamera(
CameraUpdate.newCameraPosition(
CameraPosition(target: position, zoom: 15),
),
);
await Future.delayed(const Duration(seconds: 1));
await showModalBottomSheet(
context: context, context: context,
apiKey: DotEnv().env['API_KEY'], builder: (context) => addLokasiModal(),
mode: Mode.overlay); backgroundColor: Colors.transparent,
if (locationPrediction != null) { isScrollControlled: true);
final placemark = await Geolocator() }
.placemarkFromAddress(locationPrediction.description); },
final latitude = placemark[0].position.latitude; child: Container(
final longitude = placemark[0].position.longitude; width: double.infinity,
final position = LatLng(latitude, longitude); decoration: BoxDecoration(
setState(() { color: Colors.white,
data['latitude'] = latitude; borderRadius: regularBorderRadius,
data['longitude'] = longitude; boxShadow: regularShadow),
alamatController.text = locationPrediction.description padding: const EdgeInsets.all(doubleSpace),
.split(',') margin: const EdgeInsets.only(
.sublist(1) top: doubleSpace, left: doubleSpace, right: doubleSpace),
.join(); child: const Text(
namaLokasitController.text = 'Cari lokasi yang anda inginkan',
locationPrediction.description.split(',')[0]; style: TextStyle(color: Colors.grey),
markers.add(Marker(
markerId: MarkerId('Selected Location'),
position: position));
});
await mapController.animateCamera(
CameraUpdate.newCameraPosition(
CameraPosition(target: position, zoom: 15),
),
);
await Future.delayed(const Duration(seconds: 1));
await showModalBottomSheet(
context: context,
builder: (context) => addLokasiModal(),
backgroundColor: Colors.transparent,
isScrollControlled: true);
}
},
child: Container(
width: double.infinity,
decoration: BoxDecoration(
color: Colors.white,
borderRadius: regularBorderRadius,
boxShadow: regularShadow),
padding: const EdgeInsets.all(doubleSpace),
margin: const EdgeInsets.only(
top: doubleSpace, left: doubleSpace, right: doubleSpace),
child: const Text(
'Cari lokasi yang anda inginkan',
style: TextStyle(color: Colors.grey),
),
), ),
), ),
if (isLoading) const Center(child: CircularProgressIndicator()) ),
], if (isLoading) const Center(child: CircularProgressIndicator())
), ],
), ),
onWillPop: () => Navigator.of(context).pushReplacement( ),
MaterialPageRoute( );
builder: (BuildContext context) => const Pencarian())));
} }
void onCreated(GoogleMapController controller) { void onCreated(GoogleMapController controller) {
...@@ -283,8 +284,8 @@ class _AddLokasiState extends State<AddLokasi> { ...@@ -283,8 +284,8 @@ class _AddLokasiState extends State<AddLokasi> {
), ),
)), )),
Expanded( Expanded(
child: FlatButton( child: TextButton(
color: greenPrimary, style: TextButton.styleFrom(backgroundColor: greenPrimary),
onPressed: () { onPressed: () {
addLocationToApi(); addLocationToApi();
setState(() { setState(() {
......
...@@ -206,9 +206,9 @@ class AddInformasiState extends State<AddInformasi> { ...@@ -206,9 +206,9 @@ class AddInformasiState extends State<AddInformasi> {
style: TextStyle(fontSize: 18), style: TextStyle(fontSize: 18),
textAlign: TextAlign.left, textAlign: TextAlign.left,
), ),
FlatButton( TextButton(
key: const Key('Button Input Foto Gallery'), key: const Key('Button Input Foto Gallery'),
padding: EdgeInsets.zero, style: TextButton.styleFrom(padding: EdgeInsets.zero),
onPressed: () async { onPressed: () async {
final imageSelected = await _getImage(); final imageSelected = await _getImage();
setState(() { setState(() {
...@@ -240,9 +240,9 @@ class AddInformasiState extends State<AddInformasi> { ...@@ -240,9 +240,9 @@ class AddInformasiState extends State<AddInformasi> {
), ),
), ),
), ),
FlatButton( TextButton(
key: const Key('Button Input Foto Camera'), key: const Key('Button Input Foto Camera'),
padding: EdgeInsets.zero, style: TextButton.styleFrom(padding: EdgeInsets.zero),
onPressed: () async { onPressed: () async {
final imageSelected = await _getCameraImage(); final imageSelected = await _getCameraImage();
setState(() { setState(() {
...@@ -318,10 +318,14 @@ class AddInformasiState extends State<AddInformasi> { ...@@ -318,10 +318,14 @@ class AddInformasiState extends State<AddInformasi> {
decoration: BoxDecoration(boxShadow: regularShadow), decoration: BoxDecoration(boxShadow: regularShadow),
child: ButtonTheme( child: ButtonTheme(
height: 55.0, height: 55.0,
child: FlatButton( child: TextButton(
color: greenPrimary, style: TextButton.styleFrom(
shape: RoundedRectangleBorder( backgroundColor: greenPrimary,
borderRadius: BorderRadius.circular(10.0)), shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10.0)),
padding: const EdgeInsets.symmetric(vertical: 10.0)
),
onPressed: _validateInformationInput,
child: Row( child: Row(
mainAxisAlignment: MainAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center,
children: [ children: [
...@@ -333,8 +337,6 @@ class AddInformasiState extends State<AddInformasi> { ...@@ -333,8 +337,6 @@ class AddInformasiState extends State<AddInformasi> {
color: Colors.white, fontSize: 20.0)), color: Colors.white, fontSize: 20.0)),
], ],
), ),
padding: const EdgeInsets.symmetric(vertical: 10.0),
onPressed: _validateInformationInput,
), ),
)), )),
const SizedBox( const SizedBox(
...@@ -419,7 +421,7 @@ class AddInformasiState extends State<AddInformasi> { ...@@ -419,7 +421,7 @@ class AddInformasiState extends State<AddInformasi> {
.buffer .buffer
.asUint8List(); .asUint8List();
newKomentarData['image'] = newKomentarData['image'] =
await MultipartFile.fromBytes(bytes, filename: 'kursiroda.jpg'); MultipartFile.fromBytes(bytes, filename: 'kursiroda.jpg');
print('Fasilitas null dalem addinfo adalah: ' + _jenisFasilitas); print('Fasilitas null dalem addinfo adalah: ' + _jenisFasilitas);
break; break;
case 'LF': case 'LF':
...@@ -427,103 +429,103 @@ class AddInformasiState extends State<AddInformasi> { ...@@ -427,103 +429,103 @@ class AddInformasiState extends State<AddInformasi> {
(await rootBundle.load('assets/images/liftdisabilitas.jpg')) (await rootBundle.load('assets/images/liftdisabilitas.jpg'))
.buffer .buffer
.asUint8List(); .asUint8List();
newKomentarData['image'] = await MultipartFile.fromBytes(bytes, newKomentarData['image'] =
filename: 'liftdisabilitas.jpg'); MultipartFile.fromBytes(bytes, filename: 'liftdisabilitas.jpg');
break; break;
case 'TD': case 'TD':
var bytes = var bytes =
(await rootBundle.load('assets/images/toiletdisabilitas.jpg')) (await rootBundle.load('assets/images/toiletdisabilitas.jpg'))
.buffer .buffer
.asUint8List(); .asUint8List();
newKomentarData['image'] = await MultipartFile.fromBytes(bytes, newKomentarData['image'] =
filename: 'toiletdisabilitas.jpg'); MultipartFile.fromBytes(bytes, filename: 'toiletdisabilitas.jpg');
break; break;
case 'MM': case 'MM':
var bytes = (await rootBundle.load('assets/images/masjidmushola.jpg')) var bytes = (await rootBundle.load('assets/images/masjidmushola.jpg'))
.buffer .buffer
.asUint8List(); .asUint8List();
newKomentarData['image'] = await MultipartFile.fromBytes(bytes, newKomentarData['image'] =
filename: 'masjidmushola.jpg'); MultipartFile.fromBytes(bytes, filename: 'masjidmushola.jpg');
break; break;
case 'GB': case 'GB':
var bytes = (await rootBundle.load('assets/images/guidingblock.jpg')) var bytes = (await rootBundle.load('assets/images/guidingblock.jpg'))
.buffer .buffer
.asUint8List(); .asUint8List();
newKomentarData['image'] = await MultipartFile.fromBytes(bytes, newKomentarData['image'] =
filename: 'guidingblock.jpg'); MultipartFile.fromBytes(bytes, filename: 'guidingblock.jpg');
break; break;
case 'BM': case 'BM':
var bytes = (await rootBundle.load('assets/images/bidangmiring.jpg')) var bytes = (await rootBundle.load('assets/images/bidangmiring.jpg'))
.buffer .buffer
.asUint8List(); .asUint8List();
newKomentarData['image'] = await MultipartFile.fromBytes(bytes, newKomentarData['image'