Merge pull request #4140 from overleaf/ae-react-share-modal

Remove Angular share modal code

GitOrigin-RevId: 136b10c7b9768f2d8de13e48b16fd71947506624
This commit is contained in:
Alf Eaton 2021-06-07 10:43:26 +01:00 committed by Copybot
parent 9130c37337
commit cce0051be6
16 changed files with 13 additions and 1997 deletions

View file

@ -887,10 +887,6 @@ const ProjectController = {
'new_navigation_ui',
user.alphaProgram
),
showReactShareModal: shouldDisplayFeature(
'new_share_modal_ui',
true
),
showReactDropboxModal: shouldDisplayFeature(
'new_dropbox_modal_ui',
user.betaProgram

View file

@ -81,7 +81,6 @@ block content
else
include ./editor/header
include ./editor/share
!= moduleIncludes("publish:body", locals)
include ./editor/history/toolbarV2.pug

View file

@ -1,10 +1,9 @@
div(ng-controller=showReactShareModal ? 'ReactShareProjectModalController': 'ShareController')
if showReactShareModal
share-project-modal(
handle-hide="handleHide"
show="show"
is-admin="isAdmin"
)
div(ng-controller="ReactShareProjectModalController")
share-project-modal(
handle-hide="handleHide"
show="show"
is-admin="isAdmin"
)
div(ng-controller="EditorNavigationToolbarController")
editor-navigation-toolbar-root(

View file

@ -119,17 +119,16 @@ header.toolbar.toolbar-header.toolbar-with-labels(
a.btn.btn-full-height(
href
ng-click="openShareProjectModal(permissions.admin);"
ng-controller=(showReactShareModal ? 'ReactShareProjectModalController': 'ShareController')
ng-controller="ReactShareProjectModalController"
)
i.fa.fa-fw.fa-group
p.toolbar-label #{translate("share")}
if showReactShareModal
share-project-modal(
handle-hide="handleHide"
show="show"
is-admin="isAdmin"
)
share-project-modal(
handle-hide="handleHide"
show="show"
is-admin="isAdmin"
)
!= moduleIncludes('publish:button', locals)
if !isRestrictedTokenMember

View file

@ -1,287 +0,0 @@
script(type='text/ng-template', id='shareProjectModalTemplate')
.modal-header
button.close(
type="button"
data-dismiss="modal"
ng-click="cancel()"
aria-label="Close"
)
span(aria-hidden="true") ×
h3 #{translate("share_project")}
.modal-body.modal-body-share
.container-fluid
if isRestrictedTokenMember
//- Token-based access
.row.public-access-level
.col-xs-12.access-token-display-area
div.access-token-wrapper
strong #{translate('anyone_with_link_can_view')}
pre.access-token {{ readOnlyTokenLink }}
if !isRestrictedTokenMember
//- Private (with token-access available)
.row.public-access-level(ng-show="isAdmin && project.publicAccesLevel == 'private'")
.col-xs-12.text-center
| #{translate('link_sharing_is_off')}
|   
a(
href
ng-click="makeTokenBased()"
) #{translate('turn_on_link_sharing')}
span   
a(
href="/learn/how-to/What_is_Link_Sharing%3F"
target="_blank"
)
i.fa.fa-question-circle(
tooltip=translate('learn_more_about_link_sharing')
)
//- Token-based access
.row.public-access-level(ng-show="isAdmin && project.publicAccesLevel == 'tokenBased'")
.col-xs-12.text-center
strong
| #{translate('link_sharing_is_on')}.
|   
a(
href
ng-click="makePrivate()"
) #{translate('turn_off_link_sharing')}
span   
a(
href="/learn/how-to/What_is_Link_Sharing%3F"
target="_blank"
)
i.fa.fa-question-circle(
tooltip=translate('learn_more_about_link_sharing')
)
.col-xs-12.access-token-display-area
div.access-token-wrapper
strong #{translate('anyone_with_link_can_edit')}
pre.access-token(ng-show="readAndWriteTokenLink") {{ readAndWriteTokenLink }}
pre.access-token(ng-hide="readAndWriteTokenLink") #{translate('loading')}…
div.access-token-wrapper
strong #{translate('anyone_with_link_can_view')}
pre.access-token(ng-show="readOnlyTokenLink") {{ readOnlyTokenLink }}
pre.access-token(ng-hide="readOnlyTokenLink") #{translate('loading')}…
//- legacy public-access
.row.public-access-level(ng-show="isAdmin && (project.publicAccesLevel == 'readAndWrite' || project.publicAccesLevel == 'readOnly')")
.col-xs-12.text-center
strong(ng-if="project.publicAccesLevel == 'readAndWrite'") #{translate("this_project_is_public")}
strong(ng-if="project.publicAccesLevel == 'readOnly'") #{translate("this_project_is_public_read_only")}
|   
a(
href
ng-click="makePrivate()"
) #{translate("make_private")}
.row.project-member
.col-xs-7 {{ project.owner.email }}
.text-left.col-xs-3 #{translate("owner")}
form.form-horizontal(
ng-if="isAdmin"
ng-repeat="member in project.members"
ng-controller="ShareProjectModalMemberRowController"
)
.row.form-group.project-member
.col-xs-7.form-control-static {{ member.email }}
.col-xs-3
select.privileges.form-control.input-sm(name="privileges" ng-model="form.privileges")
option(value="owner") #{translate("owner")}
option(value="readAndWrite") #{translate("can_edit")}
option(value="readOnly") #{translate("read_only")}
.col-xs-2.form-control-static.text-center(ng-hide="form.isModified()")
a(
href
tooltip=translate('remove_collaborator')
tooltip-placement="bottom"
ng-click="removeMember(member)"
aria-label=translate('remove_collaborator')
)
i.fa.fa-times
.col-xs-2.text-center(ng-show="form.isModified()")
button.btn.btn-sm.btn-success(
type="submit"
ng-click="form.submit()"
) #{translate("change")}
.text-sm
| #{translate("or")}
|
button.btn.btn-inline-link(ng-click="form.reset()") #{translate("cancel").toLowerCase()}
.row.project-member(ng-if="!isAdmin" ng-repeat="member in project.members")
.col-xs-7 {{ member.email }}
.col-xs-3
span(ng-if="member.privileges == 'readAndWrite'") #{translate("can_edit")}
span(ng-if="member.privileges == 'readOnly'") #{translate("read_only")}
.row.project-invite(ng-repeat="invite in project.invites")
.col-xs-7 {{ invite.email }} 
div.small
| #{translate("invite_not_accepted")}. 
button.btn.btn-inline-link(
ng-show="isAdmin",
ng-click="resendInvite(invite, $event)"
) #{translate("resend")}
.col-xs-3.text-left
// todo: get invite privileges
span(ng-show="invite.privileges == 'readAndWrite'") #{translate("can_edit")}
span(ng-show="invite.privileges == 'readOnly'") #{translate("read_only")}
.col-xs-2.text-center(ng-if="isAdmin")
a(
href
tooltip=translate('revoke_invite')
tooltip-placement="bottom"
ng-click="revokeInvite(invite)"
)
i.fa.fa-times
.row.invite-controls(ng-show="isAdmin")
form(ng-show="canAddCollaborators")
.small #{translate("share_with_your_collabs")}
.form-group
tags-input(
class="tags-input"
template="shareTagTemplate"
placeholder=settings.customisation.shareProjectPlaceholder || 'joe@example.com, sue@example.com, …'
ng-model="inputs.contacts"
focus-on="open"
display-property="display"
add-on-paste="true"
add-on-enter="false"
replace-spaces-with-dashes="false"
type="email"
)
auto-complete(
source="filterAutocompleteUsers($query)"
template="shareAutocompleteTemplate"
display-property="email"
min-length="0"
)
.form-group
.pull-right
select.privileges.form-control(
ng-model="inputs.privileges"
name="privileges"
)
option(value="readAndWrite") #{translate("can_edit")}
option(value="readOnly") #{translate("read_only")}
|   
//- We have to use mousedown here since click has issues with the
//- blur handler in tags-input sometimes changing its height and
//- moving this button, preventing the click registering.
button.btn.btn-info(
type="submit"
ng-mousedown="addMembers()"
ng-keyup="$event.keyCode == 13 ? addMembers() : null"
) #{translate("share")}
div(ng-hide="canAddCollaborators")
p.text-center #{translate("need_to_upgrade_for_more_collabs")}. Also:
.row
.col-md-8.col-md-offset-2
ul.list-unstyled
li
i.fa.fa-check  
| #{translate("unlimited_projects")}
li
i.fa.fa-check  
| #{translate("collabs_per_proj", {collabcount:'Multiple'})}
li
i.fa.fa-check  
| #{translate("full_doc_history")}
li
i.fa.fa-check  
| #{translate("sync_to_dropbox")}
li
i.fa.fa-check  
| #{translate("sync_to_github")}
li
i.fa.fa-check  
|#{translate("compile_larger_projects")}
p.text-center.row-spaced-thin(ng-show="user.allowedFreeTrial" ng-controller="FreeTrialModalController")
a.btn.btn-success(
href
ng-class="buttonClass"
ng-click="startFreeTrial('projectMembers')"
) #{translate("start_free_trial")}
p.text-center.row-spaced-thin(ng-show="!user.allowedFreeTrial" ng-controller="UpgradeModalController")
a.btn.btn-success(
href
ng-class="buttonClass"
ng-click="upgradePlan('projectMembers')"
) #{translate("upgrade")}
p.small(ng-show="startedFreeTrial")
| #{translate("refresh_page_after_starting_free_trial")}
.row.public-access-level.public-access-level--notice(ng-show="!isAdmin")
.col-xs-12.text-center(ng-show="project.publicAccesLevel == 'private'") #{translate("to_add_more_collaborators")}
.col-xs-12.text-center(ng-show="project.publicAccesLevel == 'tokenBased'") #{translate("to_change_access_permissions")}
.modal-footer.modal-footer-share
.modal-footer-left
i.fa.fa-refresh.fa-spin(ng-show="state.inflight")
span.text-danger.error(ng-show="state.error")
span(ng-switch="state.errorReason")
span(ng-switch-when="cannot_invite_non_user")
| #{translate("cannot_invite_non_user")}
span(ng-switch-when="cannot_verify_user_not_robot")
| #{translate("cannot_verify_user_not_robot")}
span(ng-switch-when="cannot_invite_self")
| #{translate("cannot_invite_self")}
span(ng-switch-when="invalid_email")
| #{translate("invalid_email")}
span(ng-switch-default)
| #{translate("generic_something_went_wrong")}
.modal-footer-right
button.btn.btn-default(
ng-click="done()"
) #{translate("close")}
script(type="text/ng-template", id="shareTagTemplate")
.tag-template
span(ng-if="data.type")
i.fa.fa-fw(ng-class="{'fa-user': data.type != 'group', 'fa-group': data.type == 'group'}")
|
span {{$getDisplayText()}}
|
a(href, ng-click="$removeTag()").remove-button
i.fa.fa-fw.fa-close
script(type="text/ng-template", id="shareAutocompleteTemplate")
.autocomplete-template
div(ng-if="data.type == 'user'")
i.fa.fa-fw.fa-user
|
span(ng-bind-html="$highlight(data.display)")
div(ng-if="data.type == 'group'")
i.fa.fa-fw.fa-group
|
span(ng-bind-html="$highlight(data.name)")
span.subdued.small(ng-show="data.member_count") ({{ data.member_count }} members)
script(type="text/ng-template", id="ownershipTransferConfirmTemplate")
.modal-header
button.close(
type="button"
data-dismiss="modal"
ng-click="cancel()"
aria-label="Close"
)
span(aria-hidden="true") ×
h3 #{translate("change_project_owner")}
.modal-body
p !{translate('project_ownership_transfer_confirmation_1', { user: '{{ member.email }}', project: '{{ project.name }}' }, ['strong', 'strong'])}
p #{translate('project_ownership_transfer_confirmation_2')}
.modal-footer
.modal-footer-left
i.fa.fa-refresh.fa-spin(ng-show="state.inflight")
span.text-danger.error(ng-show="state.error") #{translate("generic_something_went_wrong")}
.modal-footer-right
button.btn.btn-default(ng-click="cancel()") #{translate("cancel")}
button.btn.btn-success(ng-click="confirm()") #{translate("change_owner")}

View file

@ -35,7 +35,6 @@ const App = angular
'ErrorCatcher',
'localStorage',
'sessionStorage',
'ngTagsInput',
'ui.select',
])
.config(function ($qProvider, $httpProvider, uiSelectConfig) {

View file

@ -35,7 +35,6 @@ import SafariScrollPatcher from './ide/SafariScrollPatcher'
import { loadServiceWorker } from './ide/pdfng/directives/serviceWorkerManager'
import './ide/cobranding/CobrandingDataService'
import './ide/settings/index'
import './ide/share/index'
import './ide/binary-files/index'
import './ide/chat/index'
import './ide/clone/index'
@ -64,6 +63,7 @@ import './main/system-messages'
import '../../modules/modules-ide.js'
import './shared/context/controllers/root-context-controller'
import './features/editor-navigation-toolbar/controllers/editor-navigation-toolbar-controller'
import './features/share-project-modal/controllers/react-share-project-modal-controller'
import getMeta from './utils/meta'
App.controller(

View file

@ -1,35 +0,0 @@
import App from '../../../base'
App.controller(
'OwnershipTransferConfirmModalController',
function ($scope, $window, $modalInstance, projectMembers) {
$scope.state = {
inflight: false,
error: false,
}
$scope.confirm = function () {
const userId = $scope.member._id
transferOwnership(userId)
}
$scope.cancel = function () {
$modalInstance.dismiss()
}
function transferOwnership(userId) {
$scope.state.inflight = true
$scope.state.error = false
projectMembers
.transferOwnership(userId)
.then(() => {
$scope.state.inflight = false
$scope.state.error = false
$window.location.reload()
})
.catch(() => {
$scope.state.inflight = false
$scope.state.error = true
})
}
}
)

View file

@ -1,55 +0,0 @@
import App from '../../../base'
App.controller('ShareController', function (
$scope,
$modal,
ide,
projectInvites,
projectMembers,
// eslint-disable-next-line camelcase
eventTracking
) {
$scope.openShareProjectModal = function (isAdmin) {
$scope.isAdmin = isAdmin
eventTracking.sendMBOnce('ide-open-share-modal-once')
$modal.open({
templateUrl: 'shareProjectModalTemplate',
controller: 'ShareProjectModalController',
scope: $scope,
})
}
ide.socket.on('project:tokens:changed', data => {
if (data.tokens != null) {
ide.$scope.project.tokens = data.tokens
$scope.$digest()
}
})
ide.socket.on('project:membership:changed', data => {
if (data.members) {
projectMembers
.getMembers()
.then(response => {
if (response.data.members) {
$scope.project.members = response.data.members
}
})
.catch(() => {
console.error('Error fetching members for project')
})
}
if (data.invites) {
projectInvites
.getInvites()
.then(response => {
if (response.data.invites) {
$scope.project.invites = response.data.invites
}
})
.catch(() => {
console.error('Error fetching invites for project')
})
}
})
})

View file

@ -1,309 +0,0 @@
import _ from 'lodash'
import App from '../../../base'
App.controller('ShareProjectModalController', function (
$scope,
$modalInstance,
$timeout,
projectMembers,
projectInvites,
$modal,
$http,
ide,
validateCaptcha,
validateCaptchaV3,
settings,
// eslint-disable-next-line camelcase
eventTracking
) {
$scope.inputs = {
privileges: 'readAndWrite',
contacts: [],
}
$scope.state = {
error: null,
errorReason: null,
inflight: false,
startedFreeTrial: false,
invites: [],
}
$modalInstance.opened.then(() =>
$timeout(() => $scope.$broadcast('open'), 200)
)
const INFINITE_COLLABORATORS = -1
$scope.refreshCanAddCollaborators = function () {
const allowedNoOfMembers = $scope.project.features.collaborators
$scope.canAddCollaborators =
$scope.project.members.length + $scope.project.invites.length <
allowedNoOfMembers || allowedNoOfMembers === INFINITE_COLLABORATORS
}
$scope.refreshCanAddCollaborators()
$scope.$watch('canAddCollaborators', function () {
if (!$scope.canAddCollaborators) {
eventTracking.send(
'subscription-funnel',
'editor-click-feature',
'projectMembers'
)
}
})
$scope.$watch(
'(project.members.length + project.invites.length)',
_noOfMembers => $scope.refreshCanAddCollaborators()
)
$scope.autocompleteContacts = []
if ($scope.isRestrictedTokenMember) {
// Restricted token members are users who join via a read-only link.
// They will not be able to invite any users, so skip the lookup of
// their contacts. This request would result in a 403 for anonymous
// users, which in turn would redirect them to the /login.
} else {
$http.get('/user/contacts').then(processContactsResponse)
}
function processContactsResponse(response) {
const { data } = response
$scope.autocompleteContacts = data.contacts || []
for (const contact of $scope.autocompleteContacts) {
if (contact.type === 'user') {
if (
contact.first_name === contact.email.split('@')[0] &&
!contact.last_name
) {
// User has not set their proper name so use email as canonical display property
contact.display = contact.email
} else {
contact.name = `${contact.first_name} ${contact.last_name}`
contact.display = `${contact.name} <${contact.email}>`
}
} else {
// Must be a group
contact.display = contact.name
}
}
}
const getCurrentMemberEmails = () =>
($scope.project.members || []).map(u => u.email)
const getCurrentInviteEmails = () =>
($scope.project.invites || []).map(u => u.email)
$scope.filterAutocompleteUsers = function ($query) {
const currentMemberEmails = getCurrentMemberEmails()
return $scope.autocompleteContacts.filter(function (contact) {
if (
contact.email != null &&
currentMemberEmails.includes(contact.email)
) {
return false
}
for (const text of [contact.name, contact.email]) {
if (
text != null &&
text.toLowerCase().indexOf($query.toLowerCase()) > -1
) {
return true
}
}
return false
})
}
$scope.addMembers = function () {
const addMembers = function () {
if ($scope.inputs.contacts.length === 0) {
return
}
const members = $scope.inputs.contacts
$scope.inputs.contacts = []
$scope.clearError()
$scope.state.inflight = true
if ($scope.project.invites == null) {
$scope.project.invites = []
}
const currentMemberEmails = getCurrentMemberEmails()
const currentInviteEmails = getCurrentInviteEmails()
addNextMember()
function addNextMember() {
let email
if (members.length === 0 || !$scope.canAddCollaborators) {
$scope.state.inflight = false
$scope.$apply()
return
}
const member = members.shift()
if (member.type === 'user') {
email = member.email
} else {
// Not an auto-complete object, so email == display
email = member.display
}
email = email.toLowerCase()
if (currentMemberEmails.includes(email)) {
// Skip this existing member
return addNextMember()
}
// do v3 captcha to collect data only
validateCaptchaV3('invite')
// do v2 captcha
const ExposedSettings = window.ExposedSettings
validateCaptcha(function (response) {
$scope.grecaptchaResponse = response
const invites = $scope.project.invites || []
const invite = _.find(invites, invite => invite.email === email)
let request
if (currentInviteEmails.includes(email) && invite) {
request = projectInvites.resendInvite(invite._id)
} else {
request = projectInvites.sendInvite(
email,
$scope.inputs.privileges,
$scope.grecaptchaResponse
)
}
request
.then(function (response) {
const { data } = response
if (data.error) {
$scope.setError(data.error)
$scope.state.inflight = false
} else {
if (data.invite) {
const { invite } = data
$scope.project.invites.push(invite)
} else {
const users =
data.users != null
? data.users
: data.user != null
? [data.user]
: []
$scope.project.members.push(...users)
}
}
setTimeout(
() =>
// Give $scope a chance to update $scope.canAddCollaborators
// with new collaborator information.
addNextMember(),
0
)
})
.catch(function (httpResponse) {
const { data } = httpResponse
$scope.state.inflight = false
$scope.setError(data.errorReason)
})
}, ExposedSettings.recaptchaDisabled.invite)
}
}
$timeout(addMembers, 50) // Give email list a chance to update
}
$scope.removeMember = function (member) {
$scope.monitorRequest(
projectMembers.removeMember(member).then(function () {
const index = $scope.project.members.indexOf(member)
if (index === -1) {
return
}
$scope.project.members.splice(index, 1)
})
)
}
$scope.revokeInvite = function (invite) {
$scope.monitorRequest(
projectInvites.revokeInvite(invite._id).then(function () {
const index = $scope.project.invites.indexOf(invite)
if (index === -1) {
return
}
$scope.project.invites.splice(index, 1)
})
)
}
$scope.resendInvite = function (invite, event) {
$scope.monitorRequest(
projectInvites
.resendInvite(invite._id)
.then(function () {
event.target.blur()
})
.catch(function () {
event.target.blur()
})
)
}
$scope.makeTokenBased = function () {
$scope.project.publicAccesLevel = 'tokenBased'
settings.saveProjectAdminSettings({ publicAccessLevel: 'tokenBased' })
eventTracking.sendMB('project-make-token-based')
}
$scope.makePrivate = function () {
$scope.project.publicAccesLevel = 'private'
settings.saveProjectAdminSettings({ publicAccessLevel: 'private' })
}
$scope.$watch('project.tokens.readAndWrite', function (token) {
if (token != null) {
$scope.readAndWriteTokenLink = `${location.origin}/${token}`
} else {
$scope.readAndWriteTokenLink = null
}
})
$scope.$watch('project.tokens.readOnly', function (token) {
if (token != null) {
$scope.readOnlyTokenLink = `${location.origin}/read/${token}`
} else {
$scope.readOnlyTokenLink = null
}
})
$scope.done = () => $modalInstance.close()
$scope.cancel = () => $modalInstance.dismiss()
$scope.monitorRequest = function monitorRequest(request) {
$scope.clearError()
$scope.state.inflight = true
return request
.then(() => {
$scope.state.inflight = false
$scope.clearError()
})
.catch(err => {
$scope.state.inflight = false
$scope.setError(err.data && err.data.error)
})
}
$scope.clearError = function clearError() {
$scope.state.error = false
}
$scope.setError = function setError(reason) {
$scope.state.error = true
$scope.state.errorReason = reason
}
})

View file

@ -1,46 +0,0 @@
import App from '../../../base'
App.controller(
'ShareProjectModalMemberRowController',
function ($scope, $modal, projectMembers) {
$scope.form = {
privileges: $scope.member.privileges,
isModified() {
return this.privileges !== $scope.member.privileges
},
submit() {
const userId = $scope.member._id
const privilegeLevel = $scope.form.privileges
if (privilegeLevel === 'owner') {
openOwnershipTransferConfirmModal(userId)
} else {
setPrivilegeLevel(userId, privilegeLevel)
}
},
reset() {
this.privileges = $scope.member.privileges
$scope.clearError()
},
}
function setPrivilegeLevel(userId, privilegeLevel) {
$scope.monitorRequest(
projectMembers
.setMemberPrivilegeLevel(userId, privilegeLevel)
.then(() => {
$scope.member.privileges = privilegeLevel
})
)
}
function openOwnershipTransferConfirmModal(userId) {
$modal.open({
templateUrl: 'ownershipTransferConfirmTemplate',
controller: 'OwnershipTransferConfirmModalController',
scope: $scope,
})
}
}
)

View file

@ -1,7 +0,0 @@
import './controllers/ShareController'
import './controllers/ShareProjectModalController'
import './controllers/ShareProjectModalMemberRowController'
import './controllers/OwnershipTransferConfirmModalController'
import './services/projectMembers'
import './services/projectInvites'
import '../../features/share-project-modal/controllers/react-share-project-modal-controller'

View file

@ -1,37 +0,0 @@
import App from '../../../base'
export default App.factory('projectInvites', (ide, $http) => ({
sendInvite(email, privileges, grecaptchaResponse) {
return $http.post(`/project/${ide.project_id}/invite`, {
email,
privileges,
_csrf: window.csrfToken,
'g-recaptcha-response': grecaptchaResponse,
})
},
revokeInvite(inviteId) {
return $http({
url: `/project/${ide.project_id}/invite/${inviteId}`,
method: 'DELETE',
headers: {
'X-Csrf-Token': window.csrfToken,
},
})
},
resendInvite(inviteId, privileges) {
return $http.post(`/project/${ide.project_id}/invite/${inviteId}/resend`, {
_csrf: window.csrfToken,
})
},
getInvites() {
return $http.get(`/project/${ide.project_id}/invites`, {
json: true,
headers: {
'X-Csrf-Token': window.csrfToken,
},
})
},
}))

View file

@ -1,48 +0,0 @@
import App from '../../../base'
App.factory('projectMembers', (ide, $http) => ({
removeMember(member) {
return $http({
url: `/project/${ide.project_id}/users/${member._id}`,
method: 'DELETE',
headers: {
'X-Csrf-Token': window.csrfToken,
},
})
},
addGroup(groupId, privileges) {
return $http.post(`/project/${ide.project_id}/group`, {
group_id: groupId,
privileges,
_csrf: window.csrfToken,
})
},
getMembers() {
return $http.get(`/project/${ide.project_id}/members`, {
json: true,
headers: {
'X-Csrf-Token': window.csrfToken,
},
})
},
setMemberPrivilegeLevel(userId, privilegeLevel) {
return $http.put(
`/project/${ide.project_id}/users/${userId}`,
{ privilegeLevel },
{
headers: {
'X-Csrf-Token': window.csrfToken,
},
}
)
},
transferOwnership(userId) {
return $http.post(`/project/${ide.project_id}/transfer-ownership`, {
user_id: userId,
_csrf: window.csrfToken,
})
},
}))

View file

@ -8,7 +8,6 @@ import 'libs/ng-context-menu-0.1.4'
import 'libs/jquery.storage'
import 'libs/angular-cookie'
import 'libs/passfield'
import 'libs/ng-tags-input-3.0.0'
import 'libs/select/select'
// CSS

File diff suppressed because it is too large Load diff