Другие технические решения

Материал из Вики проекта PascalABC.NET
Перейти к навигацииПерейти к поиску

Контроль запросов и ошибок

Если на сервере возникает необрабатываемое исключение, клиент не получает ответ на AJAX-запрос, и система перестает корректно работать.

Необходимо сделать так, чтобы клиент всегда получал ответ на запрос серверу и корректно его обрабатывал.

Для этого разработана следующая архитектура:

  • монитор запросов к серверу на клиенте [JavaScript]
  • использование try со специальным полиморфным возвращаемым объектом с сервера
  • логирование непредвиденных исключений в БД

Монитор запросов

// Вьюер сетевых операций
function QueryViewer{
// --------------------------------- Поля
    // Хэш операций
    this.QueriesHash;
    
// --------------------------------- Методы
    // Добавляет информацию о запросе
    this.AddQuery(queryID, queryInfo);
    // Возвращает информацию о запросе
    this.GetQueryInfo(queryID);           
    // Завершает запрос успешно
    this.QueryFinishSuccess(queryID); 
    // Завершает запрос с ошибкой errorCode
    this.QueryFinishFailed(queryID, errorCode);
    // Удаляет информацию о запросе
    this.RemoveQuery(queryID);        
}

// Информация о запросе
function QueryInfo {
    this.QueryType;                        // Тип запроса
    this.QueryData;                        // Связанные данные
    
    this.QueryState;                       // Статус запроса
    this.ErrorCode;                        // Код ошибки
}

Визуализация пока простая, выводятся состояния запросов.

Возвращаемые объекты

    /// Возвращаемая клиенту информация
    public class ReturnInfo {
        /// Возвращаемые данные
        public Object Data
        /// Системная информация
        public SystemInfo SysInfo
    }

    /// Системная информация
    public class SystemInfo { 
        /// Код ошибки
        public ErrorCode ErrCode 
        /// Идентификатор запроса
        public string QueryID
    }

Логирование исключений

В базу записывается следующая информация:

имя пользователя
тип операции
время
сообщение исключения
имя файла, связанного с операцией (если оно есть)
каталог

Текущие сделанные запросы

LoadFirstFileContent
GetSessionExistingFileNames
GetUserExistingFileItems
GetSamplesExistingFileNames
CheckNewFileName
CheckPublishedFileName
SaveDocument

Графика в WDE

До сих пор была возможность работы только с консольными приложениями. Однако, графика весьма заманчива. Одно из возможных решений — использование HTML-элемента для работы с графикой <canvas>.

Canvas

Canvas предоставляет достаточно богатый набор возможностей работы с графикой: от рисования простых фигур до анимации и работы с клавиатурой и мышью. Небольшой туториал находится здесь

Графическое окно

Элемент Canvas размещается модели окна Prototype window

Ссылки

Горячие клавиши

Для горячих клавиш надо изменять код редактора

Подсветка синтаксиса

Глюк с размыванием текста в большинстве случаев возникает при переходе на новую строку.
Добавим восстановление синтаксиса после каждого Enter'а. Для этого надо залезть в код edit_area_full.js и в районе обработки клавиатуры добавить:

