types issueshttps://gitlab.coko.foundation/pubsweet/types/-/issues2019-09-16T09:43:59Zhttps://gitlab.coko.foundation/pubsweet/types/-/issues/27Setup this repo as a Typescript package2019-09-16T09:43:59ZPeter EastSetup this repo as a Typescript packageThere are a few things to do before we can start developing properly here with regards to using typescript and having some form of CI/CD
## TODOs:
- [x] Choose a node version (10) - this repo will not produce executable javascrtipt, it'...There are a few things to do before we can start developing properly here with regards to using typescript and having some form of CI/CD
## TODOs:
- [x] Choose a node version (10) - this repo will not produce executable javascrtipt, it'll only contain types that other packages can use so it doesn't matter if we use a different version of node to the rest of pubsweet.
- [x] Set up build/lint/prettier config - This is pretty much a copypasta task
- [x] Set up the CI - so that we don't break everything every time we merge anything
- [x] Write the types - they're already written in a MR in pubsweet, we just need to move them here
- [ ] Deploy the package to npm - it's probably going to be called `@pubsweet/types`
- [ ] Configure the CI pipeline to enable CDhttps://gitlab.coko.foundation/pubsweet/types/-/issues/26Temporary notes from last discussion to be included in the main document2019-01-18T03:45:13ZJureTemporary notes from last discussion to be included in the main document```
interface Object {
id: ID!
created: DateTime!
updated: DateTime
}
type Organization implements Object {
id: ID!
created: DateTime!
updated: DateTime
name: String!
journals: [Journal]
}
# Have a way t...```
interface Object {
id: ID!
created: DateTime!
updated: DateTime
}
type Organization implements Object {
id: ID!
created: DateTime!
updated: DateTime
name: String!
journals: [Journal]
}
# Have a way to extend the base Organization for JournalPublishers
type Journal implements Object {
id: ID!
created: DateTime!
updated: DateTime
journalTitle: String!
manuscripts: [Manuscript]
meta: JournalMeta
}
# Ask Tam about "meta,fields"
type JournalMeta {
publisherName: String
}
type Manuscript implements Object {
id: ID!
created: DateTime!
updated: DateTime
manuscriptVersions: [ManuscriptVersion]
files: [File]
teams: [Team]
reviews: [Review]
status: String
lastStepVisited: String
decision: String
meta: ManuscriptMeta
}
type ManuscriptVersion implements Object {
id: ID!
created: DateTime!
updated: DateTime
files: [File]
teams: [Team]
reviews: [Review]
status: String
lastStepVisited: String
decision: String
meta: ManuscriptMeta
}
type ManuscriptMeta {
title: String!
articleType: String
articleIds: [ArticleId]
abstract: String
subjects: [String]
history: [MetaDate]
publicationDates: [MetaDate]
notes: [Note]
}
type ArticleId {
pubIdType: String
id: String
}
type MetaDate {
type: String
date: DateTime
}
# Implementation guideline: have a separate table for nodes
type Note implements Object {
id: ID!
created: DateTime!
updated: DateTime
notesType: String
content: String
}
# Implementation guideline: use columns in files tables
# to link files to comments and manuscript (comment_id, manuscript_id)
type File implements Object {
id: ID!
created: DateTime!
updated: DateTime
type: String
label: String
filename: String
url: String
mimeType: String
size: Int
}
type Review implements Object {
id: ID!
created: DateTime!
updated: DateTime
comments: [Comment]
recommendation: String
open: Boolean
user: User
}
type Comment {
type: String
content: String
files: [File]
}
type AuditLog {
id: ID!
created: DateTime!
user: User
action: String
object: Object
objectType: String
}
extend type Team {
created: DateTime!
updated: DateTime
teamMembers: [TeamMember]
role: String
objectId: Object
objectType: String
}
type TeamMember {
user: User
status: String
alias: Alias
}
type Alias {
name: Name
email: Email
aff: String
}
extend type User {
created: DateTime!
updated: DateTime
identities: [Identity]
defaultIdentity: String
}
# Todo move ElifeIdentity to elife.graphqls
union Identity = Local | External | ElifeIdentity
type Local {
name: Name
email: Email
aff: String
}
type External {
identifier: String
email: Email
aff: String
}
type Name {
surname: String
givenNames: String
title: String
}
scalar DateTime
scalar Email
```https://gitlab.coko.foundation/pubsweet/types/-/issues/23Clarify whether user identities is an object or array2018-08-16T10:41:07ZTamlyn RhodesClarify whether user identities is an object or arrayIn the readme we show user `identities` as an object with keys corresponding to each identity, e.g.
```js
user = {
identities: {
local: {
email: 'a@b',
//...
},
orcid: {
orcidId: '0001',
//...
...In the readme we show user `identities` as an object with keys corresponding to each identity, e.g.
```js
user = {
identities: {
local: {
email: 'a@b',
//...
},
orcid: {
orcidId: '0001',
//...
}
}
}
```
But in the schema we show `identities` as an array, e.g.
```js
user = {
identities: [
{
type: 'local', // not currently in schema
email: 'a@b',
//...
},
{
type: 'orcid', // not currently in schema
orcidId: '0001',
//...
}
]
}
```
I don't have a strong preference for either but if we're going with an array then we need to add a `type` key to the identity type (as shown above).https://gitlab.coko.foundation/pubsweet/types/-/issues/25Teams2018-08-07T10:35:35ZTamlyn RhodesTeamsCan someone help me understand the value of the `Team` type?
## Current model
```graphql
type Team {
id: ID!
created: DateTime!
updated: DateTime
members: [TeamMember]
role: String
objectId: Object
objectTy...Can someone help me understand the value of the `Team` type?
## Current model
```graphql
type Team {
id: ID!
created: DateTime!
updated: DateTime
members: [TeamMember]
role: String
objectId: Object
objectType: String
}
type TeamMember {
user: User
status: String
alias: Alias
}
type Alias {
name: Name
email: Email
aff: String
}
```
I have a few problems with this:
1. Hard to grok.
- I've had to explain several times to new developers on the project (multiple times to the same people in some cases) that a `Team` does not model the team of people associated with an object but only the people of a specific role.
- Most teams (at least in `elife-xpub`) have a single member which goes against the natural usage of the term.
2. Overhead in managing teams in the code
- When you want to add a member, you first need to check if there's an existing team of the appropriate role and create one if not
- When removing a member you need to check if the resulting team is empty and if so delete it
- Does code need to handle cases like having two teams of the same type for the same object?
3. All fields on `TeamMember` are optional because
- Not all team members will have a `user` (e.g. a suggested reviewer added by email may not have an associated user until they log in)
- Not all team members will have a `status` (e.g. it's only for modelling reviewer invitations AFAICR)
- Not all team members will have an `alias` (e.g. an editor assigned to a manuscript doesn't need an alias)
4. There's a bunch of other properties that need to be associated with team members and these depend on the role:
- reviewers need invitation dates, reminders sent etc
- authors need their corresponding author, rank etc.
- eLife editors need their eLife person ID
We can model these extra properties as a union type like `union TeamMemberMeta = ReviewerMemberMeta | EditorMemberMeta | AuthorMemberMeta`. In Apollo server you have to write a `resolveType` function for each union type and interface which, when passed a data object, returns the type of that object. You can try and guess the type from the combination of properties (e.g. if it has a `corresponding` property then it must be an `AuthorMemberMeta`) but it's complicated and it doesn't work if the properties are optional, or you can store the type along with the object.
If we take the more reliable route and store the type of team member meta then we're essentially duplicating the role: once on the team and again on each team member's meta. What happens if we have a team of authors with some members having only editor member meta?
## Suggestions
1. Merge (the as yet non-existent) `TeamMemberMeta` into `TeamMember` so it becomes a union type or interface. This means we can have `status` and `alias` only when it makes sense.
2. Move `role` up into `TeamMember` and use this in `resolveType` as the type discriminator
## Intermediate model
```diff
type Team {
id: ID!
created: DateTime!
updated: DateTime
members: [TeamMember]
- role: String
objectId: Object
objectType: String
}
-type TeamMember {
+interface TeamMember {
+ role: String!
user: User
- status: String
- alias: Alias
}
+type ReviewerMember implements TeamMember {
+ role: String!
+ user: User
+ status: String!
+ alias: Alias
+ reminders: [Date]
+}
type Alias {
name: Name
email: Email
aff: String
}
+type AuthorMember implements TeamMember {
+ #...
+}
#...
```
This means we now only have one team per entity and that team holds all team members of any role.
Having arrived here, I notice that `Team` no longer has any meaningful properties. It's just a way of linking members to an object. So we can replace the entity with an interface:
## Suggested model
```diff
type Manuscript implements TeamObject {
#...
+ members: [TeamMember]
}
-type Team {
+interface TeamObject {
- id: ID!
- created: DateTime!
- updated: DateTime
members: [TeamMember]
- objectId: Object
- objectType: String
}
interface TeamMember {
role: String!
}
type ReviewerMember implements TeamMember {
role: String!
user: User
status: String!
alias: Alias
reminders: [Date]
}
type Alias {
name: Name
email: Email
aff: String
}
type AuthorMember implements TeamMember {
#...
}
#...
```https://gitlab.coko.foundation/pubsweet/types/-/issues/10Open review option2018-08-01T15:31:54ZYannis BarlasOpen review optionThere is currently no option to capture whether a review itself (ie. the `content` property) should be available to the submitting author.
I think we should have this and then it's up to the journal to decide whether that is an opt-in...There is currently no option to capture whether a review itself (ie. the `content` property) should be available to the submitting author.
I think we should have this and then it's up to the journal to decide whether that is an opt-in scenario, disallowed or required.https://gitlab.coko.foundation/pubsweet/types/-/issues/15urls2018-05-16T11:15:33ZGhost UserurlsOne last thing that came from our use case: a `links` entity with `type,description,url` fields. Maybe `Files` could be generalized to `Links` or `Urls`?One last thing that came from our use case: a `links` entity with `type,description,url` fields. Maybe `Files` could be generalized to `Links` or `Urls`?