* added backups menu
* project recovery dialog
* only show recover button in Cloud tab
* Human-readable time diffs for recovery dialog
* reverted project list context menu, ca and es translations
upd4.2
Bernat Romagosa 2018-06-06 09:06:34 +02:00 zatwierdzone przez Jens Mönig
rodzic 976a964200
commit f3ffe66a2b
4 zmienionych plików z 313 dodań i 5 usunięć

Wyświetl plik

@ -494,10 +494,11 @@ Cloud.prototype.getThumbnail = function (
);
};
Cloud.prototype.getProject = function (projectName, onSuccess, onError) {
Cloud.prototype.getProject = function (projectName, delta, onSuccess, onError) {
this.withCredentialsRequest(
'GET',
'/projects/%username/' + encodeURIComponent(projectName),
'/projects/%username/' +
encodeURIComponent(projectName) + (delta ? '?delta=' + delta : ''),
onSuccess,
onError,
'Could not fetch project ' + projectName,
@ -536,6 +537,22 @@ Cloud.prototype.getProjectMetadata = function (
);
};
Cloud.prototype.getProjectVersionMetadata = function (
projectName,
onSuccess,
onError
) {
this.withCredentialsRequest(
'GET',
'/projects/%username/' +
encodeURIComponent(projectName) +
'/versions',
onSuccess,
onError,
'Could not fetch versions for project ' + projectName
);
};
Cloud.prototype.deleteProject = function (
projectName,
username,

285
gui.js
Wyświetl plik

@ -5735,6 +5735,7 @@ ProjectDialogMorph.prototype.init = function (ide, task) {
this.deleteButton = null;
this.shareButton = null;
this.unshareButton = null;
this.recoverButton = null;
// initialize inherited properties:
ProjectDialogMorph.uber.init.call(
@ -5871,6 +5872,8 @@ ProjectDialogMorph.prototype.buildContents = function () {
if (this.task === 'open') {
this.addButton('openProject', 'Open');
this.action = 'openProject';
this.recoverButton = this.addButton('recoveryDialog', 'Recover');
this.recoverButton.hide();
} else { // 'save'
this.addButton('saveProject', 'Save');
this.action = 'saveProject';
@ -6161,6 +6164,7 @@ ProjectDialogMorph.prototype.setSource = function (source) {
this.body.add(this.listField);
this.shareButton.hide();
this.unshareButton.hide();
this.recoverButton.hide();
/*
this.publishButton.hide();
this.unpublishButton.hide();
@ -6295,6 +6299,7 @@ ProjectDialogMorph.prototype.installCloudProjectList = function (pl) {
myself.edit();
};
this.body.add(this.listField);
this.recoverButton.show();
this.shareButton.show();
this.unshareButton.hide();
this.deleteButton.show();
@ -6314,6 +6319,13 @@ ProjectDialogMorph.prototype.clearDetails = function () {
this.preview.drawNew();
};
ProjectDialogMorph.prototype.recoveryDialog = function () {
var proj = this.listField.selected;
if (!proj) {return; }
new ProjectRecoveryDialogMorph(this.ide, proj.projectname, this).popUp();
this.hide();
};
ProjectDialogMorph.prototype.openProject = function () {
var proj = this.listField.selected,
src;
@ -6332,22 +6344,23 @@ ProjectDialogMorph.prototype.openProject = function () {
}
};
ProjectDialogMorph.prototype.openCloudProject = function (project) {
ProjectDialogMorph.prototype.openCloudProject = function (project, delta) {
var myself = this;
myself.ide.nextSteps([
function () {
myself.ide.showMessage('Fetching project\nfrom the cloud...');
},
function () {
myself.rawOpenCloudProject(project);
myself.rawOpenCloudProject(project, delta);
}
]);
};
ProjectDialogMorph.prototype.rawOpenCloudProject = function (proj) {
ProjectDialogMorph.prototype.rawOpenCloudProject = function (proj, delta) {
var myself = this;
SnapCloud.getProject(
proj.projectname,
delta,
function (clouddata) {
myself.ide.source = 'cloud';
myself.ide.nextSteps([
@ -6742,6 +6755,272 @@ ProjectDialogMorph.prototype.fixLayout = function () {
this.changed();
};
// ProjectRecoveryDialogMorph /////////////////////////////////////////
// I show previous versions for a particular project and
// let users recover them.
ProjectRecoveryDialogMorph.prototype = new DialogBoxMorph();
ProjectRecoveryDialogMorph.prototype.constructor = ProjectRecoveryDialogMorph;
ProjectRecoveryDialogMorph.uber = DialogBoxMorph.prototype;
// ProjectRecoveryDialogMorph instance creation:
function ProjectRecoveryDialogMorph(ide, project, browser) {
this.init(ide, project, browser);
}
ProjectRecoveryDialogMorph.prototype.init = function (ide, projectName, browser) {
// initialize inherited properties:
ProjectRecoveryDialogMorph.uber.init.call(
this,
this, // target
null, // function
null // environment
);
this.ide = ide;
this.browser = browser;
this.key = 'recoverProject';
this.projectName = projectName;
this.versions = null;
this.handle = null;
this.listField = null;
this.preview = null;
this.notesText = null;
this.notesField = null;
this.labelString = 'Recover project';
this.createLabel();
this.buildContents();
};
ProjectRecoveryDialogMorph.prototype.buildContents = function () {
this.addBody(new Morph());
this.body.color = this.color;
this.buildListField();
this.preview = new Morph();
this.preview.fixLayout = nop;
this.preview.edge = InputFieldMorph.prototype.edge;
this.preview.fontSize = InputFieldMorph.prototype.fontSize;
this.preview.typeInPadding = InputFieldMorph.prototype.typeInPadding;
this.preview.contrast = InputFieldMorph.prototype.contrast;
this.preview.drawNew = function () {
InputFieldMorph.prototype.drawNew.call(this);
if (this.texture) {
this.drawTexture(this.texture);
}
};
this.preview.drawCachedTexture = function () {
var context = this.image.getContext('2d');
context.drawImage(this.cachedTexture, this.edge, this.edge);
this.changed();
};
this.preview.drawRectBorder = InputFieldMorph.prototype.drawRectBorder;
this.preview.setExtent(
this.ide.serializer.thumbnailSize.add(this.preview.edge * 2)
);
this.body.add(this.preview);
this.preview.drawNew();
this.notesField = new ScrollFrameMorph();
this.notesField.fixLayout = nop;
this.notesField.edge = InputFieldMorph.prototype.edge;
this.notesField.fontSize = InputFieldMorph.prototype.fontSize;
this.notesField.typeInPadding = InputFieldMorph.prototype.typeInPadding;
this.notesField.contrast = InputFieldMorph.prototype.contrast;
this.notesField.drawNew = InputFieldMorph.prototype.drawNew;
this.notesField.drawRectBorder = InputFieldMorph.prototype.drawRectBorder;
this.notesField.acceptsDrops = false;
this.notesField.contents.acceptsDrops = false;
this.notesText = new TextMorph('');
this.notesField.isTextLineWrapping = true;
this.notesField.padding = 3;
this.notesField.setContents(this.notesText);
this.notesField.setWidth(this.preview.width());
this.body.add(this.notesField);
this.addButton('recoverProject', 'Recover');
this.addButton('cancel', 'Cancel');
this.setExtent(new Point(360, 300));
this.fixLayout();
};
ProjectRecoveryDialogMorph.prototype.buildListField = function () {
var myself = this;
this.listField = new ListMorph([]);
this.fixListFieldItemColors();
this.listField.fixLayout = nop;
this.listField.edge = InputFieldMorph.prototype.edge;
this.listField.fontSize = InputFieldMorph.prototype.fontSize;
this.listField.typeInPadding = InputFieldMorph.prototype.typeInPadding;
this.listField.contrast = InputFieldMorph.prototype.contrast;
this.listField.drawNew = InputFieldMorph.prototype.drawNew;
this.listField.drawRectBorder = InputFieldMorph.prototype.drawRectBorder;
this.listField.action = function (item) {
var version;
if (item === undefined) { return; }
version = detect(
myself.versions,
function (version) {
return version.lastupdated === item;
});
myself.notesText.text = version.notes || '';
myself.notesText.drawNew();
myself.notesField.contents.adjustBounds();
myself.preview.texture = version.thumbnail;
myself.preview.cachedTexture = null;
myself.preview.drawNew();
};
SnapCloud.getProjectVersionMetadata(
this.projectName,
function (versions) {
var today = new Date(),
yesterday = new Date();
yesterday.setDate(today.getDate() - 1);
myself.versions = versions;
myself.versions.forEach(function (version) {
var date = new Date(new Date().getTime() - version.lastupdated * 1000);
if (date.toDateString() === today.toDateString()) {
version.lastupdated = localize('Today, ') + date.toLocaleTimeString();
} else if (date.toDateString() === yesterday.toDateString()) {
version.lastupdated = localize('Yesterday, ') + date.toLocaleTimeString();
} else {
version.lastupdated = date.toLocaleString();
}
});
myself.listField.elements =
myself.versions.map(function (version) {
return version.lastupdated;
});
myself.clearDetails();
myself.listField.buildListContents();
myself.fixListFieldItemColors();
myself.listField.adjustScrollBars();
myself.listField.scrollY(myself.listField.top());
myself.fixLayout();
},
this.ide.cloudError()
);
this.body.add(this.listField);
};
ProjectRecoveryDialogMorph.prototype.cancel = function () {
var myself = this;
this.browser.show();
this.browser.listField.select(
detect(
this.browser.projectList,
function (item) { return item.projectname === myself.projectName }
)
);
ProjectRecoveryDialogMorph.uber.cancel.call(this);
};
ProjectRecoveryDialogMorph.prototype.recoverProject = function () {
var lastupdated = this.listField.selected,
version = detect(
this.versions,
function (version) {
return version.lastupdated === lastupdated;
});
this.browser.openCloudProject({ projectname: this.projectName }, version.delta);
this.destroy();
};
ProjectRecoveryDialogMorph.prototype.popUp = function () {
var world = this.ide.world();
if (world) {
ProjectRecoveryDialogMorph.uber.popUp.call(this, world);
this.handle = new HandleMorph(
this,
300,
300,
this.corner,
this.corner
);
}
};
ProjectRecoveryDialogMorph.prototype.fixListFieldItemColors =
ProjectDialogMorph.prototype.fixListFieldItemColors;
ProjectRecoveryDialogMorph.prototype.clearDetails =
ProjectDialogMorph.prototype.clearDetails;
ProjectRecoveryDialogMorph.prototype.fixLayout = function () {
var titleHeight = fontHeight(this.titleFontSize) + this.titlePadding * 2,
thin = this.padding / 2,
oldFlag = Morph.prototype.trackChanges;
Morph.prototype.trackChanges = false;
if (this.body) {
this.body.setPosition(this.position().add(new Point(
this.padding,
titleHeight + this.padding
)));
this.body.setExtent(new Point(
this.width() - this.padding * 2,
this.height()
- this.padding * 3 // top, bottom and button padding.
- titleHeight
- this.buttons.height()
));
this.listField.setWidth(
this.body.width()
- this.preview.width()
- this.padding
);
this.listField.contents.children[0].adjustWidths();
this.listField.setPosition(this.body.position());
this.listField.setHeight(this.body.height());
this.preview.setRight(this.body.right());
this.preview.setTop(this.listField.top());
this.notesField.setTop(this.preview.bottom() + thin);
this.notesField.setLeft(this.preview.left());
this.notesField.setHeight(
this.body.bottom() - this.preview.bottom() - thin
);
}
if (this.label) {
this.label.setCenter(this.center());
this.label.setTop(
this.top() + (titleHeight - this.label.height()) / 2
);
}
if (this.buttons) {
this.buttons.fixLayout();
this.buttons.setCenter(this.center());
this.buttons.setBottom(this.bottom() - this.padding);
}
Morph.prototype.trackChanges = oldFlag;
this.changed();
};
// LibraryImportDialogMorph ///////////////////////////////////////////
// I am preview dialog shown before importing a library.
// I inherit from a DialogMorph but look similar to

Wyświetl plik

@ -1074,6 +1074,12 @@ SnapTranslator.dict.ca = {
'Segur que vols esborrar',
'rename...':
'canvia el nom...',
'Recover':
'Recupera',
'Today, ':
'Avui, ',
'Yesterday, ':
'Ahir, ',
// costume editor
'Costume Editor':

Wyświetl plik

@ -2404,6 +2404,12 @@ SnapTranslator.dict.es = {
'Publicado.',
'unpublished.':
'No publicado',
'Recover':
'Recuperar',
'Today, ':
'Hoy, ',
'Yesterday, ':
'Ayer, ',
// costume editor @todo (wasn't this superseed by paint editor?)
'Costume Editor':