Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Library owner transfer widget #1923

Merged
merged 2 commits into from Sep 16, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
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;
});