Use Ember to load project list

This commit is contained in:
James Allen
2014-06-11 14:52:23 +01:00
parent 99705ebb4f
commit 1eaba59df0
8 changed files with 59126 additions and 504 deletions
@@ -216,13 +216,11 @@ _buildListViewModel = (projects, collabertions, readOnlyProjects, tags, tagsGrou
return project
tags = _.sortBy tags, (tag)->
-tag.project_ids.length
sortedProjects = _.sortBy projects, (project)->
return - project.lastUpdated
return {
title:'Your Projects'
priority_title: true
projects: sortedProjects
projects: JSON.stringify(projects)
tags:tags
projectTabActive: true
}
+7 -13
View File
@@ -16,8 +16,6 @@ html(itemscope, itemtype='http://schema.org/Product')
meta(itemprop="image", content="https://www.sharelatex.com/favicon.ico")
meta(name="description", content="Online LaTeX editor for collaborative editing, great for Maths or Sciences. You don't need to install LaTeX so it's great for beginners too.")
block scripts
- if (typeof(gaToken) != "undefined")
script(type='text/javascript').
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
@@ -27,13 +25,18 @@ html(itemscope, itemtype='http://schema.org/Product')
ga('create', '#{gaToken}', 'sharelatex.com');
ga('send', 'pageview');
- else
script(type='text/javascript')
script(type='text/javascript').
window.ga = function() { console.log("Sending to GA", arguments) };
script(type="text/javscript").
script(type="text/javascript").
window.csrfToken = "#{csrfToken}";
script(src=jsPath+'libs/jquery.js')
script(src=jsPath+'libs/handlebars-1.1.2.js')
script(src=jsPath+'libs/ember-1.5.1.js')
script(src=jsPath+'libs/ember-data-1.0.0-beta.8.js')
script(src=jsPath+'libs/moment.js')
block scripts
- if (typeof(bodyClasses) == "undefined")
- var bodyClasses = []
@@ -53,15 +56,6 @@ html(itemscope, itemtype='http://schema.org/Product')
button(data-dismiss="modal").btn OK
include layout/footer
include modals
if !locals.supressDefaultJs
script(type='text/javascript').
require = {
"urlArgs" : "fingerprint=#{fingerprint(jsPath + 'main.js')}"
}
script(data-main=jsPath+'main.js', src=jsPath+'libs/require.js?fingerprint=' + fingerprint(jsPath + 'libs/require.js'), baseurl=jsPath)
- if (typeof(tenderUrl) != "undefined")
script(src="https://#{tenderUrl}/tender_widget.js" )
script(type="text/javascript").
+158 -192
View File
@@ -1,197 +1,163 @@
extends ../layout
block scripts
script(src=jsPath+'project-list.js')
block content
mixin formatAccessLevel(accessLevel)
-if (accessLevel == "owner")
span Owner
-else if (accessLevel == "readWrite")
span Read and Write
-else if (accessLevel == "readOnly")
span Read Only
-else
span Unknown?
#projectList
mixin formatOwnerText(level, publicLevel)
-if (level == "owner")
span Me
-else
span #{formatProjectPublicAccessLevel()}  
mixin formatAccessLevel(project.accessLevel)
mixin tag(project_id, tagName, showDeleteIcon)
span.label.label-info.tag-label(data-project-id=project_id, data-tag=tagName)
span.text #{tagName}  
- if (showDeleteIcon)
i.fa.fa-times.delete-tag(data-project-id=project_id, data-tag=tagName)
mixin projectList(projects)
-each project in projects
- project_id = project._id.toString()
li.project_entry(id=project_id).container-fluid
.row
.col-md-6
input(type="checkbox").select-item
span.title
a.projectName(href="/project/#{project._id}") #{project.name}
span.project-tags(data-project-id=project_id)
- each tag in project.tags
mixin tag(project_id, tag.name, true)
.col-md-2
span.owner
mixin formatOwnerText(project.accessLevel, project.publicAccesLevel)
.col-md-4
span.last-modified.isoDate #{project.lastUpdated.toISOString()}
.content.content-alt
.container
.row
.col-md-2
#newProject.dropdown
a.btn.btn-primary.dropdown-toggle(data-toggle="dropdown", href="#") New Project
ul.dropdown-menu(role="menu")
li
a#blankNewProject(href="#", data-csrf=csrfToken) Blank Project
li
a#newProjectExample(href="#", data-csrf=csrfToken) Example Project
li
a#uploadNewProject(href="#", data-csrf=csrfToken) Upload Project
li.divider
li.dropdown-header Templates
li
a.menu-indent(href="/templates/cv") CV or Resume
li
a.menu-indent(href="/templates/cover-letters") Cover Letter
li
a.menu-indent(href="/templates/journals") Journal Article
li
a.menu-indent(href="/templates/presentations") Presentation
li
a.menu-indent(href="/templates/thesis") Thesis
li
a.menu-indent(href="/templates/bibliographies") Bibliographies
li
a.menu-indent(href="/templates") View All »
.row-spaced
ul.list-unstyled.folders-menu.js-folders-menu
li
a.menu-indent(href="#") All projects
li
a.menu-indent(href="#") Your projects
li
a.menu-indent(href="#") Shared with you
li
h2 Folders
li
a.menu-indent(href="#")
i.icon.fa.fa-folder-o
| PhD work
span.small (5)
li
a.menu-indent(href="#")
i.icon.fa.fa-folder-o
| Notes
span.small (2)
li
a.menu-indent(href="#")
i.icon.fa.fa-folder-o
| Papers
span.small (1)
.row-spaced-small
ul.list-unstyled.folders-menu
li
a.menu-indent(href="#")
i.icon.fa.fa-plus
| New Folder
-if (settings.enableSubscriptions)
.row-spaced
a(href="/user/bonus").btn.btn-info Upgrade Account
.col-md-10
.container-fluid
.row
.col-md-12
form.project-search.form-horizontal(role="form")
.form-group.has-feedback.col-md-7
input(placeholder='Search projects…', autofocus='autofocus').form-control.col-md-7
i.fa.fa-search.form-control-feedback
//- i.fa.fa-remove
.project-tools.js-toggle-tools
.btn-toolbar
.btn-group
a.btn.btn-default(href='#', data-toggle="tooltip", data-placement="bottom", title="", data-original-title="Download")
i.fa.fa-cloud-download
a.btn.btn-default(href='#', data-toggle="tooltip", data-placement="bottom", title="", data-original-title="Delete")
i.fa.fa-trash-o
.btn-group
a.btn.btn-default.dropdown-toggle(href="#", data-toggle="dropdown")
i.fa.fa-folder-open-o
|
span.caret
ul.dropdown-menu.dropdown-menu-right(role="menu")
li.dropdown-header Add to folder
li
a.menu-indent(href="#") PhD
li
a.menu-indent(href="#") Personal
li
a.menu-indent(href="#") Papers
.btn-group
a.btn.btn-default.dropdown-toggle(data-toggle="dropdown", href="#") More
span.caret
ul.dropdown-menu.dropdown-menu-right(role="menu")
li
a(href='/project/'+"5369c5737fc6b47f048da1f5"+'/clone', data-csrf=csrfToken).cloneProject Make a Copy...
-if ("owner" == "owner")
li
a(href='/project/'+"5369c5737fc6b47f048da1f5"+'/rename', data-name="the project", data-id="5369c5737fc6b47f048da1f5", data-csrf=csrfToken).renameProject Rename...
-else
li
a(href='/project/'+"5369c5737fc6b47f048da1f5"+'/leave', data-name="the project", data-id="5369c5737fc6b47f048da1f5", data-csrf=csrfToken).leaveProject Leave Project
.row.row-spaced
.col-md-12
.card.card-thin
- if (projects.length > 0)
ul.list-unstyled.project-list
li.container-fluid
.row
.col-md-6
input(type="checkbox").select-all
span.title TITLE
.col-md-2
span.owner OWNER
.col-md-4
span.last-modified LAST MODIFIED
mixin projectList(projects)
- else
.row
.span12
.welcome
h1
i.fa.fa-arrow-left
| Welcome! Follow the arrow to get started
p New to LaTeX? Start by having a look at our
a(href="/templates") templates
| or
a(href="/learn") help guides
| .
script(type="text/template")#tagTemplate
mixin tag('{{ project_id }}', '{{ tagName }}', true)
- locals.supressDefaultJs = true
script(type="text/javascript").
window.requirejs = {
"paths" : {
"moment": "libs/moment"
}
};
script(
data-main=jsPath+'list.js?fingerprint='+fingerprint(jsPath + 'list.js'),
baseurl=jsPath,
src=jsPath+'libs/require.js?fingerprint='+fingerprint(jsPath + 'libs/require.js')
)
window.data = { projects: !{projects} };
script(type="text/x-handlebars", data-template-name="projects")
- if (projects.length > 0)
ul.list-unstyled.project-list
li.container-fluid
.row
.col-md-6
input(type="checkbox").select-all
span.title TITLE
.col-md-2
span.owner OWNER
.col-md-4
span.last-modified LAST MODIFIED
{{#each itemController="project"}}
li.project_entry.container-fluid
.row
.col-md-6
input(type="checkbox").select-item
span.title
<a class="projectName" {{ bind-attr href=url }}>{{name}}</a>
.col-md-2
span.owner {{ownerName}}
.col-md-4
span.last-modified.isoDate {{formattedLastUpdated}}
{{/each}}
- else
.row
.span12
.welcome
h1
i.fa.fa-arrow-left
| Welcome! Follow the arrow to get started
p New to LaTeX? Start by having a look at our
a(href="/templates") templates
| or
a(href="/learn") help guides
| .
script(type="text/x-handlebars", data-template-name="application")
.content.content-alt
.container
.row
.col-md-2
#newProject.dropdown
a.btn.btn-primary.dropdown-toggle(data-toggle="dropdown", href="#") New Project
ul.dropdown-menu(role="menu")
li
a#blankNewProject(href="#", data-csrf=csrfToken) Blank Project
li
a#newProjectExample(href="#", data-csrf=csrfToken) Example Project
li
a#uploadNewProject(href="#", data-csrf=csrfToken) Upload Project
li.divider
li.dropdown-header Templates
li
a.menu-indent(href="/templates/cv") CV or Resume
li
a.menu-indent(href="/templates/cover-letters") Cover Letter
li
a.menu-indent(href="/templates/journals") Journal Article
li
a.menu-indent(href="/templates/presentations") Presentation
li
a.menu-indent(href="/templates/thesis") Thesis
li
a.menu-indent(href="/templates/bibliographies") Bibliographies
li
a.menu-indent(href="/templates") View All »
.row-spaced
ul.list-unstyled.folders-menu.js-folders-menu
li
a.menu-indent(href="#") All projects
li
a.menu-indent(href="#") Your projects
li
a.menu-indent(href="#") Shared with you
li
h2 Folders
li
a.menu-indent(href="#")
i.icon.fa.fa-folder-o
| PhD work
span.small (5)
li
a.menu-indent(href="#")
i.icon.fa.fa-folder-o
| Notes
span.small (2)
li
a.menu-indent(href="#")
i.icon.fa.fa-folder-o
| Papers
span.small (1)
.row-spaced-small
ul.list-unstyled.folders-menu
li
a.menu-indent(href="#")
i.icon.fa.fa-plus
| New Folder
-if (settings.enableSubscriptions)
.row-spaced
a(href="/user/bonus").btn.btn-info Upgrade Account
.col-md-10
.container-fluid
.row
.col-md-12
form.project-search.form-horizontal(role="form")
.form-group.has-feedback.col-md-7
input(placeholder='Search projects…', autofocus='autofocus').form-control.col-md-7
i.fa.fa-search.form-control-feedback
//- i.fa.fa-remove
.project-tools.js-toggle-tools
.btn-toolbar
.btn-group
a.btn.btn-default(href='#', data-toggle="tooltip", data-placement="bottom", title="", data-original-title="Download")
i.fa.fa-cloud-download
a.btn.btn-default(href='#', data-toggle="tooltip", data-placement="bottom", title="", data-original-title="Delete")
i.fa.fa-trash-o
.btn-group
a.btn.btn-default.dropdown-toggle(href="#", data-toggle="dropdown")
i.fa.fa-folder-open-o
|
span.caret
ul.dropdown-menu.dropdown-menu-right(role="menu")
li.dropdown-header Add to folder
li
a.menu-indent(href="#") PhD
li
a.menu-indent(href="#") Personal
li
a.menu-indent(href="#") Papers
.btn-group
a.btn.btn-default.dropdown-toggle(data-toggle="dropdown", href="#") More
span.caret
ul.dropdown-menu.dropdown-menu-right(role="menu")
li
a(href='/project/'+"5369c5737fc6b47f048da1f5"+'/clone', data-csrf=csrfToken).cloneProject Make a Copy...
-if ("owner" == "owner")
li
a(href='/project/'+"5369c5737fc6b47f048da1f5"+'/rename', data-name="the project", data-id="5369c5737fc6b47f048da1f5", data-csrf=csrfToken).renameProject Rename...
-else
li
a(href='/project/'+"5369c5737fc6b47f048da1f5"+'/leave', data-name="the project", data-id="5369c5737fc6b47f048da1f5", data-csrf=csrfToken).leaveProject Leave Project
.row.row-spaced
.col-md-12
.card.card-thin
{{ render "projects" }}
-296
View File
@@ -1,296 +0,0 @@
require [
"tags"
"moment"
"event_tracking"
"gui"
"libs/underscore"
"libs/fineuploader"
"libs/jquery.storage"
], (tagsManager, moment)->
$('.isoDate').each (i, d)->
html = $(d)
unparsedDate = html.text().trim()
formatedDate = moment(unparsedDate).format("Do MMM YYYY, h:mm:ss a")
html.text(formatedDate)
refreshProjectFilter = ->
words = $('#projectFilter').val().split(" ")
words = _.filter words, (word)->
word.length > 0
projects = $('.project_entry')
_.each projects, (project)->
name = $(project).find(".projectName").text()
tagsText = $(project).find(".project-tags").text()
searchText = "#{name} #{tagsText}".toLowerCase()
hide = false
_.each words, (word)->
if searchText.indexOf(word.toLowerCase()) == -1
hide = true
if hide
$(project).hide()
else
$(project).show()
$('#projectFilter').on "keyup", (e)->
if(e.keyCode == 13)
e.preventDefault()
refreshProjectFilter()
$('.search .icon-remove').on 'click', (e)->
$('#projectFilter').val("").focus()
refreshProjectFilter()
$('body').on 'click', '.tag-label .text', (event)->
event.preventDefault()
event.stopPropagation()
tag = $(event.target).text()
$('input#projectFilter').val(tag).focus()
refreshProjectFilter()
$('.deleteProject').click (event)->
event.preventDefault()
$modal = $('#deleteEntityModal')
$confirm = $modal.find('.confirm')
$modal.modal({backdrop:true, show:true, keyboard:true})
name = $(@).data("name")
id = $(@).data("id")
$modal.find(".name").text(name)
href = this.href
self = @
$confirm.on 'click', (e) =>
$.ajax
url: href
type:'DELETE'
data:
_csrf: $(@).data("csrf")
success: (data)->
$modal.modal('hide')
if data.message
new Message data
else
$("##{id}").fadeOut(1000)
$modal.on 'hide', ->
$confirm.off 'click'
$modal.find('.cancel').click (e)->
$modal.modal('hide')
$('.archiveProject').click (event)->
event.preventDefault()
$modal = $('#archiveEntityModal')
$confirm = $modal.find('.confirm')
$modal.modal({backdrop:true, show:true, keyboard:true})
name = $(@).data("name")
id = $(@).data("id")
$modal.find(".name").text(name)
href = this.href
self = @
$confirm.on 'click', (e) =>
$.ajax
url: href
type:'DELETE'
data:
_csrf: $(@).data("csrf")
success: (data)->
$modal.modal('hide')
if data.message
new Message data
else
$("##{id}").fadeOut(1000)
$modal.on 'hide', ->
$confirm.off 'click'
$modal.find('.cancel').click (e)->
$modal.modal('hide')
$('.renameProject').click (event)->
event.preventDefault()
$modal = $('#renameProjectModal')
$confirm = $modal.find('#confirmRename')
$modal.modal({backdrop:true, show:true, keyboard:true})
name = $(@).data("name")
nameEl = $modal.find("#projectNewName").val(name)
nameEl.select()
href = this.href
self = @
window.r = @
$confirm.on 'click', (e) =>
newProjectName = nameEl.val()
$.ajax
url: href
type:'POST'
data:
_csrf: $(@).data("csrf")
newProjectName:newProjectName
success: (data)->
$modal.modal('hide')
if data.message
new Message data
else
$(self.parentNode.parentNode.parentNode.parentNode).find(".projectName").text(newProjectName)
$(self.parentNode.parentNode).find("li a").each ()->
$(this).data('name', newProjectName)
$modal.on 'hide', ->
$confirm.off 'click'
$modal.find('.cancel').click (e)->
$modal.modal('hide')
$(".leaveProject").click (event) ->
event.preventDefault()
$modal = $('#leaveProjectModal')
$confirm = $modal.find('.confirm')
$modal.modal({backdrop:true, show:true, keyboard:true})
name = $(@).data("name")
id = $(@).data("id")
nameEl = $modal.find(".name").text(name)
href = this.href
self = @
$confirm.on 'click', (e)=>
$.ajax
url: href
type: 'POST'
data:
_csrf: $(@).data("csrf")
success: (data)->
$modal.modal('hide')
if data.message
new Message data
else
$("##{id}").fadeOut(1000)
$modal.on 'hide', ->
$confirm.off 'click'
$modal.find('.cancel').click (e)->
$modal.modal('hide')
$('.cloneProject').click (event)->
event.preventDefault()
$modal = $('#cloneProjectModal')
$confirm = $('#confirmCloneProject')
$modal.modal({backdrop:true, show:true, keyboard:true})
$modal.find('input').val('').focus()
href = this.href
$confirm.click (e)=>
$confirm.attr("disabled", true)
$confirm.text("Cloning...")
projectName = $modal.find('input').val()
$.ajax
url: href
type:'POST'
data:
projectName: projectName
_csrf: $(@).data("csrf")
success: (data)->
if data.redir?
window.location = data.redir
else if data.project_id?
window.location = '/project/'+data.project_id
$modal.on 'hide', ->
$confirm.off 'click'
$modal.find('.cancel').click (e)->
$modal.modal('hide')
$('.restoreProject').click (event) ->
event.preventDefault()
id = $(@).data("id")
$.ajax
url: @href
type: 'POST'
data:
_csrf: $(@).data("csrf")
success: (data)->
$("##{id}").fadeOut(1000)
newProject = (template, fileToOpen) ->
$modal = $('#newProjectModal')
$confirm = $('#confirmNewProject')
$modal.modal({backdrop:true, show:true, keyboard:true})
$modal.find('input').val('').focus()
$confirm.click (e) =>
$confirm.attr("disabled", true)
$confirm.text("Creating...")
projectName = $modal.find('input').val()?.trim()
$.ajax
url: '/project/new'
type:'POST'
data:{projectName: projectName, template: template, _csrf: $(@).data("csrf")}
success: (data)->
if data.message
new Message data
else
window.location = '/project/'+data.project_id + (if fileToOpen? then ("#" + fileToOpen) else "")
$modal.on 'hide', ->
$confirm.off 'click'
$modal.find('.cancel').click (e)->
$modal.modal('hide')
$('#blankNewProject').click (event)->
newProject.call(@, 'none')
$('#newProjectExample').click (event)->
newProject.call(@, 'example')
$('#newProjectVisual').click (event)->
newProject.call(@, 'visual', 'main.tex')
$('#uploadNewProject').click (event)->
event.preventDefault()
$modal = $('#projectUploadModal')
$modal.modal({backdrop:true, show:true, keyboard:true})
new qq.FineUploader
element: document.getElementById('projectFileUpload')
multiple: false
disabledCancelForFormUploads: true
validation:
allowedExtensions: ["zip"]
request:
endpoint: "/project/new/upload"
forceMultipart: true
params:
_csrf: $(@).data("csrf")
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-large">
<div>{uploadButtonText}</div>
</div>
<span class="or btn-large"> or </span>
<span class="drag-here btn-large">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>
"""
$modal.find('.cancel').click (e)->
$modal.modal('hide')
sysMsgKey = "dismiss-system-message-090114"
if $.localStorage(sysMsgKey)
$("#systemMessage").hide()
else
$("#systemMessage").show()
$("a#dismissSystemMessage").on "click", (e) ->
e.preventDefault()
$("#systemMessage").hide()
$.localStorage(sysMsgKey, true)
@@ -0,0 +1,45 @@
window.ProjectList = Ember.Application.create {
rootElement: "#projectList"
}
ProjectList.ApplicationRoute = Ember.Route.extend {
model: () ->
return @store.find("project")
setupController: () ->
@controllerFor('projects').set('model', @store.find("project"))
}
ProjectList.Project = DS.Model.extend {
name: DS.attr("string")
ownerName: DS.attr("string")
lastUpdated: DS.attr("date")
}
ProjectList.ProjectsController = Ember.ArrayController.extend {
sortProperties: ["lastUpdated"]
sortAscending: false
}
ProjectList.ProjectController = Ember.ObjectController.extend {
url: (() ->
"/project/#{@get("model").get("id")}"
).property("id")
formattedLastUpdated: (() ->
date = @get("model").get("lastUpdated")
return moment(date).format("Do MMM YYYY, h:mm a")
).property("lastUpdated")
}
ProjectList.ApplicationAdapter = DS.Adapter.extend {
findAll: (store, type, sinceToken) ->
return new Ember.RSVP.Promise (resolve, reject) ->
resolve(
window.data.projects.map (project) ->
id: project._id
name: project.name
lastUpdated: project.lastUpdated
)
}
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff