Skip to content

Commit

Permalink
Merge pull request #1923 from thostetler/library-owner-transfer
Browse files Browse the repository at this point in the history
Library owner transfer widget
  • Loading branch information
ehenneken committed Sep 16, 2019
2 parents befd346 + 556049a commit f93c26e
Show file tree
Hide file tree
Showing 9 changed files with 245 additions and 85 deletions.
2 changes: 1 addition & 1 deletion .gitignore
Expand Up @@ -32,7 +32,7 @@ src/styles/css

.vagrant

src/discovery.vars.js
src/config/discovery.vars.js
grunt/requirejs.js
.*
!.babelrc
Expand Down
23 changes: 0 additions & 23 deletions src/config/discovery.vars.js

This file was deleted.

1 change: 1 addition & 0 deletions src/js/components/api_targets.js
Expand Up @@ -72,6 +72,7 @@ function (
// can get info about all libraries, or list of bibcodes associated w/specific lib (libraries/id)
// post to /libraries/ to create a library
LIBRARIES: 'biblib/libraries',
LIBRARY_TRANSFER: 'biblib/transfer',
// can post, put, and delete changes to individual libs using this endpoint
DOCUMENTS: 'biblib/documents',
PERMISSIONS: 'biblib/permissions',
Expand Down
13 changes: 13 additions & 0 deletions src/js/components/library_controller.js
Expand Up @@ -445,6 +445,18 @@ function (
return this.composeRequest(endpoint, 'POST', { data: data });
},

transferOwnership: function (libId, newOwnerEmail) {
if (!newOwnerEmail || !_.isString(newOwnerEmail)) {
throw 'new owner email address must be a string';
}
if (!libId || !_.isString(libId)) {
throw 'library Id must be a string';
}
const endpoint = ApiTargets.LIBRARY_TRANSFER + '/' + libId;
const data = { email: newOwnerEmail };
return this.composeRequest(endpoint, 'POST', { data });
},


// /*
// * email, permission, value
Expand Down Expand Up @@ -571,6 +583,7 @@ function (
updateLibraryMetadata: 'updateLibraryMetadata',

importLibraries: 'importLibraries',
transferOwnership: 'transferOwnership',

// currently called by library individual widget to get
// lists of bibs to pass to export, metrics, vis widgets etc
Expand Down
81 changes: 50 additions & 31 deletions src/js/widgets/library_individual/templates/make-public.html
@@ -1,34 +1,53 @@


{{#if public}}

<h3><i class="fa fa-lg fa-unlock"></i> This Library is Public</h3>

<div class="s-permissions-list-container">

<p><b>Public libraries</b> are available for all to read.</p>
<p><b>Private libraries</b> are visible to only you and any collaborators.</p>

<p> The public address of this library is <a target="_blank" rel="noopener" href="https://ui.adsabs.harvard.edu/public-libraries/{{id}}">https://ui.adsabs.harvard.edu/public-libraries/{{id}}</a></p>
<p><button class="btn btn-danger btn-inverted public-button make-private"><i class="fa fa-lg fa-lock"></i> Make this library private. </button></p>

<div>
{{#if public}}
<div class="row">
<div class="col-xs-12">
<h3><i class="fa fa-lg fa-unlock"></i> This Library is Public</h3>
</div>

{{else}}

<h3> <i class="fa fa-lg fa-lock"></i> This Library is Private</h3>

<div class="s-permissions-list-container">

<p><b>Public libraries</b> are available for all to read.</p>
<p><b>Private libraries</b> are visible to only you and any collaborators.</p>

<p>
<button class="btn btn-success btn-inverted public-button make-public"><i class="fa fa-lg fa-unlock"></i> Make this library public. </button>
</p>
</div>
<div class="row">
<div class="col-xs-12">
<div class="panel">
<div class="panel-body">
<p><b>Public libraries</b> are available for all to read.</p>
<p><b>Private libraries</b> are visible to only you and any collaborators.</p>
<p> The public address of this library is <a target="_blank" rel="noopener"
href="https://ui.adsabs.harvard.edu/public-libraries/{{id}}">https://ui.adsabs.harvard.edu/public-libraries/{{id}}</a>
</p>
<div class="btn-toolbar">
<button class="btn btn-danger btn-inverted public-button make-private"><i class="fa fa-lg fa-lock"></i>
Make this library private.</button>
<button class="btn btn-danger btn-inverted public-button make-private"><i class="fa fa-lg fa-lock"></i>
Make this library private.</button>
</div>
</div>
</div>
</div>

{{/if}}


</div>
{{else}}
<div class="row">
<div class="col-xs-12">
<h3><i class="fa fa-lg fa-lock"></i> This Library is Private</h3>
</div>
</div>
<div class="row">
<div class="col-xs-12">
<div class="panel">
<div class="panel-body">
<p><b>Public libraries</b> are available for all to read.</p>
<p><b>Private libraries</b> are visible to only you and any collaborators.</p>
<p> The public address of this library is <a target="_blank" rel="noopener"
href="https://ui.adsabs.harvard.edu/public-libraries/{{id}}">https://ui.adsabs.harvard.edu/public-libraries/{{id}}</a>
</p>
<div class="btn-toolbar">
<button class="btn btn-success btn-inverted public-button make-public"><i class="fa fa-lg fa-unlock" aria-hidden="true"></i>
Make this library public.</button>
<button class="btn btn-info btn-inverted" data-toggle="modal" data-target="#transferOwnershipModal"><i class="fa fa-lg fa-paper-plane" aria-hidden="true"></i>
Transfer Ownership</button>
</div>
</div>
</div>
</div>
</div>
{{/if}}
</div>
@@ -0,0 +1,47 @@
<div class="modal fade" id="transferOwnershipModal" tabindex="-1" role="dialog"
aria-labelledby="transforOwnershipModal">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span
aria-hidden="true">&times;</span></button>
<h4 class="modal-title" id="transforOwnershipModal">Transfer Ownership</h4>
</div>
<div class="modal-body">
<form class="form-horizontal">
<fieldset>
<!-- Text input-->
<div class="form-group">
<label class="col-md-4 control-label" for="textinput">New Owner</label>
<div class="col-md-7">
<input id="textinput" name="textinput" type="email" placeholder="new-owner@test.com"
class="form-control input-md" required="" value="" autofocus aria-describedby="helpBlock">
<span class="help-block" id="helpBlock">Enter the email address of the new user</span>
</div>
</div>

<div class="alert alert-danger" id="error-message" style="display: none;">
<i class="fa fa-exclamation-triangle" aria-hidden="true"></i>
<span></span>
</div>

<div class="text-center" id="loader" style="display: none;">
<i class="fa fa-spinner fa-spin" aria-hidden="true"></i>
</div>

<div class="alert alert-success" id="success-message" style="display: none;">
<i class="fa fa-checkmark" aria-hidden="true"></i>
<span></span>
</div>

</fieldset>
</form>

</div>
<div class="modal-footer">
<button type="button" class="btn btn-default close-button" data-dismiss="modal">Close</button>
<button type="button" class="btn btn-primary confirm-button">Confirm</button>
</div>
</div>
</div>
</div>
143 changes: 114 additions & 29 deletions src/js/widgets/library_individual/views/manage_permissions.js
@@ -1,58 +1,143 @@
define([
'marionette',
define(['marionette',
'hbs!js/widgets/library_individual/templates/manage-permissions-container',
'hbs!js/widgets/library_individual/templates/make-public',
'bootstrap'
], function (
Marionette,
ManagePermissionsContainer,
MakePublicTemplate,
Bootstrap
) {
var PermissionsModel = Backbone.Model.extend({

});

'hbs!../templates/transfer-ownership-modal'
], function (Marionette, ManagePermissionsContainer, MakePublicTemplate, transferOwnershipModal) {
var PermissionsModel = Backbone.Model.extend({});
var PermissionsCollection = Backbone.Collection.extend({

model: PermissionsModel

});

const TransferOwnershipModalView = Backbone.View.extend({
initialize() {
this.render = _.debounce(this.render, 500);
this.onConfirm = _.debounce(this.onConfirm, 1000);
this.model = new (Backbone.Model.extend({
defaults: {
error: false,
loading: false
}
}));
const container = document.createElement('div');
document.body.appendChild(container);
this.setElement(container);
this.model.on('change:error', () => { this.showErrorMessage(); });
this.model.on('change:loading', () => { this.showLoading(); });
this.model.on('change:success', () => { this.showSuccessMessage(); });
},
showErrorMessage() {
const error = this.model.get('error');
const el = $('#error-message', this.el);
if (error && error.length > 0) {
el.fadeIn();
$('span', el).text(error);
} else {
el.hide();
}
},
showSuccessMessage() {
const success = this.model.get('success');
const el = $('#success-message', this.el);
if (success && success.length > 0) {
el.fadeIn();
$('span', el).text(success);
} else {
el.hide();
}
},
showLoading() {
const loading = this.model.get('loading');
const el = $('#loader', this.el);
loading ? el.show() : el.hide();
},
getModal() {
return $('#transferOwnershipModal', this.$el);
},
render() {
this.$el.html(transferOwnershipModal(this.model.toJSON()));
this.getModal().off().on('show.bs.modal', () => {
this.model.clear().set(this.model.defaults);
}).on('shown.bs.modal', () => {
$('input', this.$el).focus();
});
},
events: {
'click .confirm-button': '_onConfirm',
'submit form': '_onConfirm'
},
getEmailAddress() {
return $('input', this.el).val();
},
_onConfirm(e) {
this.model.set({
loading: true,
error: false
});

const msg = 'Are you sure?';
if (confirm(msg)) {
this.onConfirm(e);
} else {
this.model.set({
loading: false,
error: true
});
}

var ManagePermissionsView = Marionette.ItemView.extend({
},
onConfirm(e) {
e.preventDefault();
const email = this.getEmailAddress();
this.trigger('confirm-transfer-ownership', email, {
done: () => {
this.model.set({
success: `Success! Ownership has been transferred to ${ email }`,
loading: false
});
setTimeout(() => {
this.getModal().modal('hide');
this.trigger('reset-and-navigate');
}, 2000);
},
fail: ({ responseJSON }) => {
if (responseJSON && responseJSON.error) {
this.model.set({
error: responseJSON.error,
loading: false
});
}
}
});
}
});

var ManagePermissionsView = Marionette.ItemView.extend({
className: 'library-admin-view',

initialize: function (options) {
var options = options || {};

this.model.set('host', window.location.host);
},
this.modal = new TransferOwnershipModalView();

// just forward any trigger calls
this.modal.on('all', (...args) => this.trigger(...args));
},
events: {
'click .public-button': 'togglePublicState'
},

togglePublicState: function (e) {
var pub = $(e.target).hasClass('make-public');
this.trigger('update-public-status', pub);
},

modelEvents: {

'change:public': 'render'

},

template: ManagePermissionsContainer,

onRender: function () {
this.$('.public-container').html(MakePublicTemplate(this.model.toJSON()));
}
this.$('.public-container').html(MakePublicTemplate(this.model
.toJSON()));

this.modal.render();
}
});


return ManagePermissionsView;
});

0 comments on commit f93c26e

Please sign in to comment.