Как переопределить кнопку DEL на View?

GROMILA

Well-known member
08.04.2004
297
0
#1
Народ, это снова я и мои траблы.

Ситуация: МАНАГЕР (есть все права) заходит на View
и нечаянно жмет DEL+F9. И ему вываливается стандартный диалог.

Вопрос: А как ему выдать мой диалог с крутой надписью:
"Ты че делаешь, придурок, это же удалять ЗАПРЕЩЕНО."
И еще оповестить при этом всех пользователей по почте в сети, что,
дескать, спасайся кто может.

Как навесить на событие DEL свой добавочный скрипт с диалогом?
 
N
#2
Привет, Gromila.

Во-первых, для опрделенного человека или группы людей, для которых запрещено удалять документы, тебе необходимо создать соответствующую группу в ACL базы данных, дать им уровень Manager и убрать привилегию Delete documents.
Во-вторых, можно создать скрипт, реагирующий на событие удаления документов: Other - Database Resources - Database Script - Querydocumentdelete. В обработчике этого события нельзя пользоваться ф-ей MessageBox. Можно, например, написат следующее:

<code>
Print "Document deletion not allowed."
Continue = False
</code>

Для решения проблемы, нужно тебе более подробно описать ситуационный момент.
 

GROMILA

Well-known member
08.04.2004
297
0
#3
Правами не решить!

Поясняю:
есть куча документов в моей БД и куча представлений!!

Задача:
Только для представления View1, которое только для документов Form1 нужно перехватить калавишу DEL.
Для всех остальных документов и представлений - НЕ НУЖНО.

Пусть я не смогу вывести диалог, но КОД хотябы отменяющий это действие я могу как-то написать?
плюс код, который еще что-нибудь сделает, например, писанет в другой документ пару ласковых.

Спасибо.
 

GROMILA

Well-known member
08.04.2004
297
0
#4
Приведу пример нужной мне обработки удаления

Ситуация:
Есть View1, отображающее 3 документа с полями (Сотрудник,Статус)

Отображение View1:

Код:
       Сотрудник  Статус
Документ1: Иванов     0
Документ2: Петров     1
Документ3: Сидоро     0
Админ залазит на это представление и метит клавишей DEL все 3 документа.
Потом жмет обновить (F9 или мышой или ....)

Задание:
Необходимо удалить документы где Статус=0
если среди отмаркированных на удаление есть документы Статус=1, то
- их не удалять
- вывести на экран сообщение о попытке удалить БЕССМЕРТНЫХ сотрудников!
- сделать запись в документ-журнал о том, что админ пытался мочить, но не замочил Петрова.
- Петрову выслать уведомление по почте, что АДМИН имеет на него зуб.

Вопрос:
Помогите, люди добрые!
 
N
#5
Привет, Gromila, еще раз.

Я решил твою проблему. Следующий код проверен на работоспособность. Его необходимо записать в Other - Database Resources - Database Script. После компилирования и сохранения кода необходимо закрыть полностью соответствующую бд в designer и notes. Он выполняет следующее: при попытке удаления документов формы "temp1", статус которых "status = 1" из представления "temp1" 1. не удаляет эти документы, 2. выводится сообщение на экран о невозможности удаления документов, 3. формируется лог_сообщение, которое записывается в "документ-журнал" с указанием даты и имени персоны, которая пыталась удалить документы, 4. отсылается уведомление выбранным людям по потче с соответствующим сообщением (в моем случае уведомление отсылаетсяодному человеку).

Код:
(Declaration)
Type LogMsg 
msg As String
doclink_unid As String	
End Type

Dim session As NotesSession
Dim ws As NotesUIWorkspace
Dim db As NotesDatabase
Dim uidb As NotesUIDatabase
Dim collection As NotesDocumentCollection
Dim doc As NotesDocument
Dim uiview As NotesUIView
Dim view As NotesView
Dim rtitem As NotesRichTextItem
Dim rtitemStyle As NotesRichTextStyle
Dim rtitemPStyle As NotesRichTextParagraphStyle
Dim dateTime As NotesDateTime
Dim log_msg() As LogMsg

(Initialize)
Sub Initialize

Set session = New NotesSession
Set ws = New NotesUIWorkspace
Set db = session.CurrentDatabase	

End Sub

(Querydocumentdelete)
Sub Querydocumentdelete(Source As Notesuidatabase, Continue As Variant)
Dim n As Integer
Dim msg As String
Dim search_str As String
Dim log_file As NotesDocument
Dim collection_log_file As NotesDocumentCollection
Dim dividing_line As Variant

