mirror of
https://github.com/timokz/flutter-vienna-hackathon-25.git
synced 2025-11-08 18:44:20 +01:00
define quote endpoint
This commit is contained in:
parent
c952f17e30
commit
ff8de67cbb
10 changed files with 614 additions and 132 deletions
|
|
@ -13,13 +13,12 @@ import 'package:serverpod_client/serverpod_client.dart' as _i1;
|
|||
|
||||
abstract class Quote implements _i1.SerializableModel {
|
||||
Quote._({
|
||||
required this.id,
|
||||
this.id,
|
||||
required this.userId,
|
||||
required this.text,
|
||||
this.authorName,
|
||||
required this.lat,
|
||||
required this.lng,
|
||||
required this.geohash,
|
||||
required this.long,
|
||||
required this.createdAt,
|
||||
required this.visibility,
|
||||
required this.upvotes,
|
||||
|
|
@ -28,13 +27,12 @@ abstract class Quote implements _i1.SerializableModel {
|
|||
});
|
||||
|
||||
factory Quote({
|
||||
required int id,
|
||||
int? id,
|
||||
required int userId,
|
||||
required String text,
|
||||
String? authorName,
|
||||
required double lat,
|
||||
required double lng,
|
||||
required String geohash,
|
||||
required double long,
|
||||
required DateTime createdAt,
|
||||
required int visibility,
|
||||
required int upvotes,
|
||||
|
|
@ -44,13 +42,12 @@ abstract class Quote implements _i1.SerializableModel {
|
|||
|
||||
factory Quote.fromJson(Map<String, dynamic> jsonSerialization) {
|
||||
return Quote(
|
||||
id: jsonSerialization['id'] as int,
|
||||
id: jsonSerialization['id'] as int?,
|
||||
userId: jsonSerialization['userId'] as int,
|
||||
text: jsonSerialization['text'] as String,
|
||||
authorName: jsonSerialization['authorName'] as String?,
|
||||
lat: (jsonSerialization['lat'] as num).toDouble(),
|
||||
lng: (jsonSerialization['lng'] as num).toDouble(),
|
||||
geohash: jsonSerialization['geohash'] as String,
|
||||
long: (jsonSerialization['long'] as num).toDouble(),
|
||||
createdAt:
|
||||
_i1.DateTimeJsonExtension.fromJson(jsonSerialization['createdAt']),
|
||||
visibility: jsonSerialization['visibility'] as int,
|
||||
|
|
@ -62,7 +59,10 @@ abstract class Quote implements _i1.SerializableModel {
|
|||
);
|
||||
}
|
||||
|
||||
int id;
|
||||
/// The database id, set if the object has been inserted into the
|
||||
/// database or if it has been fetched from the database. Otherwise,
|
||||
/// the id will be null.
|
||||
int? id;
|
||||
|
||||
int userId;
|
||||
|
||||
|
|
@ -72,9 +72,7 @@ abstract class Quote implements _i1.SerializableModel {
|
|||
|
||||
double lat;
|
||||
|
||||
double lng;
|
||||
|
||||
String geohash;
|
||||
double long;
|
||||
|
||||
DateTime createdAt;
|
||||
|
||||
|
|
@ -95,8 +93,7 @@ abstract class Quote implements _i1.SerializableModel {
|
|||
String? text,
|
||||
String? authorName,
|
||||
double? lat,
|
||||
double? lng,
|
||||
String? geohash,
|
||||
double? long,
|
||||
DateTime? createdAt,
|
||||
int? visibility,
|
||||
int? upvotes,
|
||||
|
|
@ -106,13 +103,12 @@ abstract class Quote implements _i1.SerializableModel {
|
|||
@override
|
||||
Map<String, dynamic> toJson() {
|
||||
return {
|
||||
'id': id,
|
||||
if (id != null) 'id': id,
|
||||
'userId': userId,
|
||||
'text': text,
|
||||
if (authorName != null) 'authorName': authorName,
|
||||
'lat': lat,
|
||||
'lng': lng,
|
||||
'geohash': geohash,
|
||||
'long': long,
|
||||
'createdAt': createdAt.toJson(),
|
||||
'visibility': visibility,
|
||||
'upvotes': upvotes,
|
||||
|
|
@ -131,13 +127,12 @@ class _Undefined {}
|
|||
|
||||
class _QuoteImpl extends Quote {
|
||||
_QuoteImpl({
|
||||
required int id,
|
||||
int? id,
|
||||
required int userId,
|
||||
required String text,
|
||||
String? authorName,
|
||||
required double lat,
|
||||
required double lng,
|
||||
required String geohash,
|
||||
required double long,
|
||||
required DateTime createdAt,
|
||||
required int visibility,
|
||||
required int upvotes,
|
||||
|
|
@ -149,8 +144,7 @@ class _QuoteImpl extends Quote {
|
|||
text: text,
|
||||
authorName: authorName,
|
||||
lat: lat,
|
||||
lng: lng,
|
||||
geohash: geohash,
|
||||
long: long,
|
||||
createdAt: createdAt,
|
||||
visibility: visibility,
|
||||
upvotes: upvotes,
|
||||
|
|
@ -163,13 +157,12 @@ class _QuoteImpl extends Quote {
|
|||
@_i1.useResult
|
||||
@override
|
||||
Quote copyWith({
|
||||
int? id,
|
||||
Object? id = _Undefined,
|
||||
int? userId,
|
||||
String? text,
|
||||
Object? authorName = _Undefined,
|
||||
double? lat,
|
||||
double? lng,
|
||||
String? geohash,
|
||||
double? long,
|
||||
DateTime? createdAt,
|
||||
int? visibility,
|
||||
int? upvotes,
|
||||
|
|
@ -177,13 +170,12 @@ class _QuoteImpl extends Quote {
|
|||
Object? tags = _Undefined,
|
||||
}) {
|
||||
return Quote(
|
||||
id: id ?? this.id,
|
||||
id: id is int? ? id : this.id,
|
||||
userId: userId ?? this.userId,
|
||||
text: text ?? this.text,
|
||||
authorName: authorName is String? ? authorName : this.authorName,
|
||||
lat: lat ?? this.lat,
|
||||
lng: lng ?? this.lng,
|
||||
geohash: geohash ?? this.geohash,
|
||||
long: long ?? this.long,
|
||||
createdAt: createdAt ?? this.createdAt,
|
||||
visibility: visibility ?? this.visibility,
|
||||
upvotes: upvotes ?? this.upvotes,
|
||||
|
|
|
|||
|
|
@ -6,3 +6,4 @@ environment:
|
|||
|
||||
dependencies:
|
||||
serverpod_client: 2.9.1
|
||||
serverpod_auth_server: ^2.9.1
|
||||
|
|
|
|||
|
|
@ -27,6 +27,8 @@ dependencies:
|
|||
serverpod_flutter: 2.9.1
|
||||
wien_talks_client:
|
||||
path: ../wien_talks_client
|
||||
serverpod_auth_shared_flutter: ^2.9.1
|
||||
|
||||
|
||||
|
||||
# The following adds the Cupertino Icons font to your application.
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@
|
|||
// ignore_for_file: no_leading_underscores_for_library_prefixes
|
||||
import 'package:serverpod/serverpod.dart' as _i1;
|
||||
import '../greeting_endpoint.dart' as _i2;
|
||||
import '../quotes/location_endpoint.dart' as _i3;
|
||||
import 'package:serverpod_auth_server/serverpod_auth_server.dart' as _i3;
|
||||
|
||||
class Endpoints extends _i1.EndpointDispatch {
|
||||
@override
|
||||
|
|
@ -22,13 +22,7 @@ class Endpoints extends _i1.EndpointDispatch {
|
|||
server,
|
||||
'greeting',
|
||||
null,
|
||||
),
|
||||
'recipe': _i3.RecipeEndpoint()
|
||||
..initialize(
|
||||
server,
|
||||
'recipe',
|
||||
null,
|
||||
),
|
||||
)
|
||||
};
|
||||
connectors['greeting'] = _i1.EndpointConnector(
|
||||
name: 'greeting',
|
||||
|
|
@ -54,29 +48,6 @@ class Endpoints extends _i1.EndpointDispatch {
|
|||
)
|
||||
},
|
||||
);
|
||||
connectors['recipe'] = _i1.EndpointConnector(
|
||||
name: 'recipe',
|
||||
endpoint: endpoints['recipe']!,
|
||||
methodConnectors: {
|
||||
'postQuote': _i1.MethodConnector(
|
||||
name: 'postQuote',
|
||||
params: {
|
||||
'quote': _i1.ParameterDescription(
|
||||
name: 'quote',
|
||||
type: _i1.getType<String>(),
|
||||
nullable: false,
|
||||
)
|
||||
},
|
||||
call: (
|
||||
_i1.Session session,
|
||||
Map<String, dynamic> params,
|
||||
) async =>
|
||||
(endpoints['recipe'] as _i3.RecipeEndpoint).postQuote(
|
||||
session,
|
||||
params['quote'],
|
||||
),
|
||||
)
|
||||
},
|
||||
);
|
||||
modules['serverpod_auth'] = _i3.Endpoints()..initializeEndpoints(server);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,9 +11,10 @@
|
|||
// ignore_for_file: no_leading_underscores_for_library_prefixes
|
||||
import 'package:serverpod/serverpod.dart' as _i1;
|
||||
import 'package:serverpod/protocol.dart' as _i2;
|
||||
import 'greeting.dart' as _i3;
|
||||
import 'quotes/create_quote.dart' as _i4;
|
||||
import 'quotes/quote.dart' as _i5;
|
||||
import 'package:serverpod_auth_server/serverpod_auth_server.dart' as _i3;
|
||||
import 'greeting.dart' as _i4;
|
||||
import 'quotes/create_quote.dart' as _i5;
|
||||
import 'quotes/quote.dart' as _i6;
|
||||
export 'greeting.dart';
|
||||
export 'quotes/create_quote.dart';
|
||||
export 'quotes/quote.dart';
|
||||
|
|
@ -26,7 +27,100 @@ class Protocol extends _i1.SerializationManagerServer {
|
|||
static final Protocol _instance = Protocol._();
|
||||
|
||||
static final List<_i2.TableDefinition> targetTableDefinitions = [
|
||||
..._i2.Protocol.targetTableDefinitions
|
||||
_i2.TableDefinition(
|
||||
name: 'quote',
|
||||
dartName: 'Quote',
|
||||
schema: 'public',
|
||||
module: 'wien_talks',
|
||||
columns: [
|
||||
_i2.ColumnDefinition(
|
||||
name: 'id',
|
||||
columnType: _i2.ColumnType.bigint,
|
||||
isNullable: false,
|
||||
dartType: 'int?',
|
||||
columnDefault: 'nextval(\'quote_id_seq\'::regclass)',
|
||||
),
|
||||
_i2.ColumnDefinition(
|
||||
name: 'userId',
|
||||
columnType: _i2.ColumnType.bigint,
|
||||
isNullable: false,
|
||||
dartType: 'int',
|
||||
),
|
||||
_i2.ColumnDefinition(
|
||||
name: 'text',
|
||||
columnType: _i2.ColumnType.text,
|
||||
isNullable: false,
|
||||
dartType: 'String',
|
||||
),
|
||||
_i2.ColumnDefinition(
|
||||
name: 'authorName',
|
||||
columnType: _i2.ColumnType.text,
|
||||
isNullable: true,
|
||||
dartType: 'String?',
|
||||
),
|
||||
_i2.ColumnDefinition(
|
||||
name: 'lat',
|
||||
columnType: _i2.ColumnType.doublePrecision,
|
||||
isNullable: false,
|
||||
dartType: 'double',
|
||||
),
|
||||
_i2.ColumnDefinition(
|
||||
name: 'long',
|
||||
columnType: _i2.ColumnType.doublePrecision,
|
||||
isNullable: false,
|
||||
dartType: 'double',
|
||||
),
|
||||
_i2.ColumnDefinition(
|
||||
name: 'createdAt',
|
||||
columnType: _i2.ColumnType.timestampWithoutTimeZone,
|
||||
isNullable: false,
|
||||
dartType: 'DateTime',
|
||||
),
|
||||
_i2.ColumnDefinition(
|
||||
name: 'visibility',
|
||||
columnType: _i2.ColumnType.bigint,
|
||||
isNullable: false,
|
||||
dartType: 'int',
|
||||
),
|
||||
_i2.ColumnDefinition(
|
||||
name: 'upvotes',
|
||||
columnType: _i2.ColumnType.bigint,
|
||||
isNullable: false,
|
||||
dartType: 'int',
|
||||
),
|
||||
_i2.ColumnDefinition(
|
||||
name: 'downvotes',
|
||||
columnType: _i2.ColumnType.bigint,
|
||||
isNullable: false,
|
||||
dartType: 'int',
|
||||
),
|
||||
_i2.ColumnDefinition(
|
||||
name: 'tags',
|
||||
columnType: _i2.ColumnType.json,
|
||||
isNullable: true,
|
||||
dartType: 'List<String>?',
|
||||
),
|
||||
],
|
||||
foreignKeys: [],
|
||||
indexes: [
|
||||
_i2.IndexDefinition(
|
||||
indexName: 'quote_pkey',
|
||||
tableSpace: null,
|
||||
elements: [
|
||||
_i2.IndexElementDefinition(
|
||||
type: _i2.IndexElementDefinitionType.column,
|
||||
definition: 'id',
|
||||
)
|
||||
],
|
||||
type: 'btree',
|
||||
isUnique: true,
|
||||
isPrimary: true,
|
||||
)
|
||||
],
|
||||
managed: true,
|
||||
),
|
||||
..._i3.Protocol.targetTableDefinitions,
|
||||
..._i2.Protocol.targetTableDefinitions,
|
||||
];
|
||||
|
||||
@override
|
||||
|
|
@ -35,23 +129,23 @@ class Protocol extends _i1.SerializationManagerServer {
|
|||
Type? t,
|
||||
]) {
|
||||
t ??= T;
|
||||
if (t == _i3.Greeting) {
|
||||
return _i3.Greeting.fromJson(data) as T;
|
||||
if (t == _i4.Greeting) {
|
||||
return _i4.Greeting.fromJson(data) as T;
|
||||
}
|
||||
if (t == _i4.CreateQuoteRequest) {
|
||||
return _i4.CreateQuoteRequest.fromJson(data) as T;
|
||||
if (t == _i5.CreateQuoteRequest) {
|
||||
return _i5.CreateQuoteRequest.fromJson(data) as T;
|
||||
}
|
||||
if (t == _i5.Quote) {
|
||||
return _i5.Quote.fromJson(data) as T;
|
||||
if (t == _i6.Quote) {
|
||||
return _i6.Quote.fromJson(data) as T;
|
||||
}
|
||||
if (t == _i1.getType<_i3.Greeting?>()) {
|
||||
return (data != null ? _i3.Greeting.fromJson(data) : null) as T;
|
||||
if (t == _i1.getType<_i4.Greeting?>()) {
|
||||
return (data != null ? _i4.Greeting.fromJson(data) : null) as T;
|
||||
}
|
||||
if (t == _i1.getType<_i4.CreateQuoteRequest?>()) {
|
||||
return (data != null ? _i4.CreateQuoteRequest.fromJson(data) : null) as T;
|
||||
if (t == _i1.getType<_i5.CreateQuoteRequest?>()) {
|
||||
return (data != null ? _i5.CreateQuoteRequest.fromJson(data) : null) as T;
|
||||
}
|
||||
if (t == _i1.getType<_i5.Quote?>()) {
|
||||
return (data != null ? _i5.Quote.fromJson(data) : null) as T;
|
||||
if (t == _i1.getType<_i6.Quote?>()) {
|
||||
return (data != null ? _i6.Quote.fromJson(data) : null) as T;
|
||||
}
|
||||
if (t == _i1.getType<List<String>?>()) {
|
||||
return (data != null
|
||||
|
|
@ -63,6 +157,9 @@ class Protocol extends _i1.SerializationManagerServer {
|
|||
? (data as List).map((e) => deserialize<String>(e)).toList()
|
||||
: null) as T;
|
||||
}
|
||||
try {
|
||||
return _i3.Protocol().deserialize<T>(data, t);
|
||||
} on _i1.DeserializationTypeNotFoundException catch (_) {}
|
||||
try {
|
||||
return _i2.Protocol().deserialize<T>(data, t);
|
||||
} on _i1.DeserializationTypeNotFoundException catch (_) {}
|
||||
|
|
@ -73,19 +170,23 @@ class Protocol extends _i1.SerializationManagerServer {
|
|||
String? getClassNameForObject(Object? data) {
|
||||
String? className = super.getClassNameForObject(data);
|
||||
if (className != null) return className;
|
||||
if (data is _i3.Greeting) {
|
||||
if (data is _i4.Greeting) {
|
||||
return 'Greeting';
|
||||
}
|
||||
if (data is _i4.CreateQuoteRequest) {
|
||||
if (data is _i5.CreateQuoteRequest) {
|
||||
return 'CreateQuoteRequest';
|
||||
}
|
||||
if (data is _i5.Quote) {
|
||||
if (data is _i6.Quote) {
|
||||
return 'Quote';
|
||||
}
|
||||
className = _i2.Protocol().getClassNameForObject(data);
|
||||
if (className != null) {
|
||||
return 'serverpod.$className';
|
||||
}
|
||||
className = _i3.Protocol().getClassNameForObject(data);
|
||||
if (className != null) {
|
||||
return 'serverpod_auth.$className';
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
|
@ -96,29 +197,43 @@ class Protocol extends _i1.SerializationManagerServer {
|
|||
return super.deserializeByClassName(data);
|
||||
}
|
||||
if (dataClassName == 'Greeting') {
|
||||
return deserialize<_i3.Greeting>(data['data']);
|
||||
return deserialize<_i4.Greeting>(data['data']);
|
||||
}
|
||||
if (dataClassName == 'CreateQuoteRequest') {
|
||||
return deserialize<_i4.CreateQuoteRequest>(data['data']);
|
||||
return deserialize<_i5.CreateQuoteRequest>(data['data']);
|
||||
}
|
||||
if (dataClassName == 'Quote') {
|
||||
return deserialize<_i5.Quote>(data['data']);
|
||||
return deserialize<_i6.Quote>(data['data']);
|
||||
}
|
||||
if (dataClassName.startsWith('serverpod.')) {
|
||||
data['className'] = dataClassName.substring(10);
|
||||
return _i2.Protocol().deserializeByClassName(data);
|
||||
}
|
||||
if (dataClassName.startsWith('serverpod_auth.')) {
|
||||
data['className'] = dataClassName.substring(15);
|
||||
return _i3.Protocol().deserializeByClassName(data);
|
||||
}
|
||||
return super.deserializeByClassName(data);
|
||||
}
|
||||
|
||||
@override
|
||||
_i1.Table? getTableForType(Type t) {
|
||||
{
|
||||
var table = _i3.Protocol().getTableForType(t);
|
||||
if (table != null) {
|
||||
return table;
|
||||
}
|
||||
}
|
||||
{
|
||||
var table = _i2.Protocol().getTableForType(t);
|
||||
if (table != null) {
|
||||
return table;
|
||||
}
|
||||
}
|
||||
switch (t) {
|
||||
case _i6.Quote:
|
||||
return _i6.Quote.t;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -11,16 +11,14 @@
|
|||
// ignore_for_file: no_leading_underscores_for_library_prefixes
|
||||
import 'package:serverpod/serverpod.dart' as _i1;
|
||||
|
||||
abstract class Quote
|
||||
implements _i1.SerializableModel, _i1.ProtocolSerialization {
|
||||
abstract class Quote implements _i1.TableRow<int?>, _i1.ProtocolSerialization {
|
||||
Quote._({
|
||||
required this.id,
|
||||
this.id,
|
||||
required this.userId,
|
||||
required this.text,
|
||||
this.authorName,
|
||||
required this.lat,
|
||||
required this.lng,
|
||||
required this.geohash,
|
||||
required this.long,
|
||||
required this.createdAt,
|
||||
required this.visibility,
|
||||
required this.upvotes,
|
||||
|
|
@ -29,13 +27,12 @@ abstract class Quote
|
|||
});
|
||||
|
||||
factory Quote({
|
||||
required int id,
|
||||
int? id,
|
||||
required int userId,
|
||||
required String text,
|
||||
String? authorName,
|
||||
required double lat,
|
||||
required double lng,
|
||||
required String geohash,
|
||||
required double long,
|
||||
required DateTime createdAt,
|
||||
required int visibility,
|
||||
required int upvotes,
|
||||
|
|
@ -45,13 +42,12 @@ abstract class Quote
|
|||
|
||||
factory Quote.fromJson(Map<String, dynamic> jsonSerialization) {
|
||||
return Quote(
|
||||
id: jsonSerialization['id'] as int,
|
||||
id: jsonSerialization['id'] as int?,
|
||||
userId: jsonSerialization['userId'] as int,
|
||||
text: jsonSerialization['text'] as String,
|
||||
authorName: jsonSerialization['authorName'] as String?,
|
||||
lat: (jsonSerialization['lat'] as num).toDouble(),
|
||||
lng: (jsonSerialization['lng'] as num).toDouble(),
|
||||
geohash: jsonSerialization['geohash'] as String,
|
||||
long: (jsonSerialization['long'] as num).toDouble(),
|
||||
createdAt:
|
||||
_i1.DateTimeJsonExtension.fromJson(jsonSerialization['createdAt']),
|
||||
visibility: jsonSerialization['visibility'] as int,
|
||||
|
|
@ -63,7 +59,12 @@ abstract class Quote
|
|||
);
|
||||
}
|
||||
|
||||
int id;
|
||||
static final t = QuoteTable();
|
||||
|
||||
static const db = QuoteRepository._();
|
||||
|
||||
@override
|
||||
int? id;
|
||||
|
||||
int userId;
|
||||
|
||||
|
|
@ -73,9 +74,7 @@ abstract class Quote
|
|||
|
||||
double lat;
|
||||
|
||||
double lng;
|
||||
|
||||
String geohash;
|
||||
double long;
|
||||
|
||||
DateTime createdAt;
|
||||
|
||||
|
|
@ -87,6 +86,9 @@ abstract class Quote
|
|||
|
||||
List<String>? tags;
|
||||
|
||||
@override
|
||||
_i1.Table<int?> get table => t;
|
||||
|
||||
/// Returns a shallow copy of this [Quote]
|
||||
/// with some or all fields replaced by the given arguments.
|
||||
@_i1.useResult
|
||||
|
|
@ -96,8 +98,7 @@ abstract class Quote
|
|||
String? text,
|
||||
String? authorName,
|
||||
double? lat,
|
||||
double? lng,
|
||||
String? geohash,
|
||||
double? long,
|
||||
DateTime? createdAt,
|
||||
int? visibility,
|
||||
int? upvotes,
|
||||
|
|
@ -107,13 +108,12 @@ abstract class Quote
|
|||
@override
|
||||
Map<String, dynamic> toJson() {
|
||||
return {
|
||||
'id': id,
|
||||
if (id != null) 'id': id,
|
||||
'userId': userId,
|
||||
'text': text,
|
||||
if (authorName != null) 'authorName': authorName,
|
||||
'lat': lat,
|
||||
'lng': lng,
|
||||
'geohash': geohash,
|
||||
'long': long,
|
||||
'createdAt': createdAt.toJson(),
|
||||
'visibility': visibility,
|
||||
'upvotes': upvotes,
|
||||
|
|
@ -125,13 +125,12 @@ abstract class Quote
|
|||
@override
|
||||
Map<String, dynamic> toJsonForProtocol() {
|
||||
return {
|
||||
'id': id,
|
||||
if (id != null) 'id': id,
|
||||
'userId': userId,
|
||||
'text': text,
|
||||
if (authorName != null) 'authorName': authorName,
|
||||
'lat': lat,
|
||||
'lng': lng,
|
||||
'geohash': geohash,
|
||||
'long': long,
|
||||
'createdAt': createdAt.toJson(),
|
||||
'visibility': visibility,
|
||||
'upvotes': upvotes,
|
||||
|
|
@ -140,6 +139,30 @@ abstract class Quote
|
|||
};
|
||||
}
|
||||
|
||||
static QuoteInclude include() {
|
||||
return QuoteInclude._();
|
||||
}
|
||||
|
||||
static QuoteIncludeList includeList({
|
||||
_i1.WhereExpressionBuilder<QuoteTable>? where,
|
||||
int? limit,
|
||||
int? offset,
|
||||
_i1.OrderByBuilder<QuoteTable>? orderBy,
|
||||
bool orderDescending = false,
|
||||
_i1.OrderByListBuilder<QuoteTable>? orderByList,
|
||||
QuoteInclude? include,
|
||||
}) {
|
||||
return QuoteIncludeList._(
|
||||
where: where,
|
||||
limit: limit,
|
||||
offset: offset,
|
||||
orderBy: orderBy?.call(Quote.t),
|
||||
orderDescending: orderDescending,
|
||||
orderByList: orderByList?.call(Quote.t),
|
||||
include: include,
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return _i1.SerializationManager.encode(this);
|
||||
|
|
@ -150,13 +173,12 @@ class _Undefined {}
|
|||
|
||||
class _QuoteImpl extends Quote {
|
||||
_QuoteImpl({
|
||||
required int id,
|
||||
int? id,
|
||||
required int userId,
|
||||
required String text,
|
||||
String? authorName,
|
||||
required double lat,
|
||||
required double lng,
|
||||
required String geohash,
|
||||
required double long,
|
||||
required DateTime createdAt,
|
||||
required int visibility,
|
||||
required int upvotes,
|
||||
|
|
@ -168,8 +190,7 @@ class _QuoteImpl extends Quote {
|
|||
text: text,
|
||||
authorName: authorName,
|
||||
lat: lat,
|
||||
lng: lng,
|
||||
geohash: geohash,
|
||||
long: long,
|
||||
createdAt: createdAt,
|
||||
visibility: visibility,
|
||||
upvotes: upvotes,
|
||||
|
|
@ -182,13 +203,12 @@ class _QuoteImpl extends Quote {
|
|||
@_i1.useResult
|
||||
@override
|
||||
Quote copyWith({
|
||||
int? id,
|
||||
Object? id = _Undefined,
|
||||
int? userId,
|
||||
String? text,
|
||||
Object? authorName = _Undefined,
|
||||
double? lat,
|
||||
double? lng,
|
||||
String? geohash,
|
||||
double? long,
|
||||
DateTime? createdAt,
|
||||
int? visibility,
|
||||
int? upvotes,
|
||||
|
|
@ -196,13 +216,12 @@ class _QuoteImpl extends Quote {
|
|||
Object? tags = _Undefined,
|
||||
}) {
|
||||
return Quote(
|
||||
id: id ?? this.id,
|
||||
id: id is int? ? id : this.id,
|
||||
userId: userId ?? this.userId,
|
||||
text: text ?? this.text,
|
||||
authorName: authorName is String? ? authorName : this.authorName,
|
||||
lat: lat ?? this.lat,
|
||||
lng: lng ?? this.lng,
|
||||
geohash: geohash ?? this.geohash,
|
||||
long: long ?? this.long,
|
||||
createdAt: createdAt ?? this.createdAt,
|
||||
visibility: visibility ?? this.visibility,
|
||||
upvotes: upvotes ?? this.upvotes,
|
||||
|
|
@ -211,3 +230,326 @@ class _QuoteImpl extends Quote {
|
|||
);
|
||||
}
|
||||
}
|
||||
|
||||
class QuoteTable extends _i1.Table<int?> {
|
||||
QuoteTable({super.tableRelation}) : super(tableName: 'quote') {
|
||||
userId = _i1.ColumnInt(
|
||||
'userId',
|
||||
this,
|
||||
);
|
||||
text = _i1.ColumnString(
|
||||
'text',
|
||||
this,
|
||||
);
|
||||
authorName = _i1.ColumnString(
|
||||
'authorName',
|
||||
this,
|
||||
);
|
||||
lat = _i1.ColumnDouble(
|
||||
'lat',
|
||||
this,
|
||||
);
|
||||
long = _i1.ColumnDouble(
|
||||
'long',
|
||||
this,
|
||||
);
|
||||
createdAt = _i1.ColumnDateTime(
|
||||
'createdAt',
|
||||
this,
|
||||
);
|
||||
visibility = _i1.ColumnInt(
|
||||
'visibility',
|
||||
this,
|
||||
);
|
||||
upvotes = _i1.ColumnInt(
|
||||
'upvotes',
|
||||
this,
|
||||
);
|
||||
downvotes = _i1.ColumnInt(
|
||||
'downvotes',
|
||||
this,
|
||||
);
|
||||
tags = _i1.ColumnSerializable(
|
||||
'tags',
|
||||
this,
|
||||
);
|
||||
}
|
||||
|
||||
late final _i1.ColumnInt userId;
|
||||
|
||||
late final _i1.ColumnString text;
|
||||
|
||||
late final _i1.ColumnString authorName;
|
||||
|
||||
late final _i1.ColumnDouble lat;
|
||||
|
||||
late final _i1.ColumnDouble long;
|
||||
|
||||
late final _i1.ColumnDateTime createdAt;
|
||||
|
||||
late final _i1.ColumnInt visibility;
|
||||
|
||||
late final _i1.ColumnInt upvotes;
|
||||
|
||||
late final _i1.ColumnInt downvotes;
|
||||
|
||||
late final _i1.ColumnSerializable tags;
|
||||
|
||||
@override
|
||||
List<_i1.Column> get columns => [
|
||||
id,
|
||||
userId,
|
||||
text,
|
||||
authorName,
|
||||
lat,
|
||||
long,
|
||||
createdAt,
|
||||
visibility,
|
||||
upvotes,
|
||||
downvotes,
|
||||
tags,
|
||||
];
|
||||
}
|
||||
|
||||
class QuoteInclude extends _i1.IncludeObject {
|
||||
QuoteInclude._();
|
||||
|
||||
@override
|
||||
Map<String, _i1.Include?> get includes => {};
|
||||
|
||||
@override
|
||||
_i1.Table<int?> get table => Quote.t;
|
||||
}
|
||||
|
||||
class QuoteIncludeList extends _i1.IncludeList {
|
||||
QuoteIncludeList._({
|
||||
_i1.WhereExpressionBuilder<QuoteTable>? where,
|
||||
super.limit,
|
||||
super.offset,
|
||||
super.orderBy,
|
||||
super.orderDescending,
|
||||
super.orderByList,
|
||||
super.include,
|
||||
}) {
|
||||
super.where = where?.call(Quote.t);
|
||||
}
|
||||
|
||||
@override
|
||||
Map<String, _i1.Include?> get includes => include?.includes ?? {};
|
||||
|
||||
@override
|
||||
_i1.Table<int?> get table => Quote.t;
|
||||
}
|
||||
|
||||
class QuoteRepository {
|
||||
const QuoteRepository._();
|
||||
|
||||
/// Returns a list of [Quote]s matching the given query parameters.
|
||||
///
|
||||
/// Use [where] to specify which items to include in the return value.
|
||||
/// If none is specified, all items will be returned.
|
||||
///
|
||||
/// To specify the order of the items use [orderBy] or [orderByList]
|
||||
/// when sorting by multiple columns.
|
||||
///
|
||||
/// The maximum number of items can be set by [limit]. If no limit is set,
|
||||
/// all items matching the query will be returned.
|
||||
///
|
||||
/// [offset] defines how many items to skip, after which [limit] (or all)
|
||||
/// items are read from the database.
|
||||
///
|
||||
/// ```dart
|
||||
/// var persons = await Persons.db.find(
|
||||
/// session,
|
||||
/// where: (t) => t.lastName.equals('Jones'),
|
||||
/// orderBy: (t) => t.firstName,
|
||||
/// limit: 100,
|
||||
/// );
|
||||
/// ```
|
||||
Future<List<Quote>> find(
|
||||
_i1.Session session, {
|
||||
_i1.WhereExpressionBuilder<QuoteTable>? where,
|
||||
int? limit,
|
||||
int? offset,
|
||||
_i1.OrderByBuilder<QuoteTable>? orderBy,
|
||||
bool orderDescending = false,
|
||||
_i1.OrderByListBuilder<QuoteTable>? orderByList,
|
||||
_i1.Transaction? transaction,
|
||||
}) async {
|
||||
return session.db.find<Quote>(
|
||||
where: where?.call(Quote.t),
|
||||
orderBy: orderBy?.call(Quote.t),
|
||||
orderByList: orderByList?.call(Quote.t),
|
||||
orderDescending: orderDescending,
|
||||
limit: limit,
|
||||
offset: offset,
|
||||
transaction: transaction,
|
||||
);
|
||||
}
|
||||
|
||||
/// Returns the first matching [Quote] matching the given query parameters.
|
||||
///
|
||||
/// Use [where] to specify which items to include in the return value.
|
||||
/// If none is specified, all items will be returned.
|
||||
///
|
||||
/// To specify the order use [orderBy] or [orderByList]
|
||||
/// when sorting by multiple columns.
|
||||
///
|
||||
/// [offset] defines how many items to skip, after which the next one will be picked.
|
||||
///
|
||||
/// ```dart
|
||||
/// var youngestPerson = await Persons.db.findFirstRow(
|
||||
/// session,
|
||||
/// where: (t) => t.lastName.equals('Jones'),
|
||||
/// orderBy: (t) => t.age,
|
||||
/// );
|
||||
/// ```
|
||||
Future<Quote?> findFirstRow(
|
||||
_i1.Session session, {
|
||||
_i1.WhereExpressionBuilder<QuoteTable>? where,
|
||||
int? offset,
|
||||
_i1.OrderByBuilder<QuoteTable>? orderBy,
|
||||
bool orderDescending = false,
|
||||
_i1.OrderByListBuilder<QuoteTable>? orderByList,
|
||||
_i1.Transaction? transaction,
|
||||
}) async {
|
||||
return session.db.findFirstRow<Quote>(
|
||||
where: where?.call(Quote.t),
|
||||
orderBy: orderBy?.call(Quote.t),
|
||||
orderByList: orderByList?.call(Quote.t),
|
||||
orderDescending: orderDescending,
|
||||
offset: offset,
|
||||
transaction: transaction,
|
||||
);
|
||||
}
|
||||
|
||||
/// Finds a single [Quote] by its [id] or null if no such row exists.
|
||||
Future<Quote?> findById(
|
||||
_i1.Session session,
|
||||
int id, {
|
||||
_i1.Transaction? transaction,
|
||||
}) async {
|
||||
return session.db.findById<Quote>(
|
||||
id,
|
||||
transaction: transaction,
|
||||
);
|
||||
}
|
||||
|
||||
/// Inserts all [Quote]s in the list and returns the inserted rows.
|
||||
///
|
||||
/// The returned [Quote]s will have their `id` fields set.
|
||||
///
|
||||
/// This is an atomic operation, meaning that if one of the rows fails to
|
||||
/// insert, none of the rows will be inserted.
|
||||
Future<List<Quote>> insert(
|
||||
_i1.Session session,
|
||||
List<Quote> rows, {
|
||||
_i1.Transaction? transaction,
|
||||
}) async {
|
||||
return session.db.insert<Quote>(
|
||||
rows,
|
||||
transaction: transaction,
|
||||
);
|
||||
}
|
||||
|
||||
/// Inserts a single [Quote] and returns the inserted row.
|
||||
///
|
||||
/// The returned [Quote] will have its `id` field set.
|
||||
Future<Quote> insertRow(
|
||||
_i1.Session session,
|
||||
Quote row, {
|
||||
_i1.Transaction? transaction,
|
||||
}) async {
|
||||
return session.db.insertRow<Quote>(
|
||||
row,
|
||||
transaction: transaction,
|
||||
);
|
||||
}
|
||||
|
||||
/// Updates all [Quote]s in the list and returns the updated rows. If
|
||||
/// [columns] is provided, only those columns will be updated. Defaults to
|
||||
/// all columns.
|
||||
/// This is an atomic operation, meaning that if one of the rows fails to
|
||||
/// update, none of the rows will be updated.
|
||||
Future<List<Quote>> update(
|
||||
_i1.Session session,
|
||||
List<Quote> rows, {
|
||||
_i1.ColumnSelections<QuoteTable>? columns,
|
||||
_i1.Transaction? transaction,
|
||||
}) async {
|
||||
return session.db.update<Quote>(
|
||||
rows,
|
||||
columns: columns?.call(Quote.t),
|
||||
transaction: transaction,
|
||||
);
|
||||
}
|
||||
|
||||
/// Updates a single [Quote]. The row needs to have its id set.
|
||||
/// Optionally, a list of [columns] can be provided to only update those
|
||||
/// columns. Defaults to all columns.
|
||||
Future<Quote> updateRow(
|
||||
_i1.Session session,
|
||||
Quote row, {
|
||||
_i1.ColumnSelections<QuoteTable>? columns,
|
||||
_i1.Transaction? transaction,
|
||||
}) async {
|
||||
return session.db.updateRow<Quote>(
|
||||
row,
|
||||
columns: columns?.call(Quote.t),
|
||||
transaction: transaction,
|
||||
);
|
||||
}
|
||||
|
||||
/// Deletes all [Quote]s in the list and returns the deleted rows.
|
||||
/// This is an atomic operation, meaning that if one of the rows fail to
|
||||
/// be deleted, none of the rows will be deleted.
|
||||
Future<List<Quote>> delete(
|
||||
_i1.Session session,
|
||||
List<Quote> rows, {
|
||||
_i1.Transaction? transaction,
|
||||
}) async {
|
||||
return session.db.delete<Quote>(
|
||||
rows,
|
||||
transaction: transaction,
|
||||
);
|
||||
}
|
||||
|
||||
/// Deletes a single [Quote].
|
||||
Future<Quote> deleteRow(
|
||||
_i1.Session session,
|
||||
Quote row, {
|
||||
_i1.Transaction? transaction,
|
||||
}) async {
|
||||
return session.db.deleteRow<Quote>(
|
||||
row,
|
||||
transaction: transaction,
|
||||
);
|
||||
}
|
||||
|
||||
/// Deletes all rows matching the [where] expression.
|
||||
Future<List<Quote>> deleteWhere(
|
||||
_i1.Session session, {
|
||||
required _i1.WhereExpressionBuilder<QuoteTable> where,
|
||||
_i1.Transaction? transaction,
|
||||
}) async {
|
||||
return session.db.deleteWhere<Quote>(
|
||||
where: where(Quote.t),
|
||||
transaction: transaction,
|
||||
);
|
||||
}
|
||||
|
||||
/// Counts the number of rows matching the [where] expression. If omitted,
|
||||
/// will return the count of all rows in the table.
|
||||
Future<int> count(
|
||||
_i1.Session session, {
|
||||
_i1.WhereExpressionBuilder<QuoteTable>? where,
|
||||
int? limit,
|
||||
_i1.Transaction? transaction,
|
||||
}) async {
|
||||
return session.db.count<Quote>(
|
||||
where: where?.call(Quote.t),
|
||||
limit: limit,
|
||||
transaction: transaction,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,12 +0,0 @@
|
|||
import 'dart:async';
|
||||
|
||||
import 'package:serverpod/serverpod.dart';
|
||||
|
||||
class RecipeEndpoint extends Endpoint {
|
||||
Future<String> postQuote(Session session, String quote) async {
|
||||
// validate content
|
||||
|
||||
// persist quote
|
||||
return Future.value('none');
|
||||
}
|
||||
}
|
||||
|
|
@ -1,12 +1,12 @@
|
|||
class: Quote
|
||||
table: quote
|
||||
fields:
|
||||
id: int
|
||||
id: int?
|
||||
userId: int
|
||||
text: String
|
||||
authorName: String?
|
||||
lat: double
|
||||
lng: double
|
||||
geohash: String
|
||||
long: double
|
||||
createdAt: DateTime
|
||||
visibility: int
|
||||
upvotes: int
|
||||
|
|
|
|||
|
|
@ -0,0 +1,28 @@
|
|||
import 'package:serverpod/serverpod.dart';
|
||||
import 'package:wien_talks_server/src/generated/protocol.dart';
|
||||
|
||||
String validateQuote(CreateQuoteRequest req) {
|
||||
final text = req.text.trim();
|
||||
if (text.isEmpty || text.length > 500) {
|
||||
throw FormatException('Text must be 1..500 chars');
|
||||
}
|
||||
if (req.lat.isNaN || req.lng.isNaN) {
|
||||
throw FormatException('Invalid coordinates');
|
||||
}
|
||||
if (req.lat < -90 || req.lat > 90 || req.lng < -180 || req.lng > 180) {
|
||||
throw FormatException('Coordinates out of bounds');
|
||||
}
|
||||
return text;
|
||||
}
|
||||
|
||||
Future<List<Quote>> listNearby(
|
||||
Session session, {
|
||||
required double lat,
|
||||
required double lng,
|
||||
int radiusMeters = 1500,
|
||||
int limit = 50,
|
||||
}) async {
|
||||
throw UnimplementedError();
|
||||
}
|
||||
|
||||
enum Visibility { public, private, locallyPublic }
|
||||
|
|
@ -0,0 +1,43 @@
|
|||
import 'package:serverpod/serverpod.dart';
|
||||
import 'package:wien_talks_server/src/generated/protocol.dart';
|
||||
import 'package:wien_talks_server/src/quotes/quote_controller.dart';
|
||||
|
||||
class QuoteEndpoint extends Endpoint {
|
||||
Future<Quote> create(Session session, CreateQuoteRequest req) async {
|
||||
final authInfo = await session.authenticated;
|
||||
final userId = authInfo?.userId;
|
||||
|
||||
if (userId == null) {
|
||||
throw Exception('Not signed in');
|
||||
}
|
||||
|
||||
String text = validateQuote(req);
|
||||
|
||||
final quote = Quote(
|
||||
id: 0,
|
||||
userId: userId,
|
||||
text: text,
|
||||
authorName: req.authorName?.trim().isEmpty == true
|
||||
? null
|
||||
: req.authorName!.trim(),
|
||||
lat: req.lat,
|
||||
long: req.lng,
|
||||
createdAt: DateTime.now().toUtc(),
|
||||
visibility: 0,
|
||||
upvotes: 0,
|
||||
downvotes: 0,
|
||||
);
|
||||
|
||||
final inserted = await session.db.insertRow<Quote>(quote);
|
||||
return inserted;
|
||||
}
|
||||
|
||||
Future<Quote> getQuoteById(Session session, int id) async {
|
||||
final quote = await Quote.db.findById(session, id);
|
||||
if (quote != null) {
|
||||
return quote;
|
||||
}
|
||||
|
||||
throw Exception('Quote not found');
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Reference in a new issue