mirror of
https://github.com/overleaf/overleaf.git
synced 2025-04-08 21:00:45 +00:00
Wrap project list code in require.js
This commit is contained in:
parent
c56648ab80
commit
012371333f
18 changed files with 629 additions and 95526 deletions
|
@ -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",
|
||||
|
|
|
@ -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"
|
||||
};
|
||||
|
|
|
@ -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(
|
||||
|
|
10
services/web/public/coffee/app/base.coffee
Normal file
10
services/web/public/coffee/app/base.coffee
Normal file
|
@ -0,0 +1,10 @@
|
|||
define [
|
||||
"../libs/angular-autocomplete/angular-autocomplete"
|
||||
"../libs/ui-bootstrap"
|
||||
], () ->
|
||||
App = angular.module("SharelatexApp", [
|
||||
"ui.bootstrap"
|
||||
"autocomplete"
|
||||
])
|
||||
|
||||
return App
|
5
services/web/public/coffee/app/main.coffee
Normal file
5
services/web/public/coffee/app/main.coffee
Normal file
|
@ -0,0 +1,5 @@
|
|||
define [
|
||||
"project-list"
|
||||
"user-details"
|
||||
], () ->
|
||||
angular.bootstrap(document.body, ["SharelatexApp"])
|
580
services/web/public/coffee/app/project-list.coffee
Normal file
580
services/web/public/coffee/app/project-list.coffee
Normal 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')
|
|
@ -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'])
|
||||
|
|
@ -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')
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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(){
|
|||
}
|
||||
};
|
||||
});
|
||||
|
||||
})
|
||||
|
|
21675
services/web/public/js/libs/angular.js
vendored
21675
services/web/public/js/libs/angular.js
vendored
File diff suppressed because it is too large
Load diff
1951
services/web/public/js/libs/bootstrap.js
vendored
1951
services/web/public/js/libs/bootstrap.js
vendored
File diff suppressed because it is too large
Load diff
|
@ -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
12099
services/web/public/js/libs/jquery.dataTables.js
vendored
12099
services/web/public/js/libs/jquery.dataTables.js
vendored
File diff suppressed because it is too large
Load diff
File diff suppressed because one or more lines are too long
Loading…
Add table
Reference in a new issue