James Allen 12 лет назад
Родитель
Сommit
f1eee96c85

+ 2 - 117
services/web/app/views/project/editor.jade

@@ -40,125 +40,10 @@ block content
 					i.fa.fa-comment
 
 		#editor-content(ng-cloak, layout="main", ng-hide="state.loading")
-			aside#file-tree.ui-layout-west(ng-controller="FileTreeController")
-				.toolbar.toolbar-small
-					a(
-						href,
-						ng-click="openNewDocModal()",
-						tooltip-html-unsafe="New<br>File",
-						tooltip-placement="bottom"
-					)
-						i.fa.fa-file
-					a(
-						href,
-						ng-click="openNewFolderModal()",
-						tooltip="New Folder",
-						tooltip-placement="bottom"
-					)
-						i.fa.fa-folder
-					a(href, tooltip="Upload File", tooltip-placement="bottom")
-						i.fa.fa-upload
-
-					.toolbar-right
-						a(href, tooltip="Rename", tooltip-placement="bottom")
-							i.fa.fa-pencil
-						a(href, tooltip="Delete", tooltip-placement="bottom", tooltip-append-to-body="true")
-							i.fa.fa-trash-o
-
-				ul.list-unstyled.file-tree-list
-					file-entity(
-						entity="entity",
-						ng-repeat="entity in rootFolder.children | orderBy:[orderByFoldersFirst, 'name']"
-					)
+			include ./editor/file-tree
+			
 			.ui-layout-center
 
-	script(type='text/ng-template', id='entityListItemTemplate')
-		li(
-			ng-class="{ 'selected': entity.selected }",
-			ng-controller="FileTreeEntityController"
-		)
-			.entity(ng-if="entity.type == 'doc'")
-				.entity-name(ng-click="select()")
-					//- Just a spacer to align with folders
-					i.fa.fa-fw.toggle
-					i.fa.fa-fw.fa-file
-					|  {{ entity.name }}
-
-			.entity(ng-if="entity.type == 'file'")
-				.entity-name(ng-click="select()")
-					i.fa.fa-fw.toggle
-					i.fa.fa-fw.fa-image
-					|  {{ entity.name }}
-
-			.entity(ng-if="entity.type == 'folder'", ng-controller="FileTreeFolderController")
-				.entity-name
-					i.fa.fa-fw.toggle(
-						ng-class="{'fa-chevron-right': !expanded, 'fa-chevron-down': expanded}"
-						ng-click="toggleExpanded()"
-					)
-				
-					i.fa.fa-fw(
-						ng-class="{\
-							'fa-folder': !expanded, \
-							'fa-folder-open': expanded \
-						}"
-						ng-click="select()"
-					)
-					span(ng-click="select()")  {{ entity.name }}
-
-				ul.list-unstyled(ng-show="expanded")
-					file-entity(entity="child", ng-repeat="child in entity.children | orderBy:[orderByFoldersFirst, 'name']")
-
-	script(type='text/ng-template', id='newDocModalTemplate')
-		.modal-header
-			h3 New File
-		.modal-body
-			form(novalidate, name="newDocForm")
-				input.form-control(
-					type="text",
-					placeholder="File Name",
-					required,
-					ng-model="inputs.name",
-					ng-enter="create()",
-					focus-on="open"
-				)
-		.modal-footer
-			button.btn.btn-default(
-				ng-disabled="state.inflight"
-				ng-click="cancel()"
-			) Cancel
-			button.btn.btn-primary(
-				ng-disabled="newDocForm.$invalid || state.inflight"
-				ng-click="create()"
-			)
-				span(ng-hide="state.inflight") Create
-				span(ng-show="state.inflight") Creating...
-
-	script(type='text/ng-template', id='newFolderModalTemplate')
-		.modal-header
-			h3 New File
-		.modal-body
-			form(novalidate, name="newFolderForm")
-				input.form-control(
-					type="text",
-					placeholder="Folder Name",
-					required,
-					ng-model="inputs.name",
-					ng-enter="create()",
-					focus-on="open"
-				)
-		.modal-footer
-			button.btn.btn-default(
-				ng-disabled="state.inflight"
-				ng-click="cancel()"
-			) Cancel
-			button.btn.btn-primary(
-				ng-disabled="newFolderForm.$invalid || state.inflight"
-				ng-click="create()"
-			)
-				span(ng-hide="state.inflight") Create
-				span(ng-show="state.inflight") Creating...
-
 	//- #loadingScreen
 	//- 	h3 Loading...
 	//- 	p#loadingMessage Loading editor

