|
|
@ -1,37 +1,177 @@ |
|
|
|
# directus_starter |
|
|
|
|
|
|
|
run this project with `flutter -v run -d *chrome* --web-port=28080` |
|
|
|
A starter to bootstrap the creation of Apps synced with a directus API |
|
|
|
the project *must* stay deployable on Android / IOS / WEB / WIN |
|
|
|
Use **GetX** for state management, routing and translating |
|
|
|
|
|
|
|
## Structure |
|
|
|
**Before runing the project be sure to set `apiUrl` in `/lib/globals.dart`** |
|
|
|
|
|
|
|
`@/views/` for app screens and components |
|
|
|
`@/components/` dart files here are not meant to be used, they are here for reference |
|
|
|
`@/store` all state provider |
|
|
|
`@/template` for all the reusables layouts |
|
|
|
run this project with `flutter -v run -d *chrome* --web-port=8085` |
|
|
|
|
|
|
|
## Localization |
|
|
|
## With VSCode |
|
|
|
Create a `launch.json` file in `*root*/.vscode/` : |
|
|
|
``` |
|
|
|
{ |
|
|
|
"version": "0.2.0", |
|
|
|
"configurations": [ |
|
|
|
|
|
|
|
{ |
|
|
|
"name": "Flutter", |
|
|
|
"request": "launch", |
|
|
|
"type": "dart", |
|
|
|
"args": ["-d", "chrome","--web-port", "8085"], |
|
|
|
} |
|
|
|
] |
|
|
|
} |
|
|
|
``` |
|
|
|
|
|
|
|
# Structure |
|
|
|
> "`@`" is shorthand for `project_dir/lib` |
|
|
|
|
|
|
|
- `@/views/` app screens |
|
|
|
- `@/components/` widgets used in view |
|
|
|
- `@/store` state providers |
|
|
|
- `@/template` reusables layouts |
|
|
|
- `@/lang` translations files |
|
|
|
|
|
|
|
# State Management |
|
|
|
State Management is done with Getx ( [GetX doc](https://github.com/jonataslaw/getx) ) |
|
|
|
|
|
|
|
All the data is persisted online throught a Directus API ( [Directus doc](https://docs.directus.io) ) |
|
|
|
|
|
|
|
## Create a controller: |
|
|
|
for a directus collection named **car** |
|
|
|
simply add a file `carsController.dart` in `@/store` : |
|
|
|
|
|
|
|
```dart |
|
|
|
// @/store/carsController.dart |
|
|
|
import 'package:directus_starter/store/itemsController.dart'; |
|
|
|
|
|
|
|
class CarsController extends ItemsController { |
|
|
|
CarsController() |
|
|
|
: super("project", fields: ['*']) { |
|
|
|
return; |
|
|
|
} |
|
|
|
} |
|
|
|
``` |
|
|
|
|
|
|
|
## Display the data: |
|
|
|
|
|
|
|
```dart |
|
|
|
import 'package:flutter/material.dart'; |
|
|
|
import 'package:get/get.dart'; |
|
|
|
import 'package:directus_starter/store/carsController.dart'; |
|
|
|
|
|
|
|
class CarDemo extends StatelessWidget{ |
|
|
|
|
|
|
|
//make the carsController accessible |
|
|
|
final CarsController carsController = Get.put(carsController()); |
|
|
|
|
|
|
|
@override |
|
|
|
Widget build(BuildContext context){ |
|
|
|
return Scaffold( |
|
|
|
appBar: AppBar(...), |
|
|
|
body: Center( |
|
|
|
child: Obx( () => Text(carsController.items[0]["model"]) ) |
|
|
|
) |
|
|
|
) |
|
|
|
} |
|
|
|
} |
|
|
|
``` |
|
|
|
|
|
|
|
`carsController.items` return a `Map<String, dynamic>` that you can use in a `ListView.builder` |
|
|
|
>see `@/views/project.dart` for a real world example |
|
|
|
|
|
|
|
|
|
|
|
## Controller Helpers |
|
|
|
|
|
|
|
```dart |
|
|
|
//getter itemsMppedOnId |
|
|
|
carsController.itemsMappedOnId; |
|
|
|
//return |
|
|
|
Map<String ,dynamic> { |
|
|
|
'car1':{ |
|
|
|
'id': 'car1', |
|
|
|
'model': 'Model X', |
|
|
|
'brand': 'Tesla' |
|
|
|
}, |
|
|
|
'car2':{ |
|
|
|
'id': 'car2', |
|
|
|
'model': 'Model 3', |
|
|
|
'brand': 'Tesla' |
|
|
|
}, |
|
|
|
'car3':{ |
|
|
|
'id': 'car3', |
|
|
|
'model': 'Model S', |
|
|
|
'brand': 'Tesla' |
|
|
|
}, |
|
|
|
} |
|
|
|
|
|
|
|
// imagin you have user that has a relation with a car, the userController will give you the car id so you can access the car entity with: |
|
|
|
|
|
|
|
var carIdOfUser = 'car1'; |
|
|
|
carsController.mappedOnId[carIdOfUser]; |
|
|
|
|
|
|
|
// with function getItemById() |
|
|
|
carController.getItemById(carIdOfUser); |
|
|
|
|
|
|
|
// with function getItemsByIds() |
|
|
|
// if user has multiple cars and relation is a one(user) to many(cars) |
|
|
|
carController.getItemsByIds(['car1', 'car2' ,'car3']); |
|
|
|
|
|
|
|
``` |
|
|
|
|
|
|
|
## Modify the data |
|
|
|
|
|
|
|
```dart |
|
|
|
///# add a car |
|
|
|
|
|
|
|
var newCar = { |
|
|
|
'model': 'Model XXX', |
|
|
|
'brand': 'Tesla' |
|
|
|
} |
|
|
|
// newCar MUST NOT contains an 'id' field, it will be generated by the API |
|
|
|
|
|
|
|
carController.create(newCar) |
|
|
|
// return false if the api reject the new car |
|
|
|
|
|
|
|
|
|
|
|
///# Modify a car |
|
|
|
var updatedCar = { |
|
|
|
'id': carController.item[0].id, |
|
|
|
'brand': 'Hummer', |
|
|
|
} |
|
|
|
//updatedCar MUST contains the id of the item to update |
|
|
|
carController.patch(updatedCar) |
|
|
|
// return false if the api reject the updated car |
|
|
|
|
|
|
|
|
|
|
|
///# delete a car |
|
|
|
//pass only the id of the item to delere |
|
|
|
carController.delete(carController.item[0].id) |
|
|
|
// return false if the api refuse to delete the car |
|
|
|
|
|
|
|
``` |
|
|
|
|
|
|
|
___ |
|
|
|
# Localization |
|
|
|
|
|
|
|
language files are located in `@/lang/` |
|
|
|
locals default values are stored in `@/globals.dart` |
|
|
|
then these values are feeded into the getMaterialApp call in `@/main.dart` |
|
|
|
|
|
|
|
### usage : |
|
|
|
## usage: |
|
|
|
use `Text('key'.tr);` in any widget to get the translated text |
|
|
|
|
|
|
|
#### change local |
|
|
|
## change local: |
|
|
|
```dart |
|
|
|
var locale = Locale('en', 'US'); |
|
|
|
Get.updateLocale(locale); |
|
|
|
``` |
|
|
|
|
|
|
|
#### get system local |
|
|
|
## get system local: |
|
|
|
```dart |
|
|
|
return GetMaterialApp( |
|
|
|
locale: Get.deviceLocale, |
|
|
|
); |
|
|
|
``` |
|
|
|
|
|
|
|
## api |
|
|
|
|
|
|
|
|
|
|
|
## stores |
|
|
|
``` |