first commit
This commit is contained in:
34
services/web/frontend/stories/fixtures/chat-messages.js
Normal file
34
services/web/frontend/stories/fixtures/chat-messages.js
Normal file
@@ -0,0 +1,34 @@
|
||||
const ONE_MINUTE = 60 * 1000
|
||||
|
||||
const user = {
|
||||
id: 'fake_user',
|
||||
first_name: 'mortimer',
|
||||
email: 'fake@example.com',
|
||||
}
|
||||
|
||||
const user2 = {
|
||||
id: 'another_fake_user',
|
||||
first_name: 'leopold',
|
||||
email: 'another_fake@example.com',
|
||||
}
|
||||
|
||||
let nextMessageId = 1
|
||||
|
||||
export function generateMessages(count) {
|
||||
const messages = []
|
||||
let timestamp = new Date().getTime() // newest message goes first
|
||||
for (let i = 0; i <= count; i++) {
|
||||
const author = Math.random() > 0.5 ? user : user2
|
||||
// modify the timestamp so the previous message has 70% chances to be within 5 minutes from
|
||||
// the current one, for grouping purposes
|
||||
timestamp -= (4.3 + Math.random()) * ONE_MINUTE
|
||||
|
||||
messages.push({
|
||||
id: '' + nextMessageId++,
|
||||
content: `message #${i}`,
|
||||
user: author,
|
||||
timestamp,
|
||||
})
|
||||
}
|
||||
return messages
|
||||
}
|
220
services/web/frontend/stories/fixtures/compile.js
Normal file
220
services/web/frontend/stories/fixtures/compile.js
Normal file
@@ -0,0 +1,220 @@
|
||||
import examplePdf from './storybook-example.pdf'
|
||||
import { cloneDeep } from 'lodash'
|
||||
|
||||
export const dispatchDocChanged = () => {
|
||||
window.dispatchEvent(
|
||||
new CustomEvent('doc:changed', { detail: { doc_id: 'foo' } })
|
||||
)
|
||||
}
|
||||
|
||||
export const outputFiles = [
|
||||
{
|
||||
path: 'output.pdf',
|
||||
build: '123',
|
||||
url: '/build/output.pdf',
|
||||
type: 'pdf',
|
||||
},
|
||||
{
|
||||
path: 'output.bbl',
|
||||
build: '123',
|
||||
url: '/build/output.bbl',
|
||||
type: 'bbl',
|
||||
},
|
||||
{
|
||||
path: 'output.bib',
|
||||
build: '123',
|
||||
url: '/build/output.bib',
|
||||
type: 'bib',
|
||||
},
|
||||
{
|
||||
path: 'example.txt',
|
||||
build: '123',
|
||||
url: '/build/example.txt',
|
||||
type: 'txt',
|
||||
},
|
||||
{
|
||||
path: 'output.log',
|
||||
build: '123',
|
||||
url: '/build/output.log',
|
||||
type: 'log',
|
||||
},
|
||||
{
|
||||
path: 'output.blg',
|
||||
build: '123',
|
||||
url: '/build/output.blg',
|
||||
type: 'blg',
|
||||
},
|
||||
]
|
||||
|
||||
export const mockCompile = (fetchMock, delay = 1000) =>
|
||||
fetchMock.post(
|
||||
'express:/project/:projectId/compile',
|
||||
{
|
||||
body: {
|
||||
status: 'success',
|
||||
clsiServerId: 'foo',
|
||||
compileGroup: 'priority',
|
||||
pdfDownloadDomain: '',
|
||||
outputFiles: cloneDeep(outputFiles),
|
||||
},
|
||||
},
|
||||
{ delay }
|
||||
)
|
||||
|
||||
export const mockCompileError = (fetchMock, status = 'success', delay = 1000) =>
|
||||
fetchMock.post(
|
||||
'express:/project/:projectId/compile',
|
||||
{
|
||||
body: {
|
||||
status,
|
||||
clsiServerId: 'foo',
|
||||
compileGroup: 'priority',
|
||||
},
|
||||
},
|
||||
{ delay, overwriteRoutes: true }
|
||||
)
|
||||
|
||||
export const mockCompileValidationIssues = (
|
||||
fetchMock,
|
||||
validationProblems,
|
||||
delay = 1000
|
||||
) =>
|
||||
fetchMock.post(
|
||||
'express:/project/:projectId/compile',
|
||||
() => {
|
||||
return {
|
||||
body: {
|
||||
status: 'validation-problems',
|
||||
validationProblems,
|
||||
clsiServerId: 'foo',
|
||||
compileGroup: 'priority',
|
||||
},
|
||||
}
|
||||
},
|
||||
{ delay }
|
||||
)
|
||||
|
||||
export const mockClearCache = fetchMock =>
|
||||
fetchMock.delete('express:/project/:projectId/output', 204, {
|
||||
delay: 1000,
|
||||
})
|
||||
|
||||
export const mockBuildFile = fetchMock =>
|
||||
fetchMock.get('express:/build/:file', (url, options, request) => {
|
||||
const { pathname } = new URL(url, 'https://example.com')
|
||||
|
||||
switch (pathname) {
|
||||
case '/build/output.blg':
|
||||
return 'This is BibTeX, Version 4.0' // FIXME
|
||||
|
||||
case '/build/output.log':
|
||||
return `
|
||||
The LaTeX compiler output
|
||||
* With a lot of details
|
||||
|
||||
Wrapped in an HTML <pre> element with
|
||||
preformatted text which is to be presented exactly
|
||||
as written in the HTML file
|
||||
|
||||
(whitespace included™)
|
||||
|
||||
The text is typically rendered using a non-proportional ("monospace") font.
|
||||
|
||||
LaTeX Font Info: External font \`cmex10' loaded for size
|
||||
(Font) <7> on input line 18.
|
||||
LaTeX Font Info: External font \`cmex10' loaded for size
|
||||
(Font) <5> on input line 18.
|
||||
! Undefined control sequence.
|
||||
<recently read> \\Zlpha
|
||||
|
||||
main.tex, line 23
|
||||
|
||||
`
|
||||
|
||||
case '/build/output.pdf':
|
||||
return new Promise(resolve => {
|
||||
const xhr = new XMLHttpRequest()
|
||||
xhr.addEventListener('load', () => {
|
||||
resolve({
|
||||
status: 200,
|
||||
headers: {
|
||||
'Content-Length': xhr.getResponseHeader('Content-Length'),
|
||||
'Content-Type': xhr.getResponseHeader('Content-Type'),
|
||||
},
|
||||
body: xhr.response,
|
||||
})
|
||||
})
|
||||
xhr.open('GET', examplePdf)
|
||||
xhr.responseType = 'arraybuffer'
|
||||
xhr.send()
|
||||
})
|
||||
|
||||
default:
|
||||
console.log(pathname)
|
||||
return 404
|
||||
}
|
||||
})
|
||||
|
||||
const mockHighlights = [
|
||||
{
|
||||
page: 1,
|
||||
h: 85.03936,
|
||||
v: 509.999878,
|
||||
width: 441.921265,
|
||||
height: 8.855677,
|
||||
},
|
||||
{
|
||||
page: 1,
|
||||
h: 85.03936,
|
||||
v: 486.089539,
|
||||
width: 441.921265,
|
||||
height: 8.855677,
|
||||
},
|
||||
{
|
||||
page: 1,
|
||||
h: 85.03936,
|
||||
v: 498.044708,
|
||||
width: 441.921265,
|
||||
height: 8.855677,
|
||||
},
|
||||
{
|
||||
page: 1,
|
||||
h: 85.03936,
|
||||
v: 521.955078,
|
||||
width: 441.921265,
|
||||
height: 8.855677,
|
||||
},
|
||||
]
|
||||
|
||||
export const mockEventTracking = fetchMock =>
|
||||
fetchMock.get('express:/event/:event', 204)
|
||||
|
||||
export const mockValidPdf = fetchMock =>
|
||||
fetchMock.get('express:/build/output.pdf', (url, options, request) => {
|
||||
return new Promise(resolve => {
|
||||
const xhr = new XMLHttpRequest()
|
||||
xhr.addEventListener('load', () => {
|
||||
resolve({
|
||||
status: 200,
|
||||
headers: {
|
||||
'Content-Length': xhr.getResponseHeader('Content-Length'),
|
||||
'Content-Type': xhr.getResponseHeader('Content-Type'),
|
||||
'Accept-Ranges': 'bytes',
|
||||
},
|
||||
body: xhr.response,
|
||||
})
|
||||
})
|
||||
xhr.open('GET', examplePdf)
|
||||
xhr.responseType = 'arraybuffer'
|
||||
xhr.send()
|
||||
})
|
||||
})
|
||||
|
||||
export const mockSynctex = fetchMock =>
|
||||
fetchMock
|
||||
.get('express:/project/:projectId/sync/code', () => {
|
||||
return { pdf: cloneDeep(mockHighlights) }
|
||||
})
|
||||
.get('express:/project/:projectId/sync/pdf', () => {
|
||||
return { code: [{ file: 'main.tex', line: 100 }] }
|
||||
})
|
41
services/web/frontend/stories/fixtures/contacts.js
Normal file
41
services/web/frontend/stories/fixtures/contacts.js
Normal file
@@ -0,0 +1,41 @@
|
||||
export const contacts = [
|
||||
// user with edited name
|
||||
{
|
||||
type: 'user',
|
||||
email: 'test-user@example.com',
|
||||
first_name: 'Test',
|
||||
last_name: 'User',
|
||||
name: 'Test User',
|
||||
},
|
||||
// user with default name (email prefix)
|
||||
{
|
||||
type: 'user',
|
||||
email: 'test@example.com',
|
||||
first_name: 'test',
|
||||
},
|
||||
// no last name
|
||||
{
|
||||
type: 'user',
|
||||
first_name: 'Eratosthenes',
|
||||
email: 'eratosthenes@example.com',
|
||||
},
|
||||
// more users
|
||||
{
|
||||
type: 'user',
|
||||
first_name: 'Claudius',
|
||||
last_name: 'Ptolemy',
|
||||
email: 'ptolemy@example.com',
|
||||
},
|
||||
{
|
||||
type: 'user',
|
||||
first_name: 'Abd al-Rahman',
|
||||
last_name: 'Al-Sufi',
|
||||
email: 'al-sufi@example.com',
|
||||
},
|
||||
{
|
||||
type: 'user',
|
||||
first_name: 'Nicolaus',
|
||||
last_name: 'Copernicus',
|
||||
email: 'copernicus@example.com',
|
||||
},
|
||||
]
|
40
services/web/frontend/stories/fixtures/document.ts
Normal file
40
services/web/frontend/stories/fixtures/document.ts
Normal file
@@ -0,0 +1,40 @@
|
||||
export function mockDocument(text: string) {
|
||||
return {
|
||||
doc_id: 'story-doc',
|
||||
getSnapshot: () => text,
|
||||
hasBufferedOps: () => false,
|
||||
}
|
||||
}
|
||||
|
||||
export const document = {
|
||||
tex: `\\documentclass{article}
|
||||
|
||||
% Language setting
|
||||
% Replace \`english' with e.g. \`spanish' to change the document language
|
||||
\\usepackage[english]{babel}
|
||||
|
||||
% Set page size and margins
|
||||
% Replace \`letterpaper' with\`a4paper' for UK/EU standard size
|
||||
\\usepackage[letterpaper,top=2cm,bottom=2cm,left=3cm,right=3cm,marginparwidth=1.75cm]{geometry}
|
||||
|
||||
% Useful packages
|
||||
\\usepackage{amsmath}
|
||||
\\usepackage{graphicx}
|
||||
\\usepackage[colorlinks=true, allcolors=blue]{hyperref}
|
||||
|
||||
\\title{Your Paper}
|
||||
\\author{You}
|
||||
|
||||
\\begin{document}
|
||||
\\maketitle
|
||||
|
||||
\\begin{abstract}
|
||||
Your abstract.
|
||||
\\end{abstract}
|
||||
|
||||
\\section{Introduction}
|
||||
|
||||
Your introduction goes here! Simply start writing your document and use the Recompile button to view the updated PDF preview. Examples of commonly used commands and features are listed below, to help you get started.
|
||||
|
||||
Once you're familiar with the editor, you can find various project setting in the Overleaf menu, accessed via the button in the very top left of the editor. To view tutorials, user guides, and further documentation, please visit our \\href{https://www.overleaf.com/learn}{help library}, or head to our plans page to \\href{https://www.overleaf.com/user/subscription/plans}{choose your plan}.`,
|
||||
}
|
44
services/web/frontend/stories/fixtures/file-tree-base.js
Normal file
44
services/web/frontend/stories/fixtures/file-tree-base.js
Normal file
@@ -0,0 +1,44 @@
|
||||
export const rootFolderBase = [
|
||||
{
|
||||
_id: '5e74f1a7ce17ae0041dfd054',
|
||||
name: 'rootFolder',
|
||||
folders: [
|
||||
{
|
||||
_id: '5f638e58b652df0026c5c8f5',
|
||||
name: 'a folder',
|
||||
folders: [
|
||||
{
|
||||
_id: '5f956f62700e19000177daa0',
|
||||
name: 'sub folder',
|
||||
folders: [],
|
||||
fileRefs: [],
|
||||
docs: [],
|
||||
},
|
||||
],
|
||||
fileRefs: [
|
||||
{ _id: '5cffb9d93da45d3995d05362', name: 'file-in-a-folder.pdf' },
|
||||
],
|
||||
docs: [
|
||||
{ _id: '5f46786322d556004e72a555', name: 'doc-in-a-folder.tex' },
|
||||
],
|
||||
},
|
||||
{
|
||||
_id: '5f638e68b652df0026c5c8f6',
|
||||
name: 'another folder',
|
||||
folders: [],
|
||||
fileRefs: [],
|
||||
docs: [],
|
||||
},
|
||||
],
|
||||
fileRefs: [{ _id: '5f11c78e0924770027412a67', name: 'univers.jpg' }],
|
||||
docs: [
|
||||
{ _id: '5e74f1a7ce17ae0041dfd056', name: 'main.tex' },
|
||||
{ _id: '5f46789522d556004e72a556', name: 'perso.bib' },
|
||||
{
|
||||
_id: '5da532e29019e800015321c6',
|
||||
name: 'zotero.bib',
|
||||
linkedFileData: { provider: 'zotero' },
|
||||
},
|
||||
],
|
||||
},
|
||||
]
|
52
services/web/frontend/stories/fixtures/file-tree-limit.js
Normal file
52
services/web/frontend/stories/fixtures/file-tree-limit.js
Normal file
@@ -0,0 +1,52 @@
|
||||
const FILE_PER_FOLDER = 2
|
||||
const DOC_PER_FOLDER = 3
|
||||
const FOLDER_PER_FOLDER = 2
|
||||
const MAX_DEPTH = 7
|
||||
|
||||
function fakeId() {
|
||||
return Math.random().toString(16).replace(/0\./, 'random-test-id-')
|
||||
}
|
||||
|
||||
function makeFileRefs(path) {
|
||||
const fileRefs = []
|
||||
|
||||
for (let index = 0; index < FILE_PER_FOLDER; index++) {
|
||||
fileRefs.push({ _id: fakeId(), name: `${path}-file-${index}.jpg` })
|
||||
}
|
||||
return fileRefs
|
||||
}
|
||||
|
||||
function makeDocs(path) {
|
||||
const docs = []
|
||||
|
||||
for (let index = 0; index < DOC_PER_FOLDER; index++) {
|
||||
docs.push({ _id: fakeId(), name: `${path}-doc-${index}.tex` })
|
||||
}
|
||||
return docs
|
||||
}
|
||||
|
||||
function makeFolders(path, depth = 0) {
|
||||
const folders = []
|
||||
|
||||
for (let index = 0; index < FOLDER_PER_FOLDER; index++) {
|
||||
const folderPath = `${path}-folder-${index}`
|
||||
folders.push({
|
||||
_id: fakeId(),
|
||||
name: folderPath,
|
||||
folders: depth < MAX_DEPTH ? makeFolders(folderPath, depth + 1) : [],
|
||||
fileRefs: makeFileRefs(folderPath),
|
||||
docs: makeDocs(folderPath),
|
||||
})
|
||||
}
|
||||
return folders
|
||||
}
|
||||
|
||||
export const rootFolderLimit = [
|
||||
{
|
||||
_id: fakeId(),
|
||||
name: 'rootFolder',
|
||||
folders: makeFolders('root'),
|
||||
fileRefs: makeFileRefs('root'),
|
||||
docs: makeDocs('root'),
|
||||
},
|
||||
]
|
48
services/web/frontend/stories/fixtures/project.ts
Normal file
48
services/web/frontend/stories/fixtures/project.ts
Normal file
@@ -0,0 +1,48 @@
|
||||
import { Project } from '../../../types/project'
|
||||
|
||||
export const project: Project = {
|
||||
_id: '63e21c07946dd8c76505f85a',
|
||||
name: 'A Project',
|
||||
features: {
|
||||
collaborators: -1, // unlimited
|
||||
},
|
||||
publicAccesLevel: 'private',
|
||||
tokens: {
|
||||
readOnly: 'ro-token',
|
||||
readAndWrite: 'rw-token',
|
||||
},
|
||||
owner: {
|
||||
_id: 'project-owner',
|
||||
email: 'stories@overleaf.com',
|
||||
},
|
||||
members: [
|
||||
{
|
||||
_id: 'viewer-member',
|
||||
type: 'user',
|
||||
privileges: 'readOnly',
|
||||
name: 'Viewer User',
|
||||
email: 'viewer@example.com',
|
||||
},
|
||||
{
|
||||
_id: 'author-member',
|
||||
type: 'user',
|
||||
privileges: 'readAndWrite',
|
||||
name: 'Author User',
|
||||
email: 'author@example.com',
|
||||
},
|
||||
],
|
||||
invites: [
|
||||
{
|
||||
_id: 'test-invite-1',
|
||||
privileges: 'readOnly',
|
||||
name: 'Invited Viewer',
|
||||
email: 'invited-viewer@example.com',
|
||||
},
|
||||
{
|
||||
_id: 'test-invite-2',
|
||||
privileges: 'readAndWrite',
|
||||
name: 'Invited Author',
|
||||
email: 'invited-author@example.com',
|
||||
},
|
||||
],
|
||||
}
|
BIN
services/web/frontend/stories/fixtures/storybook-example.pdf
Normal file
BIN
services/web/frontend/stories/fixtures/storybook-example.pdf
Normal file
Binary file not shown.
Reference in New Issue
Block a user