Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(cat-voices): adding author list to document metadata to store in db #2059

Merged
merged 6 commits into from
Mar 21, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,9 @@ final class DocumentDataMetadata extends Equatable {
/// "Products & Integrations".
final SignedDocumentRef? categoryId;

/// List of authors represented by CatalystId
final List<CatalystId>? authors;

DocumentDataMetadata({
required this.type,
required this.selfRef,
Expand All @@ -49,6 +52,7 @@ final class DocumentDataMetadata extends Equatable {
this.campaignId,
this.electionId,
this.categoryId,
this.authors,
}) : assert(
selfRef.isExact,
'selfRef have to be exact. Make sure version is not null',
Expand All @@ -67,6 +71,7 @@ final class DocumentDataMetadata extends Equatable {
campaignId,
electionId,
categoryId,
authors,
];

String get version => selfRef.version!;
Expand All @@ -81,6 +86,7 @@ final class DocumentDataMetadata extends Equatable {
Optional<String>? campaignId,
Optional<String>? electionId,
Optional<SignedDocumentRef>? categoryId,
Optional<List<CatalystId>>? authors,
}) {
return DocumentDataMetadata(
type: type ?? this.type,
Expand All @@ -92,6 +98,7 @@ final class DocumentDataMetadata extends Equatable {
campaignId: campaignId.dataOr(this.campaignId),
electionId: electionId.dataOr(this.electionId),
categoryId: categoryId.dataOr(this.categoryId),
authors: authors.dataOr(this.authors),
);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -40,13 +40,15 @@ final class ProposalDocument extends Equatable {
final class ProposalMetadata extends DocumentMetadata {
final SignedDocumentRef templateRef;
final SignedDocumentRef categoryId;
final List<CatalystId> authors;

ProposalMetadata({
required super.selfRef,
required this.templateRef,
required this.categoryId,
required this.authors,
});

@override
List<Object?> get props => super.props + [templateRef, categoryId];
List<Object?> get props => super.props + [templateRef, categoryId, authors];
}
Original file line number Diff line number Diff line change
Expand Up @@ -141,20 +141,21 @@ class DriftDocumentsDao extends DatabaseAccessor<DriftCatalystDatabase>
Future<int> countRefDocumentByType({
required DocumentRef ref,
required DocumentType type,
}) {
}) async {
final query = select(documents)
..where(
(row) => Expression.and([
row.type.equals(type.uuid),
row.metadata.jsonExtract<String>(r'$.type').equals(type.uuid),
row.metadata.jsonExtract<String>(r'$.ref.id').equals(ref.id),
if (ref.version != null)
row.metadata
.jsonExtract<String>(r'$.ref.version')
.equals(ref.version!),
]),
);

return query.get().then(
(docs) => docs.where((doc) {
// TODO(damian-molinski): JSONB filter
return doc.metadata.ref == ref;
}).length,
);
final docs = await query.get();
return docs.length;
}

@override
Expand Down Expand Up @@ -255,8 +256,11 @@ class DriftDocumentsDao extends DatabaseAccessor<DriftCatalystDatabase>
query.where((doc) => doc.type.equals(type.uuid));
}
if (authorId != null) {
// TODO(LynxLynxx): filter when catalystId is implemented as metadata
// query.where((doc) => doc.metadata.catalystId.equals(catalystId.uuid));
query.where(
(doc) => CustomExpression<bool>(
"json_extract(metadata, '\$.authors') LIKE '%$authorId%'",
),
);
}

query.orderBy([
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -184,8 +184,11 @@ class DriftDraftsDao extends DatabaseAccessor<DriftCatalystDatabase>
query.where((doc) => doc.type.equals(type.uuid));
}
if (authorId != null) {
// TODO(LynxLynxx): filter when catalystId is implemented as metadata
// query.where((doc) => doc.metadata.catalystId.equals(catalystId.uuid));
query.where(
(doc) => CustomExpression<bool>(
"json_extract(metadata, '\$.authors') LIKE '%$authorId%'",
),
);
}

query.orderBy([
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@ final class DocumentDataMetadataDto {
final String? campaignId;
final String? electionId;
final DocumentRefDto? categoryId;
final List<String>? authors;

DocumentDataMetadataDto({
required this.type,
Expand All @@ -100,6 +101,7 @@ final class DocumentDataMetadataDto {
this.campaignId,
this.electionId,
this.categoryId,
this.authors,
});

factory DocumentDataMetadataDto.fromJson(Map<String, dynamic> json) {
Expand All @@ -119,6 +121,7 @@ final class DocumentDataMetadataDto {
campaignId: data.campaignId,
electionId: data.electionId,
categoryId: data.categoryId?.toDto(),
authors: data.authors?.map((e) => e.toString()).toList(),
);

Map<String, dynamic> toJson() => _$DocumentDataMetadataDtoToJson(this);
Expand All @@ -134,6 +137,7 @@ final class DocumentDataMetadataDto {
campaignId: campaignId,
electionId: electionId,
categoryId: categoryId?.toSignedModel(),
authors: authors?.map((e) => CatalystId.fromUri(e.getUri())).toList(),
);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -365,6 +365,7 @@ final class ProposalRepositoryImpl implements ProposalRepository {
selfRef: documentData.metadata.selfRef,
templateRef: documentData.metadata.template!,
categoryId: documentData.metadata.categoryId!,
authors: documentData.metadata.authors ?? [],
);

final content = DocumentDataContentDto.fromModel(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import 'package:catalyst_voices_models/catalyst_voices_models.dart';
import 'package:catalyst_voices_repositories/catalyst_voices_repositories.dart';
import 'package:catalyst_voices_repositories/src/database/catalyst_database.dart';
import 'package:catalyst_voices_repositories/src/database/dao/drafts_dao.dart';
import 'package:drift/drift.dart' show DatabaseConnection;
import 'package:drift/drift.dart' show DatabaseConnection, Uint8List;
import 'package:drift/native.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:uuid_plus/uuid_plus.dart';
Expand Down Expand Up @@ -133,6 +133,81 @@ void main() {
allOf(hasLength(refs.length), containsAll(refs)),
);
});

test('authors are correctly extracted', () async {
final authorId1 = CatalystId(host: 'test', role0Key: Uint8List(32));
final authorId2 = CatalystId(host: 'test1', role0Key: Uint8List(32));

final ref = DraftRef.generateFirstRef();
// Given
final draft = DraftFactory.build(
metadata: DocumentDataMetadata(
type: DocumentType.proposalDocument,
selfRef: ref,
authors: [
authorId1,
authorId2,
],
),
);

await database.draftsDao.save(draft);
final doc = await database.draftsDao.query(ref: ref);
expect(
doc?.metadata.authors,
[
authorId1,
authorId2,
],
);
});

test('when updating proposal author list is not deleted', () async {
final authorId1 = CatalystId(host: 'test', role0Key: Uint8List(32));
final authorId2 = CatalystId(host: 'test1', role0Key: Uint8List(32));

final ref = DraftRef.generateFirstRef();
// Given
final draft = DraftFactory.build(
metadata: DocumentDataMetadata(
type: DocumentType.proposalDocument,
selfRef: ref,
authors: [
authorId1,
authorId2,
],
),
content: const DocumentDataContent({
'title': 'Dev',
}),
);

final updateDraft = draft.copyWith(
metadata: draft.metadata.copyWith(
authors: null,
),
content: const DocumentDataContent({
'title': 'Update',
}),
);

await database.draftsDao.save(draft);
await database.draftsDao.save(updateDraft);

final updated = await database.draftsDao.query(ref: ref);

expect(
updated?.metadata.authors?.length,
equals(2),
);
expect(
updated?.metadata.authors,
equals([
authorId1,
authorId2,
]),
);
});
});

group('count', () {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -138,13 +138,15 @@ final class ProposalServiceImpl implements ProposalService {
required SignedDocumentRef categoryId,
}) async {
final draftRef = DraftRef.generateFirstRef();
final catalystId = await _getUserCatalystId();
await _proposalRepository.upsertDraftProposal(
document: DocumentData(
metadata: DocumentDataMetadata(
type: DocumentType.proposalDocument,
selfRef: draftRef,
template: template,
categoryId: categoryId,
authors: [catalystId],
),
content: content,
),
Expand Down Expand Up @@ -274,6 +276,9 @@ final class ProposalServiceImpl implements ProposalService {
required SignedDocumentRef template,
required SignedDocumentRef categoryId,
}) async {
// TODO(LynxLynxx): when we start supporting multiple authors
// we need to get the list of authors actually stored in the db and
// add them to the authors list if they are not already there
await _proposalRepository.upsertDraftProposal(
document: DocumentData(
metadata: DocumentDataMetadata(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ void main() {
),
templateRef: SignedDocumentRef.generateFirstRef(),
categoryId: SignedDocumentRef.generateFirstRef(),
authors: const [],
),
document: const Document(
schema: proposalTemplate,
Expand All @@ -79,6 +80,7 @@ void main() {
),
templateRef: SignedDocumentRef.generateFirstRef(),
categoryId: SignedDocumentRef.generateFirstRef(),
authors: const [],
),
document: const Document(
schema: proposalTemplate,
Expand Down Expand Up @@ -166,6 +168,7 @@ void main() {
selfRef: proposalRef1,
templateRef: SignedDocumentRef.generateFirstRef(),
categoryId: SignedDocumentRef.generateFirstRef(),
authors: const [],
),
document: const Document(
schema: proposalTemplate,
Expand All @@ -178,6 +181,7 @@ void main() {
selfRef: proposalRef2,
templateRef: SignedDocumentRef.generateFirstRef(),
categoryId: SignedDocumentRef.generateFirstRef(),
authors: const [],
),
document: const Document(
schema: proposalTemplate,
Expand Down