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

New project page components #342

Open
wants to merge 62 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
62 commits
Select commit Hold shift + click to select a range
c5b5433
New project page
dhovart May 9, 2022
4ef39db
Add image adjustment settings component
dhovart Jun 7, 2022
b14ac30
Add Up / down arrows listeners on project page. Fix measurement tool
dhovart Jun 7, 2022
ae53c94
Add scriptconsole components. Clean up atlasmaker a bit
dhovart Jun 8, 2022
0f0b2a6
Update range slider
dhovart Jun 8, 2022
0cc2e78
Make sure to display notifications properly
dhovart Jun 8, 2022
ce5726c
Regenerate package lock file
dhovart Jun 8, 2022
32a8e74
Remove jQuery. Reorganize components using vue sfcs
dhovart Jun 9, 2022
0723cd0
Refactor MRI page (wip)
dhovart Jun 19, 2022
c4d214a
Make MRI and tools layout adaptative
dhovart Jun 26, 2022
f7a0561
Finalize the MRI page (display annotation access, style tweaks)
dhovart Jun 26, 2022
da67060
Update toolbar appearance & make it resizable
dhovart Jul 2, 2022
9ac11fa
Correct tools appearance, fix resizing issues
dhovart Aug 9, 2022
9def0c8
Fix default tools height
dhovart Aug 9, 2022
569b147
Sync annotations with atlasmaker server
dhovart Aug 9, 2022
5d0a8ea
Fix height and resizing issues
dhovart Aug 10, 2022
7a1e715
Update MRI page
dhovart Aug 10, 2022
c17f7bd
Properly resize visualization on MRI pages
dhovart Sep 20, 2022
95a9754
Correct tools resizing issues
dhovart Sep 21, 2022
c251b35
Add missing project name
dhovart Sep 26, 2022
13b3cef
Fix resize & fullscreen issues
dhovart Sep 26, 2022
92a6a54
Add embed page
dhovart Oct 24, 2022
cb81164
bump nwl-components package to 1.2.1
Jan 5, 2023
935f14b
update authenticated call count check in mri controller unit test
ntraut Feb 9, 2023
3ed8e97
fix vue compiler
ntraut Apr 13, 2023
15f3809
Fix badly resolved conflicts and remove Y.js related code for now
dhovart Jul 19, 2023
841c3ac
sync changes using hocus pocus as yjs backend
dhovart Jul 20, 2023
e0fc87a
Adjust chat height
dhovart Jul 21, 2023
b22ce6b
fix: iPad fixes
denishov Jul 25, 2023
c37fe0d
Display current slice on MRI page in tools palette header
denishov Jul 28, 2023
3e3e97b
Handle cases where MRI is empty
denishov Jul 28, 2023
c47654f
Update title in embedded projects. Add button on settings to embed pr…
denishov Jul 28, 2023
551e684
remove hardcoded crdt backend address
denishov Aug 2, 2023
1d2eb24
Handle user preferences
denishov Aug 8, 2023
8af4bb0
restore logToDatabase function
ntraut Sep 18, 2023
15345ac
give more flexibility to server configuration
ntraut Sep 18, 2023
afbb980
add eslint config for .vue files
ntraut Sep 22, 2023
de68bcd
close hocuspocus server at the end of tests
ntraut Sep 22, 2023
bf9684f
restore accidentally removed imports
ntraut Sep 23, 2023
d3c6ed9
Fix bad merge (#371)
denishov Sep 29, 2023
20161f6
Remove message that should not be logged in chat (#370)
denishov Sep 29, 2023
e66c4a8
Highlight fullscreen button when fullscreen is active (#369)
denishov Oct 2, 2023
30cb8c9
Properly lint Tools.vue
denishov Oct 2, 2023
11bf5dd
Bump nwl-components / style updates (#372)
denishov Oct 4, 2023
5eb59e1
Make sure vector layer is properly redimensionned (#368)
denishov Oct 4, 2023
0ada96c
Bump nwl-components / fade in and out for save feedback (#374)
denishov Oct 4, 2023
59d5b78
Hide by default chat in MRI mode (#375)
denishov Oct 10, 2023
a746c46
fix linting issues
ntraut Oct 19, 2023
f219d79
Fix integration tests
denishov Nov 23, 2023
0927e2f
Fix brainbox unit tests
denishov Nov 28, 2023
ae5c720
fix object merge function
ntraut Nov 29, 2023
b306d51
fix bad svg created before brain is loaded
ntraut Nov 29, 2023
7ea9c02
fix some server crashes
ntraut Nov 29, 2023
f542d63
small fixes
ntraut Dec 13, 2023
b1599e4
upgrade webpack to v5
ntraut Dec 18, 2023
19fb533
Properly check if content can be embedded (#385)
denishov Dec 29, 2023
92cf6d1
Add CSP header to allow embedding only by specific domains set in the…
denishov Jan 28, 2024
7b6b177
remove invalid characters in authorized host list
ntraut Feb 12, 2024
6052d51
lint code
ntraut Mar 29, 2024
278f29b
check that authorized hosts are valid url
ntraut Mar 29, 2024
94e4f03
return empty file array for empty project instead of void
ntraut Mar 29, 2024
1809245
set up vue compile flags
ntraut Jul 5, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .eslintignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
/public/lib/
/public/js/
/public/js/*
!/public/js/surfacenets-worker.js
dist/
/view/atlasmaker/src/tools/render3D/three.js*
12 changes: 11 additions & 1 deletion .eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,15 @@ module.exports = {
'env': {
'mocha': true
},
'extends': ['naat']
'extends': ['naat', 'plugin:vue/vue3-strongly-recommended'],
'rules': { 'vue/multi-word-component-names': 'off' },
'overrides': [
{
files: ['*.vue'],
rules: {
// 300 lines limit seems to short for *.vue files
'max-lines': 'off'
}
}
]
};
10 changes: 2 additions & 8 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,8 @@ public/_img-all/
public/.DS_Store
public/data
public/doc2/*
public/js/
public/js/ask-for-login-page.js
public/js/index-page.js
public/js/mri-page.js
public/js/project-new-page.js
public/js/project-page.js
public/js/project-settings-page.js
public/js/user-page.js
/public/js/*
!/public/js/surfacenets-worker.js
public/lib/.DS_Store
public/lib/atlasmaker-tools
public/lib/atlasmaker.js
Expand Down
12 changes: 9 additions & 3 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,14 @@
"[javascript]": {
"editor.formatOnSave": false,
"editor.codeActionsOnSave": [
"source.formatDocument", // used by rohit-gohri.format-code-action
"source.fixAll.eslint" // used by dbaeumer.vscode-eslint
// "source.formatDocument", // problem with switch case multi lines comment indents
"source.fixAll.eslint"
]
},
"[vue]": {
"editor.formatOnSave": false,
"editor.codeActionsOnSave": {
"source.fixAll.eslint": true
},
}
}
}
42 changes: 32 additions & 10 deletions app.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,21 +4,21 @@
Atlas Maker Server
Roberto Toro, 25 July 2014
*/
const nwl = require('neuroweblab');
const fs = require('fs');
const path = require('path');
const https = require('https');
const http = require('http');
const nwl = require('neuroweblab');
const express = require('express');
const compression = require('compression');
const path = require('path');
const favicon = require('serve-favicon');
const logger = require('morgan');
const tracer = require('tracer').console({ format: '[{{file}}:{{line}}] {{message}}' });
const cookieParser = require('cookie-parser');
const bodyParser = require('body-parser');
const mustacheExpress = require('mustache-express');
const Config = JSON.parse(fs.readFileSync('./cfg.json'));
const https = require('https');
const http = require('http');

const { Server: HocuspocusServer } = require('@hocuspocus/server');
global.authTokenMiddleware = nwl.authTokenMiddleware;

const AtlasmakerServer = require('./controller/atlasmakerServer/atlasmakerServer');
Expand Down Expand Up @@ -129,7 +129,7 @@ const start = async function () {
// Configure server and web socket
//========================================================================================

const server = http.createServer(app).listen(3001, () => { console.log('Listening http on port 3001'); });
const server = http.createServer(app).listen(Config.app_port, () => { console.log(`Listening http on port ${Config.app_port}`); });
const atlasmakerServer = new AtlasmakerServer(db);
atlasmakerServer.dataDirectory = dirname + '/public';

Expand All @@ -146,15 +146,37 @@ const start = async function () {
atlasmakerServer.server = http.createServer(app);
}

atlasmakerServer.server.listen(8080, () => {
atlasmakerServer.server.listen(Config.ws_port, () => {
if (Config.secure) {
console.log('Listening wss on port 8080');
console.log(`Listening wss on port ${Config.ws_port}`);
} else {
console.log('Listening ws on port 8080');
console.log(`Listening ws on port ${Config.ws_port}`);
}
atlasmakerServer.initSocketConnection();
});

//========================================================================================
// Configure Yjs backend for multiuser edition
//========================================================================================

const hocuspocusServer = HocuspocusServer.configure({
port: Config.crdt_backend_port,
onDisconnect(data) {
data.document.getArray('files').toJSON()
.forEach((json) => {
delete json._id;
db.get('mri').update({
source: json.source,
backup: { $exists: false }
}, json
, { replaceOne: true })
.catch((er) => console.log(er));
});
}
});

hocuspocusServer.listen();

//========================================================================================
// Setup routes
//========================================================================================
Expand Down Expand Up @@ -192,7 +214,7 @@ const start = async function () {
// });
// });

return { app, server, atlasmakerServer };
return { app, server, atlasmakerServer, hocuspocusServer };
};

module.exports = { start };
6 changes: 5 additions & 1 deletion cfg.json.example
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
{
"hostname": "http://localhost:3001",
"wshostname": "localhost:8080",
"wshostname": "ws://localhost:8080",
"app_port": 3001,
"ws_port": 8080,
"crdt_backend_url": "ws://localhost:8081",
"crdt_backend_port": "8081",
"secure": false,
"ssl_key": "./key.pem",
"ssl_cert": "./cert.pem",
Expand Down
52 changes: 33 additions & 19 deletions controller/atlasmakerServer/atlasmakerServer.js
Original file line number Diff line number Diff line change
@@ -1,15 +1,23 @@
/* eslint-disable max-lines */
const fs = require('fs');
const os = require('os');
const path = require('path');
const zlib = require('zlib');
const tracer = require('tracer').console({ format: '[{{file}}:{{line}}] {{message}}' });

const AsyncLock = require('async-lock');
const createDOMPurify = require('dompurify');
const jsonpatch = require('fast-json-patch');
const jpeg = require('jpeg-js'); // jpeg-js library: https://github.com/eugeneware/jpeg-js
const merge = require('merge');
const path = require('path');
const { JSDOM } = require('jsdom');
const keypress = require('keypress');
const merge = require('merge');
const tracer = require('tracer').console({ format: '[{{file}}:{{line}}] {{message}}' });
const WebSocket = require('ws');

const notifier = require('../../notifier');

const amri = require('./atlasmaker-mri');
const AsyncLock = require('async-lock');

const lock = new AsyncLock();

// Get whitelist and blacklist
Expand All @@ -19,12 +27,9 @@ const whitelist = JSON.parse(fs.readFileSync(path.join(__dirname, 'whitelist.jso
const blacklist = JSON.parse(fs.readFileSync(path.join(__dirname, 'blacklist.json')));

// var http = require('http');
const WebSocket = require('ws');
const WebSocketServer = WebSocket.Server;
let websocketserver;

const createDOMPurify = require('dompurify');
const { JSDOM } = require('jsdom');
const { window } = (new JSDOM('', {
features: {
FetchExternalResources: false, // disables resource loading over HTTP / filesystem
Expand All @@ -33,7 +38,6 @@ const { window } = (new JSDOM('', {
}));
const DOMPurify = createDOMPurify(window);

const jsonpatch = require('fast-json-patch');

const bufferTag = function (str, sz) {
const buf = Buffer.alloc(sz).fill(32);
Expand Down Expand Up @@ -274,6 +278,7 @@ data.vox_offset: ${me.Brains[i].data.vox_offset}
}
},
removeAtlasAtIndex: function (iAtlas) {
// can throw an error if me.Atlases[iAtlas] is undefined
console.log(`INFO: Removing atlas ${me.Atlases[iAtlas].filename}`);
clearInterval(me.Atlases[iAtlas].timer);
delete me.Atlases[iAtlas];
Expand Down Expand Up @@ -322,12 +327,12 @@ data.vox_offset: ${me.Brains[i].data.vox_offset}
try {
await me._saveAtlasVoxelData(atlas);
} catch (err) {
throw new Error('Can\'t save atlas voxel data', err);
console.error('Can\'t save atlas voxel data', err);
}
try {
await me._saveAtlasVectorialData(atlas);
} catch (err) {
throw new Error('Can\'t save atlas vectorial data', err);
console.error('Can\'t save atlas vectorial data', err);
}
},

Expand All @@ -351,7 +356,8 @@ data.vox_offset: ${me.Brains[i].data.vox_offset}
try {
mri = await db.get('mri').findOne({ source: atlas.source, backup: { $exists: 0 } }, { _id: 0 });
} catch (err) {
throw new Error('Can\'t find entry for atlas voxel data in DB', err);
console.error(err);
throw new Error('Can\'t find entry for atlas voxel data in DB');
}

if (mri === null) {
Expand Down Expand Up @@ -1126,6 +1132,11 @@ data.vox_offset: ${me.Brains[i].data.vox_offset}
const sourceUS = me.getUserFromUserId(data.uid);

// get brainPath from User object
if (!sourceUS.User) {
console.error('sourceUS.User object still not created, do not try to get brain slice');

return;
}
const brainPath = sourceUS.User.dirname + sourceUS.User.mri;

// update User object
Expand All @@ -1139,7 +1150,8 @@ data.vox_offset: ${me.Brains[i].data.vox_offset}
me.getBrainAtPath(brainPath)
.then(function (theData) {
me.sendSliceToUser(theData, view, slice, userSocket);
});
})
.catch((err) => console.error(err));
},
receiveRequestSlice2Message: function (data, userSocket) {
const { view } = data; // user view
Expand Down Expand Up @@ -1337,7 +1349,8 @@ data.vox_offset: ${me.Brains[i].data.vox_offset}
try {
await Promise.all(results);
} catch (err) {
throw new Error('Can\'t unload atlases', err);
console.error('Can\'t unload atlases');
console.error(err);
}
},
_sendAtlasVoxelDataToUser: function (atlasdata, userSocket, flagCompress) {
Expand Down Expand Up @@ -1396,7 +1409,7 @@ data.vox_offset: ${me.Brains[i].data.vox_offset}
* @returns {Object} An atlas (mri structure)
*/
// eslint-disable-next-line max-statements
loadAtlas: async function loadAtlas(User) {
loadAtlas: async function loadAtlas (User) {
const mriPath = path.join(me.dataDirectory, User.dirname, User.atlasFilename);

if (typeof User.dirname === 'undefined') {
Expand Down Expand Up @@ -1619,9 +1632,9 @@ data.vox_offset: ${me.Brains[i].data.vox_offset}
me.sendAtlasToUser(atlas, userSocket, true);
sourceUS.User.isMRILoaded = true;
})
.catch((err) => console.log(new Error('ERROR: Unable to load atlas', err)));
.catch((err) => console.error('ERROR: Unable to load atlas', err));
}
} else {
} else if (User) {
// receive a specific field of the User data object from the user
/** @todo If the atlas/mri for the client failed to be sent, `User` is undefined */
const changes = JSON.parse(data.description);
Expand Down Expand Up @@ -1995,7 +2008,8 @@ data.vox_offset: ${me.Brains[i].data.vox_offset}
try {
await me.unloadAtlas(sourceUS.User.dirname, sourceUS.User.atlasFilename, sourceUS.specimenName);
} catch (err) {
throw new Error('Can\'t unload atlas', err);
console.error('Can\'t unload atlas');
console.error(err);
}
}
} else {
Expand Down Expand Up @@ -2047,7 +2061,8 @@ data.vox_offset: ${me.Brains[i].data.vox_offset}
try {
await me._disconnectUser({ ws });
} catch (err) {
throw new Error('Can\'t disconnect user', err);
console.error('Can\'t disconnect user');
console.error(err);
}
});
},
Expand Down Expand Up @@ -2108,7 +2123,6 @@ free memory: ${os.freemem()}
};

// Notifications
const notifier = require('../../notifier');
notifier.on('saveAllAtlases', () => {
atlasmakerServer.saveAllAtlases();
});
Expand Down
14 changes: 7 additions & 7 deletions controller/dataSlices/dataSlices.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
/* eslint-disable max-lines */
console.log('dataSlices.js');
const dateFormat = require('dateformat');
const { AccessLevel } = require('neuroweblab');

const { ForbiddenAccessError } = require('../../errors');
const { AccessLevel } = require('neuroweblab');
const BrainboxAccessControlService = require('../../services/BrainboxAccessControlService');

/**
Expand All @@ -15,7 +15,7 @@ const BrainboxAccessControlService = require('../../services/BrainboxAccessContr
* @param {integer} length Number of files to include in the slice
* @returns {Object} user files slice
*/
const getUserFilesSlice = function getUserFilesSlice(req, requestedUser, start, length) {
const getUserFilesSlice = function getUserFilesSlice (req, requestedUser, start, length) {
console.log('getUserFilesSlice. Start, end:', start, length);
let loggedUser = 'anonymous';
if (req.isAuthenticated()) {
Expand Down Expand Up @@ -81,7 +81,7 @@ const getUserFilesSlice = function getUserFilesSlice(req, requestedUser, start,
* @param {integer} length Number of files to include in the slice
* @returns {Object} user atlas slice
*/
const getUserAtlasSlice = function getUserAtlasSlice(req, requestedUser, start, length) {
const getUserAtlasSlice = function getUserAtlasSlice (req, requestedUser, start, length) {
let loggedUser = 'anonymous';
if (req.isAuthenticated()) {
loggedUser = req.user.username;
Expand Down Expand Up @@ -146,7 +146,7 @@ const getUserAtlasSlice = function getUserAtlasSlice(req, requestedUser, start,
* @param {integer} length Number of files to include in the slice
* @returns {Object} user projects slice
*/
const getUserProjectsSlice = function getUserProjectsSlice(req, requestedUser, start, length) {
const getUserProjectsSlice = function getUserProjectsSlice (req, requestedUser, start, length) {
let loggedUser = 'anonymous';
if (req.isAuthenticated()) {
loggedUser = req.user.username;
Expand Down Expand Up @@ -218,7 +218,7 @@ const getProjectFilesSlice = async (req, projShortname, start, length, namesFlag
if (!project) {
console.log('project is empty');

return;
return [];
}

// check access
Expand Down Expand Up @@ -281,7 +281,7 @@ const getProjectFilesSlice = async (req, projShortname, start, length, namesFlag
* @param {integer} length Number of files to include in the slice
* @returns {Object} files slice
*/
const getFilesSlice = function getFilesSlice(req, start, length) {
const getFilesSlice = function getFilesSlice (req, start, length) {
let loggedUser = 'anonymous';
if (req.isAuthenticated()) {
loggedUser = req.user.username;
Expand Down Expand Up @@ -332,7 +332,7 @@ const getFilesSlice = function getFilesSlice(req, start, length) {
* @returns {Object} project slice
*/
// eslint-disable-next-line max-statements
const getProjectsSlice = async function getProjectsSlice(req, start, length) {
const getProjectsSlice = async function getProjectsSlice (req, start, length) {
let loggedUser = 'anonymous';
if (req.isAuthenticated()) {
loggedUser = req.user.username;
Expand Down
Loading