The SLTT system consists of a client running in a browser and a backend server running on a Linux machine. Only the chrome browser is currently supported. We might in the future support a standalone version of the client using Electron or a similar package.
Windows and OSx are supported.
Slideshow HERE
The client is built with React UI components. It displays information found in two state models: Project State and Video State.
This is persistent information about a single translation project. This includes the following
This is stored as a tree of mobx-state-tree objects. Any React compnent wrapped in the mobx-react
component will be reactively re-rendered whenever any data which the component uses from the Project State object changes.
Initially this information is read from the project PouchDB database on the server. Any changes made to this data by this client or any other client accessing this project on the server are automatically sent to the client causing the project state model to be updated and triggering a re-rendering of the information in the React components.
Project
name
members
Member
email
role (admin/translator/consultant/observer)
portions
Portion
name
rank (determines display sequence)
passages
Passage
name
rank
videos
PassageVideo
username
videoCreated (creation timestamp for passage video)
duration (of recorded video)
url (S3 url of video file)
statuses
PassageStatus
statusCreated (creation timestamp for this status entry)
videoCreated (creation timestamp for passage video this note applies to)
status (review status)
notes
PassageNote
videoCreated (creation timestamp for passage video this note applies to)
noteCreated (note creation timestamp)
position (time offset of note in passage video)
resolved (boolean - no further action needed on note)
segments
PassageNoteSegment (represents one comment in a note thread)
segmentCreated (creation timestamp for segment)
username
[video thread comments only]
duration
url (S3 url of video file for this thread segment video)
[text thread comments only]
text (text of comment in draft-js content format)
Each project is stored in a separate PouchDB database contained in a single directory on the server. The name of the database is the same as the name of the project. In order to avoid needing to deal with update conflicts when multiple people update the same information most of the documents in our database are intentionally immutable once written.
This document names a portion in a project. The rank field gives the display order of the portions in a project.
This document is deleted when the portion is deleted from the project. This document may be updated with a different value in the rank field when the order of this portion in the project is changed ... since this likely happens fairly rarely and the only thing that can collide is changes to the rank field, it is probably not worthwhile to create a separate document type just to record changes. We just overwrite the original document.
_id for document
#item/<portion name>/<passage name>/portion
Example document
{
_id: "#item/El Fariseo y El Publicano/portion",
name: "El Fariseo y El Publicano",
rank: 200, // an arbitrary number used for sorting/ordering portions
}
This document names a passage within a portion in a project. The rank field gives the display order of the passage in the portion.
This document is deleted when the passage is deleted from the portion. This document may be updated with a different value in the rank field when the order of this passage in the portion. See the Portion section above for why this object is mutable.
_id for document
#item/<portion name>/<passage name>/passage
Example document
{
_id: "#item/Hijo Prodigo/Partido Uno/passage",
name: "Partido Uno",
rank: 100,
}
This document type contains the information for a video draft for a passage. These entries are never modified or deleted. A draft may be hidden from view by creating Video Status entry with status 'PassagesStatus.deletedStatus'. See the next section for information on Video Status.
_id for document
<portion name>/<passage name>/<video creation time>.<file extension>/video
Example document
{
_id: "El Fariseo y El Publicano/test/2018-10-01 20.15.30.webm/video",
videoCreated: "2018-10-01 20.15.30",
username: "milesnlwork@gmail.com",
duration: 301.99,
url: "LSPeru/El_Fariseo_y_El_Publicano/test/2018-10-01_20.15.30.webm",
// This is the name of the file in the S3 bucket
}
This document type contains the information about the review status of a video draft for a passage. These documents are never modified or deleted. The status of a video draft is changed by creating a new status entry with a later 'statusCreated' date than the previous entry.
A status of 1 indicates that the video has passed the first review stage. A status of PassagesStatus.deletedStatus (10) means the video is in the trash can and should be hidden from view. We do not actually delete the video. (We don't yet have UI to get the video back out of the trashcan)
_id for document
<portion name>/<passage name>/<video creation time> <status set time>/status
Example document
{
_id: "El Fariseo y El Publicano/test/2018-10-01 20.15.30 2018-10-01 20.15.41/status",
videoCreated: "2018-10-01 20.15.30",
statusCreated: "2018-10-01 20.15.41",
status: 2,
}
Notes are made up of note segments. Each segment is a comment authored by a project member. A segment is either styled text or a sign language video. There is not a separate document for the note; instead a note consists of all the note segments with the same \<portion name>/\<passage name>/\<video created time> \<note created time>. These documents are never modified or deleted.
Creation of a Video Note Resolve document, see next section, causes a note to be hidden.
_id for document
<portion name>/<passage name>/
<video creation time> <note creation time> <note segment creation time>/notesegment
Example document
{
_id: "Hijo Prodigo/Abigail/2018-07-25 15.42.33 2018-07-31 20.39.21 2018-07-31 20.39.24.webm/notesegment",
segmentCreated: "2018-07-31 20.39.24",
videoCreated: "2018-07-25 15.42.33",
noteCreated: "2018-07-31 20.39.21",
username: "milesnlwork@gmail.com",
position: 8.104878, // time offset for location of note in video passage draft
duration: 98.918,
url: "LSPeru/Hijo_Prodigo/Abigail/2018-07-25_15.42.33.2018-07-31_20.39.21.2018-07-31_20.39.24.webm",
}
This document is created whenever a note is resolved.
For now at least resolved notes are hidden from the user (eventually we will have UI to reshow them in
order to allow the user to see resolved notes).
These documents are never modified or deleted.
_id for document
<portion name>/<passage name>/
<video creation time> <note creation time> <note resolution time>/resolved
Example document
{
_id: "Hijo Prodigo/Segundo Partido/2018-07-25 15.42.33 2018-08-02 14.09.38 2018-08-02 16.52.05/resolved",
videoCreated: "2018-07-25 15.42.33",
noteCreated: "2018-08-02 14.09.38",
segmentCreated: "2018-08-02 16.52.05", // time note resolved
position: 97.122859,
}
SLTool
Router
NavigationBar - select major mode (translation editor, portions editor, members editor)
GoogleLogin
ProjectsTabs
Tabs
TabList
Tab
TabPanel
TranslationEditor - translation editing mode see details at (A) below
PortionsEditor - Add, remove, reorder portions
SortableList
SortableItem
DragHandle
PortionView
PortionEditor
PortionAdder
MembersEditor - add/remove members, change member roles
Member
MemberRole
MemberAdder
DatabaseEditor - debugging view, root users only
RowView
TranslationEditor (A)
PassageList - select project portion, add/remove/reorder passages in portion
PortionSelector
SortableList
SortableItem
DragHandle
Passage
PassageEditor - edit name of passage
Progress - show progress of upload after drag and drop
PassageAdder
VideoMain
VideoToolbar
(Play|Pause|Record|Stop|CreateNote)Button
PassageVideoSelector - select which draft of video to play
PassageStatusSelector - set review status for selected draft
VideoRecorder
VideoPlayer
VideoMessage - tell user why there is nothing available to play
VideoPositionBar - adjust time position in video
AdjustCurrentTimeButtons
NoteBar - show notes for current video
TranslationRightPane
PassageSegmentsEditor
SegmentLabels - show the labels for current segment
SegmentLabelsEditor - edit labels for current segment
LabelTextEditor
SegmentPosition - show start position of current segment
SegmentPositionEditor - edit start position of current segment
NoteDialog - edit video note
NoteMain
VideoPlayer
VideoRecordingToolbar
VideoRecorder
NoteSegment - show a video or textual note chat segment
NoteTextEditor - edit text segment
Editor
This is nonpersistent information concerning what video passage has currently been selected and what the state of the video display is e.g. playing, recording, stopped, etc.
This is stored as a MobX object. Any React wrapped in the mobx-react
component will be reactively re-rendered whenever any data which the component uses from the Video State object changes.
Users may log into the client using their Gmail identity based on the support described at developers.google.com/identity/sign-in/web/reference. This login returns a JWT containing their identity information. This JWT is passed to the server to validate each request.
Users on DBS related projects may log in to the client using their DBS Octopus system of login credentials. This will result in a JWT which will be used to validate each request to the server. This has not been implemented yet.
The reverse proxy performs the following functions
index.js: Express.js is used to process the incoming HTTP requests from the client.
authentication.js: The JWT is extracted from the authorization header and cryptographically validated. The e-mail address field for the user is extracted and attached to the req
structure. Requests with invalid or absent JWTs are rejected.
getMembers.js: Retrieves a list of valid members for the project named in the request from the PouchDB database. This information includes the project role for each user.
Roles:
authorization.js: The user's role in the project is determined based on their e-mail address. Requests from e-mail addresses not authorized for this project are rejected.
If the user does not have an admin role in the project and the request seeks to modify the members of the project or the roles, the request is rejected.
projects.js: Return a list of project names which the current user is authorized to see.
PouchDB is an open-source JavaScript database inspired by Apache CouchDB that is designed to run well within the browser. Currently only an adapter runs in the browser and attaches it to the database running in the server. Changes made by any client are pushed to all other connected clients in real-time.
PouchDB was created to help web developers build applications that work as well offline as they do online. This is important because some locations have unreliable internet access.
PouchDB is used to store all the information from the Project State structure. There is one PouchDB database per project.
pushBlob.js: The HTML 5 video recording support produces a series of small binary blobs when recording. Each blob is sent separately to the server. Sending them as they are produced minimizes the amount of time between the video recording finishing and the full video been uploaded to the server. These blobs are stored in temporary files on the server.
concatBlob.js: After all blobs in the video have been uploaded they are concatenated together into a single blob containing the entire video and this blob is uploaded directly from the server to Amazon S3. After the data has been pushed to Amazon S3 the temporary files are deleted.
getUrl.js: in order for the client to play an existing video passage a signed URL for this video must be generated by Amazon S3. The signed URLs have a limited lifespan so they are generated on each access rather than stored in the database. Videos are played directly from S3, the video data does not pass through the internet server when being played.
In some locations access to the Internet is unreliable or slow. In these locations we will need to run a local server that maintains a copy of the Project State database and synchronizes this information with the Internet-based server when bandwidth is available. This local server will also need to cache copies of the locally recorded videos as well as videos from reference projects such as ASLV.
It will be possible for a consultant visiting a project to have a local cache server running on their machine and for the data on the consultant machine and the project's cache server to be automatically synchronized. This allows the consultant to bring back the local data in the case where the project internet connection is insufficient to do this.
Information on how to run/debug a local copy of the client on your machine is found in client/_README.md