Skip to content
Open
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
17 changes: 9 additions & 8 deletions public/locales/en/affix.json
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
{
"affixButtonTitle": "Click here to add a claim or a personality",
"affixButtonCreateClaim": "Click here to add a claim",
"affixButtonCreatePersonality": "Click here to add a personality",
"affixButtonCreateVerifiedSources": "Click here to add a source",
"affixButtonCreateVerificationRequest": "Click here to add a verification request",
"affixCallToActionButton": "Click here",
"AffixCloseTooltip": "Close",
"affixCopilotTitle": "Click here to open the Aletheia's Assistant"
"affixButtonTitle": "Click here to add a claim or a personality",
"affixButtonCreateClaim": "Click here to add a claim",
"affixButtonCreatePersonality": "Click here to add a personality",
"affixButtonCreateVerifiedSources": "Click here to add a source",
"affixButtonCreateVerificationRequest": "Click here to add a verification request",
"affixButtonCreateEvent": "Click here to add a event",
"affixCallToActionButton": "Click here",
"AffixCloseTooltip": "Close",
"affixCopilotTitle": "Click here to open the Aletheia's Assistant"
}
27 changes: 27 additions & 0 deletions public/locales/en/events.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
{
"eventCreateSuccess": "Event created successfully",
"totalItems": "{{total}} in total",
"openEvent": "See event",
"fetchError": "Error fetching events. Please try again later.",
"loadMoreButton": "Load more",
"eventsList": "Events",
"filterAll": "All",
"filterOngoing": "Ongoing",
"filterUpcoming": "Upcoming",
"filterFinished": "Finished",
"badgeLabel": "Badge",
"badgePlaceholder": "Enter tag (e.g., COP30)",
"nameLabel": "Name",
"namePlaceholder": "Enter event name",
"descriptionLabel": "Description",
"descriptionPlaceholder": "Describe the event",
"locationLabel": "Location",
"locationPlaceholder": "Enter event location",
"startDateLabel": "Start date",
"startDatePlaceholder": "Select start date",
"endDateLabel": "End date",
"endDatePlaceholder": "Select end date",
"mainTopicLabel": "Main topic",
"mainTopicPlaceholder": "Search and select the main topic",
"mainTopicLabelTooltip": "Reference topic used to link the fact-checks and verification requests that will appear on the event page."
}
4 changes: 3 additions & 1 deletion public/locales/en/seo.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,5 +17,7 @@
"verificationRequestTitle": "Verification Requests",
"verificationRequestDescription": "See verification requests on AletheiaFact.org",
"createVerificationRequestTitle": "Create verification request",
"createVerificationRequestDescription": "Create verification requests to AletheiaFact.org"
"createVerificationRequestDescription": "Create verification requests to AletheiaFact.org",
"createEventTitle": "Create event",
"createEventDescription": "Create event to AletheiaFact.org"
}
17 changes: 9 additions & 8 deletions public/locales/pt/affix.json
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
{
"affixButtonTitle": "Clique aqui para adicionar uma afirmação ou personalidade",
"affixButtonCreateClaim": "Clique aqui para adicionar uma afirmação",
"affixButtonCreatePersonality": "Clique aqui para adicionar uma personalidade",
"affixButtonCreateVerifiedSources": "Clique aqui para adicionar uma informação checada",
"affixButtonCreateVerificationRequest": "Clique aqui para adicionar uma denúncia",
"affixCallToActionButton": "Clique aqui",
"AffixCloseTooltip": "Fechar",
"affixCopilotTitle": "Clique aqui para abrir o Assistente Aletheia"
"affixButtonTitle": "Clique aqui para adicionar uma afirmação ou personalidade",
"affixButtonCreateClaim": "Clique aqui para adicionar uma afirmação",
"affixButtonCreatePersonality": "Clique aqui para adicionar uma personalidade",
"affixButtonCreateVerifiedSources": "Clique aqui para adicionar uma informação checada",
"affixButtonCreateVerificationRequest": "Clique aqui para adicionar uma denúncia",
"affixButtonCreateEvent": "Clique aqui para adicionar um evento",
"affixCallToActionButton": "Clique aqui",
"AffixCloseTooltip": "Fechar",
"affixCopilotTitle": "Clique aqui para abrir o Assistente Aletheia"
}
27 changes: 27 additions & 0 deletions public/locales/pt/events.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
{
"eventCreateSuccess": "Evento criado com sucesso",
"totalItems": "{{total}} no total",
"openEvent": "Veja evento",
"fetchError": "Erro ao carregar eventos. Por favor, tente novamente mais tarde.",
"loadMoreButton": "Carregar mais",
"eventsList": "Eventos",
"filterAll": "Todos",
"filterHappening": "Agora",
"filterUpcoming": "Em breve",
"filterFinished": "Encerrados",
"badgeLabel": "Etiqueta",
"badgePlaceholder": "Digite a etiqueta (ex: COP30)",
"nameLabel": "Nome",
"namePlaceholder": "Digite o nome do evento",
"descriptionLabel": "Descrição",
"descriptionPlaceholder": "Descreva o evento",
"locationLabel": "Local",
"locationPlaceholder": "Digite o local do evento",
"startDateLabel": "Data de início",
"startDatePlaceholder": "Selecione a data de início",
"endDateLabel": "Data de término",
"endDatePlaceholder": "Selecione a data de término",
"mainTopicLabel": "Tópico principal",
"mainTopicPlaceholder": "Busque e selecione o tópico principal",
"mainTopicLabelTooltip": "Tópico de referência usado para vincular as checagens e as denúncias que serão exibidos na página do evento."
}
4 changes: 3 additions & 1 deletion public/locales/pt/seo.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,5 +17,7 @@
"verificationRequestTitle": "Denúncias",
"verificationRequestDescription": "Veja as denúncias na AletheiaFact.org",
"createVerificationRequestTitle": "Adicione uma denuncia",
"createVerificationRequestDescription": "Adiciona uma denúncia na AletheiaFact.org"
"createVerificationRequestDescription": "Adiciona uma denúncia na AletheiaFact.org",
"createEventTitle": "Adicione um evento",
"createEventDescription": "Adicione um na AletheiaFact.org"
}
2 changes: 2 additions & 0 deletions server/app.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ import { M2MGuard } from "./auth/m2m.guard";
import { CallbackDispatcherModule } from "./callback-dispatcher/callback-dispatcher.module";
import { AiTaskModule } from "./ai-task/ai-task.module";
import { TrackingModule } from "./tracking/tracking.module";
import { EventsModule } from "./events/event.module";
import { ManagementModule } from "./management/management.module";

