Don't allow duplicate GCS folder names
parent
18df3bafb5
commit
3bdd90e2be
|
@ -614,19 +614,21 @@ static NSArray *childRecordFields = nil;
|
|||
NSURL *folderLocation;
|
||||
NSString *sql;
|
||||
|
||||
if ([[self container] hasLocalSubFolderNamed: newName])
|
||||
[NSException raise: NSInvalidArgumentException
|
||||
format: @"That name already exists"];
|
||||
|
||||
cm = [GCSChannelManager defaultChannelManager];
|
||||
folderLocation
|
||||
= [[GCSFolderManager defaultFolderManager] folderInfoLocation];
|
||||
folderLocation = [[GCSFolderManager defaultFolderManager] folderInfoLocation];
|
||||
fc = [cm acquireOpenChannelForURL: folderLocation];
|
||||
if (fc)
|
||||
{
|
||||
#warning GDLContentStore should provide methods for renaming folders
|
||||
sql
|
||||
= [NSString stringWithFormat: (@"UPDATE %@ SET c_foldername = '%@'"
|
||||
@" WHERE c_path = '%@'"),
|
||||
[folderLocation gcsTableName],
|
||||
[newName stringByReplacingString: @"'" withString: @"''"],
|
||||
ocsPath];
|
||||
sql = [NSString stringWithFormat: (@"UPDATE %@ SET c_foldername = '%@'"
|
||||
@" WHERE c_path = '%@'"),
|
||||
[folderLocation gcsTableName],
|
||||
[newName stringByReplacingString: @"'" withString: @"''"],
|
||||
ocsPath];
|
||||
[fc evaluateExpressionX: sql];
|
||||
[cm releaseChannel: fc];
|
||||
// sql = [sql stringByAppendingFormat:@" WHERE %@ = '%@'",
|
||||
|
|
|
@ -289,8 +289,18 @@
|
|||
if ([folderName length] > 0)
|
||||
{
|
||||
clientObject = [self clientObject];
|
||||
[clientObject renameTo: folderName];
|
||||
response = [self responseWith204];
|
||||
NS_DURING
|
||||
{
|
||||
[clientObject renameTo: folderName];
|
||||
response = [self responseWith204];
|
||||
}
|
||||
NS_HANDLER
|
||||
{
|
||||
message = [NSDictionary dictionaryWithObject: [localException reason] forKey: @"message"];
|
||||
response = [self responseWithStatus: 409 /* Conflict */
|
||||
andString: [message jsonRepresentation]];
|
||||
}
|
||||
NS_ENDHANDLER;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/* UIxContactFolderProperties.m - this file is part of SOGo
|
||||
*
|
||||
* Copyright (C) 2015 Inverse inc.
|
||||
* Copyright (C) 2015-2018 Inverse inc.
|
||||
*
|
||||
* This file is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
|
@ -21,8 +21,10 @@
|
|||
#import <Foundation/NSDictionary.h>
|
||||
#import <Foundation/NSValue.h>
|
||||
|
||||
#import <NGObjWeb/NSException+HTTP.h>
|
||||
#import <NGObjWeb/WORequest.h>
|
||||
|
||||
#import <SOGo/NSDictionary+Utilities.h>
|
||||
#import <SOGo/NSString+Utilities.h>
|
||||
|
||||
#import <Contacts/SOGoContactGCSFolder.h>
|
||||
|
@ -59,21 +61,34 @@
|
|||
- (WOResponse *) savePropertiesAction
|
||||
{
|
||||
WORequest *request;
|
||||
NSDictionary *params;
|
||||
WOResponse *response;
|
||||
NSDictionary *params, *message;
|
||||
id o;
|
||||
|
||||
request = [context request];
|
||||
params = [[request contentAsString] objectFromJSONString];
|
||||
response = [self responseWith204];
|
||||
|
||||
o = [params objectForKey: @"name"];
|
||||
if ([o isKindOfClass: [NSString class]])
|
||||
[addressbook renameTo: o];
|
||||
NS_DURING
|
||||
{
|
||||
o = [params objectForKey: @"name"];
|
||||
if ([o isKindOfClass: [NSString class]])
|
||||
[addressbook renameTo: o];
|
||||
|
||||
o = [params objectForKey: @"synchronize"];
|
||||
if ([o isKindOfClass: [NSNumber class]])
|
||||
[addressbook setSynchronize: [o boolValue]];
|
||||
o = [params objectForKey: @"synchronize"];
|
||||
if ([o isKindOfClass: [NSNumber class]])
|
||||
[addressbook setSynchronize: [o boolValue]];
|
||||
}
|
||||
NS_HANDLER
|
||||
{
|
||||
message = [NSDictionary dictionaryWithObject: [localException reason] forKey: @"message"];
|
||||
response = [self responseWithStatus: 400 /* Bad Request */
|
||||
andString: [message jsonRepresentation]];
|
||||
|
||||
return [self responseWith204];
|
||||
}
|
||||
NS_ENDHANDLER;
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
@end
|
||||
|
|
|
@ -581,15 +581,16 @@
|
|||
* @returns a promise of the HTTP operation
|
||||
*/
|
||||
AddressBook.prototype.$rename = function(name) {
|
||||
var i, list;
|
||||
var _this = this, i, list;
|
||||
|
||||
list = this.isSubscription? AddressBook.$subscriptions : AddressBook.$addressbooks;
|
||||
i = _.indexOf(_.map(list, 'id'), this.id);
|
||||
this.name = name;
|
||||
list.splice(i, 1);
|
||||
AddressBook.$add(this);
|
||||
|
||||
return this.$save();
|
||||
return this.$save().then(function() {
|
||||
list.splice(i, 1);
|
||||
_this.name = name;
|
||||
AddressBook.$add(_this);
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
vm.edit = edit;
|
||||
vm.revertEditing = revertEditing;
|
||||
vm.save = save;
|
||||
vm.saving = false;
|
||||
vm.confirmDelete = confirmDelete;
|
||||
vm.importCards = importCards;
|
||||
vm.showLinks = showLinks;
|
||||
|
@ -98,13 +99,18 @@
|
|||
|
||||
function save(folder) {
|
||||
var name = folder.name;
|
||||
if (name && name.length > 0) {
|
||||
if (!vm.saving && name && name.length > 0) {
|
||||
if (name != vm.originalAddressbook.name) {
|
||||
vm.saving = true;
|
||||
folder.$rename(name)
|
||||
.then(function(data) {
|
||||
vm.editMode = false;
|
||||
}, function(data, status) {
|
||||
Dialog.alert(l('Warning'), data);
|
||||
}, function() {
|
||||
revertEditing(folder);
|
||||
vm.editMode = folder.id;
|
||||
})
|
||||
.finally(function() {
|
||||
vm.saving = false;
|
||||
});
|
||||
}
|
||||
else {
|
||||
|
|
|
@ -498,18 +498,20 @@
|
|||
* @returns a promise of the HTTP operation
|
||||
*/
|
||||
Calendar.prototype.$save = function() {
|
||||
var _this = this;
|
||||
var _this = this,
|
||||
d = Calendar.$q.defer();
|
||||
|
||||
return Calendar.$$resource.save(this.id, this.$omit()).then(function(data) {
|
||||
Calendar.$$resource.save(this.id, this.$omit()).then(function(data) {
|
||||
// Make a copy of the data for an eventual reset
|
||||
_this.$shadowData = _this.$omit();
|
||||
return data;
|
||||
return d.resolve(data);
|
||||
}, function(data) {
|
||||
Calendar.$log.error(JSON.stringify(data, undefined, 2));
|
||||
// Restore previous version
|
||||
_this.$reset();
|
||||
return data;
|
||||
return d.reject(data);
|
||||
});
|
||||
|
||||
return d.promise;
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
@ -87,7 +87,7 @@
|
|||
this.inputElement.value = this.calendar.name;
|
||||
this.clickableElement.classList.add('ng-hide');
|
||||
this.inputContainer.classList.remove('ng-hide');
|
||||
if ($event.srcEvent.type == 'touchend') {
|
||||
if ($event.srcEvent && $event.srcEvent.type == 'touchend') {
|
||||
$timeout(function() {
|
||||
$ctrl.inputElement.focus();
|
||||
$ctrl.inputElement.select();
|
||||
|
@ -115,6 +115,12 @@
|
|||
$ctrl.inputContainer.classList.add('ng-hide');
|
||||
$ctrl.clickableElement.classList.remove('ng-hide');
|
||||
$ctrl.updateCalendarName();
|
||||
}, function() {
|
||||
$ctrl.editMode = true;
|
||||
$timeout(function() {
|
||||
$ctrl.inputElement.focus();
|
||||
$ctrl.inputElement.select();
|
||||
}, 200); // delayed focus for iOS
|
||||
})
|
||||
.finally(function() {
|
||||
$ctrl.inputElement.disabled = false;
|
||||
|
|
Loading…
Reference in New Issue