+ 143 - 0
services/web/app/views/project/editor/file-tree.jade

@@ -0,0 +1,143 @@
+aside#file-tree.ui-layout-west(ng-controller="FileTreeController")
+	.toolbar.toolbar-small
+		a(
+			href,
+			ng-click="openNewDocModal()",
+			tooltip-html-unsafe="New<br>File",
+			tooltip-placement="bottom"
+		)
+			i.fa.fa-file
+		a(
+			href,
+			ng-click="openNewFolderModal()",
+			tooltip="New Folder",
+			tooltip-placement="bottom"
+		)
+			i.fa.fa-folder
+		a(
+			href,
+			ng-click="openUploadFileModal()",
+			tooltip="Upload",
+			tooltip-placement="bottom"
+		)
+			i.fa.fa-upload
+
+		.toolbar-right
+			a(href, tooltip="Rename", tooltip-placement="bottom")
+				i.fa.fa-pencil
+			a(href, tooltip="Delete", tooltip-placement="bottom", tooltip-append-to-body="true")
+				i.fa.fa-trash-o
+
+	ul.list-unstyled.file-tree-list
+		file-entity(
+			entity="entity",
+			ng-repeat="entity in rootFolder.children | orderBy:[orderByFoldersFirst, 'name']"
+		)
+
+
+script(type='text/ng-template', id='entityListItemTemplate')
+	li(
+		ng-class="{ 'selected': entity.selected }",
+		ng-controller="FileTreeEntityController"
+	)
+		.entity(ng-if="entity.type == 'doc'")
+			.entity-name(ng-click="select()")
+				//- Just a spacer to align with folders
+				i.fa.fa-fw.toggle
+				i.fa.fa-fw.fa-file
+				|  {{ entity.name }}
+
+		.entity(ng-if="entity.type == 'file'")
+			.entity-name(ng-click="select()")
+				i.fa.fa-fw.toggle
+				i.fa.fa-fw.fa-image
+				|  {{ entity.name }}
+
+		.entity(ng-if="entity.type == 'folder'", ng-controller="FileTreeFolderController")
+			.entity-name
+				i.fa.fa-fw.toggle(
+					ng-class="{'fa-chevron-right': !expanded, 'fa-chevron-down': expanded}"
+					ng-click="toggleExpanded()"
+				)
+			
+				i.fa.fa-fw(
+					ng-class="{\
+						'fa-folder': !expanded, \
+						'fa-folder-open': expanded \
+					}"
+					ng-click="select()"
+				)
+				span(ng-click="select()")  {{ entity.name }}
+
+			ul.list-unstyled(ng-show="expanded")
+				file-entity(entity="child", ng-repeat="child in entity.children | orderBy:[orderByFoldersFirst, 'name']")
+
+script(type='text/ng-template', id='newDocModalTemplate')
+	.modal-header
+		h3 New File
+	.modal-body
+		form(novalidate, name="newDocForm")
+			input.form-control(
+				type="text",
+				placeholder="File Name",
+				required,
+				ng-model="inputs.name",
+				ng-enter="create()",
+				focus-on="open"
+			)
+	.modal-footer
+		button.btn.btn-default(
+			ng-disabled="state.inflight"
+			ng-click="cancel()"
+		) Cancel
+		button.btn.btn-primary(
+			ng-disabled="newDocForm.$invalid || state.inflight"
+			ng-click="create()"
+		)
+			span(ng-hide="state.inflight") Create
+			span(ng-show="state.inflight") Creating...
+
+script(type='text/ng-template', id='newFolderModalTemplate')
+	.modal-header
+		h3 New File
+	.modal-body
+		form(novalidate, name="newFolderForm")
+			input.form-control(
+				type="text",
+				placeholder="Folder Name",
+				required,
+				ng-model="inputs.name",
+				ng-enter="create()",
+				focus-on="open"
+			)
+	.modal-footer
+		button.btn.btn-default(
+			ng-disabled="state.inflight"
+			ng-click="cancel()"
+		) Cancel
+		button.btn.btn-primary(
+			ng-disabled="newFolderForm.$invalid || state.inflight"
+			ng-click="create()"
+		)
+			span(ng-hide="state.inflight") Create
+			span(ng-show="state.inflight") Creating...
+
+script(type="text/ng-template", id="uploadFileModalTemplate")
+	.modal-header
+		h3 Upload File(s)
+	.modal-body(
+		fine-upload
+		endpoint="/project/{{ project_id }}/upload"
+		waiting-for-response-text="Inserting file..."
+		failed-upload-text="Upload failed, sorry :("
+		upload-button-text="Select file(s)"
+		drag-area-text="drag file(s)"
+		hint-text="Hint: Press and hold the Control (Ctrl) key to select multiple files"
+		multiple="true"
+		on-complete-callback="onComplete"
+		on-upload-callback="onUpload"
+		params="{'folder_id': parent_folder_id}"
+	)
+		span Upload file(s)
+	.modal-footer
+		button.btn.btn-default(ng-click="cancel()") Cancel

