mirror of
https://github.com/inverse-inc/sogo.git
synced 2026-02-20 08:56:23 +00:00
Monotone-Parent: 5ce544e4196355529d09f53ee1f29a26e0df0733
Monotone-Revision: 2cf3be019f697c04a2f19de8e9693b7b7a1ddf8d Monotone-Author: wsourdeau@inverse.ca Monotone-Date: 2006-08-09T21:37:35 Monotone-Branch: ca.inverse.sogo
This commit is contained in:
@@ -29,3 +29,6 @@
|
||||
"edit" = "Editer";
|
||||
"invalidemailwarn" = "Champ de l'email invalide, continuer quand même ?";
|
||||
"new" = "Nouveau";
|
||||
|
||||
"Name or Address" = "Le nom ou l'adresse";
|
||||
"Personal Addressbook" = "Adresses personnelles";
|
||||
|
||||
@@ -14,7 +14,6 @@ ContactsUI_OBJC_FILES = \
|
||||
\
|
||||
ContactsUIProduct.m \
|
||||
UIxContactsFilterPanel.m \
|
||||
UIxContactsSelectionView.m \
|
||||
UIxContactView.m \
|
||||
UIxContactSelector.m \
|
||||
UIxContactEditor.m \
|
||||
|
||||
@@ -19,11 +19,12 @@
|
||||
02111-1307, USA.
|
||||
*/
|
||||
|
||||
#include "UIxContactEditorBase.h"
|
||||
#include <Contacts/SOGoContactObject.h>
|
||||
#include <Contacts/SOGoContactFolder.h>
|
||||
#include "common.h"
|
||||
|
||||
#include "UIxContactEditorBase.h"
|
||||
|
||||
@implementation UIxContactEditorBase
|
||||
|
||||
- (id)init {
|
||||
@@ -43,9 +44,11 @@
|
||||
|
||||
/* accessors */
|
||||
|
||||
- (void)setContentString:(NSString *)_cstr {
|
||||
- (void)setContentString:(NSString *)_cstr
|
||||
{
|
||||
ASSIGNCOPY(self->contentString, _cstr);
|
||||
}
|
||||
|
||||
- (NSString *)contentString {
|
||||
return self->contentString;
|
||||
}
|
||||
@@ -185,31 +188,36 @@
|
||||
|
||||
- (void) initSnapshot
|
||||
{
|
||||
NSString *c;
|
||||
NGVCard *vCard;
|
||||
|
||||
/* load iCalendar file */
|
||||
|
||||
c = [[self clientObject] contentAsString];
|
||||
if ([c length] == 0) /* a new contact */
|
||||
c = [self contentStringTemplate];
|
||||
|
||||
[self setContentString:c];
|
||||
[self loadValuesFromContentString:c];
|
||||
vCard = [[self clientObject] vCard];
|
||||
if (vCard)
|
||||
// if ([c length] == 0) /* a new contact */
|
||||
// c = [self contentStringTemplate];
|
||||
{
|
||||
// [self setContent: record];
|
||||
// [self loadValuesFromContentString: record];
|
||||
}
|
||||
}
|
||||
|
||||
- (id<WOActionResults>)defaultAction {
|
||||
- (id <WOActionResults>) defaultAction
|
||||
{
|
||||
// TODO: very similiar to apt-editor (apt editor would need to use std names
|
||||
[self initSnapshot];
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
- (NSString *)viewActionName {
|
||||
- (NSString *) viewActionName
|
||||
{
|
||||
/* this is overridden in the mail based contacts UI to redirect to tb.edit */
|
||||
return @"";
|
||||
}
|
||||
|
||||
- (NSString *)editActionName {
|
||||
- (NSString *) editActionName
|
||||
{
|
||||
/* this is overridden in the mail based contacts UI to redirect to tb.edit */
|
||||
return @"edit";
|
||||
}
|
||||
@@ -218,48 +226,48 @@
|
||||
{
|
||||
NSException *ex;
|
||||
NSString *uri;
|
||||
NSDictionary *record;
|
||||
// NSDictionary *record;
|
||||
NSMutableDictionary *newRecord;
|
||||
|
||||
if ([[self clientObject]
|
||||
respondsToSelector: @selector (saveContentString:)])
|
||||
{
|
||||
if (contentString)
|
||||
{
|
||||
record = [contentString propertyList];
|
||||
if (record)
|
||||
{
|
||||
newRecord = [[record mutableCopy] autorelease];
|
||||
[self saveValuesIntoRecord: newRecord];
|
||||
ex = [[self clientObject] saveRecord: newRecord];
|
||||
if (ex)
|
||||
{
|
||||
[self setErrorText: [ex reason]];
|
||||
// if ([[self clientObject]
|
||||
// respondsToSelector: @selector (saveContentString:)])
|
||||
// {
|
||||
// if (contentString)
|
||||
// {
|
||||
// record = [contentString propertyList];
|
||||
// if (record)
|
||||
// {
|
||||
// newRecord = [[record mutableCopy] autorelease];
|
||||
// [self saveValuesIntoRecord: newRecord];
|
||||
// ex = [[self clientObject] saved];
|
||||
// if (ex)
|
||||
// {
|
||||
// [self setErrorText: [ex reason]];
|
||||
|
||||
return self;
|
||||
}
|
||||
else
|
||||
{
|
||||
uri = [self viewActionName];
|
||||
if ([uri length] <= 0)
|
||||
uri = @"..";
|
||||
// return self;
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// uri = [self viewActionName];
|
||||
// if ([uri length] <= 0)
|
||||
// uri = @"..";
|
||||
|
||||
return [self redirectToLocation: [self _completeURIForMethod: uri]];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
[self setErrorText: @"Invalid property list data ..."]; // localize
|
||||
return self;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
[self setErrorText: @"Missing object content!"]; // localize
|
||||
return self;
|
||||
}
|
||||
}
|
||||
else
|
||||
// return [self redirectToLocation: [self _completeURIForMethod: uri]];
|
||||
// }
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// [self setErrorText: @"Invalid property list data ..."]; // localize
|
||||
// return self;
|
||||
// }
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// [self setErrorText: @"Missing object content!"]; // localize
|
||||
// return self;
|
||||
// }
|
||||
// }
|
||||
// else
|
||||
return [NSException exceptionWithHTTPStatus: 400 /* Bad Request */
|
||||
reason: @"method cannot be invoked on "
|
||||
@"the specified object"];
|
||||
|
||||
@@ -75,18 +75,20 @@
|
||||
/* action */
|
||||
|
||||
- (id<WOActionResults>)defaultAction {
|
||||
if ([[self clientObject] record] == nil) {
|
||||
if ([[self clientObject] vCard] == nil) {
|
||||
return [NSException exceptionWithHTTPStatus:404 /* Not Found */
|
||||
reason:@"could not locate contact"];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (BOOL)isDeletableClientObject {
|
||||
return [[self clientObject] respondsToSelector:@selector(delete)];
|
||||
- (BOOL) isDeletableClientObject
|
||||
{
|
||||
return [[self clientObject] respondsToSelector: @selector(delete)];
|
||||
}
|
||||
|
||||
- (id)deleteAction {
|
||||
- (id) deleteAction
|
||||
{
|
||||
NSException *ex;
|
||||
id url;
|
||||
|
||||
|
||||
@@ -19,9 +19,9 @@
|
||||
02111-1307, USA.
|
||||
*/
|
||||
|
||||
#include <NGObjWeb/WOComponent.h>
|
||||
#include <SOGoUI/UIxComponent.h>
|
||||
|
||||
@interface UIxContactsFilterPanel : WOComponent
|
||||
@interface UIxContactsFilterPanel : UIxComponent
|
||||
{
|
||||
NSString *searchText;
|
||||
NSString *searchCriteria;
|
||||
@@ -36,10 +36,10 @@
|
||||
|
||||
static NSArray *filters = nil;
|
||||
|
||||
+ (void)initialize {
|
||||
+ (void) initialize
|
||||
{
|
||||
NSMutableDictionary *md;
|
||||
NSMutableArray *ma;
|
||||
unsigned i;
|
||||
|
||||
md = [[NSMutableDictionary alloc] initWithCapacity:8];
|
||||
ma = [[NSMutableArray alloc] initWithCapacity:4];
|
||||
@@ -60,7 +60,8 @@ static NSArray *filters = nil;
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)dealloc {
|
||||
- (void) dealloc
|
||||
{
|
||||
[self->searchCriteria release];
|
||||
[self->searchText release];
|
||||
[super dealloc];
|
||||
@@ -68,34 +69,30 @@ static NSArray *filters = nil;
|
||||
|
||||
/* accessors */
|
||||
|
||||
- (void)setSearchText: (NSString *)_txt
|
||||
- (void) setSearchText: (NSString *)_txt
|
||||
{
|
||||
ASSIGNCOPY(self->searchText, _txt);
|
||||
}
|
||||
|
||||
- (void)setSearchCriteria: (NSString *)_txt
|
||||
- (void) setSearchCriteria: (NSString *)_txt
|
||||
{
|
||||
ASSIGNCOPY(self->searchText, _txt);
|
||||
}
|
||||
|
||||
- (NSString *)searchText
|
||||
- (NSString *) searchText
|
||||
{
|
||||
if (self->searchText == nil)
|
||||
{
|
||||
self->searchText =
|
||||
[[[[self context] request] formValueForKey:@"search"] copy];
|
||||
}
|
||||
return self->searchText;
|
||||
if (!searchText)
|
||||
searchText = [[self queryParameterForKey: @"search"] copy];
|
||||
|
||||
return searchText;
|
||||
}
|
||||
|
||||
- (NSString *)searchCriteria
|
||||
- (NSString *) searchCriteria
|
||||
{
|
||||
if (self->searchCriteria == nil)
|
||||
{
|
||||
self->searchCriteria =
|
||||
[[[[self context] request] formValueForKey:@"criteria"] copy];
|
||||
}
|
||||
return self->searchCriteria;
|
||||
if (!searchCriteria)
|
||||
searchCriteria = [[self queryParameterForKey: @"criteria"] copy];
|
||||
|
||||
return searchCriteria;
|
||||
}
|
||||
|
||||
/* filters */
|
||||
@@ -118,7 +115,7 @@ static NSArray *filters = nil;
|
||||
|
||||
- (NSString *) selectedFilter
|
||||
{
|
||||
return [[[self context] request] formValueForKey: @"filterpopup"];
|
||||
return [self queryParameterForKey: @"filterpopup"];
|
||||
}
|
||||
|
||||
@end /* UIxContactsFilterPanel */
|
||||
|
||||
@@ -22,16 +22,16 @@
|
||||
#ifndef __UIxContactsListViewBase_H__
|
||||
#define __UIxContactsListViewBase_H__
|
||||
|
||||
#include <SOGoUI/UIxComponent.h>
|
||||
#import <SOGoUI/UIxComponent.h>
|
||||
|
||||
@class NSString, NSArray;
|
||||
@class NSString;
|
||||
|
||||
@protocol SOGoContactObject;
|
||||
|
||||
@interface UIxContactsListViewBase : UIxComponent
|
||||
{
|
||||
NSArray *allRecords;
|
||||
NSArray *filteredRecords;
|
||||
NSString *searchText;
|
||||
id contact;
|
||||
id <SOGoContactObject> currentContact;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@@ -19,112 +19,104 @@
|
||||
02111-1307, USA.
|
||||
*/
|
||||
|
||||
#include "UIxContactsListViewBase.h"
|
||||
#include <Contacts/SOGoContactFolder.h>
|
||||
#include "common.h"
|
||||
#import <Contacts/SOGoContactObject.h>
|
||||
#import <Contacts/SOGoContactFolder.h>
|
||||
#import <Contacts/SOGoContactFolders.h>
|
||||
|
||||
#import "common.h"
|
||||
|
||||
#import "UIxContactsListViewBase.h"
|
||||
|
||||
@implementation UIxContactsListViewBase
|
||||
|
||||
- (void)dealloc {
|
||||
[self->allRecords release];
|
||||
[self->filteredRecords release];
|
||||
[self->searchText release];
|
||||
[self->contact release];
|
||||
- (void) dealloc
|
||||
{
|
||||
if (searchText)
|
||||
[searchText release];
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
/* accessors */
|
||||
|
||||
- (void)setContact:(id)_contact {
|
||||
ASSIGN(self->contact, _contact);
|
||||
}
|
||||
- (id)contact {
|
||||
return self->contact;
|
||||
- (void) setCurrentContact: (id <SOGoContactObject>) _contact
|
||||
{
|
||||
currentContact = _contact;
|
||||
}
|
||||
|
||||
- (void)setSearchText:(NSString *)_txt {
|
||||
ASSIGNCOPY(self->searchText, _txt);
|
||||
}
|
||||
- (id)searchText {
|
||||
if (self->searchText == nil)
|
||||
[self setSearchText:[[[self context] request] formValueForKey:@"search"]];
|
||||
return self->searchText;
|
||||
- (id <SOGoContactObject>) currentContact
|
||||
{
|
||||
return currentContact;
|
||||
}
|
||||
|
||||
- (EOQualifier *)qualifier {
|
||||
NSString *qs, *s;
|
||||
|
||||
s = [self searchText];
|
||||
if ([s length] == 0)
|
||||
return nil;
|
||||
|
||||
// TODO: just use qualifier vars
|
||||
qs = [NSString stringWithFormat:
|
||||
@"(sn isCaseInsensitiveLike: '%@*') OR "
|
||||
@"(givenname isCaseInsensitiveLike: '%@*') OR "
|
||||
@"(mail isCaseInsensitiveLike: '*%@*') OR "
|
||||
@"(telephonenumber isCaseInsensitiveLike: '*%@*')",
|
||||
s, s, s, s];
|
||||
return [EOQualifier qualifierWithQualifierFormat:qs];
|
||||
- (void) setSearchText: (NSString *) _txt
|
||||
{
|
||||
ASSIGNCOPY (searchText, _txt);
|
||||
}
|
||||
|
||||
- (NSString *)defaultSortKey {
|
||||
return @"sn";
|
||||
- (id) searchText
|
||||
{
|
||||
if (!searchText)
|
||||
[self setSearchText: [self queryParameterForKey:@"search"]];
|
||||
|
||||
return searchText;
|
||||
}
|
||||
- (NSString *)sortKey {
|
||||
|
||||
- (NSString *) defaultSortKey
|
||||
{
|
||||
return @"fn";
|
||||
}
|
||||
|
||||
- (NSString *) sortKey
|
||||
{
|
||||
NSString *s;
|
||||
|
||||
s = [[[self context] request] formValueForKey:@"sort"];
|
||||
return [s length] > 0 ? s : [self defaultSortKey];
|
||||
}
|
||||
- (EOSortOrdering *)sortOrdering {
|
||||
SEL sel;
|
||||
s = [self queryParameterForKey: @"sort"];
|
||||
if ([s length] == 0)
|
||||
s = [self defaultSortKey];
|
||||
|
||||
sel = [[[[self context] request] formValueForKey:@"desc"] boolValue]
|
||||
? EOCompareCaseInsensitiveDescending
|
||||
: EOCompareCaseInsensitiveAscending;
|
||||
|
||||
return [EOSortOrdering sortOrderingWithKey:[self sortKey] selector:sel];
|
||||
}
|
||||
- (NSArray *)sortOrderings {
|
||||
return [NSArray arrayWithObjects:[self sortOrdering], nil];
|
||||
return s;
|
||||
}
|
||||
|
||||
- (NSArray *)contactInfos {
|
||||
// TODO: should be done in the backend, but for Agenor AB its OK here
|
||||
NSArray *records;
|
||||
EOQualifier *q;
|
||||
|
||||
if (self->filteredRecords != nil)
|
||||
return self->filteredRecords;
|
||||
|
||||
records = [[self clientObject] fetchCoreInfos];
|
||||
self->allRecords =
|
||||
[[records sortedArrayUsingKeyOrderArray:[self sortOrderings]] retain];
|
||||
|
||||
if ((q = [self qualifier]) != nil) {
|
||||
[self debugWithFormat:@"qs: %@", q];
|
||||
self->filteredRecords =
|
||||
[[self->allRecords filteredArrayUsingQualifier:q] retain];
|
||||
}
|
||||
else
|
||||
self->filteredRecords = [self->allRecords retain];
|
||||
|
||||
return self->filteredRecords;
|
||||
- (NSComparisonResult) sortOrdering
|
||||
{
|
||||
return ([[self queryParameterForKey:@"desc"] boolValue]
|
||||
? NSOrderedDescending
|
||||
: NSOrderedAscending);
|
||||
}
|
||||
|
||||
- (NSArray *) contactInfos
|
||||
{
|
||||
id <SOGoContactFolder> folder;
|
||||
|
||||
folder = [self clientObject];
|
||||
|
||||
return [folder lookupContactsWithFilter: [self searchText]
|
||||
sortBy: [self sortKey]
|
||||
ordering: [self sortOrdering]];
|
||||
}
|
||||
|
||||
/* notifications */
|
||||
|
||||
- (void)sleep {
|
||||
[self->contact release]; self->contact = nil;
|
||||
[self->allRecords release]; self->allRecords = nil;
|
||||
[self->filteredRecords release]; self->filteredRecords = nil;
|
||||
- (void) sleep
|
||||
{
|
||||
if (searchText)
|
||||
{
|
||||
[searchText release];
|
||||
searchText = nil;
|
||||
}
|
||||
currentContact = nil;
|
||||
// [allRecords release];
|
||||
// allRecords = nil;
|
||||
// [filteredRecords release];
|
||||
// filteredRecords = nil;
|
||||
[super sleep];
|
||||
}
|
||||
|
||||
/* actions */
|
||||
|
||||
- (BOOL)shouldTakeValuesFromRequest:(WORequest *)_rq inContext:(WOContext*)_c{
|
||||
- (BOOL) shouldTakeValuesFromRequest: (WORequest *) _rq
|
||||
inContext: (WOContext*) _c
|
||||
{
|
||||
return YES;
|
||||
}
|
||||
|
||||
|
||||
@@ -25,7 +25,24 @@
|
||||
|
||||
#import <SOGoUI/UIxComponent.h>
|
||||
|
||||
@class NSArray;
|
||||
@class SOGoContactFolder;
|
||||
|
||||
@interface UIxContactsListViewContainer : UIxComponent
|
||||
{
|
||||
NSString *foldersPrefix;
|
||||
id currentFolder;
|
||||
}
|
||||
|
||||
- (void) setCurrentFolder: (id) folder;
|
||||
|
||||
- (NSString *) foldersPrefix;
|
||||
|
||||
- (NSArray *) contactFolders;
|
||||
|
||||
- (NSString *) contactFolderId;
|
||||
- (NSString *) currentContactFolderId;
|
||||
- (NSString *) currentContactFolderName;
|
||||
|
||||
@end
|
||||
|
||||
|
||||
@@ -25,29 +25,84 @@
|
||||
|
||||
#import <NGObjWeb/SoObjects.h>
|
||||
|
||||
#import <SoObjects/Contacts/SOGoContactFolders.h>
|
||||
#import <SoObjects/Contacts/SOGoContactFolder.h>
|
||||
|
||||
#import "UIxContactsListViewContainer.h"
|
||||
|
||||
@class SOGoContactFolders;
|
||||
|
||||
@implementation UIxContactsListViewContainer
|
||||
|
||||
- (NSString *) contactFolderName
|
||||
- (id) init
|
||||
{
|
||||
if ((self = [super init]))
|
||||
{
|
||||
foldersPrefix = nil;
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void) setCurrentFolder: (id) folder
|
||||
{
|
||||
currentFolder = folder;
|
||||
}
|
||||
|
||||
- (NSString *) foldersPrefix
|
||||
{
|
||||
NSMutableArray *folders;
|
||||
SOGoObject *currentObject;
|
||||
|
||||
folders = [NSMutableArray new];
|
||||
[folders autorelease];
|
||||
|
||||
currentObject = [self clientObject];
|
||||
while (![currentObject isKindOfClass: [SOGoContactFolders class]])
|
||||
if (!foldersPrefix)
|
||||
{
|
||||
[folders insertObject: [currentObject nameInContainer] atIndex: 0];
|
||||
currentObject = [currentObject container];
|
||||
folders = [NSMutableArray new];
|
||||
[folders autorelease];
|
||||
|
||||
currentObject = [[self clientObject] container];
|
||||
while (![currentObject isKindOfClass: [SOGoContactFolders class]])
|
||||
{
|
||||
[folders insertObject: [currentObject nameInContainer] atIndex: 0];
|
||||
currentObject = [currentObject container];
|
||||
}
|
||||
|
||||
foldersPrefix = [folders componentsJoinedByString: @"/"];
|
||||
[foldersPrefix retain];
|
||||
}
|
||||
|
||||
return [NSString stringWithFormat: @"/%@",
|
||||
[folders componentsJoinedByString: @"/"]];
|
||||
return foldersPrefix;
|
||||
}
|
||||
|
||||
- (NSString *) contactFolderId
|
||||
{
|
||||
return [NSString stringWithFormat: @"%@/%@",
|
||||
[self foldersPrefix],
|
||||
[[self clientObject] nameInContainer]];
|
||||
}
|
||||
|
||||
- (NSArray *) contactFolders
|
||||
{
|
||||
SOGoContactFolders *folderContainer;
|
||||
|
||||
folderContainer = [[self clientObject] container];
|
||||
|
||||
return [folderContainer contactFolders];
|
||||
}
|
||||
|
||||
- (NSString *) currentContactFolderId
|
||||
{
|
||||
return [NSString stringWithFormat: @"%@/%@",
|
||||
[self foldersPrefix],
|
||||
[currentFolder nameInContainer]];
|
||||
}
|
||||
|
||||
- (NSString *) currentContactFolderName
|
||||
{
|
||||
return [self labelForKey: [currentFolder displayName]];
|
||||
}
|
||||
|
||||
- (BOOL) isFolderCurrent
|
||||
{
|
||||
return [[self currentContactFolderId] isEqualToString: [self contactFolderId]];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
};
|
||||
};
|
||||
|
||||
SOGoContactFolder = {
|
||||
SOGoContactGCSFolder = {
|
||||
slots = {
|
||||
toolbar = {
|
||||
protectedBy = "View";
|
||||
@@ -41,13 +41,59 @@
|
||||
};
|
||||
};
|
||||
|
||||
SOGoContactObject = {
|
||||
SOGoContactLDAPFolder = {
|
||||
slots = {
|
||||
toolbar = {
|
||||
protectedBy = "View";
|
||||
value = "SOGoContactObject.toolbar";
|
||||
value = "SOGoContactFolder.toolbar";
|
||||
};
|
||||
};
|
||||
methods = {
|
||||
view = {
|
||||
protectedBy = "View";
|
||||
pageName = "UIxContactsListView";
|
||||
};
|
||||
new = {
|
||||
protectedBy = "View";
|
||||
pageName = "UIxContactEditor";
|
||||
actionName = "new";
|
||||
};
|
||||
select = {
|
||||
protectedBy = "View";
|
||||
pageName = "UIxContactsSelectionView";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
SOGoContactGCSEntry = {
|
||||
methods = {
|
||||
view = {
|
||||
protectedBy = "View";
|
||||
pageName = "UIxContactView";
|
||||
};
|
||||
delete = {
|
||||
protectedBy = "View";
|
||||
pageName = "UIxContactView";
|
||||
actionName = "delete";
|
||||
};
|
||||
edit = {
|
||||
protectedBy = "View";
|
||||
pageName = "UIxContactEditor";
|
||||
};
|
||||
save = {
|
||||
protectedBy = "View";
|
||||
pageName = "UIxContactEditor";
|
||||
actionName = "save";
|
||||
};
|
||||
write = {
|
||||
protectedBy = "View";
|
||||
pageName = "UIxContactEditor";
|
||||
actionName = "write";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
SOGoContactLDAPEntry = {
|
||||
methods = {
|
||||
view = {
|
||||
protectedBy = "View";
|
||||
|
||||
Reference in New Issue
Block a user