if(letter==\"Entrer\"&&target_id==\"Â\"){if(eA.press_enter())use=Ë;eA.execCommand(\"resync_highlight\");

Еще бы можно при вставке кода это делать, но пока не знаю, как это определить.

Мультифайловость в редакторе

Описание

Работа с несколькими файлами одновременно вещь весьма полезная. Выбранный редактор с подсветкой синтаксиса EditArea эту возможность предоставляет. Однако, задать заголовок вкладки в нем можно только при её первом открытии, что, конечно, неудобно. В связи с этим в файл edit_area_full.js были внесены поправки и добавлен метод для изменения не только содержимого вкладки, но и её заголовка.

changeFile

В EAL.prototype добавлен метод changeFile.

changeFile : function(id, newFile) {
    var curID = this.execCommand(id, 'curr_file')
        
    this.execCommand(id, 'change_curFileTabParams', newFile);
    this.setValue(id, newFile['text']);
},

change_curFileTabParams

В содержимое editAreaLoader.iframe_script, например, перед update_file:

"EA.Ä.change_curFileTabParams=Ã(new_Ês){var curID = this.curr_file; this.update_file(curID, new_Ês); var elem=document.getElementById(this.files[curID]['html_id']); var html_curID='tab_file_'+encodeURIComponent(curID); this.filesIdAssoc[html_curID]=curID; this.files[curID]['html_id']= html_curID; var close=\"<img src=\\\"\"+È.eAL.baseURL+\"images/close.gif\\\" title=\\\"\"+Á.get_translation('close_tab','word')+\"\\\" onclick=\\\"eA.execCommand('close_file',eA.filesIdAssoc['\"+html_curID+\"']);return Ì;\\\" class=\\\"hidden\\\" onmouseover=\\\"Á.className=''\\\" onmouseout=\\\"Á.className='hidden'\\\" />\";elem.innerHTML=\"<a onclick=\\\"javascript:eA.execCommand('switch_to_file',eA.filesIdAssoc['\"+html_curID+\"']);\\\" selec=\\\"none\\\"><b><span><strong class=\\\"edited\\\">*</strong>\"+Á.files[curID]['title']+close+\"</span></b></a>\";};"

Или, если работаете не с edit_area_full.js, в edit_area_functions.js:

EditArea.prototype.change_curFileTabParams = function(new_Ês){
    var curID = this.curr_file;
    this.update_file(curID, new_Ês);

    var elem = document.getElementById(this.files[curID]['html_id']);
    var html_curID = 'tab_file_' + encodeURIComponent(curID);
    this.filesIdAssoc[html_curID] = curID;
    this.files[curID]['html_id'] = html_curID;
    
    var close = "<img src=\""+ parent.editAreaLoader.baseURL +"images/close.gif\" title=\""+ this.get_translation('close_tab', 'word') +"\" onclick=\"editArea.execCommand('close_file', editArea.filesIdAssoc['"+ html_id +"']);return false;\" class=\"hidden\" onmouseover=\"this.className=''\" onmouseout=\"this.className='hidden'\" />";
    elem.innerHTML = "<a onclick=\"javascript:editArea.execCommand('switch_to_file', editArea.filesIdAssoc['"+ html_id +"']);\" selec=\"none\"><b><span><strong class=\"edited\">*</strong>"+ this.files[id]['title'] + close +"</span></b></a>";
}

Регулировка высоты редактора

Изначально в редакторе отсутствует возможность менять размер после загрузки страницы (кроме как воспользоваться кнопкой полного экрана).

changeHeight

В EAL.prototype добавлен метод changeHeight .

changeHeight : function(id, newHeight) {
    this.execCommand(id, 'change_Height', newHeight);
},

change_curFileTabParams

В содержимое editAreaLoader.iframe_script, например, после update_size:

"EA.Ä.change_Height=Ã(newHeight){var d=document,pd=È.document; if(typeof eAs !='undefined'&&eAs[eA.id]&&eAs[eA.id][\"displayed\"]==Ë){pd.getElementById(\"frame_\"+eA.id).Ç.height=newHeight;};};"

Заголовок текущей вкладки

Описание

Отсутствует возможность узнать заголовок вкладки. Метод getCurrFileTitle и возвращает его.

getCurrFileTitle

В EAL.prototype добавлен метод getCurrFileTitle.

getCurrFileTitle : function (id) {
    var curID = this.execCommand(id, 'curr_file')
    return this.execCommand(id, 'get_currFileTitle', curID);
},

get_currFileTitle

В содержимое editAreaLoader.iframe_script:

"EA.Ä.get_currFileTitle=Ã(id){return Á.files[id]['title']};"

Состояние вкладки — изменено ли содержимое

Описание

Позволяет узнать, изменено ли содержимое вкладки по сравнению с сохраненной версией.

currentFileIsEdited

В edit_area_full.js добавлен метод currentFileIsEdited, например, после стандартного метода setFileEditedMode.

currentFileIsEdited : function (id) {
    var curID = this.execCommand(id, 'curr_file');
    var isEdited = this.execCommand(id, 'current_file_is_edited', curID);
    return isEdited;
},

current_file_is_edited

В edit_area_full.js добавлен метод current_file_is_edited, например, перед стандартным методом set_file_edited_mode.

"EA.Ä.current_file_is_edited=Ã(id){return Á.files[id]['edited'];};"

Переход на вкладку

В EAL.prototype добавлен метод switchToFile.

switchToFile : function(id, tabID) {
    this.execCommand(id, 'switch_to_file', tabID);
},

Работа с единичными файлами (устарело)

Для работы с файлами (сохранение, переименование, удаление) удобно создать специальный объект, моделирующий файл. Нужно хранить:

  • полное имя файла
  • каталог (он же имя пользователя или id сессии)
  • отображаемое имя (оно может быть слишком длинным для полного отображения)
  • тип (сохраненный файл пользователя, или «висячий» («фантомный») файл примера)
  • некоторые параметры редактора кода
// Файл
function File(
        pName,                  // имя файла
        pPath,                  // путь к файлу (пустая строка в случае основного каталога)
        pOwnerName,             // владелец (имя пользователя или гость)
        pIsPhantom,             // фантомный ли файл (фантомный - т.е. не сохраненный на сервере)
        pPhantomType            // тип фантомного файла (новый[new], пример[sample], опубликованный файл[public])
){

// ----------------------------------------- Поля

    name;                              // имя файла
    viewName;                          // отображаемое имя файла (если не слишком длинное, то само pName)
    path;                              // путь к файлу
    fullName;                          // полное имя файла
    
    isByUser;                          // пользовательский ли это файл
    ownerName;                         // владелец (имя пользователя или ID сессии)
    
    isPhantom;                         // фантомный ли файл (фантомный - т.е. не сохраненный на сервере)
    phantomType;                       // тип фантомного файла (новый[new], пример[sample], опубликованный файл[public])
        
    isOpened;                          // открыт ли файл в редакторе
    tabID;                             // ID вкладки в редакторе
    
    sourceCode;                        // по необходимости можно использовать для хранения содержимого
    
// ----------------------------------------- Методы
    open;                              // открывает файл (в редакторе тоже)
    close;                             // закрывает файл (в редакторе тоже)
    active;                            // активирует файл в редакторе
    save;                              // устанавливает статус измененности в редакторе в ложь
    
    setFullName;                       // изменяет имя файла по полному имени
    setName;                           // изменяет имя файла
    
    updateTabTitle;                    // обновляет заголовок вкладки в соответствии с именем файла
    
    setSourceCode;                     // изменяет содержимое файла
    
    setNotPhantom;                     // изменяет статус файла на нефантомный
    setStatusClosed;                   // изменяет статус файла на закрытый
    setStatusOpened;                   // изменяет статус файла на открытый
}

Управление файлами

Реализован браузер файловVirtualFileBrowser и менеджер редактораEditorManager.

Браузер файлов

Занимается отображением содержимого каталогов. Предоставляет обработчики нажатий на кнопки.

DivID         // ID блока, к которому привязывать браузер [string]

UserName      // имя пользователя [string]
VarName       // Имя переменной, которая отвечает за данный браузер файлов [string]

BrowserTitle  // Заголовок браузера файлов [string]    
    
CurrentDir    // текущий каталог [string]
LastChosenDir // последний выбранный каталог (для загрузки файлов) [string]
DirsHash      // хэш всех каталогов 
dirNames      // список имен всех каталогов (вспомогательный) [Array<string>]
CurrentDirectoryContent      // текущий каталог [VirtualDirectoryContent]
    
UsedActions                  // Массив используемых операций с элементами браузера

turnOffCheckboxes            // Выключать ли чекбоксы

MAX_ITEMS_COUNT_ON_PAGE      // число отображаемых файлов без прокрутки

// -------------------------------- Методы
Load                // Загрузить содержимое каталога
LoadParent          // Загрузить содержимое родительского каталога
    
Display             // Отобразить браузер
DisplayEmptyBrowser // Отображает заготовку для браузера
    
DirectoryIsLoaded            // Проверяет, есть ли данные по запрошенному каталогу
ParentDirectoryIsLoaded      // Проверяет, есть ли данные по родительскому каталогу
OpenDirectory                // Открывает запрошенный каталог
OpenParentDirectory          // Открывает родительский каталог
    
GetFullFileName              // По файлу в текущем каталоге браузере возвращает полное имя файла
GetFullDirectoryName         // По папке в текущем каталоге браузере возвращает полное имя папки
    
ContainsFile                 // Проверяет наличие файла в текущем каталоге
AddNewFile                   // Добавляет в браузер (текущий каталог) новый файл
RenameFile                   // Переименовывает файл 
RemoveFile                   // Удаляет файл
ShareFile                    // Делает файл расшаренным
UnshareFile                  // Делает файл обычным
    
ContainsFolder               // Проверяет наличие каталога в текущем каталоге
AddNewFolder                 // Добавляет в браузер (текущий каталог) новый каталог
RenameFolder                 // Переименовывает каталог 
RemoveFolder                 // Удаляет каталог
ShareFolder                  // Делает каталог расшаренным
UnshareFolder                // Делает каталог обычным
    
SetStatusInfo                // Устанавливает надпись статуса
    
GetCheckedFilesList          // Возвращает список отмеченных файлов (Array<LinkCheckboxPair>)
GetCheckedDirsList           // Возвращает список отмеченных каталогов (Array<LinkCheckboxPair>)
    
// -------------------------------- Callbacks
OnFileClick                     // Нажатие на файл
OnDirectoryClick                // Нажатие на каталог
OnParentDirectoryClick          // Нажатие на ссылку на родительский каталог
    
OnRenameFileButtonClick         // Нажатие на кнопку переименования файла
OnRemoveFileButtonClick         // Нажатие на кнопку удаления файлов
OnDownloadFilesButtonClick      // Нажатие на кнопку скачивания pas-файлов  
OnRenameFolderButtonClick       // Нажатие на кнопку переименования папки
OnRemoveFolderButtonClick       // Нажатие на кнопку удаления паки
OnNewFolderButtonClick          // Нажатие на кнопку создания новой папки
OnShareFilesButtonClick         // Нажатие на кнопку расшаривания файлов
OnGetSharedLinkButtonClick      // Нажатие на кнопку получения ссылки на расшаренный файл
OnUnshareFilesButtonClick       // Нажатие на кнопку закрытия доступа к файлам

Менеджер редактора

Инкапсулирует работу с редактором. Файлы отдельно, редактор отдельно.

UserFiles                     // Список пользовательских файлов в редакторе [hash<EditorFileData>]
SampleFiles                   // Список файлов примеров в редакторе [hash<EditorFileData>]
PublicFiles                   // Список публичных файлов в редакторе [hash<EditorFileData>]
SharedFiles                   // Список расшаренных файлов в редакторе [hash<EditorFileData>]
NewUserFiles                  // Список новых пользовательских файлов в редакторе [hash<EditorFileData>]

TabIDsHash                    // Владельцы и полные имена файлов по id вкладки [hash<EditorTabFileData>]

// -------------------------------- Методы
OpenFile                  // Открыть файл в редакторе
FileIsOpened              // Проверяет, открыт ли файл в редакторе
ActiveFile                // Делает активной вкладку заданного файла
CloseFile                 // Закрывает в редакторе заданный файл (меняет статус в менеджере)
CloseFileInEditor         // Закрывает заданный файл в самом редакторе
    
GetCurrFileData           // Возвращает информацию о текущем файле редактора

SetFileEditStatusSaved    // Делает статус вкладки в редакторе нередактированной  
ChangeTabFileData         // Меняет для файла из текущей вкладки данные

GetFileFromDirectory      // Возвращает данные открытого файла из заданного каталога (его или подкаталога)