+ 11 - 1
services/web/app/views/project/list.jade

@@ -419,7 +419,17 @@ block content
 		script(type="text/ng-template", id="uploadProjectModalTemplate")
 			.modal-header
 				h3 Upload Zipped Project
-			.modal-body(ng-fine-upload)
+			.modal-body(
+				fine-upload
+				endpoint="/project/new/upload"
+				waiting-for-response-text="Creating project..."
+				failed-upload-text="Upload failed. Is it a valid zip file?"
+				upload-button-text="Select a .zip file"
+				drag-area-text="drag .zip file"
+				multiple="false"
+				allowed-extensions="['zip']"
+				on-complete-callback="onComplete"
+			)
 				span Upload a zipped project
 			.modal-footer
 				button.btn.btn-default(ng-click="cancel()") Cancel

+ 0 - 76
services/web/app/views/project/partials/manage.jade

@@ -1,76 +0,0 @@
-.box
-	.page-header      
-		h2 Project Settings
-	.tabbable
-		ul.nav.nav-tabs
-			li.active
-				a(href='#generalProjectSettings', data-toggle="tab") General
-			li
-				a(href='#exportSettings', data-toggle="tab") Export & Copy
-			li
-				a(href='#deleteProjectTab', data-toggle="tab") Delete Project
-			li#manageDropboxSettiingsTabLink
-				a(href='#dropboxProjectSettings', data-toggle='tab') Dropbox 
-					span.label.label-warning beta
-
-		.tab-content.form-horizontal
-			.tab-pane#generalProjectSettings.form.form-horizontal.active
-				if privilegeLevel == 'owner' || privilegeLevel == 'readAndWrite'
-					.control-group
-						label(for='xlInput').control-label Project Name 
-						.controls
-							.input
-								input.projectName(type='text', value=project.name)
-
-					.control-group
-						label(for='input').control-label Root Document
-						.controls
-							.input
-								select#rootDocList
-
-					.control-group
-						label(for='spellCheck').control-label
-							| Spell check
-						.controls
-							select(name="spellCheckLanguage")#spellCheckLanguageSelection
-								option(value="",selected=(project.spellCheckLanguage == "")) Off
-								optgroup(label="Language")
-									for language in languages
-										option(
-											value=language.code,
-											selected=(language.code == project.spellCheckLanguage)
-										)= language.name
-
-					.control-group#multipleCompilers
-						label(for='input').control-label Compiler
-						.controls
-							.input
-								select#compilers
-									option(value='latex') LaTeX
-									option(value='pdflatex') pdfLaTeX
-									option(value='xelatex') XeLaTeX
-									option(value='lualatex') LuaLaTeX
-				else
-					span You do not have permission to modify these settings.
-
-				if privilegeLevel == 'owner'
-					.control-group
-						label(for='select').control-label Public Access 
-						.controls
-							select#publicAccessLevel
-								option(value='private') Private
-								option(value='readOnly') Public - Read Only
-								option(value='readAndWrite') Public - Read and Write
-
-			.tab-pane#exportSettings
-				a.btn#DownloadZip Download Project as Zip
-				div &nbsp;
-				a.btn(href='/project/'+project._id+'/clone').cloneProject Clone Project
-
-			.tab-pane#deleteProjectTab
-				if privilegeLevel == 'owner'
-					button#deleteProject.btn.btn-danger Delete Project
-				else
-					span You do not have permission to modify these settings.
-
-			.tab-pane#dropboxProjectSettings

+ 0 - 38
services/web/app/views/project/partials/pdf.jade

