Skip to content

Commit

Permalink
fix: Use common searchable data types
Browse files Browse the repository at this point in the history
  • Loading branch information
Gustl22 committed Sep 11, 2024
1 parent 430752b commit 896e3be
Show file tree
Hide file tree
Showing 22 changed files with 70 additions and 59 deletions.
8 changes: 1 addition & 7 deletions wrestling_scoreboard_client/lib/view/screens/home/home.dart
Original file line number Diff line number Diff line change
Expand Up @@ -183,13 +183,7 @@ class HomeState extends ConsumerState<Home> {
Padding(
padding: const EdgeInsets.symmetric(horizontal: 8),
child: SimpleDropdown<Type?>(
options: [
null,
...dataTypes
..remove(ParticipantState)
..remove(User)
..remove(SecuredUser)
].map((type) => MapEntry(
options: [null, ...searchableDataTypes.keys].map((type) => MapEntry(
type,
Text(type != null ? localizeType(context, type) : '${localizations.optionSelect} Type'),
)),
Expand Down
2 changes: 2 additions & 0 deletions wrestling_scoreboard_common/lib/src/data/club.dart
Original file line number Diff line number Diff line change
Expand Up @@ -46,4 +46,6 @@ class Club with _$Club implements DataObject, Organizational {
Club copyWithId(int? id) {
return copyWith(id: id);
}

static Set<String> searchableAttributes = {'no', 'name'};
}
2 changes: 2 additions & 0 deletions wrestling_scoreboard_common/lib/src/data/membership.dart
Original file line number Diff line number Diff line change
Expand Up @@ -58,4 +58,6 @@ class Membership with _$Membership implements DataObject, Organizational {
Membership copyWithId(int? id) {
return copyWith(id: id);
}

static Set<String> searchableAttributes = {'no'};
}
2 changes: 2 additions & 0 deletions wrestling_scoreboard_common/lib/src/data/organization.dart
Original file line number Diff line number Diff line change
Expand Up @@ -65,4 +65,6 @@ class Organization with _$Organization implements DataObject {
Organization copyWithId(int? id) {
return copyWith(id: id);
}

static Set<String> searchableAttributes = {'name', 'abbreviation'};
}
8 changes: 8 additions & 0 deletions wrestling_scoreboard_common/lib/src/data/person.dart
Original file line number Diff line number Diff line change
Expand Up @@ -88,4 +88,12 @@ class Person with _$Person implements DataObject, Organizational {
Person copyWithId(int? id) {
return copyWith(id: id);
}

static Set<String> searchableAttributes = {
'prename',
'surname',
// 'gender', // Cannot currently search non-string values
'nationality',
// 'birth_date', // Cannot currently search non-string values
};
}
2 changes: 2 additions & 0 deletions wrestling_scoreboard_common/lib/src/data/team.dart
Original file line number Diff line number Diff line change
Expand Up @@ -53,4 +53,6 @@ class Team with _$Team implements DataObject, Organizational {
Team copyWithId(int? id) {
return copyWith(id: id);
}

static Set<String> searchableAttributes = {'name', 'description'};
}
Original file line number Diff line number Diff line change
Expand Up @@ -65,4 +65,6 @@ class Division with _$Division implements DataObject, Organizational {
Division copyWithId(int? id) {
return copyWith(id: id);
}

static Set<String> searchableAttributes = {'name'};
}
Original file line number Diff line number Diff line change
Expand Up @@ -61,4 +61,6 @@ class League with _$League implements DataObject, Organizational {
League copyWithId(int? id) {
return copyWith(id: id);
}

static Set<String> searchableAttributes = {'name'};
}
5 changes: 5 additions & 0 deletions wrestling_scoreboard_common/lib/src/data/weight_class.dart
Original file line number Diff line number Diff line change
Expand Up @@ -59,4 +59,9 @@ class WeightClass with _$WeightClass implements DataObject {
WeightClass copyWithId(int? id) {
return copyWith(id: id);
}

static Set<String> searchableAttributes = {
'weight',
'suffix',
};
}
2 changes: 2 additions & 0 deletions wrestling_scoreboard_common/lib/src/data/wrestling_event.dart
Original file line number Diff line number Diff line change
Expand Up @@ -39,4 +39,6 @@ abstract class WrestlingEvent implements DataObject, Organizational {
'comment': comment,
};
}

static Set<String> searchableAttributes = {'no', 'location', 'comment'};
}
17 changes: 17 additions & 0 deletions wrestling_scoreboard_common/lib/src/util/data_wrapper.dart
Original file line number Diff line number Diff line change
Expand Up @@ -312,3 +312,20 @@ final dataTypes = [
SecuredUser,
User,
];

/// Returns a map of data types with searchable attributes.
/// TODO: with macros, apply it to the property @Searchable.
final Map<Type, Set<String>> searchableDataTypes = {
Person: Person.searchableAttributes,
Membership: Membership.searchableAttributes,
Club: Club.searchableAttributes,
Organization: Organization.searchableAttributes,
WeightClass: WeightClass.searchableAttributes,
// Uses same attributes as WrestlingEvent ATM
Competition: WrestlingEvent.searchableAttributes,
// Uses same attributes as WrestlingEvent ATM
TeamMatch: WrestlingEvent.searchableAttributes,
Division: Division.searchableAttributes,
League: League.searchableAttributes,
Team: Team.searchableAttributes,
};
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,4 @@ class ClubController extends OrganizationalController<Club> {
obfuscate: user?.obfuscate ?? true,
);
}

@override
Set<String> getSearchableAttributes() => {'no', 'name'};
}
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,4 @@ class DivisionController extends OrganizationalController<Division> {
obfuscate: user?.obfuscate ?? true,
);
}