Set uidb = ws.CurrentDatabase
Set uiview = ws.CurrentView
Set view = uiview.View
Redim log_msg(0)	
log_msg(0).msg = "Лог-файл"
log_msg(0).doclink_unid = ""

If view.Name = "temp1" Then
Set collection = uidb.Documents  
For i = 1 To collection.Count
Set doc = collection.GetNthDocument(i) 	
If doc.Form(0) = "temp1" And doc.status(0) = 1 Then
 Messagebox "Удаление 'БЕССМЕРТНЫХ' сотрудников запрещено."
 n = Ubound(log_msg)
 Redim Preserve log_msg(n + 1)
 log_msg(n + 1).msg = "Произведена попытка несанкционированного удаления профильного документа сотрудника."
 log_msg(n + 1).doclink_unid = doc.UniversalID
 Call SendLogFile("Попытка несанкционированного удаления документа", "sergey a petushkov", log_msg)  
 
 search_str = "Form = ""log"""
 Set collection_log_file = db.Search(search_str, Nothing, 0)
 Set log_file = collection_log_file.GetFirstDocument
 Set rtitem = log_file.GetFirstItem("log_msg")
 If rtitem.Type = RICHTEXT Then   
 	Call rtitem.AppendText("Произведена попытка несанкционированного удаления профильного документа сотрудника. ")
 	Call rtitem.AddNewLine(1)
 	Call rtitem.AppendText("Выполнил: " + session.CommonUserName)
 	Call rtitem.AddNewLine(1)
 	Call rtitem.AppendText("Дата: " + Date$ + " / " + Time$)
 	dividing_line = Evaluate("@Repeat(""- -""; 20)", log_file)	
 	Call rtitem.AddNewLine(1)
 	Call rtitem.AppendText(dividing_line(0))	
 	Call rtitem.AddNewLine(1)
 	Call log_file.Save(True, True)
 End If  
 
 Continue = False 	
 
End If
Next
End If

End Sub

(SendLogFile)
Sub SendLogFile(subject As String, sendto As String, log_msg() As LogMsg)
Dim maildoc As NotesDocument 
Dim doclink As NotesDocument	
Dim dividing_line As Variant

If sendto = "" Then sendto = session.CommonUserName

Set maildoc = New NotesDocument(dB)	
maildoc.Form = "Memo"
maildoc.Subject = subject
maildoc.SendTo = sendto
maildoc.Principal = db.Title

Set rtitem = New NotesRichTextItem(maildoc, "Body") 

Set rtitemStyle = session.CreateRichTextStyle
rtitemStyle.NotesColor = COLOR_DARK_BLUE
rtitemStyle.FontSize = 8
Call rtitem.AppendStyle(rtitemStyle)
Call rtitem.AppendText(" " + db.Title )	
Call rtitem.AddNewLine(1)

rtitemStyle.NotesFont = FONT_HELV
rtitemStyle.NotesColor = COLOR_GRAY
rtitemStyle.FontSize = 14
rtitemStyle.Bold = True
Set rtitemPStyle = session.CreateRichTextParagraphStyle
rtitemPStyle.Alignment = ALIGN_CENTER
Call rtitem.AppendParagraphStyle(rtitemPStyle)
Call rtitem.AppendStyle(rtitemStyle)
Call rtitem.AppendText(log_msg(0).msg)
Call rtitem.AddNewLine(1)	
rtitemStyle.FontSize = 10
rtitemPStyle.Alignment = ALIGN_LEFT
Call rtitem.AppendParagraphStyle(rtitemPStyle)
Call rtitem.AppendStyle(rtitemStyle)
Call rtitem.AppendText("Выполнил: " + session.CommonUserName)
Call rtitem.AddNewLine(1)
Call rtitem.AppendText("Дата: " + Date$ + " / " + Time$)
Call rtitem.AddNewLine(1)

rtitemStyle.NotesColor = COLOR_BLACK
rtitemStyle.FontSize = 10
rtitemStyle.Bold = False
rtitemStyle.Underline = False 
Call rtitem.AppendStyle(rtitemStyle)

For i = 1 To Ubound(log_msg)
rtitemPStyle.Alignment = ALIGN_LEFT
Call rtitem.AppendParagraphStyle(rtitemPStyle)
Call rtitem.AddNewLine(1)
Call rtitem.AppendText(log_msg(i).msg) 	
If log_msg(i).doclink_unid <> "" Then
Call rtitem.AppendText(" Ссылка на документ: ")
Set doclink = db.GetDocumentByUNID(log_msg(i).doclink_unid)
If Not (doclink Is Nothing) Then Call rtitem.AppendDocLink(doclink, "Вы можете открыть документ, нажав на ссылку.")
End If 
rtitemPStyle.Alignment = ALIGN_CENTER
Call rtitem.AppendParagraphStyle(rtitemPStyle)
dividing_line = Evaluate("@Repeat(""- -""; 20)", maildoc)  
Call rtitem.AppendText(dividing_line(0)) 
Next

Call maildoc.Send(False)	

End Sub
 

GROMILA

Well-known member
08.04.2004
297
0
#6
Я по-другому переопределить нельзя?
Ведь если таких View несколько, то код дичайший получится!
 
V

Veselinka

#7
можно например, при дизане вьюхи - определять событие ее открытия QueryOpen и засовывать в переменные окружения SetEnvironmentVar - можно из этой вьюхи документы удалять или нет.

А потом на событии qdd базы - просто проверять значение этой переменной - оно будет атрибутом текущей вьюхи.

Я думаю есть еще 10 способов - сделать удаляемость атрибутом текущей вью и написать универсальный код события удаления, который не нужно будет модифицировать при изменении дизайна каких-то не относящихся к нему элементов. Принцип инкапсуляции.
 
N
#8
GROMILA.
:unsure:
ПРОСТО убери неужную строку: If view.Name = "temp1" Then и соответствующий закрывающий элемент End If. (тогда уже Set uiview = ws.CurrentView Set view = uiview.View тебе тоже ненужны будут).
ВСЕ! "Дичайшие" коды под каждую вью не надо писать. ;) Вопросы если есть - спрашивай.
 
N
#9
Veselinka, хочу предствить тебе для критики код, который отправляет выделенные в представлнии документы в корзину и, при необходимости, восстанавливает документы. (аналог корзины в винде) - это по поводу твоего последнего сообщния.

Код:
Sub DeleteSelectedDoc()

If Not profile_ini Then Exit Sub

Set dateTime = New NotesDateTime( "00/00/00" )
Set collection = db.UnprocessedSearch("!@IsUnavailable(Form)", dateTime, 0)
If collection.Count = 0 Then
Messagebox "Выделите документы.", MB_OK + MB_ICONEXCLAMATION, title
Exit Sub
End If

dialog_flag = Messagebox("Выделенные документы будут удалены." + Ustring$(2, 10) + "Продолжить?",_
MB_YESNO + MB_ICONQUESTION, title)
If dialog_flag = IDNO Then Exit Sub

Call collection.StampAll("is_deleted", 1)
Call collection.StampAll("deletion_date", Date$ + " / " + Time$)
Call collection.StampAll("who_deleted", session.CommonUserName)	
Call collection.PutAllInFolder("Trash", False)	

Call ws.ViewRefresh

End Sub

Sub UnDeleteSelectedDoc()

If Not profile_ini Then Exit Sub

Set dateTime = New NotesDateTime( "00/00/00" )
Set collection = db.UnprocessedSearch("!@IsUnavailable(Form)", dateTime, 0)
If collection.Count = 0 Then
Messagebox "Выделите документы.", MB_OK + MB_ICONEXCLAMATION, title
Exit Sub
End If

dialog_flag = Messagebox("Выделенные документы будут восстановлены." + Ustring$(2, 10) + "Продолжить?",_
MB_YESNO + MB_ICONQUESTION, title)
If dialog_flag = IDNO Then Exit Sub

For i = 1 To collection.Count
Set doc = collection.GetNthDocument(i)
doc.is_deleted = 0
doc.deletion_date = ""
doc.who_deleted = ""
Call doc.Save(True, True)
Call doc.RemoveFromFolder("Trash")
Next

Call ws.ViewRefresh

End Sub
 

GROMILA

Well-known member
08.04.2004
297
0
#10
VASELINKA

Я думаю есть еще 10 способов - сделать удаляемость атрибутом текущей вью и написать универсальный код события удаления, который не нужно будет модифицировать при изменении дизайна каких-то не относящихся к нему элементов. Принцип инкапсуляции.
Назови 3 из них, плиз.
Вешать обработку сразу на всю БД не хочется - плохо это, согласись!
 
V

Veselinka

#11
<!--QuoteBegin-nor+12:04:2004, 21:23 -->
<span class="vbquote">(nor @ 12:04:2004, 21:23 )</span><!--QuoteEBegin-->Veselinka, хочу предствить тебе для критики код, который отправляет выделенные в представлнии документы в корзину и, при необходимости, восстанавливает документы. (аналог корзины в винде) - это по поводу твоего последнего сообщния.

Код:
Sub DeleteSelectedDoc()

If Not profile_ini Then Exit Sub

Set dateTime = New NotesDateTime( "00/00/00" )
Set collection = db.UnprocessedSearch("!@IsUnavailable(Form)", dateTime, 0)
If collection.Count = 0 Then
 Messagebox "Выделите документы.", MB_OK + MB_ICONEXCLAMATION, title
 Exit Sub
End If

dialog_flag = Messagebox("Выделенные документы будут удалены." + Ustring$(2, 10) + "Продолжить?",_
MB_YESNO + MB_ICONQUESTION, title)
If dialog_flag = IDNO Then Exit Sub

Call collection.StampAll("is_deleted", 1)
Call collection.StampAll("deletion_date", Date$ + " / " + Time$)
Call collection.StampAll("who_deleted", session.CommonUserName)	
Call collection.PutAllInFolder("Trash", False)	

Call ws.ViewRefresh

End Sub

Sub UnDeleteSelectedDoc()

If Not profile_ini Then Exit Sub

Set dateTime = New NotesDateTime( "00/00/00" )
Set collection = db.UnprocessedSearch("!@IsUnavailable(Form)", dateTime, 0)
If collection.Count = 0 Then
 Messagebox "Выделите документы.", MB_OK + MB_ICONEXCLAMATION, title
 Exit Sub
End If

dialog_flag = Messagebox("Выделенные документы будут восстановлены." + Ustring$(2, 10) + "Продолжить?",_
MB_YESNO + MB_ICONQUESTION, title)
If dialog_flag = IDNO Then Exit Sub

For i = 1 To collection.Count
 Set doc = collection.GetNthDocument(i)
 doc.is_deleted = 0
 doc.deletion_date = ""
 doc.who_deleted = ""
 Call doc.Save(True, True)
 Call doc.RemoveFromFolder("Trash")
Next

Call ws.ViewRefresh

End Sub
[/quote]
Я не совсем поняла твою логику о связи этого кода с моим замечанием.
По-поводу этого кода могу сказать лишь, что 2ая процедура неоптимально написана - сильно не рекомендуется использовать обход коллекции методами getNthDocument(i), так как при взятии документа по индексу для каждого индекса происходит последовательный обход коллекции, то есть для коллекции из эн элементов происходит
1+2+3+N-1 переборов элементов коллекции.

Оптимальнее использовать GetNextDocument(doc).

В остальном при беглом просмотре код не показался мне где-либо неправильным или не соответствующим описанной бизнес логике.

Надо только добавить что во всех вью, в формуле селекции должно присутствовать условие непопадания во вьюхи документов с флагами удаления.

А проще было бы включить флаг soft deletion на базе и сделать вьюху типа shared, contains deleted documents. И сделать всю эту логику стандартными механизмами нотес, для этого предназначенными.
 
V

Veselinka

#12
GROMILA - по видимому ты меня не совсем понял. От написания логики контроля удаления на событии базы все равно не куда не денешься. Просто можно в этом коде получить текущую вью и по одному из атрибутов (именно этих атрибутов можно придумать с десяток) - в событии понимать - можно документы удалять или нет.

Тогда при дизайне каждой новой вью можно будет определять именно для нее выбранный для валидации атрибут - удалять из этой вью или не удалять. И не трогать код события удаления в базе.

Если интересуют навскидку примеры того, какой флаг можно поставить у вьюхи - как флаг удаляемости
1) уже приведенный пример - проставление на QO вьюхи session.SetEnvironmentVar("delete","Yes\No")
2) можно ввести нотацию именований для алиасов вьюхи - ну например ввести алиасы с постфиксом _del & _not, а на событии удаления if right(ws.currentView.View.Name,4)="_del" - Тогда удаляем иначе - делаем то что положено в этом случае
3)пока в голову не приходит - а тратить времени на длительные раздумья по этой теме возможности не имею, что-нибудь придет в голову - напишу, хотя не вижу смысла в твоей просьбе привести 3 примера. Так как для достижения цели - решения задачи - тебе и одного бы хватило.
 
N
#13
GROMILA, я в недоумении. Честное слово.
Почему плохо вешать обработку на всю бд сразу? :) Тебе нужно было при удалении обрабатывать документы и в зависимости от значений полей документов и того, в каких представлениях они располагаются, разрешать или не разрешать удаление. Я все правильно понял? Нужно учитывать несколько редставлений? - Создай массив из них и включи его в обработчик.
Или что тебе надо? Я так вообще ничего не понимаю уже. :) :blink: :blink:

Veselinka. Я тебя тоже не понял. Зачем переменные окружения? (А если пользователь не обладает соответствующими правами для создания таких переменных, что тогда?) Зачем нотация наименований? Можно пользоваться объектом CurrentView, например. Можно передавать флаг через параметр вызываемой ф-ии, например.

Насчет "кода, который отправляет выделенные в представлнии документы в корзину..." - я надеялся, что ты поделишься со мной своим аналогичным универсальным кодом: "универсальный код события удаления, который не нужно будет модифицировать при изменении дизайна каких-то не относящихся к нему элементов. Принцип инкапсуляции. " Меня это крайне заинтересовало.
"По-поводу этого кода могу сказать лишь, что 2ая процедура неоптимально написана..." Я знаю про это. Но. В представлении для удаления мышкой обычно выделяют небольшое кол-во документов. Пусть даже выделили их 1000 или чуть более. Это самый невероятный случай. При этом разница в производительности кода моего цикла For и твоего будет стремиться к нулю, уверяю тебя. Свойство "soft deletion" конкретно для этой бд мне не подходит, т.к. все удаленные документы перемещаются в папку (запрос клиента) для подтверждение удаления "администратором" системы, по этой причине представление и тем более "shared" мне не подходит.
 

GROMILA

Well-known member
08.04.2004
297
0
#14
Nor, я тоже хотел посмотреть на "Принцип инкапсуляции" вот и спрашивал про доп.пример.

Просто я после других языкав не могу понять почему есть QuerySave и нет OnDelete
Это так непривычно!

А писать дикий IF в одном месте это как-то ГОМОЗДКО выглядит.

Да, NOR, у меня еще одна проблема по поводу удаления появилась!
Почему-то, когда я удаляю записи уже по Action (по батону) все типа чики-пики очистил, но потом после закрытия БД
выскакивеает, скрывавшийся за всеми окнами диалог:
Удалено столько -то записей!!! У меня версия 6.0, а моя же БД на 5.0 уже сей БОКС не выдает!
Погано что этот диалог скрыт за окнами!!!!
 
V

Veselinka

#15
Окей,
примем в качестве флага идентифицирующего - удалять окументы из вью или неудалять - посфткс в имени вью 2 видов _not & _del

Тогда событие удаления будет выглядеть следующим образом:


Sub Querydocumentdelete(Source As Notesuidatabase, Continue As Variant)

dim ws as new NotesUIWorkspace
if right(ws.currentView.View.Name,4)="_not" then

continue=false
' далее идет код рассылки жалоб и пр
else

Set coll=source.documents
Set doc=coll.GetFirstDocument
While Not doc Is Nothing
Set ndoc=coll.GetNextDocument(doc)

' здесь вызывается функция генерации лога удаления документа

Call doc.remove(True)
Set doc=ndoc
Wend


end if

End Sub

Приведенный пример для добавления или модификации вьюхи НЕ ТРЕБУЕТ переписывания события удаления. Требуется лишь придерживаться нотации именований вьюх (можно именовать алиасы и анализировать их). То есть принцип инкапсуляции (когда все свойства и бизнес логика объекта являются его и только его свойствами и не влияют на другие объекты) выполнен.
 
N
#16
Привет, Gromilla.
Насчет втоей проблемы - никогда не встречал. Могу посоветовать следующее: открываешь File - Preferences - User Preferences - Additional Options. Там попоробуй поубирать опции типа "Display Window Menu", "Standart Dialog Box", etc. Я точно не знаю.
 
M

mony_id

#17
Ситуация: МАНАГЕР (есть все права) заходит на View
и нечаянно жмет DEL+F9. И ему вываливается стандартный диалог.

Вопрос: А как ему выдать мой диалог с крутой надписью:
"Ты че делаешь, придурок, это же удалять ЗАПРЕЩЕНО."
И еще оповестить при этом всех пользователей по почте в сети, что,
дескать, спасайся кто может.
нАПИСАНИЕ СКРИПТА в событиях вида!!!!
енто делается и работает
 
V

Veselinka

#19
нету событий у вьюхи на удаление документов!
ни в 5-ке ни в 6-ке. :p
 
N
#20
посему слушайте меня :p
событие удалния документов есть только у бд в целом