@@ -1,38 +0,0 @@
-#controls
-	button#previous
-		img(src='images/go-up.svg', align='top', height='32')
-		| Previous
-	button#next
-		img(src='images/go-down.svg', align='top', height='32')
-		| Next
-	.separator
-	input#pageNumber(type='number', value='1', size='4', min='1')
-	span /
-	span#numPages --
-	.separator
-	button#next(title='Zoom Out')
-		img(src='images/zoom-out.svg', align='top', height='32')
-	button#next(title='Zoom In')
-		img(src='images/zoom-in.svg', align='top', height='32')
-	.separator
-	select#scaleSelect
-		option#customScaleOption(value='custom')
-		option(value='0.5') 50%
-		option(value='0.75') 75%
-		option(value='1') 100%
-		option(value='1.25') 125%
-		option(value='1.5', selected='selected') 150%
-		option(value='2') 200%
-		option#pageWidthOption(value='page-width') Page Width
-		option#pageFitOption(value='page-fit') Page Fit
-	.separator
-	button#print
-		img(src='images/document-print.svg', align='top', height='32')
-		| Print
-	.separator
-	input#fileInput(type='file')
-	.separator
-	span#info --
-#loading Loading... 0%
-#viewer
-

+ 69 - 0
services/web/public/coffee/app/directives/fineUpload.coffee

@@ -0,0 +1,69 @@
+define [
+	"base"
+	"../../libs/fineuploader"
+], (App) ->
+	App.directive 'fineUpload', ($timeout) ->
+		return {
+			scope: {
+				multiple: "="
+				endpoint: "@"
+				waitingForResponseText: "@"
+				failedUploadText: "@"
+				uploadButtonText: "@"
+				dragAreaText: "@"
+				hintText: "@"
+				allowedExtensions: "="
+				onCompleteCallback: "="
+				onUploadCallback: "="
+				params: "="
+			}
+			link: (scope, element, attrs) ->
+				multiple = scope.multiple or false
+				endpoint = scope.endpoint
+				if scope.allowedExtensions?
+					validation = 
+						allowedExtensions: scope.allowedExtensions
+				else
+					validation = {}
+				text =
+					waitingForResponse: scope.waitingForResponseText or "Processing..."
+					failUpload: scope.failedUploadText or "Failed :("
+					uploadButton: scope.uploadButtonText or "Upload"
+				dragAreaText = scope.dragAreaText or "drag here"
+				hintText = scope.hintText or ""
+
+				onComplete = scope.onCompleteCallback or () ->
+				onUpload   = scope.onUploadCallback or () ->
+				params     = scope.params or {}
+				params._csrf = window.csrfToken
+
+				console.log "PARAMS", params
+
+				new qq.FineUploader
+					element: element[0]
+					multiple: multiple
+					disabledCancelForFormUploads: true
+					validation: validation
+					request:
+						endpoint: endpoint
+						forceMultipart: true
+						params: params
+						paramsInBody: false
+					callbacks:
+						onComplete: onComplete
+						onUpload:   onUpload
+					text: text
+					template: """
+						<div class="qq-uploader">
+							<div class="qq-upload-drop-area"><span>{dragZoneText}</span></div>
+							<div class="qq-upload-button btn btn-primary btn-lg">
+								<div>{uploadButtonText}</div>
+							</div>
+							<span class="or btn-lg"> or </span>
+							<span class="drag-here btn-lg">#{dragAreaText}</span>
+							<span class="qq-drop-processing"><span>{dropProcessingText}</span><span class="qq-drop-processing-spinner"></span></span>
+							<div class="small">#{hintText}</div>
+							<ul class="qq-upload-list"></ul>
+						</div>
+					"""
+		}

+ 2 - 1
services/web/public/coffee/app/ide.coffee