@override
Set<String> getSearchableAttributes() => {'name'};
}
Original file line number Diff line number Diff line change
Expand Up @@ -365,10 +365,11 @@ abstract class EntityController<T extends DataObject> {
String searchStr, {
int? organizationId,
required bool obfuscate,
required Set<String> searchableAttributes,
}) async {
final postgresTypes = getPostgresDataTypes();
bool needsPreciseSearch = false;
final orConditions = getSearchableAttributes()
final orConditions = searchableAttributes
.map((attr) {
// TODO: get postgres types generated from attributes via macros.
final postgresType = postgresTypes.containsKey(attr) ? postgresTypes[attr] : psql.Type.varChar;
Expand Down Expand Up @@ -408,10 +409,6 @@ abstract class EntityController<T extends DataObject> {
);
}

/// Returns a list of searchable attributes.
/// TODO: with macros, apply it to the property @Searchable.
Set<String> getSearchableAttributes() => {};

Future<List<T>> getMany({
List<String>? conditions,
Conjunction conjunction = Conjunction.and,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,4 @@ class LeagueController extends OrganizationalController<League> {
return Response.internalServerError(body: '{"err": "$err", "stackTrace": "$stackTrace"}');
}
}

@override
Set<String> getSearchableAttributes() => {'name'};
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,4 @@ class MembershipController extends OrganizationalController<Membership> {
raw['no'] = null;
return raw;
}

@override
Set<String> getSearchableAttributes() => {'no'};
}
Original file line number Diff line number Diff line change
Expand Up @@ -123,15 +123,16 @@ class OrganizationController extends ShelfController<Organization> {
}
}

Future<List<DataObject>> search(Request request, int id,
{required String searchStr, required Type searchType}) async {
Future<List<DataObject>> search(
Request request,
int id, {
required String searchStr,
required Type searchType,
}) async {
final apiProvider = await initApiProvider(request, id);
if (apiProvider == null) {
throw Exception('No API provider selected for the organization $id.');
}
return await apiProvider.search(searchStr: searchStr, searchType: searchType);
}

@override
Set<String> getSearchableAttributes() => {'name', 'abbreviation'};
}
Original file line number Diff line number Diff line change
Expand Up @@ -41,13 +41,4 @@ class PersonController extends OrganizationalController<Person> {
'gender': null,
};
}

@override
Set<String> getSearchableAttributes() => {
'prename',
'surname',
// 'gender', // Cannot currently search non-string values
'nationality',
// 'birth_date', // Cannot currently search non-string values
};
}
26 changes: 17 additions & 9 deletions wrestling_scoreboard_server/lib/controllers/search_controller.dart
Original file line number Diff line number Diff line change
Expand Up @@ -15,36 +15,44 @@ class SearchController {
final queryParams = request.requestedUri.queryParameters;

final likeParam = queryParams['like'];
final querySearchType = queryParams['type'];
final querySearchTypeStr = queryParams['type'];
final searchOrganizationId = int.tryParse(queryParams['org'] ?? '');
final useProvider = bool.parse(queryParams['use_provider'] ?? 'false');
final isValidLikeSearch = likeParam != null && (likeParam.length >= 3 || double.tryParse(likeParam) != null);
final searchAllTypes = querySearchType == null;
final searchAllTypes = querySearchTypeStr == null;

if (useProvider && (!isValidLikeSearch || searchAllTypes || searchOrganizationId == null)) {
return Response.badRequest(
body:
'Searching the API provider without specifying a type, the organization and a search string is not supported!');
}

final Iterable<String> searchTypes;
final Map<Type, Set<String>> searchTypeMap;
if (!searchAllTypes) {
searchTypes = [querySearchType];
final querySearchType = getTypeFromTableName(querySearchTypeStr);
final searchableAttr = searchableDataTypes[querySearchType];
searchTypeMap = {if (searchableAttr != null) querySearchType: searchableAttr};
} else {
// All searchable types
searchTypes = dataTypes.map((d) => getTableNameFromType(d));
searchTypeMap = searchableDataTypes;
}

try {
final raw = request.isRaw;
List<Map<String, dynamic>> manyJsonList = [];
for (final tableName in searchTypes) {
final searchType = getTypeFromTableName(tableName);
for (final searchTypeEntry in searchTypeMap.entries) {
final searchType = searchTypeEntry.key;
final entityController = ShelfController.getControllerFromDataType(searchType);
Map<String, dynamic>? manyJson;
if (isValidLikeSearch) {
manyJson = await entityController?.getManyJsonLike(raw, likeParam,
organizationId: searchOrganizationId, obfuscate: obfuscate);
final searchableAttributes = searchTypeEntry.value;
manyJson = await entityController?.getManyJsonLike(
raw,
likeParam,
organizationId: searchOrganizationId,
searchableAttributes: searchableAttributes,
obfuscate: obfuscate,
);
if (!searchAllTypes && useProvider && searchOrganizationId != null) {
final orgSearchRes = await OrganizationController().search(
request,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,4 @@ class TeamController extends OrganizationalController<Team> {
Future<Response> import(Request request, User? user, String teamId) async {
return Response.notFound('This operation is not supported yet!');
}

@override
Set<String> getSearchableAttributes() => {'name', 'description'};
}
Original file line number Diff line number Diff line change
Expand Up @@ -216,7 +216,4 @@ class TeamMatchController extends OrganizationalController<TeamMatch> {
}
return null;
}

@override
Set<String> getSearchableAttributes() => {'no', 'location', 'comment'};
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,4 @@ class WeightClassController extends ShelfController<WeightClass> {
'unit': null,
};
}

@override
Set<String> getSearchableAttributes() => {
'weight',
'suffix',
};
}

0 comments on commit 896e3be

Please sign in to comment.