Start rebuilding editor

This commit is contained in:
James Allen 2014-06-21 22:20:37 +01:00
parent 0d70777f7f
commit 6d0053e709
14 changed files with 488 additions and 1007 deletions

View file

@ -167,6 +167,7 @@ module.exports = ProjectController =
priority_title: true priority_title: true
bodyClasses: ["editor"] bodyClasses: ["editor"]
project : project project : project
project_id : project._id
userObject : JSON.stringify({ userObject : JSON.stringify({
id : user.id id : user.id
email : user.email email : user.email
@ -179,7 +180,6 @@ module.exports = ProjectController =
userSettingsObject: JSON.stringify({ userSettingsObject: JSON.stringify({
mode : user.ace.mode mode : user.ace.mode
theme : user.ace.theme theme : user.ace.theme
project_id : project._id
fontSize : user.ace.fontSize fontSize : user.ace.fontSize
autoComplete: user.ace.autoComplete autoComplete: user.ace.autoComplete
spellCheckLanguage: user.ace.spellCheckLanguage spellCheckLanguage: user.ace.spellCheckLanguage

View file

@ -1,5 +1,7 @@
doctype html doctype html
html(itemscope, itemtype='http://schema.org/Product') html(itemscope, itemtype='http://schema.org/Product')
block vars
head head
- if (typeof(gaExperimentCode) !== "undefined" && gaExperimentCode) - if (typeof(gaExperimentCode) !== "undefined" && gaExperimentCode)
#{gaExperimentCode} #{gaExperimentCode}
@ -38,9 +40,13 @@ html(itemscope, itemtype='http://schema.org/Product')
block scripts block scripts
body body
include layout/navbar - if(typeof(suppressNavbar) == "undefined")
include layout/navbar
block content block content
include layout/footer
- if(typeof(suppressFooter) == "undefined")
include layout/footer
- if (typeof(lookingForScribtex) != "undefined" && lookingForScribtex) - if (typeof(lookingForScribtex) != "undefined" && lookingForScribtex)
.modal.hide#scribtexModal .modal.hide#scribtexModal
@ -54,16 +60,17 @@ html(itemscope, itemtype='http://schema.org/Product')
.modal-footer .modal-footer
button(data-dismiss="modal").btn OK button(data-dismiss="modal").btn OK
script(type='text/javascript').
window.requirejs = {
"urlArgs" : "fingerprint=#{fingerprint(jsPath + 'app/main.js')}"
};
script( - if(typeof(suppressFooter) == "undefined")
data-main=jsPath+'app/main.js', script(type='text/javascript').
baseurl=jsPath, window.requirejs = {
src=jsPath+'libs/require.js?fingerprint='+fingerprint(jsPath + 'libs/require.js') "urlArgs" : "fingerprint=#{fingerprint(jsPath + 'app/main.js')}"
) };
script(
data-main=jsPath+'app/main.js',
baseurl=jsPath,
src=jsPath+'libs/require.js?fingerprint='+fingerprint(jsPath + 'libs/require.js')
)
- if (typeof(tenderUrl) != "undefined") - if (typeof(tenderUrl) != "undefined")
script(src="https://#{tenderUrl}/tender_widget.js" ) script(src="https://#{tenderUrl}/tender_widget.js" )

View file

@ -1,41 +1,136 @@
extends ../layout extends ../layout
block vars
- var suppressNavbar = true
- var suppressFooter = true
- var suppressDefaultJs = true
block scripts block scripts
//- Only use the native bootstrap on the editor page, //- Only use the native bootstrap on the editor page,
//- since we use the Angular-based bootstrap elsewhere. //- since we use the Angular-based bootstrap elsewhere.
script(src=jsPath+'libs/bootstrap-3.1.1.js') script(src=jsPath+'libs/bootstrap-3.1.1.js')
script(src=jsPath+'libs/jquery-layout.js')
script(src=jsPath+'libs/jquery.storage.js')
block content block content
#loadingScreen
h3 Loading...
p#loadingMessage Loading editor
#errorMessages .editor(ng-controller="IdeController")
#connectionLostMessage(style="display: none;")
| Lost connection.
span#trying-reconnect
| Reconnecting in
span#reconnection-countdown ?
| seconds.
a(href='#')#try-reconnect-now Try now.
span#reconnecting
| Reconnecting...
#savingProblems(style="display: none") .loading-screen(ng-show="state.loading")
| Saving... .container
h3 Loading...
.progress
.progress-bar(ng-style="{'width': state.load_progress + '%'}")
header.toolbar.toolbar-header(ng-cloak, ng-hide="state.loading")
a.btn.btn-full-height(href='#', tooltip="Menu", tooltip-placement="bottom")
i.fa.fa-bars
span.name {{ project.name }}
a(href='#', data-toggle="tooltip", title="Rename")
i.fa.fa-pencil
.toolbar-right
a.btn.btn-full-height(href='#', tooltip="Share", tooltip-placement="bottom")
i.fa.fa-group
a.btn.btn-full-height(href='#', tooltip="Recent Changes", tooltip-placement="bottom")
i.fa.fa-history
a.btn.btn-full-height(href='#', tooltip="Chat", tooltip-placement="bottom")
i.fa.fa-comment
#editor-content(ng-cloak, layout="main", ng-hide="state.loading")
aside#file-tree.ui-layout-west
.toolbar.toolbar-small
a(href, tooltip-html-unsafe="New<br>File", tooltip-placement="bottom")
i.fa.fa-file
a(href, 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"
)
.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")
//- #loadingScreen
//- h3 Loading...
//- p#loadingMessage Loading editor
//- #errorMessages
//- #connectionLostMessage(style="display: none;")
//- | Lost connection.
//- span#trying-reconnect
//- | Reconnecting in
//- span#reconnection-countdown ?
//- | seconds.
//- a(href='#')#try-reconnect-now Try now.
//- span#reconnecting
//- | Reconnecting...
//- #savingProblems(style="display: none")
//- | Saving...
div#toolbar.sidebar-navigation //- div#toolbar.sidebar-navigation
ul#tabs //- ul#tabs
#toolbar-footer //- #toolbar-footer
#tab-content.tab-content //- #tab-content.tab-content
include ../templates //- include ../templates
include ../templates/dropbox //- include ../templates/dropbox
script(src='/socket.io/socket.io.js') script(src='/socket.io/socket.io.js')
script(type='text/javascript'). script(type='text/javascript').
window.project_id = "!{project_id}"
window.sharelatex = !{sharelatexObject}; window.sharelatex = !{sharelatexObject};
window.userSettings = !{userSettingsObject}; window.userSettings = !{userSettingsObject};
window.user = !{userObject}; window.user = !{userObject};
@ -64,14 +159,15 @@ block content
script(type='text/javascript'). script(type='text/javascript').
ga('send', 'event', 'editor-interaction', 'editor-opened') ga('send', 'event', 'editor-interaction', 'editor-opened')
- locals.supressDefaultJs = true - locals.suppressDefaultJs = true
- var fingerprintedPath = fingerprint(jsPath+'libs/pdf.worker.js') - var fingerprintedPath = fingerprint(jsPath+'libs/pdf.worker.js')
- var pdfJsWorkerPath = jsPath+'libs/pdf.worker.js?fingerprint='+fingerprintedPath - var pdfJsWorkerPath = jsPath+'libs/pdf.worker.js?fingerprint='+fingerprintedPath
script(type='text/javascript'). script(type='text/javascript').
window.sharelatex.pdfJsWorkerPath = "#{pdfJsWorkerPath}" window.sharelatex.pdfJsWorkerPath = "#{pdfJsWorkerPath}"
script( script(
data-main=jsPath+'ide.js', data-main=jsPath+'app/ide.js',
baseurl=jsPath, baseurl=jsPath,
data-ace-base=jsPath+'ace', data-ace-base=jsPath+'ace',
src=jsPath+'libs/require.js?fingerprint='+fingerprint(jsPath + 'libs/require.js') src=jsPath+'libs/require.js?fingerprint='+fingerprint(jsPath + 'libs/require.js')

View file

@ -1,10 +1,12 @@
define [ define [
"../libs/angular-autocomplete/angular-autocomplete" "../libs/angular-autocomplete/angular-autocomplete"
"../libs/ui-bootstrap" "../libs/ui-bootstrap"
"modules/recursionHelper"
], () -> ], () ->
App = angular.module("SharelatexApp", [ App = angular.module("SharelatexApp", [
"ui.bootstrap" "ui.bootstrap"
"autocomplete" "autocomplete"
"RecursionHelper"
]) ])
return App return App

View file

@ -0,0 +1,50 @@
define [
"base"
"ide/file-tree/FileTreeManager"
"ide/directives/layout"
], (
App
FileTreeManager
) ->
App.controller "IdeController", ["$scope", "$timeout", ($scope, $timeout) ->
$scope.state = {
loading: true
load_progress: 40
}
window.ide = ide = {
'$scope': $scope
}
ide.fileTreeManager = new FileTreeManager(ide, $scope)
$scope.project_id = window.project_id
ioOptions =
reconnect: false
"force new connection": true
$scope.socket = io.connect null, ioOptions
$scope.socket.on "connect", () ->
$scope.$apply () ->
$scope.state.load_progress = 80
joinProject = () =>
$scope.socket.emit 'joinProject', {
project_id: $scope.project_id
}, (err, project, permissionsLevel, protocolVersion) =>
if $scope.protocolVersion? and $scope.protocolVersion != protocolVersion
location.reload(true)
$scope.$apply () ->
$scope.protocolVersion = protocolVersion
$scope.project = project
$scope.state.load_progress = 100
$scope.state.loading = false
$scope.$emit "project:joined"
console.log "Project", $scope.project, $scope.rootFolder
setTimeout(joinProject, 100) ]
angular.bootstrap(document.body, ["SharelatexApp"])

View file

@ -0,0 +1,25 @@
define [
"base"
], (App) ->
App.directive "layout", () ->
return {
link: (scope, element, attrs) ->
name = attrs.layout
options =
spacing_open: 24
spacing_closed: 24
onresize: () =>
scope.$broadcast "layout:#{name}:resize"
# Restore previously recorded state
if (state = $.localStorage("layout.main"))?
options.west = state.west
options.east = state.east
$(element).layout options
# Save state when exiting
$(window).unload () ->
$.localStorage("layout.#{name}", element.layout().readState())
}

View file

@ -0,0 +1,49 @@
define [
"ide/file-tree/directives/fileEntity"
"ide/file-tree/controllers/FileTreeFolderController"
"ide/file-tree/controllers/FileTreeEntityController"
], () ->
class FileTreeManager
constructor: (@ide, @$scope) ->
@$scope.$on "project:joined", =>
console.log "Joined"
@loadRootFolder()
forEachEntity: (callback) ->
@_forEachEntityInFolder(@$scope.rootFolder, callback)
_forEachEntityInFolder: (folder, callback) ->
for entity in folder.children
callback(entity)
if entity.children?
@_forEachEntityInFolder(entity, callback)
loadRootFolder: () ->
@$scope.rootFolder = @_parseFolder(@$scope.project.rootFolder[0])
_parseFolder: (rawFolder) ->
folder = {
name: rawFolder.name
id: rawFolder.id
type: "folder"
children: []
}
for doc in rawFolder.docs or []
folder.children.push {
name: doc.name
type: "doc"
id: doc._id
}
for file in rawFolder.fileRefs or []
folder.children.push {
name: file.name
type: "file"
id: file._id
}
for childFolder in rawFolder.folders or []
folder.children.push @_parseFolder(childFolder)
return folder

View file

@ -0,0 +1,9 @@
define [
"base"
], (App) ->
App.controller "FileTreeEntityController", ["$scope", ($scope) ->
$scope.select = ($event) ->
ide.fileTreeManager.forEachEntity (entity) ->
entity.selected = false
$scope.entity.selected = true
]

View file

@ -0,0 +1,9 @@
define [
"base"
], (App) ->
App.controller "FileTreeFolderController", ["$scope", ($scope) ->
$scope.expanded = false
$scope.toggleExpanded = () ->
$scope.expanded = !$scope.expanded
]

View file

@ -0,0 +1,15 @@
define [
"base"
], (App) ->
App.directive "fileEntity", ["RecursionHelper", (RecursionHelper) ->
return {
restrict: "E"
scope: {
entity: "="
}
templateUrl: "entityListItemTemplate"
compile: (element) ->
RecursionHelper.compile element, (scope, element, attrs, ctrl) ->
# Link function here if needed
}
]

View file

@ -0,0 +1,44 @@
#
# * An Angular service which helps with creating recursive directives.
# * @author Mark Lagendijk
# * @license MIT
#
# From: https://github.com/marklagendijk/angular-recursion
angular.module("RecursionHelper", []).factory "RecursionHelper", [
"$compile"
($compile) ->
###
Manually compiles the element, fixing the recursion loop.
@param element
@param [link] A post-link function, or an object with function(s) registered via pre and post properties.
@returns An object containing the linking functions.
###
return compile: (element, link) ->
# Normalize the link parameter
link = post: link if angular.isFunction(link)
# Break the recursion loop by removing the contents
contents = element.contents().remove()
compiledContents = undefined
pre: (if (link and link.pre) then link.pre else null)
###
Compiles and re-adds the contents
###
post: (scope, element) ->
# Compile the contents
compiledContents = $compile(contents) unless compiledContents
# Re-add the compiled contents to the element
compiledContents scope, (clone) ->
element.append clone
return
# Call the post-linking function, if any
link.post.apply null, arguments if link and link.post
return
]

View file

@ -6,7 +6,6 @@
* Licensed under the MIT license (http://www.opensource.org/licenses/mit-license.php). * Licensed under the MIT license (http://www.opensource.org/licenses/mit-license.php).
* 2013/02/10 * 2013/02/10
**/ **/
define([], function() {
;(function($, window, document) { ;(function($, window, document) {
'use strict'; 'use strict';
@ -81,5 +80,3 @@ define([], function() {
$[method].options = defaults; $[method].options = defaults;
}); });
}(jQuery, window, document)); }(jQuery, window, document));
});

File diff suppressed because it is too large Load diff

View file

@ -813,3 +813,7 @@
@content-margin-top: @line-height-computed; @content-margin-top: @line-height-computed;
@content-margin-top: @line-height-computed; @content-margin-top: @line-height-computed;
// Custom
@toolbar-border-color: @gray-lighter;