@@ -4,6 +4,7 @@ define [
 	"ide/directives/layout"
 	"ide/services/ide"
 	"directives/focusOn"
+	"directives/fineUpload"
 ], (
 	App
 	FileTreeManager
@@ -16,7 +17,7 @@ define [
 
 		window._ide = ide
 
-		ide.project_id = window.project_id
+		ide.project_id = $scope.project_id = window.project_id
 		ide.$scope = $scope
 		ide.socket = io.connect null,
 				reconnect: false

+ 6 - 2
services/web/public/coffee/app/ide/file-tree/FileTreeManager.coffee

@@ -97,7 +97,11 @@ define [
 
 			return folder
 
-		getCurrentFolder: (startFolder = @$scope.rootFolder) ->
+		getCurrentFolder: () ->
+			# Return the root folder if nothing is selected
+			@_getCurrentFolder(@$scope.rootFolder) or @$scope.rootFolder
+
+		_getCurrentFolder: (startFolder = @$scope.rootFolder) ->
 			for entity in startFolder.children or []
 				# The 'current' folder is either the one selected, or
 				# the one containing the selected doc/file
@@ -108,7 +112,7 @@ define [
 						return startFolder
 
 				if entity.type == "folder"
-					result = @getCurrentFolder(entity)
+					result = @_getCurrentFolder(entity)
 					return result if result?
 
 			return null

+ 28 - 0
services/web/public/coffee/app/ide/file-tree/controllers/FileTreeController.coffee

@@ -14,6 +14,13 @@ define [
 				controller:  "NewFolderModalController"
 			)
 
+		$scope.openUploadFileModal = () ->
+			$modal.open(
+				templateUrl: "uploadFileModalTemplate"
+				controller:  "UploadFileModalController"
+				scope: $scope
+			)
+
 		$scope.orderByFoldersFirst = (entity) ->
 			return 0 if entity.type == "folder"
 			return 1
@@ -61,6 +68,27 @@ define [
 					$scope.state.inflight = false
 					$modalInstance.close()
 
+			$scope.cancel = () ->
+				$modalInstance.dismiss('cancel')
+	]
+
+	App.controller "UploadFileModalController", [
+		"$scope", "ide", "$modalInstance", "$timeout",
+		($scope,   ide,   $modalInstance,   $timeout) ->
+			parent_folder = ide.fileTreeManager.getCurrentFolder()
+			$scope.parent_folder_id = parent_folder?.id
+
+			uploadCount = 0
+			$scope.onUpload = () ->
+				uploadCount++
+
+			$scope.onComplete = (error, name, response) ->
+				$timeout (() ->
+					uploadCount--
+					if uploadCount == 0 and response? and response.success
+						$modalInstance.close("done")
+				), 250
+
 			$scope.cancel = () ->
 				$modalInstance.dismiss('cancel')
 	]

+ 1 - 0
services/web/public/coffee/app/main.coffee

@@ -7,5 +7,6 @@ define [
 	"directives/focusInput"
 	"directives/focusOn"
 	"directives/equals"
+	"directives/fineUpload"
 ], () ->
 	angular.bootstrap(document.body, ["SharelatexApp"])

+ 4 - 35
services/web/public/coffee/app/project-list.coffee

@@ -1,6 +1,5 @@
 define [
 	"base"
-	"../libs/fineuploader"
 ], (App) ->
 	App.directive 'ngEnter', () ->
 		return (scope, element, attrs) ->
@@ -10,7 +9,6 @@ define [
 						scope.$eval(attrs.ngEnter, event: event)
 					event.preventDefault()
 
-
 	App.filter "formatDate", () ->
 		(date, format = "Do MMM YYYY, h:mm a") ->
 			moment(date).format(format)
@@ -607,40 +605,11 @@ define [
 		$scope.cancel = () ->
 			$modalInstance.dismiss('cancel')
 
-	App.directive 'ngFineUpload', ($timeout) ->
-		return (scope, element, attrs) ->
-			new qq.FineUploader
-				element: element[0]
-				multiple: false
-				disabledCancelForFormUploads: true
-				validation:
-					allowedExtensions: ["zip"]
-				request:
-					endpoint: "/project/new/upload"
-					forceMultipart: true
-					params:
-						_csrf: window.csrfToken
-				callbacks:
-					onComplete: (error, name, response)->
-						if response.project_id?
-							window.location = '/project/'+response.project_id
-				text:
-					waitingForResponse: "Creating project..."
-					failUpload: "Upload failed. Is it a valid zip file?"
-					uploadButton: "Select a .zip file"
-				template: """
-					<div class="qq-uploader">
-						<div class="qq-upload-drop-area"><span>{dragZoneText}</span></div>
-						<div class="qq-upload-button btn btn-primary btn-lg">
-							<div>{uploadButtonText}</div>
-						</div>
-						<span class="or btn-lg"> or </span>
-						<span class="drag-here btn-lg">drag a .zip file</span>
-						<span class="qq-drop-processing"><span>{dropProcessingText}</span><span class="qq-drop-processing-spinner"></span></span>
-						<ul class="qq-upload-list"></ul>
-					</div>
-				"""
 
 	App.controller 'UploadProjectModalController', ($scope, $modalInstance, $timeout) ->
 		$scope.cancel = () ->
 			$modalInstance.dismiss('cancel')
+
+		$scope.onComplete = (error, name, response) ->
+			if response.project_id?
+				window.location = '/project/' + response.project_id