mirror of
https://github.com/SamyRai/tercul-frontend.git
synced 2025-12-26 21:51:34 +00:00
- Enhanced annotation system with improved inline editing - Updated author components with new card and header designs - Improved reading view with enhanced line numbering and controls - Added new blog management features and tag management - Updated UI components with improved accessibility and styling - Enhanced search functionality with better filtering - Added new dashboard features and activity feeds - Improved translation selector and work comparison tools - Updated GraphQL integration and API hooks - Enhanced responsive design and mobile experience
710 lines
12 KiB
GraphQL
710 lines
12 KiB
GraphQL
# BlogPost type for blog queries/mutations
|
|
type BlogPost {
|
|
id: ID!
|
|
title: String!
|
|
slug: String!
|
|
content: String!
|
|
author: Author!
|
|
excerpt: String
|
|
publishedAt: String
|
|
createdAt: String!
|
|
}
|
|
# GraphQL schema for Tercul literary platform
|
|
|
|
# Core types
|
|
type Work {
|
|
id: ID!
|
|
name: String!
|
|
language: String!
|
|
content: String
|
|
createdAt: String!
|
|
updatedAt: String!
|
|
translations: [Translation!]
|
|
authors: [Author!]
|
|
tags: [Tag!]
|
|
categories: [Category!]
|
|
readabilityScore: ReadabilityScore
|
|
writingStyle: WritingStyle
|
|
emotions: [Emotion!]
|
|
topicClusters: [TopicCluster!]
|
|
moods: [Mood!]
|
|
concepts: [Concept!]
|
|
linguisticLayers: [LinguisticLayer!]
|
|
stats: WorkStats
|
|
textMetadata: TextMetadata
|
|
poeticAnalysis: PoeticAnalysis
|
|
copyright: Copyright
|
|
copyrightClaims: [CopyrightClaim!]
|
|
collections: [Collection!]
|
|
comments: [Comment!]
|
|
likes: [Like!]
|
|
bookmarks: [Bookmark!]
|
|
}
|
|
|
|
type Translation {
|
|
id: ID!
|
|
name: String!
|
|
language: String!
|
|
content: String
|
|
workId: ID!
|
|
work: Work!
|
|
translator: User
|
|
createdAt: String!
|
|
updatedAt: String!
|
|
stats: TranslationStats
|
|
copyright: Copyright
|
|
copyrightClaims: [CopyrightClaim!]
|
|
comments: [Comment!]
|
|
likes: [Like!]
|
|
}
|
|
|
|
type Author {
|
|
id: ID!
|
|
name: String!
|
|
language: String!
|
|
biography: String
|
|
birthDate: String
|
|
deathDate: String
|
|
createdAt: String!
|
|
updatedAt: String!
|
|
works: [Work!]
|
|
books: [Book!]
|
|
country: Country
|
|
city: City
|
|
place: Place
|
|
address: Address
|
|
copyrightClaims: [CopyrightClaim!]
|
|
copyright: Copyright
|
|
}
|
|
|
|
type User {
|
|
id: ID!
|
|
username: String!
|
|
email: String!
|
|
firstName: String
|
|
lastName: String
|
|
displayName: String
|
|
bio: String
|
|
avatarUrl: String
|
|
role: UserRole!
|
|
lastLoginAt: String
|
|
verified: Boolean!
|
|
active: Boolean!
|
|
createdAt: String!
|
|
updatedAt: String!
|
|
|
|
# Relationships
|
|
translations: [Translation!]
|
|
comments: [Comment!]
|
|
likes: [Like!]
|
|
bookmarks: [Bookmark!]
|
|
collections: [Collection!]
|
|
contributions: [Contribution!]
|
|
|
|
# Location
|
|
country: Country
|
|
city: City
|
|
address: Address
|
|
|
|
# Stats
|
|
stats: UserStats
|
|
}
|
|
|
|
type UserProfile {
|
|
id: ID!
|
|
userId: ID!
|
|
user: User!
|
|
phoneNumber: String
|
|
website: String
|
|
twitter: String
|
|
facebook: String
|
|
linkedIn: String
|
|
github: String
|
|
preferences: JSON
|
|
settings: JSON
|
|
createdAt: String!
|
|
updatedAt: String!
|
|
}
|
|
|
|
enum UserRole {
|
|
READER
|
|
CONTRIBUTOR
|
|
REVIEWER
|
|
EDITOR
|
|
ADMIN
|
|
}
|
|
|
|
type Book {
|
|
id: ID!
|
|
name: String!
|
|
language: String!
|
|
createdAt: String!
|
|
updatedAt: String!
|
|
works: [Work!]
|
|
stats: BookStats
|
|
copyright: Copyright
|
|
copyrightClaims: [CopyrightClaim!]
|
|
}
|
|
|
|
type Collection {
|
|
id: ID!
|
|
name: String!
|
|
description: String
|
|
createdAt: String!
|
|
updatedAt: String!
|
|
works: [Work!]
|
|
user: User
|
|
stats: CollectionStats
|
|
}
|
|
|
|
type Tag {
|
|
id: ID!
|
|
name: String!
|
|
createdAt: String!
|
|
updatedAt: String!
|
|
works: [Work!]
|
|
}
|
|
|
|
type Category {
|
|
id: ID!
|
|
name: String!
|
|
createdAt: String!
|
|
updatedAt: String!
|
|
works: [Work!]
|
|
}
|
|
|
|
type Comment {
|
|
id: ID!
|
|
text: String!
|
|
createdAt: String!
|
|
updatedAt: String!
|
|
user: User!
|
|
work: Work
|
|
translation: Translation
|
|
lineNumber: Int
|
|
parentComment: Comment
|
|
childComments: [Comment!]
|
|
likes: [Like!]
|
|
}
|
|
|
|
type Like {
|
|
id: ID!
|
|
createdAt: String!
|
|
updatedAt: String!
|
|
user: User!
|
|
work: Work
|
|
translation: Translation
|
|
comment: Comment
|
|
}
|
|
|
|
type Bookmark {
|
|
id: ID!
|
|
name: String
|
|
createdAt: String!
|
|
updatedAt: String!
|
|
user: User!
|
|
work: Work!
|
|
}
|
|
|
|
type Contribution {
|
|
id: ID!
|
|
name: String!
|
|
status: ContributionStatus!
|
|
createdAt: String!
|
|
updatedAt: String!
|
|
user: User!
|
|
work: Work
|
|
translation: Translation
|
|
}
|
|
|
|
enum ContributionStatus {
|
|
DRAFT
|
|
SUBMITTED
|
|
UNDER_REVIEW
|
|
APPROVED
|
|
REJECTED
|
|
}
|
|
|
|
type ReadabilityScore {
|
|
id: ID!
|
|
score: Float!
|
|
language: String!
|
|
createdAt: String!
|
|
updatedAt: String!
|
|
work: Work
|
|
}
|
|
|
|
type WritingStyle {
|
|
id: ID!
|
|
name: String!
|
|
language: String!
|
|
createdAt: String!
|
|
updatedAt: String!
|
|
work: Work
|
|
}
|
|
|
|
type Emotion {
|
|
id: ID!
|
|
name: String!
|
|
language: String!
|
|
createdAt: String!
|
|
updatedAt: String!
|
|
user: User
|
|
work: Work
|
|
collection: Collection
|
|
}
|
|
|
|
type TopicCluster {
|
|
id: ID!
|
|
name: String!
|
|
createdAt: String!
|
|
updatedAt: String!
|
|
works: [Work!]
|
|
}
|
|
|
|
type Mood {
|
|
id: ID!
|
|
name: String!
|
|
language: String!
|
|
createdAt: String!
|
|
updatedAt: String!
|
|
works: [Work!]
|
|
}
|
|
|
|
type Concept {
|
|
id: ID!
|
|
name: String!
|
|
createdAt: String!
|
|
updatedAt: String!
|
|
works: [Work!]
|
|
words: [Word!]
|
|
}
|
|
|
|
type Word {
|
|
id: ID!
|
|
name: String!
|
|
createdAt: String!
|
|
updatedAt: String!
|
|
concept: Concept
|
|
works: [Work!]
|
|
}
|
|
|
|
type LinguisticLayer {
|
|
id: ID!
|
|
name: String!
|
|
language: String!
|
|
createdAt: String!
|
|
updatedAt: String!
|
|
works: [Work!]
|
|
}
|
|
|
|
type WorkStats {
|
|
id: ID!
|
|
views: Int!
|
|
createdAt: String!
|
|
updatedAt: String!
|
|
work: Work!
|
|
}
|
|
|
|
type TranslationStats {
|
|
id: ID!
|
|
views: Int!
|
|
createdAt: String!
|
|
updatedAt: String!
|
|
translation: Translation!
|
|
}
|
|
|
|
type UserStats {
|
|
id: ID!
|
|
activity: Int!
|
|
createdAt: String!
|
|
updatedAt: String!
|
|
user: User!
|
|
}
|
|
|
|
type BookStats {
|
|
id: ID!
|
|
sales: Int!
|
|
createdAt: String!
|
|
updatedAt: String!
|
|
book: Book!
|
|
}
|
|
|
|
type CollectionStats {
|
|
id: ID!
|
|
items: Int!
|
|
createdAt: String!
|
|
updatedAt: String!
|
|
collection: Collection!
|
|
}
|
|
|
|
type TextMetadata {
|
|
id: ID!
|
|
analysis: String!
|
|
language: String!
|
|
createdAt: String!
|
|
updatedAt: String!
|
|
work: Work!
|
|
}
|
|
|
|
type PoeticAnalysis {
|
|
id: ID!
|
|
structure: String!
|
|
language: String!
|
|
createdAt: String!
|
|
updatedAt: String!
|
|
work: Work!
|
|
}
|
|
|
|
type Copyright {
|
|
id: ID!
|
|
name: String!
|
|
language: String!
|
|
createdAt: String!
|
|
updatedAt: String!
|
|
workOwner: Author
|
|
works: [Work!]
|
|
translations: [Translation!]
|
|
books: [Book!]
|
|
sources: [Source!]
|
|
}
|
|
|
|
type CopyrightClaim {
|
|
id: ID!
|
|
details: String!
|
|
createdAt: String!
|
|
updatedAt: String!
|
|
work: Work
|
|
translation: Translation
|
|
book: Book
|
|
source: Source
|
|
author: Author
|
|
user: User
|
|
}
|
|
|
|
type Country {
|
|
id: ID!
|
|
name: String!
|
|
language: String!
|
|
createdAt: String!
|
|
updatedAt: String!
|
|
authors: [Author!]
|
|
users: [User!]
|
|
}
|
|
|
|
type City {
|
|
id: ID!
|
|
name: String!
|
|
language: String!
|
|
createdAt: String!
|
|
updatedAt: String!
|
|
country: Country
|
|
authors: [Author!]
|
|
users: [User!]
|
|
}
|
|
|
|
type Place {
|
|
id: ID!
|
|
name: String!
|
|
language: String!
|
|
createdAt: String!
|
|
updatedAt: String!
|
|
city: City
|
|
country: Country
|
|
authors: [Author!]
|
|
}
|
|
|
|
type Address {
|
|
id: ID!
|
|
street: String!
|
|
createdAt: String!
|
|
updatedAt: String!
|
|
city: City
|
|
country: Country
|
|
authors: [Author!]
|
|
users: [User!]
|
|
}
|
|
|
|
type Source {
|
|
id: ID!
|
|
name: String!
|
|
language: String!
|
|
createdAt: String!
|
|
updatedAt: String!
|
|
copyright: Copyright
|
|
copyrightClaims: [CopyrightClaim!]
|
|
works: [Work!]
|
|
}
|
|
|
|
type Edge {
|
|
id: ID!
|
|
sourceTable: String!
|
|
sourceId: ID!
|
|
targetTable: String!
|
|
targetId: ID!
|
|
relation: String!
|
|
language: String
|
|
extra: JSON
|
|
createdAt: String!
|
|
updatedAt: String!
|
|
}
|
|
|
|
scalar JSON
|
|
|
|
# Queries
|
|
type Query {
|
|
# Work queries
|
|
work(id: ID!): Work
|
|
works(
|
|
limit: Int
|
|
offset: Int
|
|
language: String
|
|
authorId: ID
|
|
categoryId: ID
|
|
tagId: ID
|
|
search: String
|
|
): [Work!]!
|
|
|
|
# Translation queries
|
|
translation(id: ID!): Translation
|
|
translations(
|
|
workId: ID!
|
|
language: String
|
|
limit: Int
|
|
offset: Int
|
|
): [Translation!]!
|
|
|
|
# Author queries
|
|
author(id: ID!): Author
|
|
authors(limit: Int, offset: Int, search: String, countryId: ID): [Author!]!
|
|
|
|
# User queries
|
|
user(id: ID!): User
|
|
userByEmail(email: String!): User
|
|
userByUsername(username: String!): User
|
|
users(limit: Int, offset: Int, role: UserRole): [User!]!
|
|
me: User
|
|
userProfile(userId: ID!): UserProfile
|
|
|
|
# Collection queries
|
|
collection(id: ID!): Collection
|
|
collections(userId: ID, limit: Int, offset: Int): [Collection!]!
|
|
|
|
# Tag queries
|
|
tag(id: ID!): Tag
|
|
tags(limit: Int, offset: Int): [Tag!]!
|
|
|
|
# Category queries
|
|
category(id: ID!): Category
|
|
categories(limit: Int, offset: Int): [Category!]!
|
|
|
|
# Comment queries
|
|
comment(id: ID!): Comment
|
|
comments(
|
|
workId: ID
|
|
translationId: ID
|
|
userId: ID
|
|
limit: Int
|
|
offset: Int
|
|
): [Comment!]!
|
|
|
|
# Bookmark queries
|
|
bookmark(id: ID!): Bookmark
|
|
bookmarks(userId: ID, workId: ID): [Bookmark!]!
|
|
|
|
# Like queries
|
|
like(id: ID!): Like
|
|
likes(userId: ID, workId: ID, translationId: ID, commentId: ID): [Like!]!
|
|
|
|
# Contribution queries
|
|
contribution(id: ID!): Contribution
|
|
contributions(userId: ID, workId: ID, translationId: ID): [Contribution!]!
|
|
|
|
# Blog queries (optional, if BlogPost type exists)
|
|
blog(id: ID!): BlogPost
|
|
blogs(userId: ID, limit: Int, offset: Int): [BlogPost!]!
|
|
|
|
# Search
|
|
search(
|
|
query: String!
|
|
limit: Int
|
|
offset: Int
|
|
filters: SearchFilters
|
|
): SearchResults!
|
|
}
|
|
|
|
input SearchFilters {
|
|
languages: [String!]
|
|
categories: [ID!]
|
|
tags: [ID!]
|
|
authors: [ID!]
|
|
dateFrom: String
|
|
dateTo: String
|
|
}
|
|
|
|
type SearchResults {
|
|
works: [Work!]!
|
|
translations: [Translation!]!
|
|
authors: [Author!]!
|
|
total: Int!
|
|
}
|
|
|
|
# Mutations
|
|
type Mutation {
|
|
# Authentication
|
|
register(input: RegisterInput!): AuthPayload!
|
|
login(email: String!, password: String!): AuthPayload!
|
|
|
|
# Work mutations
|
|
createWork(input: WorkInput!): Work!
|
|
updateWork(id: ID!, input: WorkInput!): Work!
|
|
deleteWork(id: ID!): Boolean!
|
|
|
|
# Translation mutations
|
|
createTranslation(input: TranslationInput!): Translation!
|
|
updateTranslation(id: ID!, input: TranslationInput!): Translation!
|
|
deleteTranslation(id: ID!): Boolean!
|
|
|
|
# Author mutations
|
|
createAuthor(input: AuthorInput!): Author!
|
|
updateAuthor(id: ID!, input: AuthorInput!): Author!
|
|
deleteAuthor(id: ID!): Boolean!
|
|
|
|
# User mutations
|
|
updateUser(id: ID!, input: UserInput!): User!
|
|
deleteUser(id: ID!): Boolean!
|
|
|
|
# Collection mutations
|
|
createCollection(input: CollectionInput!): Collection!
|
|
updateCollection(id: ID!, input: CollectionInput!): Collection!
|
|
deleteCollection(id: ID!): Boolean!
|
|
addWorkToCollection(collectionId: ID!, workId: ID!): Collection!
|
|
removeWorkFromCollection(collectionId: ID!, workId: ID!): Collection!
|
|
|
|
# Comment mutations
|
|
createComment(input: CommentInput!): Comment!
|
|
updateComment(id: ID!, input: CommentInput!): Comment!
|
|
deleteComment(id: ID!): Boolean!
|
|
|
|
# Like mutations
|
|
createLike(input: LikeInput!): Like!
|
|
deleteLike(id: ID!): Boolean!
|
|
|
|
# Bookmark mutations
|
|
createBookmark(input: BookmarkInput!): Bookmark!
|
|
deleteBookmark(id: ID!): Boolean!
|
|
|
|
# Contribution mutations
|
|
createContribution(input: ContributionInput!): Contribution!
|
|
updateContribution(id: ID!, input: ContributionInput!): Contribution!
|
|
deleteContribution(id: ID!): Boolean!
|
|
reviewContribution(
|
|
id: ID!
|
|
status: ContributionStatus!
|
|
feedback: String
|
|
): Contribution!
|
|
|
|
# Additional authentication mutations
|
|
logout: Boolean!
|
|
refreshToken: AuthPayload!
|
|
forgotPassword(email: String!): Boolean!
|
|
resetPassword(token: String!, newPassword: String!): Boolean!
|
|
verifyEmail(token: String!): Boolean!
|
|
resendVerificationEmail(email: String!): Boolean!
|
|
|
|
# User profile mutations
|
|
updateProfile(input: UserInput!): User!
|
|
changePassword(currentPassword: String!, newPassword: String!): Boolean!
|
|
}
|
|
|
|
# Input types
|
|
input RegisterInput {
|
|
username: String!
|
|
email: String!
|
|
password: String!
|
|
firstName: String!
|
|
lastName: String!
|
|
}
|
|
|
|
type AuthPayload {
|
|
token: String!
|
|
user: User!
|
|
}
|
|
|
|
input WorkInput {
|
|
name: String!
|
|
language: String!
|
|
content: String
|
|
authorIds: [ID!]
|
|
tagIds: [ID!]
|
|
categoryIds: [ID!]
|
|
}
|
|
|
|
input TranslationInput {
|
|
name: String!
|
|
language: String!
|
|
content: String
|
|
workId: ID!
|
|
}
|
|
|
|
input AuthorInput {
|
|
name: String!
|
|
language: String!
|
|
biography: String
|
|
birthDate: String
|
|
deathDate: String
|
|
countryId: ID
|
|
cityId: ID
|
|
placeId: ID
|
|
addressId: ID
|
|
}
|
|
|
|
input UserInput {
|
|
username: String
|
|
email: String
|
|
password: String
|
|
firstName: String
|
|
lastName: String
|
|
displayName: String
|
|
bio: String
|
|
avatarUrl: String
|
|
role: UserRole
|
|
verified: Boolean
|
|
active: Boolean
|
|
countryId: ID
|
|
cityId: ID
|
|
addressId: ID
|
|
}
|
|
|
|
input CollectionInput {
|
|
name: String!
|
|
description: String
|
|
workIds: [ID!]
|
|
}
|
|
|
|
input CommentInput {
|
|
text: String!
|
|
workId: ID
|
|
translationId: ID
|
|
lineNumber: Int
|
|
parentCommentId: ID
|
|
}
|
|
|
|
input LikeInput {
|
|
workId: ID
|
|
translationId: ID
|
|
commentId: ID
|
|
}
|
|
|
|
input BookmarkInput {
|
|
name: String
|
|
workId: ID!
|
|
}
|
|
|
|
input ContributionInput {
|
|
name: String!
|
|
workId: ID
|
|
translationId: ID
|
|
status: ContributionStatus
|
|
}
|