Creating Documents
What is a Document
A Document, or Memo outside of the developer realm, is a single entity of information within a folder. This can be, for example, either a File (Image, PDF, Video, ...) or a text. We will cover those two types in this documentation.
All Documents share the same core functionality, where the different types add unique functions.
The core functionality includes:
- metadata like a description, labels, URL, location, creation/upload/last modified date
- belongs to a specific folder
- revisions of every change
- comment system with mentioning
- can have thumbnails if we support the type
- can be shared in a memolink
Text Document
A text document adds two attributes: the text content and the background color. The content is written in markdown to make it easy to read even when not using an editor.
Not all Markdown features are available, though.
Every text document generates a pdf version of it, too, so the user can download it.
File Document
File documents add multiple attributes depending on the actual type. All of them add a download URL.
- PDFs include a separate print version which fixes a few bugs in how browsers interpret the PDF.
- The content of pdfs will be indexed so the user can find the pdf based on its content.
- Emails (.msg/.eml) and word files get a pdf preview which content will then be indexed too.
- Videos get an mp4 version to maximize the compatibility for playback.
Shape of a Document
Basic Shape of a document
{
id
description
labels # array of strings
createdAt
uploadedAt
lastModified
revisionCount
location {
id
latitude
longitude
longName
}
thumbnailUrls {
width80 #base64 encoded
width300
width450
width720
width1280
width1920
}
downloadUrl
printableUrl
pdfPreviewUrl
textContent
textContentBackground
}
More details about the Shape of a Document you can find in the API Reference (DocumentType)
Generally Creating Documents
All create document mutations take the following input shape of optional fields:
{
"description": "",
"labels": ["label1"],
"folderId": "",
"linkedId": "",
"createdAt": "",
"location": {
"latitude": 0.0,
"longitude": 0.0
}
}
Name | Info |
---|---|
createdAt | String - must be a date formatted in ISO 8601. |
linkedId | String - can be any string you want. links other documents together. |
folderId | String - if empty it will be added into the inbox. |
labels | Array of Strings - can be any string. if the label is not yet being used in the account, it will be added to the label managment |
location | latitude and longitude are floats. when set this will be used to show the document on the map and tried to find an address for it |
Creating Text Document
Creating a text document is the most straightforward document you can do from a technical view.
The only required field here is textContent
. This content should consist of Markdown.
The following Markdown features are working:
Name | Code |
---|---|
H1-H4 | # , ## , ### , #### |
Bold | **something nice** |
Italic | *something nice* |
Line through | ~~something nice~~ |
Unordered List | - or * |
Ordered list | 1. , 2. , ... |
Todo list | - [ ] or * [ ] for unchecked items and for checked - [x] or * [x] |
links | [this will be shown](https://actual.url.here) |
There might other features be working, but those we do not support offically.
The other argument that is available here is textContentBackground
. This is a color in hex. The color will give the text memo a background color in the thumbnail and the web app, making it easier to distinguish different types.
The following colors can be selected in the web app:
- #FFFFFF (if none is set, white will be used)
- #FFFDC8 (default color on web)
- #C8EEFF
- #C8FFCA
- #FFC8FB
- #FFC8C8
mutation createDocumentText($textContent: String!, $backgroundColor: String!) {
createDocumentText(
textContent: $textContent
backgroundColor: $backgroundColor
) {
id
textContent
textContentBackground
}
}
Creating File Document
Please note that to run this mutation you have to set a X-Apollo-Operation-Name
header, as seen below in the curl example. To find out how and why you can read this on the Apollo GraphQL Docs. Otherwise see the next section on how to upload files without needing to set that.
This can be a little more complex as we are now dealing not just with only text values and instead with binaries.
The only required field here is file
.
mutation createDocumentFile($file: Upload!) {
createDocumentFile(file: $file) {
id
downloadUrl
}
}
This section could vary depending on which language and packages you use. So to make it as easy to understand and follow for everyone, we will use curl.
The following example will upload a file named test.jpg
from the local directory to the inbox of your MemoMeister account.
$ curl https://api.memomeister.com/graphql \
-H 'authorization: api-key <YOUR-API-KEY>' \
-H 'X-Apollo-Operation-Name: createDocumentFile' \
-F operations='{ "query": "mutation createDocumentFile ($file: Upload!) { createDocumentFile(file: $file) { id downloadUrl } }", "variables": { "file": null } }' \
-F map='{ "0": ["variables.file"] }' \
-F 0=@test.jpg
If you want to read more about how it works, please have a look over the spec of the implementation https://github.com/jaydenseric/graphql-multipart-request-spec
The ordering of the fields in the multipart request is important. The operations
field must be the first field, followed by the map
field, and then the files. In case this does not work out for you, then the S3 Upload Version might be the better option for you.
We might change the file extension slightly depending on the file and the filename. We do this to ensure that the extension is the right one for the file contents to avoid issues in our system and customer confusion.
Creating a Document with uploading to S3 Directly (Multipart upload)
Another option to upload files is to upload them directly to S3. This is useful when you have a big file that you want to upload in parts or when you want to have a resumeable upload. To achieve this you at least need 2 mutations. startUploadTransaction
and createDocumentFromUploadTransaction
.
A part can be between 5mb and 1gb in size. the last or only part can be as big as it needs to be
To initiate the upload you need to call startUploadTransaction
with the filename and the partCount. The partCount is optional and can be used to directly get the first n parts signed urls.
# partCount: is useful when directly wanting to have the first n parts signed urls
mutation startUploadTransaction($filename: String!, $partCount: Int) {
startUploadTransaction(fileName: $filename, partCount: $partCount) {
uploadId
signedUrls {
partNumber
signedUrl
}
}
}
The response will contain the uploadId and the signedUrls. The signedUrls are a list of parts with the partNumber and the signedUrl. The signedUrl is the url where you can upload the part to. Those urls are only valid for a short time. In case URLs are expired, you can call getUploadTransactionSignedUrlForParts
to get new signed urls for the parts you need.
# in parts you specify a list of parts you want to get
mutation getUploadTransactionSignedUrlForParts(
$uploadId: String!
$parts: [Int]!
) {
getUploadTransactionSignedUrlForParts(uploadId: $uploadId, parts: $parts) {
uploadId
signedUrls {
partNumber
signedUrl
}
}
}
After you uploaded all parts you can call createDocumentFromUploadTransaction
to create the document. this mutation is similar to the createDocumentFile
mutation but instead of the file you pass in the uploadId and the parts.
# in this case parts is a list of { partNumber: int, etag: string }
# the rest of the arguments you can pass in here are the same as in any other createDocument mutation
mutation createDocumentFromUploadTransaction(
$uploadId: String!
$parts: [UploadTransactionPartsListType]!
) {
createDocumentFromUploadTransaction(uploadId: $uploadId, parts: $parts) {
id
}
}