@Module({})
Expand Down Expand Up @@ -123,6 +124,7 @@ export class AppModule implements NestModule {
ClaimRevisionModule,
HistoryModule,
TrackingModule,
EventsModule,
ManagementModule,
StateEventModule,
SourceModule,
Expand Down
65 changes: 64 additions & 1 deletion server/claim/types/sentence/sentence.service.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,18 @@
import {
BadRequestException,
Injectable,
InternalServerErrorException,
Logger,
NotFoundException,
} from "@nestjs/common";
import { Model } from "mongoose";
import { SentenceDocument, Sentence } from "./schemas/sentence.schema";
import { InjectModel } from "@nestjs/mongoose";
import { ReportService } from "../../../report/report.service";
import { UtilService } from "../../../util";
import { allCop30WikiDataIds } from "../../../../src/constants/cop30Filters";
import type { Cop30Sentence } from "../../../../src/types/Cop30Sentence";
import { TopicRelatedSentencesResponse } from "./types/sentence.interfaces";
import { allCop30WikiDataIds } from "../../../../src/constants/cop30Filters";
import type { Cop30Stats } from "../../../../src/types/Cop30Stats";
import { buildStats } from "../../../../src/components/Home/COP30/utils/classification";

Expand All @@ -24,13 +27,73 @@ interface FindAllOptionsFilters {

@Injectable()
export class SentenceService {
private readonly logger = new Logger(SentenceService.name);

constructor(
@InjectModel(Sentence.name)
private SentenceModel: Model<SentenceDocument>,
private reportService: ReportService,
private util: UtilService
) {}

/**
* Fetches sentences based on topic values and enriches them with review classification.
* Uses an aggregation pipeline for cross-collection lookup.
* @param query - Topic wikidataId array to filter sentences.
* @returns A list of sentences with their respective classification.
*/
async getSentencesByTopics(query: string[]): Promise<TopicRelatedSentencesResponse[]> {
try {
this.logger.debug(`Fetching sentences for topics: ${query.join(', ')}`);

const aggregation: any[] = [
{ $match: { "topics.value": { $in: query } } },
{
$lookup: {
from: "reviewtasks",
let: { sentenceDataHash: "$data_hash" },
pipeline: [
{
$match: {
$expr: {
$eq: [
"$machine.context.reviewData.data_hash",
"$$sentenceDataHash",
],
},
},
},
{
$project: {
_id: 0,
classification: "$machine.context.reviewData.classification",
},
},
],
as: "reviewInfo",
},
},
{
$addFields: {
classification: {
$arrayElemAt: ["$reviewInfo.classification", 0],
},
},
},
{ $project: { reviewInfo: 0 } },
];

const result = await this.SentenceModel.aggregate(aggregation).exec();

this.logger.log(`Found ${result.length} sentences for the requested topics.`);

return result;
} catch (error) {
this.logger.error(`Error in getSentencesByTopics: ${error.message}`, error.stack);
throw new InternalServerErrorException("Failed to aggregate sentences with review data.");
}
}

async getSentencesWithCop30Topics(): Promise<Cop30Sentence[]> {
const aggregation = [
{ $match: { "topics.value": { $in: allCop30WikiDataIds } } },
Expand Down
12 changes: 12 additions & 0 deletions server/claim/types/sentence/types/sentence.interfaces.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { Sentence } from "../schemas/sentence.schema";

export interface Review {
personality: string;
usersId: string;
isPartialReview: boolean;
}

export type TopicRelatedSentencesResponse = Sentence & {
classification?: string;
review?: Review;
}
67 changes: 67 additions & 0 deletions server/events/dto/event.dto.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
import {
IsArray,
IsDate,
IsNotEmpty,
IsObject,
IsOptional,
IsString
} from "class-validator";
import { ApiProperty, PartialType } from "@nestjs/swagger";
import { Type } from "class-transformer";
import type { TopicData } from "../../topic/types/topic.interfaces";

export class CreateEventDTO {
@IsString()
@IsOptional()
@ApiProperty()
nameSpace?: string;

@IsString()
@IsNotEmpty()
@ApiProperty()
badge: string;

@IsString()
@IsNotEmpty()
@ApiProperty()
name: string;

@IsString()
@IsNotEmpty()
@ApiProperty()
description: string;

@IsString()
@IsNotEmpty()
@ApiProperty()
location: string;

@IsDate()
@IsNotEmpty()
@Type(() => Date)
@ApiProperty()
startDate: Date;

@IsDate()
@IsNotEmpty()
@Type(() => Date)
@ApiProperty()
endDate: Date;

@IsObject()
@IsNotEmpty()
@ApiProperty()
mainTopic: TopicData;

@IsString()
@IsOptional()
@ApiProperty()
recaptcha?: string;
}

export class UpdateEventDTO extends PartialType(CreateEventDTO) {
@IsArray()
@IsOptional()
@ApiProperty()
filterTopics: TopicData[];
}
26 changes: 26 additions & 0 deletions server/events/dto/filter.dto.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import {
IsOptional,
IsInt,
Min,
IsString
} from "class-validator";
import { Type } from "class-transformer";

export class FilterEventsDTO {
@Type(() => Number)
@IsInt()
@Min(0)
page?: number = 0;

@Type(() => Number)
@IsInt()
@Min(1)
pageSize?: number = 10;

@IsString()
order?: "asc" | "desc";

@IsOptional()
@IsString()
status?: string;
}
Loading
Loading