Просмотр исходного кода

starting to generalize from labels to metadata

Nate Stemen 9 лет назад
Родитель
Сommit
e53a24f8f5

+ 36 - 0
services/web/app/coffee/Features/ProjectMetadata/MetadataController.coffee

@@ -0,0 +1,36 @@
+EditorRealTimeController = require "../Editor/EditorRealTimeController"
+MetadataHandler = require './MetadataHandler'
+logger = require 'logger-sharelatex'
+
+
+module.exports = MetadataController =
+
+	getAllMetadata: (req, res, next) ->
+		project_id = req.params.project_id
+		logger.log {project_id}, "getting metadata for project"
+		MetadataHandler.getMetadataForProject project_id, (err, projectMetadata) ->
+			if err?
+				logger.err {project_id, err}, "[MetadataController] error getting metadata from project"
+				return next(err)
+			res.json {
+				projectId: project_id
+				projectLabels: projectMetadata["labels"]
+				projectPackages: projectMetadata["packages"]
+			}
+
+	broadcastMetadataForDoc: (req, res, next) ->
+		project_id = req.params.project_id
+		doc_id = req.params.doc_id
+		logger.log {project_id, doc_id}, "getting metadata for doc"
+		MetadataHandler.getMetadataForDoc project_id, doc_id, (err, docMetadata) ->
+			if err?
+				logger.err {project_id, doc_id, err}, "[MetadataController] error getting metadata from doc"
+				return next(err)
+			EditorRealTimeController.emitToRoom project_id, "broadcastDocMetadata", {
+				docId: doc_id
+				metadata: {
+					labels: docMetadata["labels"]
+					packages: docMetadata["packages"]
+				}
+			}
+			res.sendStatus(200)

+ 50 - 0
services/web/app/coffee/Features/ProjectMetadata/MetadataHandler.coffee

@@ -0,0 +1,50 @@
+ProjectEntityHandler = require "../Project/ProjectEntityHandler"
+DocumentUpdaterHandler = require '../DocumentUpdater/DocumentUpdaterHandler'
+
+
+module.exports = MetadataHandler =
+
+	labelCaptureRegex: () ->
+		/\\label\{([^\}\n\\]{0,80})\}/g
+
+	packageCaptureRegex: () ->
+		/\\usepackage(?:\[((?:.|\n)*?)])?\s*?{((?:.|\n)*?)}/gm
+
+	getMetadataForProject: (projectId, callback=(err, projectMetadata)->) ->
+		DocumentUpdaterHandler.flushProjectToMongo projectId. (err) ->
+			if err?
+				return callback(err)
+			ProjectEntityHandler.getAllDocs projectId, (err, docs) ->
+				if err?
+					return callback(err)
+				projectMetadata = MetadataHandler.extractMetadataFromProjectDocs docs
+				callback(null, projectMetadata)
+
+	getMetadataForDoc: (projectId, docId, callback=(err, docMetadata)->) ->
+		DocumentUpdaterHandler.flushDocToMongo projectId, docId, (err) ->
+			if err?
+				return callback(err)
+			ProjectEntityHandler.getDoc projectId, docId, (err, lines) ->
+				if err?
+					return callback(err)
+				docMetadata = MetadataHandler.extractMetadataFromDoc lines
+				callback(null, docMetadata)
+
+	extractMetadataFromProjectDocs: (projectDocs) ->
+		projectMetadata = {}
+		for _path, doc of projectDocs
+			projectMetadata[doc._id] = MetadataHandler.extractMetadataFromDoc doc.lines
+		return projectMetadata
+
+	extractMetadataFromDoc: (lines) ->
+		docMetadata = {labels: [] packages: []}
+		label_re = MetadataHandler.labelCaptureRegex()
+		package_re = MetadataHandler.packageCaptureRegex()
+		for line in lines # FIXME: usepackage can run over multiple lines
+			while labelMatch = label_re.exec line
+				if labelMatch[1]
+					docMetadata.labels.push labelMatch[1]
+			while packageMatch = package_re.exec line
+				if packageMatch[2]
+					docMetadata.packages.push packageMatch[2]
+		return docMetadata

+ 3 - 0
services/web/app/coffee/router.coffee

@@ -204,6 +204,9 @@ module.exports = class Router
 		webRouter.get '/project/:project_id/labels', AuthorizationMiddlewear.ensureUserCanReadProject, AuthenticationController.requireLogin(), LabelsController.getAllLabels
 		webRouter.post '/project/:project_id/doc/:doc_id/labels', AuthorizationMiddlewear.ensureUserCanReadProject, AuthenticationController.requireLogin(), LabelsController.broadcastLabelsForDoc
 
+		webRouter.get '/project/:project_id/metadata', AuthorizationMiddlewear.ensureUserCanReadProject, AuthenticationController.requireLogin(), MetadataController.getAllMetadata
+		webRouter.post '/project/:project_id/doc/:doc_id/metadata'. AuthorizationMiddlewear.ensureUserCanReadProject, AuthenticationController.requireLogin(), MetadataController.broadcastMetadataForDoc
+
 		webRouter.get    '/tag', AuthenticationController.requireLogin(), TagsController.getAllTags
 		webRouter.post   '/tag', AuthenticationController.requireLogin(), TagsController.createTag
 		webRouter.post   '/tag/:tag_id/rename', AuthenticationController.requireLogin(), TagsController.renameTag

+ 13 - 0
services/web/public/coffee/ide/metadata/MetadataManager.coffee

@@ -0,0 +1,13 @@
+define [], () ->
+
+	class MetadataManager
+
+		constructor: (@ide, @$scope, @metadata) ->
+
+			@ide.socket.on 'broadcastDocMetadata', (data) =>
+				@metadata.onBroadcastDocMetadata(data)
+			@$scope.$on 'entity:deleted', @metadata.onEntityDeleted
+			@$scope.$on 'file:upload:complete', @metadata.fileUploadComplete
+
+		loadProjectMetadataFromServer: () ->
+			@metadata.loadProjectMetadataFromServer()

+ 46 - 0
services/web/public/coffee/ide/metadata/services/metadata.coffee

@@ -0,0 +1,46 @@
+define [
+	"base"
+], (App) ->
+
+	App.factory 'metadata', ($http, ide) ->
+
+		state = {documents: {}}
+
+		metadata = {
+			state: state
+		}
+
+		metadata.onBroadcastDocMetadata = (data) ->
+			if data.docId and data.metadata
+				state.documents[data.docId] = data.metadata
+
+		metadata.onEntityDeleted = (e, entity) ->
+			if entity.type == 'doc'
+				delete state.documents[entity.id]
+
+		metadata.onFileUploadComplete = (e, upload) ->
+			if upload.entity_type == 'doc'
+				metadata.loadDocMetadataFromServer(upload.entity_id)
+
+		metadata.getAllMetadata = () ->
+			labels = _.flatten(meta['labels'] for docId, meta of state.documents)
+			packages = _.flatten(meta['packages'] for docId, meta of state.documents)
+			{labels: labels, packages: packages}
+
+		metadata.loadProjectMetadataFromServer = () ->
+			$http
+				.get("/project/#{window.project_id}/metadata")
+				.then (response) ->
+					{ data } = response
+					if data.projectMetadata
+						for docId, docMetadata of data.projectMetadata
+							state.documents[docId] = docMetadata
+
+		metadata.loadDocMetadataFromServer = (docId) ->
+			$http
+				.post(
+					"/project/#{window.project_id}/doc/#{docId}/metadata",
+					{_csrf: window.csrfToken}
+				)
+
+		return metadata