Wrap project list code in require.js

This commit is contained in:
James Allen 2014-06-17 12:43:42 +01:00
parent c56648ab80
commit 012371333f
18 changed files with 629 additions and 95526 deletions

View file

@ -17,7 +17,7 @@ logger.log "Generating file fingerprints..."
for path in [
"#{jsPath}libs/require.js",
"#{jsPath}ide.js",
"#{jsPath}main.js",
"#{jsPath}app/main.js",
"#{jsPath}list.js",
"#{jsPath}libs/pdf.js",
"#{jsPath}libs/pdf.worker.js",

View file

@ -31,11 +31,8 @@ html(itemscope, itemtype='http://schema.org/Product')
script(type="text/javascript").
window.csrfToken = "#{csrfToken}";
script(src=jsPath+'libs/jquery.js')
script(src=jsPath+'libs/angular-1.2.17.js')
script(src=jsPath+'libs/moment.js')
//script(src=jsPath+'libs/bootstrap.js')
script(src=jsPath+'libs/ui-bootstrap-0.11.0.js')
script(src=jsPath+'libs/moment-2.4.0.js')
block scripts
- if (typeof(bodyClasses) == "undefined")
@ -56,11 +53,22 @@ html(itemscope, itemtype='http://schema.org/Product')
button(data-dismiss="modal").btn OK
include layout/footer
- if (typeof(tenderUrl) != "undefined")
script(src="https://#{tenderUrl}/tender_widget.js" )
script(type="text/javascript").
Tender = {
hideToggle: true,
widgetToggles: $(".js-tender-widget"),
category: "questions"
};
script(type='text/javascript').
window.requirejs = {
"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")
script(src="https://#{tenderUrl}/tender_widget.js" )
script(type="text/javascript").
Tender = {
hideToggle: true,
widgetToggles: $(".js-tender-widget"),
category: "questions"
};

View file

@ -7,16 +7,16 @@ block scripts
tags: !{JSON.stringify(tags)}
};
script(src=jsPath+'libs/fineuploader.js')
script(src=jsPath+'project-list.js')
block content
.content.content-alt(ng-app="ProjectPageApp", ng-controller="ProjectPageController")
.content.content-alt(ng-controller="ProjectPageController")
.container
.row
.col-md-2
#newProject.dropdown
a.btn.btn-primary.dropdown-toggle(data-toggle="dropdown", href="#") New Project
a.btn.btn-primary.dropdown-toggle(
href="#",
data-toggle="dropdown"
) New Project
ul.dropdown-menu(role="menu")
li
a(

View file

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

View file

@ -0,0 +1,5 @@
define [
"project-list"
"user-details"
], () ->
angular.bootstrap(document.body, ["SharelatexApp"])

View file

@ -0,0 +1,580 @@
define [
"base"
"../libs/fineuploader"
], (App) ->
App.directive 'ngEnter', () ->
return (scope, element, attrs) ->
element.bind "keydown keypress", (event) ->
if event.which == 13
scope.$apply () ->
scope.$eval(attrs.ngEnter, event: event)
event.preventDefault()
App.directive 'ngFocusOn', ($timeout) ->
return {
restrict: 'AC'
link: (scope, element, attrs) ->
scope.$on attrs.ngFocusOn, () ->
element.focus()
}
App.filter "formatDate", () ->
(date, format = "Do MMM YYYY, h:mm a") ->
moment(date).format(format)
App.controller "ProjectPageController", ($scope, $modal, $http, $q) ->
$scope.projects = window.data.projects
$scope.visibleProjects = $scope.projects
$scope.tags = window.data.tags
$scope.allSelected = false
$scope.selectedProjects = []
$scope.filter = "all"
# Allow tags to be accessed on projects as well
projectsById = {}
for project in $scope.projects
projectsById[project.id] = project
for tag in $scope.tags
for project_id in tag.project_ids or []
project = projectsById[project_id]
if project?
project.tags ||= []
project.tags.push tag
# Any individual changes to the selection buttons invalidates
# our 'select all'
$scope.$on "selected:on-change", (e) ->
$scope.allSelected = false
$scope.$broadcast "selection:change"
# Selecting or deselecting all should apply to all projects
$scope.onSelectAllChange = () ->
for project in $scope.visibleProjects
project.selected = $scope.allSelected
$scope.$broadcast "selection:change"
$scope.$watch "searchText", (value) ->
$scope.updateVisibleProjects()
$scope.setFilter = (filter) ->
$scope.filter = filter
$scope.updateVisibleProjects()
$scope.clearProjectSelections = () ->
for project in $scope.projects
project.selected = false
$scope.allSelected = false
$scope.$broadcast "selection:change"
$scope.updateSelectedProjects = () ->
$scope.selectedProjects = $scope.projects.filter (project) -> project.selected
$scope.getSelectedProjects = () ->
$scope.selectedProjects
$scope.getSelectedProjectIds = () ->
$scope.selectedProjects.map (project) -> project.id
$scope.getFirstSelectedProject = () ->
$scope.selectedProjects[0]
$scope.$on "selection:change", () ->
$scope.updateSelectedProjects()
$scope.updateVisibleProjects = () ->
$scope.visibleProjects = []
selectedTag = $scope.getSelectedTag()
for project in $scope.projects
visible = true
# Only show if it matches any search text
if $scope.searchText? and $scope.searchText != ""
if !project.name.toLowerCase().match($scope.searchText.toLowerCase())
visible = false
# Only show if it matches the selected tag
if $scope.filter == "tag" and selectedTag? and project.id not in selectedTag.project_ids
visible = false
# Hide projects we own if we only want to see shared projects
if $scope.filter == "shared" and project.accessLevel == "owner"
visible = false
# Hide projects we don't own if we only want to see owned projects
if $scope.filter == "owned" and project.accessLevel != "owner"
visible = false
if $scope.filter == "archived"
# Only show archived projects
if !project.archived
visible = false
else
# Only show non-archived projects
if project.archived
visible = false
if visible
$scope.visibleProjects.push project
else
# We don't want hidden selections
project.selected = false
$scope.updateSelectedProjects()
$scope.getSelectedTag = () ->
for tag in $scope.tags
return tag if tag.selected
return null
$scope._removeProjectIdsFromTagArray = (tag, remove_project_ids) ->
# Remove project_id from tag.project_ids
remaining_project_ids = []
removed_project_ids = []
for project_id in tag.project_ids
if project_id not in remove_project_ids
remaining_project_ids.push project_id
else
removed_project_ids.push project_id
tag.project_ids = remaining_project_ids
return removed_project_ids
$scope._removeProjectFromList = (project) ->
index = $scope.projects.indexOf(project)
if index > -1
$scope.projects.splice(index, 1)
$scope.removeSelectedProjectsFromTag = (tag) ->
selected_project_ids = $scope.getSelectedProjectIds()
selected_projects = $scope.getSelectedProjects()
removed_project_ids = $scope._removeProjectIdsFromTagArray(tag, selected_project_ids)
# Remove tag from project.tags
remaining_tags = []
for project in selected_projects
project.tags ||= []
index = project.tags.indexOf tag
if index > -1
project.tags.splice(index, 1)
for project_id in removed_project_ids
$http.post "/project/#{project_id}/tag", {
deletedTag: tag.name
_csrf: window.csrfToken
}
# If we're filtering by this tag then we need to remove
# the projects from view
$scope.updateVisibleProjects()
$scope.addSelectedProjectsToTag = (tag) ->
selected_projects = $scope.getSelectedProjects()
# Add project_ids into tag.project_ids
added_project_ids = []
for project_id in $scope.getSelectedProjectIds()
unless project_id in tag.project_ids
tag.project_ids.push project_id
added_project_ids.push project_id
# Add tag into each project.tags
for project in selected_projects
project.tags ||= []
unless tag in project.tags
project.tags.push tag
for project_id in added_project_ids
# TODO Factor this out into another provider?
$http.post "/project/#{project_id}/tag", {
tag: tag.name
_csrf: window.csrfToken
}
$scope.createTag = (name) ->
$scope.tags.push {
name: name
project_ids: []
}
$scope.openNewTagModal = () ->
modalInstance = $modal.open(
templateUrl: "newTagModalTemplate"
controller: "NewTagModalController"
)
modalInstance.result.then(
(newTagName) ->
$scope.createTag(newTagName)
)
$scope.createProject = (name, template = "none") ->
deferred = $q.defer()
$http
.post("/project/new", {
_csrf: window.csrfToken
projectName: name
template: template
})
.success((data, status, headers, config) ->
$scope.projects.push {
name: name
_id: data.project_id
accessLevel: "owner"
# TODO: Check access level if correct after adding it in
# to the rest of the app
}
$scope.updateVisibleProjects()
deferred.resolve(data.project_id)
)
.error((data, status, headers, config) ->
deferred.reject()
)
return deferred.promise
$scope.openCreateProjectModal = (template = "none") ->
modalInstance = $modal.open(
templateUrl: "newProjectModalTemplate"
controller: "NewProjectModalController"
resolve:
template: () -> template
scope: $scope
)
modalInstance.result.then (project_id) ->
window.location = "/project/#{project_id}"
$scope.renameProject = (project, newName) ->
project.name = newName
$http.post "/project/#{project.id}/rename", {
newProjectName: newName
_csrf: window.csrfToken
}
$scope.openRenameProjectModal = () ->
project = $scope.getFirstSelectedProject()
return if !project? or project.accessLevel != "owner"
modalInstance = $modal.open(
templateUrl: "renameProjectModalTemplate"
controller: "RenameProjectModalController"
resolve:
projectName: () -> project.name
)
modalInstance.result.then(
(newName) ->
$scope.renameProject(project, newName)
)
$scope.cloneProject = (project, cloneName) ->
deferred = $q.defer()
$http
.post("/project/#{project.id}/clone", {
_csrf: window.csrfToken
projectName: cloneName
})
.success((data, status, headers, config) ->
$scope.projects.push {
name: cloneName
id: data.project_id
accessLevel: "owner"
# TODO: Check access level if correct after adding it in
# to the rest of the app
}
$scope.updateVisibleProjects()
deferred.resolve(data.project_id)
)
.error((data, status, headers, config) ->
deferred.reject()
)
return deferred.promise
$scope.openCloneProjectModal = () ->
project = $scope.getFirstSelectedProject()
return if !project?
modalInstance = $modal.open(
templateUrl: "cloneProjectModalTemplate"
controller: "CloneProjectModalController"
resolve:
project: () -> project
scope: $scope
)
$scope.openArchiveProjectsModal = () ->
modalInstance = $modal.open(
templateUrl: "deleteProjectsModalTemplate"
controller: "DeleteProjectsModalController"
resolve:
projects: () -> $scope.getSelectedProjects()
)
modalInstance.result.then () ->
$scope.archiveOrLeaveSelectedProjects()
$scope.archiveOrLeaveSelectedProjects = () ->
selected_projects = $scope.getSelectedProjects()
selected_project_ids = $scope.getSelectedProjectIds()
# Remove project from any tags
for tag in $scope.tags
$scope._removeProjectIdsFromTagArray(tag, selected_project_ids)
for project in selected_projects
if project.accessLevel == "owner"
project.archived = true
$http {
method: "DELETE"
url: "/project/#{project.id}"
headers:
"X-CSRF-Token": window.csrfToken
}
else
$scope._removeProjectFromList project
$http {
method: "POST"
url: "/project/#{project.id}/leave"
headers:
"X-CSRF-Token": window.csrfToken
}
$scope.updateVisibleProjects()
$scope.openDeleteProjectsModal = () ->
modalInstance = $modal.open(
templateUrl: "deleteProjectsModalTemplate"
controller: "DeleteProjectsModalController"
resolve:
projects: () -> $scope.getSelectedProjects()
)
modalInstance.result.then () ->
$scope.deleteSelectedProjects()
$scope.deleteSelectedProjects = () ->
selected_projects = $scope.getSelectedProjects()
selected_project_ids = $scope.getSelectedProjectIds()
# Remove projects from array
for project in selected_projects
$scope._removeProjectFromList project
# Remove project from any tags
for tag in $scope.tags
$scope._removeProjectIdsFromTagArray(tag, selected_project_ids)
for project_id in selected_project_ids
$http {
method: "DELETE"
url: "/project/#{project_id}?forever=true"
headers:
"X-CSRF-Token": window.csrfToken
}
$scope.updateVisibleProjects()
$scope.restoreSelectedProjects = () ->
selected_projects = $scope.getSelectedProjects()
selected_project_ids = $scope.getSelectedProjectIds()
for project in selected_projects
project.archived = false
for project_id in selected_project_ids
$http {
method: "POST"
url: "/project/#{project_id}/restore"
headers:
"X-CSRF-Token": window.csrfToken
}
$scope.updateVisibleProjects()
$scope.openUploadProjectModal = () ->
modalInstance = $modal.open(
templateUrl: "uploadProjectModalTemplate"
controller: "UploadProjectModalController"
)
App.controller "ProjectListItemController", ($scope) ->
$scope.onSelectedChange = () ->
$scope.$emit "selected:on-change"
$scope.ownerName = () ->
if $scope.project.accessLevel == "owner"
return "You"
else if $scope.project.owner?
return "#{$scope.project.owner.first_name} #{$scope.project.owner.last_name}"
else
return "?"
App.controller "TagListController", ($scope) ->
$scope.filterProjects = (filter = "all") ->
$scope._clearTags()
$scope.setFilter(filter)
$scope._clearTags = () ->
for tag in $scope.tags
tag.selected = false
App.controller "TagListItemController", ($scope) ->
$scope.selectTag = () ->
$scope._clearTags()
$scope.tag.selected = true
$scope.setFilter("tag")
App.controller "TagDropdownItemController", ($scope) ->
$scope.$on "selection:change", (e, newValue, oldValue) ->
$scope.recalculateProjectsInTag()
$scope.recalculateProjectsInTag = () ->
$scope.areSelectedProjectsInTag = false
for project_id in $scope.getSelectedProjectIds()
if project_id in $scope.tag.project_ids
$scope.areSelectedProjectsInTag = true
else
partialSelection = true
if $scope.areSelectedProjectsInTag and partialSelection
$scope.areSelectedProjectsInTag = "partial"
$scope.addOrRemoveProjectsFromTag = () ->
if $scope.areSelectedProjectsInTag == true
$scope.removeSelectedProjectsFromTag($scope.tag)
$scope.areSelectedProjectsInTag = false
else if $scope.areSelectedProjectsInTag == false or $scope.areSelectedProjectsInTag == "partial"
$scope.addSelectedProjectsToTag($scope.tag)
$scope.areSelectedProjectsInTag = true
App.controller 'NewTagModalController', ($scope, $modalInstance, $timeout) ->
$scope.inputs =
newTagName: ""
$modalInstance.opened.then () ->
$timeout () ->
$scope.$broadcast "open"
, 700
$scope.create = () ->
$modalInstance.close($scope.inputs.newTagName)
$scope.cancel = () ->
$modalInstance.dismiss('cancel')
App.controller 'RenameProjectModalController', ($scope, $modalInstance, $timeout, projectName) ->
$scope.inputs =
projectName: projectName
$modalInstance.opened.then () ->
$timeout () ->
$scope.$broadcast "open"
, 700
$scope.rename = () ->
$modalInstance.close($scope.inputs.projectName)
$scope.cancel = () ->
$modalInstance.dismiss('cancel')
App.controller 'CloneProjectModalController', ($scope, $modalInstance, $timeout, project) ->
$scope.inputs =
projectName: project.name + " (Copy)"
$scope.state =
inflight: false
$modalInstance.opened.then () ->
$timeout () ->
$scope.$broadcast "open"
, 700
$scope.clone = () ->
$scope.state.inflight = true
$scope
.cloneProject(project, $scope.inputs.projectName)
.then (project_id) ->
$scope.state.inflight = false
$modalInstance.close(project_id)
$scope.cancel = () ->
$modalInstance.dismiss('cancel')
App.controller 'NewProjectModalController', ($scope, $modalInstance, $timeout, template) ->
$scope.inputs =
projectName: ""
$scope.state =
inflight: false
$modalInstance.opened.then () ->
$timeout () ->
$scope.$broadcast "open"
, 700
$scope.create = () ->
$scope.state.inflight = true
$scope
.createProject($scope.inputs.projectName, template)
.then (project_id) ->
$scope.state.inflight = false
$modalInstance.close(project_id)
$scope.cancel = () ->
$modalInstance.dismiss('cancel')
App.controller 'DeleteProjectsModalController', ($scope, $modalInstance, $timeout, projects) ->
$scope.projectsToDelete = projects.filter (project) -> project.accessLevel == "owner"
$scope.projectsToLeave = projects.filter (project) -> project.accessLevel != "owner"
if $scope.projectsToLeave.length > 0 and $scope.projectsToDelete.length > 0
$scope.action = "Delete & Leave"
else if $scope.projectsToLeave.length == 0 and $scope.projectsToDelete.length > 0
$scope.action = "Delete"
else
$scope.action = "Leave"
$scope.delete = () ->
$modalInstance.close()
$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')

View file

@ -1,18 +1,18 @@
define ["libs/algolia", "libs/angular", "libs/angular-autocomplete/angular-autocomplete"], (algolia)->
app = angular.module("userProfileInformationApp", ["autocomplete"])
app.factory "Institutions", ->
define [
"base"
"../libs/algolia"
], (App, algolia)->
App.factory "Institutions", ->
new AlgoliaSearch("SK53GL4JLY", "1606ccef5b70ac44680b61e6b0285126").initIndex("institutions")
app.directive "focusInput", ($timeout) ->
App.directive "focusInput", ($timeout) ->
return (scope, element, attr) ->
scope.$watch attr.focusInput, (value) ->
if value
$timeout ->
element.select()
app.controller "UpdateForm", ($scope, $http, Institutions)->
App.controller "UpdateForm", ($scope, $http, Institutions)->
$scope.institutions = []
$scope.formVisable = false
$scope.hidePersonalInfoSection = true
@ -55,7 +55,3 @@ define ["libs/algolia", "libs/angular", "libs/angular-autocomplete/angular-autoc
$scope.institutions = _.map response.hits, (institution)->
"#{institution.name} (<span class='muted'>#{institution.domain}</span>)"
angular.bootstrap(document.getElementById("userProfileInformation"), ['userProfileInformationApp'])

View file

@ -1,582 +0,0 @@
window.ProjectPageApp = angular.module("ProjectPageApp", ['ui.bootstrap'])
$ () ->
$(".js-tags-dropdown-menu input, .js-tags-dropdown-menu a").click (e) ->
e.stopPropagation()
ProjectPageApp.directive 'ngEnter', () ->
return (scope, element, attrs) ->
element.bind "keydown keypress", (event) ->
if event.which == 13
scope.$apply () ->
scope.$eval(attrs.ngEnter, event: event)
event.preventDefault()
ProjectPageApp.directive 'ngFocusOn', ($timeout) ->
return {
restrict: 'AC'
link: (scope, element, attrs) ->
scope.$on attrs.ngFocusOn, () ->
element.focus()
}
ProjectPageApp.filter "formatDate", () ->
(date, format = "Do MMM YYYY, h:mm a") ->
moment(date).format(format)
ProjectPageApp.controller "ProjectPageController", ($scope, $modal, $http, $q) ->
$scope.projects = window.data.projects
$scope.visibleProjects = $scope.projects
$scope.tags = window.data.tags
$scope.allSelected = false
$scope.selectedProjects = []
$scope.filter = "all"
# Allow tags to be accessed on projects as well
projectsById = {}
for project in $scope.projects
projectsById[project.id] = project
for tag in $scope.tags
for project_id in tag.project_ids or []
project = projectsById[project_id]
if project?
project.tags ||= []
project.tags.push tag
# Any individual changes to the selection buttons invalidates
# our 'select all'
$scope.$on "selected:on-change", (e) ->
$scope.allSelected = false
$scope.$broadcast "selection:change"
# Selecting or deselecting all should apply to all projects
$scope.onSelectAllChange = () ->
for project in $scope.visibleProjects
project.selected = $scope.allSelected
$scope.$broadcast "selection:change"
$scope.$watch "searchText", (value) ->
$scope.updateVisibleProjects()
$scope.setFilter = (filter) ->
$scope.filter = filter
$scope.updateVisibleProjects()
$scope.clearProjectSelections = () ->
for project in $scope.projects
project.selected = false
$scope.allSelected = false
$scope.$broadcast "selection:change"
$scope.updateSelectedProjects = () ->
$scope.selectedProjects = $scope.projects.filter (project) -> project.selected
$scope.getSelectedProjects = () ->
$scope.selectedProjects
$scope.getSelectedProjectIds = () ->
$scope.selectedProjects.map (project) -> project.id
$scope.getFirstSelectedProject = () ->
$scope.selectedProjects[0]
$scope.$on "selection:change", () ->
$scope.updateSelectedProjects()
$scope.updateVisibleProjects = () ->
$scope.visibleProjects = []
selectedTag = $scope.getSelectedTag()
for project in $scope.projects
visible = true
# Only show if it matches any search text
if $scope.searchText? and $scope.searchText != ""
if !project.name.toLowerCase().match($scope.searchText.toLowerCase())
visible = false
# Only show if it matches the selected tag
if $scope.filter == "tag" and selectedTag? and project.id not in selectedTag.project_ids
visible = false
# Hide projects we own if we only want to see shared projects
if $scope.filter == "shared" and project.accessLevel == "owner"
visible = false
# Hide projects we don't own if we only want to see owned projects
if $scope.filter == "owned" and project.accessLevel != "owner"
visible = false
if $scope.filter == "archived"
# Only show archived projects
if !project.archived
visible = false
else
# Only show non-archived projects
if project.archived
visible = false
if visible
$scope.visibleProjects.push project
else
# We don't want hidden selections
project.selected = false
$scope.updateSelectedProjects()
$scope.getSelectedTag = () ->
for tag in $scope.tags
return tag if tag.selected
return null
$scope._removeProjectIdsFromTagArray = (tag, remove_project_ids) ->
# Remove project_id from tag.project_ids
remaining_project_ids = []
removed_project_ids = []
for project_id in tag.project_ids
if project_id not in remove_project_ids
remaining_project_ids.push project_id
else
removed_project_ids.push project_id
tag.project_ids = remaining_project_ids
return removed_project_ids
$scope._removeProjectFromList = (project) ->
index = $scope.projects.indexOf(project)
if index > -1
$scope.projects.splice(index, 1)
$scope.removeSelectedProjectsFromTag = (tag) ->
selected_project_ids = $scope.getSelectedProjectIds()
selected_projects = $scope.getSelectedProjects()
removed_project_ids = $scope._removeProjectIdsFromTagArray(tag, selected_project_ids)
# Remove tag from project.tags
remaining_tags = []
for project in selected_projects
project.tags ||= []
index = project.tags.indexOf tag
if index > -1
project.tags.splice(index, 1)
for project_id in removed_project_ids
$http.post "/project/#{project_id}/tag", {
deletedTag: tag.name
_csrf: window.csrfToken
}
# If we're filtering by this tag then we need to remove
# the projects from view
$scope.updateVisibleProjects()
$scope.addSelectedProjectsToTag = (tag) ->
selected_projects = $scope.getSelectedProjects()
# Add project_ids into tag.project_ids
added_project_ids = []
for project_id in $scope.getSelectedProjectIds()
unless project_id in tag.project_ids
tag.project_ids.push project_id
added_project_ids.push project_id
# Add tag into each project.tags
for project in selected_projects
project.tags ||= []
unless tag in project.tags
project.tags.push tag
for project_id in added_project_ids
# TODO Factor this out into another provider?
$http.post "/project/#{project_id}/tag", {
tag: tag.name
_csrf: window.csrfToken
}
$scope.createTag = (name) ->
$scope.tags.push {
name: name
project_ids: []
}
$scope.openNewTagModal = () ->
modalInstance = $modal.open(
templateUrl: "newTagModalTemplate"
controller: "NewTagModalController"
)
modalInstance.result.then(
(newTagName) ->
$scope.createTag(newTagName)
)
$scope.createProject = (name, template = "none") ->
deferred = $q.defer()
$http
.post("/project/new", {
_csrf: window.csrfToken
projectName: name
template: template
})
.success((data, status, headers, config) ->
$scope.projects.push {
name: name
_id: data.project_id
accessLevel: "owner"
# TODO: Check access level if correct after adding it in
# to the rest of the app
}
$scope.updateVisibleProjects()
deferred.resolve(data.project_id)
)
.error((data, status, headers, config) ->
deferred.reject()
)
return deferred.promise
$scope.openCreateProjectModal = (template = "none") ->
modalInstance = $modal.open(
templateUrl: "newProjectModalTemplate"
controller: "NewProjectModalController"
resolve:
template: () -> template
scope: $scope
)
modalInstance.result.then (project_id) ->
window.location = "/project/#{project_id}"
$scope.renameProject = (project, newName) ->
project.name = newName
$http.post "/project/#{project.id}/rename", {
newProjectName: newName
_csrf: window.csrfToken
}
$scope.openRenameProjectModal = () ->
project = $scope.getFirstSelectedProject()
return if !project? or project.accessLevel != "owner"
modalInstance = $modal.open(
templateUrl: "renameProjectModalTemplate"
controller: "RenameProjectModalController"
resolve:
projectName: () -> project.name
)
modalInstance.result.then(
(newName) ->
$scope.renameProject(project, newName)
)
$scope.cloneProject = (project, cloneName) ->
deferred = $q.defer()
$http
.post("/project/#{project.id}/clone", {
_csrf: window.csrfToken
projectName: cloneName
})
.success((data, status, headers, config) ->
$scope.projects.push {
name: cloneName
id: data.project_id
accessLevel: "owner"
# TODO: Check access level if correct after adding it in
# to the rest of the app
}
$scope.updateVisibleProjects()
deferred.resolve(data.project_id)
)
.error((data, status, headers, config) ->
deferred.reject()
)
return deferred.promise
$scope.openCloneProjectModal = () ->
project = $scope.getFirstSelectedProject()
return if !project?
modalInstance = $modal.open(
templateUrl: "cloneProjectModalTemplate"
controller: "CloneProjectModalController"
resolve:
project: () -> project
scope: $scope
)
$scope.openArchiveProjectsModal = () ->
modalInstance = $modal.open(
templateUrl: "deleteProjectsModalTemplate"
controller: "DeleteProjectsModalController"
resolve:
projects: () -> $scope.getSelectedProjects()
)
modalInstance.result.then () ->
$scope.archiveOrLeaveSelectedProjects()
$scope.archiveOrLeaveSelectedProjects = () ->
selected_projects = $scope.getSelectedProjects()
selected_project_ids = $scope.getSelectedProjectIds()
# Remove project from any tags
for tag in $scope.tags
$scope._removeProjectIdsFromTagArray(tag, selected_project_ids)
for project in selected_projects
if project.accessLevel == "owner"
project.archived = true
$http {
method: "DELETE"
url: "/project/#{project.id}"
headers:
"X-CSRF-Token": window.csrfToken
}
else
$scope._removeProjectFromList project
$http {
method: "POST"
url: "/project/#{project.id}/leave"
headers:
"X-CSRF-Token": window.csrfToken
}
$scope.updateVisibleProjects()
$scope.openDeleteProjectsModal = () ->
modalInstance = $modal.open(
templateUrl: "deleteProjectsModalTemplate"
controller: "DeleteProjectsModalController"
resolve:
projects: () -> $scope.getSelectedProjects()
)
modalInstance.result.then () ->
$scope.deleteSelectedProjects()
$scope.deleteSelectedProjects = () ->
selected_projects = $scope.getSelectedProjects()
selected_project_ids = $scope.getSelectedProjectIds()
# Remove projects from array
for project in selected_projects
$scope._removeProjectFromList project
# Remove project from any tags
for tag in $scope.tags
$scope._removeProjectIdsFromTagArray(tag, selected_project_ids)
for project_id in selected_project_ids
$http {
method: "DELETE"
url: "/project/#{project_id}?forever=true"
headers:
"X-CSRF-Token": window.csrfToken
}
$scope.updateVisibleProjects()
$scope.restoreSelectedProjects = () ->
selected_projects = $scope.getSelectedProjects()
selected_project_ids = $scope.getSelectedProjectIds()
for project in selected_projects
project.archived = false
for project_id in selected_project_ids
$http {
method: "POST"
url: "/project/#{project_id}/restore"
headers:
"X-CSRF-Token": window.csrfToken
}
$scope.updateVisibleProjects()
$scope.openUploadProjectModal = () ->
modalInstance = $modal.open(
templateUrl: "uploadProjectModalTemplate"
controller: "UploadProjectModalController"
)
ProjectPageApp.controller "ProjectListItemController", ($scope) ->
$scope.onSelectedChange = () ->
$scope.$emit "selected:on-change"
$scope.ownerName = () ->
if $scope.project.accessLevel == "owner"
return "You"
else if $scope.project.owner?
return "#{$scope.project.owner.first_name} #{$scope.project.owner.last_name}"
else
return "?"
ProjectPageApp.controller "TagListController", ($scope) ->
$scope.filterProjects = (filter = "all") ->
$scope._clearTags()
$scope.setFilter(filter)
$scope._clearTags = () ->
for tag in $scope.tags
tag.selected = false
ProjectPageApp.controller "TagListItemController", ($scope) ->
$scope.selectTag = () ->
$scope._clearTags()
$scope.tag.selected = true
$scope.setFilter("tag")
ProjectPageApp.controller "TagDropdownItemController", ($scope) ->
$scope.$on "selection:change", (e, newValue, oldValue) ->
$scope.recalculateProjectsInTag()
$scope.recalculateProjectsInTag = () ->
$scope.areSelectedProjectsInTag = false
for project_id in $scope.getSelectedProjectIds()
if project_id in $scope.tag.project_ids
$scope.areSelectedProjectsInTag = true
else
partialSelection = true
if $scope.areSelectedProjectsInTag and partialSelection
$scope.areSelectedProjectsInTag = "partial"
$scope.addOrRemoveProjectsFromTag = () ->
if $scope.areSelectedProjectsInTag == true
$scope.removeSelectedProjectsFromTag($scope.tag)
$scope.areSelectedProjectsInTag = false
else if $scope.areSelectedProjectsInTag == false or $scope.areSelectedProjectsInTag == "partial"
$scope.addSelectedProjectsToTag($scope.tag)
$scope.areSelectedProjectsInTag = true
ProjectPageApp.controller 'NewTagModalController', ($scope, $modalInstance, $timeout) ->
$scope.inputs =
newTagName: ""
$modalInstance.opened.then () ->
$timeout () ->
$scope.$broadcast "open"
, 700
$scope.create = () ->
$modalInstance.close($scope.inputs.newTagName)
$scope.cancel = () ->
$modalInstance.dismiss('cancel')
ProjectPageApp.controller 'RenameProjectModalController', ($scope, $modalInstance, $timeout, projectName) ->
$scope.inputs =
projectName: projectName
$modalInstance.opened.then () ->
$timeout () ->
$scope.$broadcast "open"
, 700
$scope.rename = () ->
$modalInstance.close($scope.inputs.projectName)
$scope.cancel = () ->
$modalInstance.dismiss('cancel')
ProjectPageApp.controller 'CloneProjectModalController', ($scope, $modalInstance, $timeout, project) ->
$scope.inputs =
projectName: project.name + " (Copy)"
$scope.state =
inflight: false
$modalInstance.opened.then () ->
$timeout () ->
$scope.$broadcast "open"
, 700
$scope.clone = () ->
$scope.state.inflight = true
$scope
.cloneProject(project, $scope.inputs.projectName)
.then (project_id) ->
$scope.state.inflight = false
$modalInstance.close(project_id)
$scope.cancel = () ->
$modalInstance.dismiss('cancel')
ProjectPageApp.controller 'NewProjectModalController', ($scope, $modalInstance, $timeout, template) ->
$scope.inputs =
projectName: ""
$scope.state =
inflight: false
$modalInstance.opened.then () ->
$timeout () ->
$scope.$broadcast "open"
, 700
$scope.create = () ->
$scope.state.inflight = true
$scope
.createProject($scope.inputs.projectName, template)
.then (project_id) ->
$scope.state.inflight = false
$modalInstance.close(project_id)
$scope.cancel = () ->
$modalInstance.dismiss('cancel')
ProjectPageApp.controller 'DeleteProjectsModalController', ($scope, $modalInstance, $timeout, projects) ->
$scope.projectsToDelete = projects.filter (project) -> project.accessLevel == "owner"
$scope.projectsToLeave = projects.filter (project) -> project.accessLevel != "owner"
if $scope.projectsToLeave.length > 0 and $scope.projectsToDelete.length > 0
$scope.action = "Delete & Leave"
else if $scope.projectsToLeave.length == 0 and $scope.projectsToDelete.length > 0
$scope.action = "Delete"
else
$scope.action = "Leave"
$scope.delete = () ->
$modalInstance.close()
$scope.cancel = () ->
$modalInstance.dismiss('cancel')
ProjectPageApp.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>
"""
ProjectPageApp.controller 'UploadProjectModalController', ($scope, $modalInstance, $timeout) ->
$scope.cancel = () ->
$modalInstance.dismiss('cancel')

View file

@ -3836,6 +3836,7 @@ function createInjector(modulesToLoad) {
/* jshint -W022 */
e = e.message + '\n' + e.stack;
}
console.log(module)
throw $injectorMinErr('modulerr', "Failed to instantiate module {0} due to:\n{1}",
module, e.stack || e.message || e);
}

View file

@ -1,9 +1,5 @@
/* --- Made by justgoscha and licensed under MIT license --- */
define(["libs/angular"], function(){
var app = angular.module('autocomplete', []);
app.directive('autocomplete', function() {
@ -260,5 +256,3 @@ app.directive('suggestion', function(){
}
};
});
})

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -1,263 +0,0 @@
/* BASICS */
.CodeMirror {
/* Set height, width, borders, and global font properties here */
font-family: monospace;
height: 300px;
}
.CodeMirror-scroll {
/* Set scrolling behaviour here */
overflow: auto;
}
/* PADDING */
.CodeMirror-lines {
padding: 4px 0; /* Vertical padding around content */
}
.CodeMirror pre {
padding: 0 4px; /* Horizontal padding of content */
}
.CodeMirror-scrollbar-filler, .CodeMirror-gutter-filler {
background-color: white; /* The little square between H and V scrollbars */
}
/* GUTTER */
.CodeMirror-gutters {
border-right: 1px solid #ddd;
background-color: #f7f7f7;
white-space: nowrap;
}
.CodeMirror-linenumbers {}
.CodeMirror-linenumber {
padding: 0 3px 0 5px;
min-width: 20px;
text-align: right;
color: #999;
}
/* CURSOR */
.CodeMirror div.CodeMirror-cursor {
border-left: 1px solid black;
z-index: 3;
}
/* Shown when moving in bi-directional text */
.CodeMirror div.CodeMirror-secondarycursor {
border-left: 1px solid silver;
}
.CodeMirror.cm-keymap-fat-cursor div.CodeMirror-cursor {
width: auto;
border: 0;
background: #7e7;
z-index: 1;
}
/* Can style cursor different in overwrite (non-insert) mode */
.CodeMirror div.CodeMirror-cursor.CodeMirror-overwrite {}
.cm-tab { display: inline-block; }
/* DEFAULT THEME */
.cm-s-default .cm-keyword {color: #708;}
.cm-s-default .cm-atom {color: #219;}
.cm-s-default .cm-number {color: #164;}
.cm-s-default .cm-def {color: #00f;}
.cm-s-default .cm-variable {color: black;}
.cm-s-default .cm-variable-2 {color: #05a;}
.cm-s-default .cm-variable-3 {color: #085;}
.cm-s-default .cm-property {color: black;}
.cm-s-default .cm-operator {color: black;}
.cm-s-default .cm-comment {color: #a50;}
.cm-s-default .cm-string {color: #a11;}
.cm-s-default .cm-string-2 {color: #f50;}
.cm-s-default .cm-meta {color: #555;}
.cm-s-default .cm-error {color: #f00;}
.cm-s-default .cm-qualifier {color: #555;}
.cm-s-default .cm-builtin {color: #30a;}
.cm-s-default .cm-bracket {color: #997;}
.cm-s-default .cm-tag {color: #170;}
.cm-s-default .cm-attribute {color: #00c;}
.cm-s-default .cm-header {color: blue;}
.cm-s-default .cm-quote {color: #090;}
.cm-s-default .cm-hr {color: #999;}
.cm-s-default .cm-link {color: #00c;}
.cm-negative {color: #d44;}
.cm-positive {color: #292;}
.cm-header, .cm-strong {font-weight: bold;}
.cm-em {font-style: italic;}
.cm-link {text-decoration: underline;}
.cm-invalidchar {color: #f00;}
div.CodeMirror span.CodeMirror-matchingbracket {color: #0f0;}
div.CodeMirror span.CodeMirror-nonmatchingbracket {color: #f22;}
.CodeMirror-activeline-background {background: #e8f2ff;}
/* STOP */
/* The rest of this file contains styles related to the mechanics of
the editor. You probably shouldn't touch them. */
.CodeMirror {
line-height: 1;
position: relative;
overflow: hidden;
background: white;
color: black;
}
.CodeMirror-scroll {
/* 30px is the magic margin used to hide the element's real scrollbars */
/* See overflow: hidden in .CodeMirror */
margin-bottom: -30px; margin-right: -30px;
padding-bottom: 30px; padding-right: 30px;
height: 100%;
outline: none; /* Prevent dragging from highlighting the element */
position: relative;
-moz-box-sizing: content-box;
box-sizing: content-box;
}
.CodeMirror-sizer {
position: relative;
}
/* The fake, visible scrollbars. Used to force redraw during scrolling
before actuall scrolling happens, thus preventing shaking and
flickering artifacts. */
.CodeMirror-vscrollbar, .CodeMirror-hscrollbar, .CodeMirror-scrollbar-filler, .CodeMirror-gutter-filler {
position: absolute;
z-index: 6;
display: none;
}
.CodeMirror-vscrollbar {
right: 0; top: 0;
overflow-x: hidden;
overflow-y: scroll;
}
.CodeMirror-hscrollbar {
bottom: 0; left: 0;
overflow-y: hidden;
overflow-x: scroll;
}
.CodeMirror-scrollbar-filler {
right: 0; bottom: 0;
}
.CodeMirror-gutter-filler {
left: 0; bottom: 0;
}
.CodeMirror-gutters {
position: absolute; left: 0; top: 0;
padding-bottom: 30px;
z-index: 3;
}
.CodeMirror-gutter {
white-space: normal;
height: 100%;
-moz-box-sizing: content-box;
box-sizing: content-box;
padding-bottom: 30px;
margin-bottom: -32px;
display: inline-block;
/* Hack to make IE7 behave */
*zoom:1;
*display:inline;
}
.CodeMirror-gutter-elt {
position: absolute;
cursor: default;
z-index: 4;
}
.CodeMirror-lines {
cursor: text;
}
.CodeMirror pre {
/* Reset some styles that the rest of the page might have set */
-moz-border-radius: 0; -webkit-border-radius: 0; border-radius: 0;
border-width: 0;
background: transparent;
font-family: inherit;
font-size: inherit;
margin: 0;
white-space: pre;
word-wrap: normal;
line-height: inherit;
color: inherit;
z-index: 2;
position: relative;
overflow: visible;
}
.CodeMirror-wrap pre {
word-wrap: break-word;
white-space: pre-wrap;
word-break: normal;
}
.CodeMirror-code pre {
border-right: 30px solid transparent;
width: -webkit-fit-content;
width: -moz-fit-content;
width: fit-content;
}
.CodeMirror-wrap .CodeMirror-code pre {
border-right: none;
width: auto;
}
.CodeMirror-linebackground {
position: absolute;
left: 0; right: 0; top: 0; bottom: 0;
z-index: 0;
}
.CodeMirror-linewidget {
position: relative;
z-index: 2;
overflow: auto;
}
.CodeMirror-widget {}
.CodeMirror-wrap .CodeMirror-scroll {
overflow-x: hidden;
}
.CodeMirror-measure {
position: absolute;
width: 100%;
height: 0;
overflow: hidden;
visibility: hidden;
}
.CodeMirror-measure pre { position: static; }
.CodeMirror div.CodeMirror-cursor {
position: absolute;
visibility: hidden;
border-right: none;
width: 0;
}
.CodeMirror-focused > .CodeMirror-scroll > .CodeMirror-sizer > div > .CodeMirror-lines > div > div.CodeMirror-cursor {
visibility: visible;
}
.CodeMirror-selected { background: #d9d9d9; }
.CodeMirror-focused .CodeMirror-selected { background: #d7d4f0; }
.cm-searching {
background: #ffa;
background: rgba(255, 255, 0, .4);
}
/* IE7 hack to prevent it from returning funny offsetTops on the spans */
.CodeMirror span { *vertical-align: text-bottom; }
@media print {
/* Hide the cursor when printing */
.CodeMirror div.CodeMirror-cursor {
visibility: hidden;
}
}

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

File diff suppressed because it is too large Load diff

File diff suppressed because one or more lines are too long