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

Create TypeScript model for Notes Data API #479

Closed
GlennPruitt opened this issue Sep 20, 2023 · 9 comments
Closed

Create TypeScript model for Notes Data API #479

GlennPruitt opened this issue Sep 20, 2023 · 9 comments
Assignees

Comments

@GlennPruitt
Copy link

GlennPruitt commented Sep 20, 2023

As a funder I want to have a description of all APIs in the BT space. Specifically, I want a model of the API for Project Notes Data that will be exposed by Platform.Bible to extension developers. This model must be written in an easy-to-read format (previously GraphQL).

Only needs to be done for publicly available APIs (aka ones that can be consumed by an extension)

Write documentation for the Project Notes Data API.

Talk to Michael Marshall for more details.

@tjcouch-sil
Copy link
Member

tjcouch-sil commented Sep 20, 2023

Tom mentioned Paratext 9 Plugins' IProjectNote related to this

@FoolRunning
Copy link
Contributor

FoolRunning commented Sep 21, 2023

From a quick search, GraphQL is a query language for describing how to get data from an API (like SQL). Why would we want to constrain our design to that specific query language? I feel like this is a step backwards from how we've designed our data access via actual method calls. It seems like a lot of complication to add for no gain in functionality.

@darren8c
Copy link

I am fine if we use GraphQL, but "This model must be written in GaphQL" should not be part of a use case description, and should not be a technical requirement given to the developers unless it is the only option. The developers on the project should decide the technology used. Perhaps GraphQL is the best technology, but in Scrum this should be left to the developers to decide how it is implemented since they are closest to the technical solution. They can receive feedback from stakeholders, product owner(s), and others outside the team, but it is there responsibility to determine the best way to do that.

For example, if we are interfacing with an external system, and the only way to communicate with that system is via a certain protocol we should say that, but when there are multiple options to solve a problem then the developers should determine how to do that.

@GlennPruitt
Copy link
Author

GlennPruitt commented Sep 25, 2023 via email

@lyonsil lyonsil transferred this issue from paranext/paranext Sep 29, 2023
@lyonsil lyonsil added this to the 2023-11 Tech Demo milestone Sep 29, 2023
@tjcouch-sil tjcouch-sil moved this from 🔖 ToDo to 🏗 In progress in Paranext Oct 4, 2023
@tjcouch-sil tjcouch-sil self-assigned this Oct 4, 2023
@tjcouch-sil
Copy link
Member

tjcouch-sil commented Oct 4, 2023

Adapted from the following in Paratext 9's Plugin Interface Docs:

Partial GraphQL implementation (abandoned)

# Represents a DateTimeOffset
scalar Date

# An object representing a project note
type ProjectNote {
  # A selection in the Scripture text representing the "anchor" location of the note.
  anchor: ScriptureTextSelection!
  # Present in a note when it has been assigned to a particular user.
  assignedUser: UserInfo
  # The comments that comprise the note
  comments: [Comment]!
  # Flag indicating whether all the comments of the note have been read by the current user.
  isRead: Boolean!
  # Flag indicating whether this note is resolved.
  isResolved: Boolean!
  # Present in a note when it has been assigned to reply-to a particular user.
  replyToUser: UserInfo
}

# A selection in the Scripture text
type ScriptureTextSelection {
  # The raw USFM text following the SelectedText (typically the remainder of the verse represented by VerseRefEnd).
  afterContext: String!
  # The raw USFM text preceding the SelectedText (typically the entirety of the verse represented by VerseRefStart up to Offset).
  beforeContext: String!
  # The character offset (in the raw USFM data) starting from the point before the \v (i.e., the slash is the 0th character).
  offset: Int!
  # The selected text represented by this object. Can be an empty string (representing an insertion point).
  selectedText: String!
  # The verse where the selection ends.
  verseRefEnd: VerseRef!
  # The verse where the selection starts.
  verseRefStart: VerseRef!
}

# An object representing information about a user
type UserInfo {
  # Gets the registration name of the current user or an empty string if there is no registration information
  name: String!
}

type VerseRef {
}

# An object representing a comment in a project note
type Comment {
  # User to whom a comment is/was assigned.
  assignedUser: UserInfo
  # User who authored this comment
  author: UserInfo!
  # The list of paragraphs making up the contents of this comment.
  contents: [CommentParagraph]
  # Date/time this comment was created
  created: Date!
  # The language used in the comment (except where specified explicitly in a FormattedString).
  language: Language
}

# An object representing a language definition
# SUBJECT TO CHANGE
type Language {
  # Gets the default font.
  font: Font
  # Gets the IETF BCP-47 language tag.
  id: String!
  # Gets whether the language is displayed right-to-left.
  isRtoL: Boolean!
}

# Object representing a font
# SUBJECT TO CHANGE
type Font {
  # A comma-separated list of selected feature options for a Graphite font. REVIEW: Although Paratext does not seem to support selection of features for Open Type fonts, it's possible that existing LDML files may have this information and it could be used by Paratext (and therefore maybe passed on here).
  features: String
  # Name of the font family, which represents a group of fonts that have a similar font face.
  fontFamily: String
  # The language tag needed to tell a Graphite font which set of customized rules to use.
  language: String
  # The em-size measured in in points
  size: Float
}

# Object representing a paragraph in a comment
# SUBJECT TO CHANGE DEPENDING ON HOW WE WANT TO MAKE RICH TEXT EDITING
type CommentParagraph {
  # List of formatted text spans that make up the paragraph
  spans: [FormattedString]
}

# A span of text that has formatting specified.
# SUBJECT TO CHANGE DEPENDING ON HOW WE WANT TO MAKE RICH TEXT EDITING
type FormattedString {
  # The language in which the text is written. If null, the language is the Comment.Language of the owning comment.
  language: Language
  # Flags indicating the style
  style: Style!
  # The text of the string. Cannot be null or empty.
  text: String!
}

# Indicates which styles are applied on a FormattedString.
# SUBJECT TO CHANGE DEPENDING ON HOW WE WANT TO MAKE RICH TEXT EDITING
enum Style {
  # Includes bold formatting
  Bold
  # Includes italics formatting
  Italic
  # No special formatting
  Plain
}

@tjcouch-sil tjcouch-sil changed the title Create GraphQL model for Notes Data API Create TypeScript model for Notes Data API Oct 6, 2023
@tjcouch-sil
Copy link
Member

tjcouch-sil commented Oct 6, 2023

Relied heavily on IProject and IProjectNote to create the types.

First draft: ProjectNotesDataProviderExpanded

Notes for ease of reading:

@tjcouch-sil
Copy link
Member

Added in #538

@github-project-automation github-project-automation bot moved this from 👀 In review to ✅ Done in Paranext Oct 9, 2023
@tjcouch-sil
Copy link
Member

tjcouch-sil commented Oct 9, 2023

Some thoughts from Matt to discuss sometime with Tim, particularly regarding figuring out what all we can do to the api and still work with PT9:

  • Language really shouldn't have font and isRtoL, I think. Rather Language should just be the ID/langauge tag, and there should be a dictionary somewhere else that maps those IDs to things including, but perhaps not limited to, fonts and right-to-left (or more generically text direction).
  • I would try to keep the data model totally separate from the presentation layer at least in terms of terminology. For instance, I don't love that a paragraph has spans. Paragraphs have sentences. Or if we're trying to be less granular, paragraphs have snippets of text. HTML has spans, not paragraphs.
  • When expressed outside of GraphQL, I'm hoping created is a DateTime or something that explicitly includes both a date component and a time component, not just a date in terms of the type name.
  • Having isRead and isResolved seems odd to be at the same scope. I'm assuming isResolved applies to a scope that includes multiple/all users (e.g., stored for the project overall). But isRead applies just at the scope of the current user per the definition. It seems odd to mix those together in the same object like that. Now if isRead is really about whether assignedUser read it or not, that's different and would apply at a project level.
  • Why does ProjectNote contain a Comment (which has an assigned user value itself) and an assignedUser field?
  • It's kind of surprising that comments or project notes don't have some kind of independent ID associated with them. The replyToUser field is really strange to me. If we're trying to have replies, the reply should be to some other ProjectNote or Comment, and then you'll need to reference what you are replying to. Also, when would replyToUser ever be different than assignedUser?

Note: most of ProjectNote (everything but comments) is derived information; helper data. ProjectNote doesn't exist in the underlying data

@tjcouch-sil
Copy link
Member

Follow-up changes:
Language can just be a code in addNote. Maybe everywhere. Add LanguageTag type and remove Language type
Date - specify in comments or field that it is particularly about a time
isRead - convenience flag; could be moved somewhere else. Where?
assignedUser - comments: most recently assigned user(ish). Like "From"
replyToUser - comments: second to most recent assigned user(ish). Like "To"
Comment id is made of thread id and date - should probably add this to ProjectNote and Comment

Note: we can use Fields tag on notes to add information in the future as needed

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
Status: ✅ Done
Development

No branches or pull requests

5 participants