Merge branch 'staging' into restricted-registration
commit
93589d03e4
|
@ -27,6 +27,8 @@
|
|||
* Add DAPSI to our sponsor list
|
||||
* checkup
|
||||
* check for duplicate or incorrect headers
|
||||
* save rendered markmap, mathjax, and mermaid as images
|
||||
* guard against incorrect iPhone behaviour that broke the ability to toggle between grid and list mode
|
||||
|
||||
# 4.4.0
|
||||
|
||||
|
|
|
@ -606,7 +606,7 @@
|
|||
}
|
||||
}
|
||||
|
||||
.cp-app-drive-content-list {
|
||||
div.cp-app-drive-content-list {
|
||||
.cp-app-drive-element-grid {
|
||||
display: none;
|
||||
}
|
||||
|
@ -896,7 +896,13 @@
|
|||
.cp-toolbar-bottom {
|
||||
.cp-toolbar-bottom-right {
|
||||
.fa-history { order: 50; }
|
||||
.fa-list, .fa-th-large { order: 25; }
|
||||
// .fa-list, .fa-th-large,
|
||||
.cp-app-drive-viewmode-button {
|
||||
order: 25;
|
||||
i {
|
||||
margin-right: 0;
|
||||
}
|
||||
}
|
||||
#cp-app-drive-toolbar-context-mobile, #cp-app-drive-toolbar-contextbuttons { order: 0; }
|
||||
#cp-app-drive-toolbar-context-mobile {
|
||||
.fa { margin: 0 !important; }
|
||||
|
|
|
@ -253,36 +253,32 @@ define([
|
|||
|
||||
create['registration'] = function () {
|
||||
var key = 'registration';
|
||||
var $div = makeBlock(key, true); // Msg.admin_registrationHint, .admin_registrationTitle, .admin_registrationButton
|
||||
var $button = $div.find('button'); // XXX restricted-registration: a checkbox might be better. it's easy to misinterpret the verb "OPEN" as an adjective
|
||||
var $div = makeBlock(key); // Msg.admin_registrationHint, .admin_registrationTitle, .admin_registrationButton
|
||||
|
||||
var state = APP.instanceStatus.restrictRegistration;
|
||||
if (state) {
|
||||
$button.text(Messages.admin_registrationAllow);
|
||||
} else {
|
||||
$button.removeClass('btn-primary').addClass('btn-danger');
|
||||
}
|
||||
var called = false;
|
||||
$div.find('button').click(function () {
|
||||
called = true;
|
||||
var $cbox = $(UI.createCheckbox('cp-settings-userfeedback',
|
||||
Messages.admin_registrationTitle,
|
||||
state, { label: { class: 'noTitle' } }));
|
||||
var spinner = UI.makeSpinner($cbox);
|
||||
var $checkbox = $cbox.find('input').on('change', function() {
|
||||
spinner.spin();
|
||||
var val = $checkbox.is(':checked') || false;
|
||||
$checkbox.attr('disabled', 'disabled');
|
||||
sFrameChan.query('Q_ADMIN_RPC', {
|
||||
cmd: 'ADMIN_DECREE',
|
||||
data: ['RESTRICT_REGISTRATION', [!state]]
|
||||
data: ['RESTRICT_REGISTRATION', [val]]
|
||||
}, function (e) {
|
||||
if (e) { UI.warn(Messages.error); console.error(e); }
|
||||
APP.updateStatus(function () {
|
||||
called = false;
|
||||
spinner.done();
|
||||
state = APP.instanceStatus.restrictRegistration;
|
||||
if (state) {
|
||||
console.log($button);
|
||||
$button.text(Messages.admin_registrationAllow);
|
||||
$button.addClass('btn-primary').removeClass('btn-danger');
|
||||
} else {
|
||||
$button.text(Messages.admin_registrationButton);
|
||||
$button.removeClass('btn-primary').addClass('btn-danger');
|
||||
}
|
||||
$checkbox[0].checked = state;
|
||||
$checkbox.removeAttr('disabled');
|
||||
});
|
||||
});
|
||||
});
|
||||
$cbox.appendTo($div);
|
||||
|
||||
return $div;
|
||||
};
|
||||
|
||||
|
|
|
@ -375,7 +375,7 @@ define([
|
|||
}
|
||||
});
|
||||
}
|
||||
if (data.teams.indexOf(1) === -1 || teamId === 0) {
|
||||
if (APP.loggedIn && (data.teams.indexOf(1) === -1 || teamId === 0)) {
|
||||
options.push({
|
||||
tag: 'a',
|
||||
attributes: {
|
||||
|
@ -387,10 +387,10 @@ define([
|
|||
importCalendar({
|
||||
id: id,
|
||||
teamId: teamId
|
||||
}, function (obj) {
|
||||
if (obj && obj.error) {
|
||||
console.error(obj.error);
|
||||
return void UI.warn(obj.error);
|
||||
}, function (err) {
|
||||
if (err) {
|
||||
console.error(err);
|
||||
return void UI.warn(Messages.error);
|
||||
}
|
||||
});
|
||||
return true;
|
||||
|
@ -677,14 +677,16 @@ define([
|
|||
importCalendar({
|
||||
id: tempCalendars[0],
|
||||
teamId: 0
|
||||
}, function (obj) {
|
||||
if (obj && obj.error) {
|
||||
console.error(obj.error);
|
||||
return void UI.warn(obj.error);
|
||||
}, function (err) {
|
||||
if (err) {
|
||||
console.error(err);
|
||||
return void UI.warn(Messages.error);
|
||||
}
|
||||
});
|
||||
});
|
||||
APP.$calendars.append(h('div.cp-calendar-entry.cp-ghost', importTemp));
|
||||
if (APP.loggedIn) {
|
||||
APP.$calendars.append(h('div.cp-calendar-entry.cp-ghost', importTemp));
|
||||
}
|
||||
return;
|
||||
}
|
||||
var myCalendars = filter(1);
|
||||
|
@ -1111,6 +1113,8 @@ define([
|
|||
var privateData = metadataMgr.getPrivateData();
|
||||
var user = metadataMgr.getUserData();
|
||||
|
||||
APP.loggedIn = common.isLoggedIn();
|
||||
|
||||
common.setTabTitle(Messages.calendar);
|
||||
|
||||
// Fix flatpickr selection
|
||||
|
@ -1248,6 +1252,11 @@ define([
|
|||
var store = window.cryptpadStore;
|
||||
APP.module.execCommand('SUBSCRIBE', null, function (obj) {
|
||||
if (obj.empty && !privateData.calendarHash) {
|
||||
if (!privateData.loggedIn) {
|
||||
return void UI.errorLoadingScreen(Messages.mustLogin, false, function () {
|
||||
common.setLoginRedirect('login');
|
||||
});
|
||||
}
|
||||
// No calendar yet, create one
|
||||
newCalendar({
|
||||
teamId: 1,
|
||||
|
@ -1255,7 +1264,7 @@ define([
|
|||
color: user.color,
|
||||
title: Messages.calendar_default
|
||||
}, function (err) {
|
||||
if (err) { return void UI.errorLoadingScreen(Messages.error); } // XXX
|
||||
if (err) { return void UI.errorLoadingScreen(Messages.error); }
|
||||
store.get('calendarView', makeCalendar);
|
||||
UI.removeLoadingScreen();
|
||||
});
|
||||
|
|
|
@ -20,7 +20,7 @@ define(function() {
|
|||
* users and these users will be redirected to the login page if they still try to access
|
||||
* the app
|
||||
*/
|
||||
config.registeredOnlyTypes = ['file', 'contacts', 'notifications', 'support', 'calendar'];
|
||||
config.registeredOnlyTypes = ['file', 'contacts', 'notifications', 'support'];
|
||||
|
||||
/* CryptPad is available is multiple languages, but only English and French are maintained
|
||||
* by the developers. The other languages may be outdated, and any missing string for a langauge
|
||||
|
|
|
@ -575,12 +575,18 @@ define([
|
|||
}
|
||||
else if (callback) {*/
|
||||
// Old import button, used in settings
|
||||
button
|
||||
.click(common.prepareFeedback(type))
|
||||
.click(importContent((data && data.binary) ? 'application/octet-stream' : 'text/plain', callback, {
|
||||
var importer = importContent((data && data.binary) ? 'application/octet-stream' : 'text/plain', callback, {
|
||||
accept: data ? data.accept : undefined,
|
||||
binary: data ? data.binary : undefined
|
||||
}));
|
||||
});
|
||||
|
||||
var handler = data.first? function () {
|
||||
data.first(importer);
|
||||
}: importer; //importContent;
|
||||
|
||||
button
|
||||
.click(common.prepareFeedback(type))
|
||||
.click(handler);
|
||||
//}
|
||||
break;
|
||||
case 'upload':
|
||||
|
|
|
@ -122,8 +122,8 @@ define([
|
|||
var $trashEmptyIcon = $('<span>', {"class": "fa fa-trash-o"});
|
||||
//var $collapseIcon = $('<span>', {"class": "fa fa-minus-square-o cp-app-drive-icon-expcol"});
|
||||
var $expandIcon = $('<span>', {"class": "fa fa-plus-square-o cp-app-drive-icon-expcol"});
|
||||
var $listIcon = $('<button>', {"class": "fa fa-list"});
|
||||
var $gridIcon = $('<button>', {"class": "fa fa-th-large"});
|
||||
//var $listIcon = $('<button>', {"class": "fa fa-list"});
|
||||
//var $gridIcon = $('<button>', {"class": "fa fa-th-large"});
|
||||
var $sortAscIcon = $('<span>', {"class": "fa fa-angle-up sortasc"});
|
||||
var $sortDescIcon = $('<span>', {"class": "fa fa-angle-down sortdesc"});
|
||||
var $closeIcon = $('<span>', {"class": "fa fa-times"});
|
||||
|
@ -2407,36 +2407,52 @@ define([
|
|||
return $box;
|
||||
};
|
||||
|
||||
var getOppositeViewMode = function (viewMode) {
|
||||
viewMode = viewMode || getViewMode();
|
||||
var newViewMode = viewMode === 'grid'? 'list': 'grid';
|
||||
return newViewMode;
|
||||
};
|
||||
|
||||
// Create the button allowing the user to switch from list to icons modes
|
||||
var createViewModeButton = function ($container) {
|
||||
var $listButton = $listIcon.clone();
|
||||
var $gridButton = $gridIcon.clone();
|
||||
var viewMode = getViewMode();
|
||||
var gridIcon = h('i.fa.fa-th-large', { title: Messages.fm_viewGridButton });
|
||||
var listIcon = h('i.fa.fa-list', { title: Messages.fm_viewListButton });
|
||||
|
||||
$listButton.click(function () {
|
||||
$gridButton.show();
|
||||
$listButton.hide();
|
||||
setViewMode('list');
|
||||
$('#' + FOLDER_CONTENT_ID).removeClass('cp-app-drive-content-grid');
|
||||
$('#' + FOLDER_CONTENT_ID).addClass('cp-app-drive-content-list');
|
||||
Feedback.send('DRIVE_LIST_MODE');
|
||||
});
|
||||
$gridButton.click(function () {
|
||||
$listButton.show();
|
||||
$gridButton.hide();
|
||||
setViewMode('grid');
|
||||
$('#' + FOLDER_CONTENT_ID).addClass('cp-app-drive-content-grid');
|
||||
$('#' + FOLDER_CONTENT_ID).removeClass('cp-app-drive-content-list');
|
||||
Feedback.send('DRIVE_GRID_MODE');
|
||||
});
|
||||
var $button = $(h('button.cp-app-drive-viewmode-button', [
|
||||
gridIcon,
|
||||
listIcon
|
||||
]));
|
||||
var $gridIcon = $(gridIcon);
|
||||
var $listIcon = $(listIcon);
|
||||
var showMode = function (mode) {
|
||||
if (mode === 'grid') {
|
||||
$gridIcon.hide();
|
||||
$listIcon.show();
|
||||
} else {
|
||||
$listIcon.hide();
|
||||
$gridIcon.show();
|
||||
}
|
||||
};
|
||||
setViewMode(viewMode || 'grid');
|
||||
showMode(viewMode);
|
||||
|
||||
if (getViewMode() === 'list') {
|
||||
$listButton.hide();
|
||||
} else {
|
||||
$gridButton.hide();
|
||||
}
|
||||
$listButton.attr('title', Messages.fm_viewListButton);
|
||||
$gridButton.attr('title', Messages.fm_viewGridButton);
|
||||
$container.append($listButton).append($gridButton);
|
||||
$button.click(function (e) {
|
||||
console.error(e);
|
||||
var viewMode = getViewMode();
|
||||
var newViewMode = getOppositeViewMode(viewMode);
|
||||
setViewMode(newViewMode);
|
||||
showMode(newViewMode);
|
||||
var $folder = $('#' + FOLDER_CONTENT_ID);
|
||||
if (newViewMode === 'list') {
|
||||
$folder.removeClass('cp-app-drive-content-grid').addClass('cp-app-drive-content-list');
|
||||
Feedback.send('DRIVE_LIST_MODE');
|
||||
} else {
|
||||
$folder.addClass('cp-app-drive-content-grid').removeClass('cp-app-drive-content-list');
|
||||
Feedback.send('DRIVE_GRID_MODE');
|
||||
}
|
||||
});
|
||||
$container.append($button);
|
||||
};
|
||||
var emptyTrashModal = function () {
|
||||
var ownedInTrash = manager.ownedInTrash();
|
||||
|
|
|
@ -51,6 +51,8 @@ define([
|
|||
{
|
||||
var saveAs = window.saveAs;
|
||||
var Nacl = window.nacl;
|
||||
Messages.oo_exportChrome = "Your browser cannot handle conversion to and from Microsoft Office formats. We suggest using a recent version of Firefox or Chrome."; // XXX
|
||||
Messages.oo_importBin = "Click OK to import CryptPad's internal .bin format."; // XXX
|
||||
|
||||
var APP = window.APP = {
|
||||
$: $,
|
||||
|
@ -74,6 +76,7 @@ define([
|
|||
};
|
||||
|
||||
var supportsXLSX = function () {
|
||||
//if (true) { return false; } // XXX
|
||||
return !(typeof(Atomics) === "undefined" || typeof (SharedArrayBuffer) === "undefined");
|
||||
};
|
||||
|
||||
|
@ -1927,7 +1930,7 @@ define([
|
|||
|
||||
if (!supportsXLSX()) {
|
||||
ext = ['.bin'];
|
||||
warning = '<div class="alert alert-info cp-alert-top">'+Messages.oo_exportChrome+'</div>';
|
||||
warning = h('div.alert.alert-info.cp-alert-top', Messages.oo_exportChrome);
|
||||
}
|
||||
|
||||
var types = ext.map(function (val) {
|
||||
|
@ -1950,7 +1953,12 @@ define([
|
|||
};
|
||||
var $select = UIElements.createDropdown(dropdownConfig);
|
||||
|
||||
UI.prompt(Messages.exportPrompt+warning, Util.fixFileName(suggestion), function (filename) {
|
||||
var promptMessage = h('span', [
|
||||
Messages.exportPrompt,
|
||||
warning
|
||||
]);
|
||||
|
||||
UI.prompt(promptMessage, Util.fixFileName(suggestion), function (filename) {
|
||||
// $select.getValue()
|
||||
if (!(typeof(filename) === 'string' && filename)) { return; }
|
||||
var ext = ($select.getValue() || '').slice(1);
|
||||
|
@ -2520,15 +2528,28 @@ define([
|
|||
} else if (type === "doc") {
|
||||
accept = ['.bin', '.odt', '.docx'];
|
||||
}
|
||||
var first;
|
||||
if (!supportsXLSX()) {
|
||||
accept = ['.bin'];
|
||||
first = function (cb) {
|
||||
var msg = h('span', [
|
||||
Messages.oo_exportChrome,
|
||||
' ', h('span', Messages.oo_importBin),
|
||||
]);
|
||||
UI.confirm(msg, function (yes) {
|
||||
if (yes) {
|
||||
cb();
|
||||
}
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
if (common.isLoggedIn()) {
|
||||
window.CryptPad_deleteLastCp = deleteLastCp;
|
||||
var $importXLSX = common.createButton('import', true, {
|
||||
accept: accept,
|
||||
binary : ["ods", "xlsx", "odt", "docx", "odp", "pptx"]
|
||||
binary : ["ods", "xlsx", "odt", "docx", "odp", "pptx"],
|
||||
first: first,
|
||||
}, importXLSXFile);
|
||||
$importXLSX.appendTo(toolbar.$drawer);
|
||||
common.createButton('hashtag', true).appendTo(toolbar.$drawer);
|
||||
|
|
|
@ -114,8 +114,8 @@ define([
|
|||
}
|
||||
}
|
||||
|
||||
// XXX add a limit to make sure we don't go too far in the past? ==> 1 week
|
||||
var missed = useLastVisit && ev.start > last && ev.end <= now;
|
||||
var oneWeekAgo = now - (7 * 24 * 3600 * 1000);
|
||||
var missed = useLastVisit && ev.start > last && ev.end <= now && ev.end > oneWeekAgo;
|
||||
if (ev.end <= now && !missed) {
|
||||
// No reminder for past events
|
||||
delete reminders[uid];
|
||||
|
@ -543,6 +543,8 @@ define([
|
|||
var hash = Hash.getEditHashFromKeys(secret);
|
||||
var roHash = Hash.getViewHashFromKeys(secret);
|
||||
|
||||
if (!ctx.loggedIn) { hash = undefined; }
|
||||
|
||||
var cal = {
|
||||
href: hash && Hash.hashToHref(hash, 'calendar'),
|
||||
roHref: roHash && Hash.hashToHref(roHash, 'calendar'),
|
||||
|
@ -846,8 +848,9 @@ define([
|
|||
Calendar.init = function (cfg, waitFor, emit) {
|
||||
var calendar = {};
|
||||
var store = cfg.store;
|
||||
if (!store.loggedIn || !store.proxy.edPublic) { return; } // XXX logged in only? we should al least allow read-only for URL calendars
|
||||
//if (!store.loggedIn || !store.proxy.edPublic) { return; } // XXX logged in only? we should al least allow read-only for URL calendars
|
||||
var ctx = {
|
||||
loggedIn: store.loggedIn && store.proxy.edPublic,
|
||||
store: store,
|
||||
Store: cfg.Store,
|
||||
pinPads: cfg.pinPads,
|
||||
|
@ -918,17 +921,21 @@ define([
|
|||
}
|
||||
if (cmd === 'IMPORT') {
|
||||
if (ctx.store.offline) { return void cb({error: 'OFFLINE'}); }
|
||||
if (!ctx.loggedIn) { return void cb({error: 'NOT_LOGGED_IN'}); }
|
||||
return void importCalendar(ctx, data, clientId, cb);
|
||||
}
|
||||
if (cmd === 'IMPORT_ICS') {
|
||||
if (ctx.store.offline) { return void cb({error: 'OFFLINE'}); }
|
||||
if (!ctx.loggedIn) { return void cb({error: 'NOT_LOGGED_IN'}); }
|
||||
return void importICSCalendar(ctx, data, clientId, cb);
|
||||
}
|
||||
if (cmd === 'ADD') {
|
||||
if (ctx.store.offline) { return void cb({error: 'OFFLINE'}); }
|
||||
if (!ctx.loggedIn) { return void cb({error: 'NOT_LOGGED_IN'}); }
|
||||
return void addCalendar(ctx, data, clientId, cb);
|
||||
}
|
||||
if (cmd === 'CREATE') {
|
||||
if (!ctx.loggedIn) { return void cb({error: 'NOT_LOGGED_IN'}); }
|
||||
if (data.initialCalendar) {
|
||||
return void ctx.Store.onReadyEvt.reg(function () {
|
||||
createCalendar(ctx, data, clientId, cb);
|
||||
|
@ -939,22 +946,27 @@ define([
|
|||
}
|
||||
if (cmd === 'UPDATE') {
|
||||
if (ctx.store.offline) { return void cb({error: 'OFFLINE'}); }
|
||||
if (!ctx.loggedIn) { return void cb({error: 'NOT_LOGGED_IN'}); }
|
||||
return void updateCalendar(ctx, data, clientId, cb);
|
||||
}
|
||||
if (cmd === 'DELETE') {
|
||||
if (ctx.store.offline) { return void cb({error: 'OFFLINE'}); }
|
||||
if (!ctx.loggedIn) { return void cb({error: 'NOT_LOGGED_IN'}); }
|
||||
return void deleteCalendar(ctx, data, clientId, cb);
|
||||
}
|
||||
if (cmd === 'CREATE_EVENT') {
|
||||
if (ctx.store.offline) { return void cb({error: 'OFFLINE'}); }
|
||||
if (!ctx.loggedIn) { return void cb({error: 'NOT_LOGGED_IN'}); }
|
||||
return void createEvent(ctx, data, clientId, cb);
|
||||
}
|
||||
if (cmd === 'UPDATE_EVENT') {
|
||||
if (ctx.store.offline) { return void cb({error: 'OFFLINE'}); }
|
||||
if (!ctx.loggedIn) { return void cb({error: 'NOT_LOGGED_IN'}); }
|
||||
return void updateEvent(ctx, data, clientId, cb);
|
||||
}
|
||||
if (cmd === 'DELETE_EVENT') {
|
||||
if (ctx.store.offline) { return void cb({error: 'OFFLINE'}); }
|
||||
if (!ctx.loggedIn) { return void cb({error: 'NOT_LOGGED_IN'}); }
|
||||
return void deleteEvent(ctx, data, clientId, cb);
|
||||
}
|
||||
};
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue