Моё портфолио

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

Secure business cloud

Май 2014
* * * *

Закакзчик прислал краткое ТЗ и макет свёрстанный в Adobe Photoshop. Требовалось сделать сайт-визитку. Время поджимало. Было решено использовать DHTML, JavaScript плагины jQuery и jQuery UI в качестве клиенской части. В качестве серверной части написан на скорую руку perl-обработчик AJAX запроса, который общается с клиенской частью посредством формата JSON. Работу удалось выполнить в рекордные сроки - 1 день. Работы включали: создание доменного имени, установку необходимого софта на сервере заказчика, написание клиенской и серверной части. Проект претерпел несколько правок по части дизайна, после чего был сдан заказчику.

http://cloud.smallbusiness.ru

 

Блог (mnshome.info)

Лето 2013
* * * *

Сайт блога. На самом блоге есть тег блог посвященный процессу разработки сайта, там же можно найти информацию о том как он устроен и как работает. Стоит отметить, что за время работы блога, основной акцент сместился в сторону использования модуля-фреймворка MPMinus. Блог является ярким примером того как работает связка mod_perl (Apache + Perl) и MVC. Процесс разработки был увлекательным, размер проекта, без учёта иллюстративного и медиа материала, уменьшился и стал чуть булее мегабайта. Блог устанавливается как модуль в систему, что дает возможность создания его дистрибутива с возможностью последующего быстрого разворачивания на целевую площадку. Сейчас блог работает за NGinx сервером, что обеспечивает дополнительную его отказоустойчивость. Процесс разработки был поэтапный, и последний этап, который включал в себя «переезд» на модуль MPMinus, занял примерно 1 неделю, когда как сам цикл занял примерно месяц рабочего времени.

http://www.mnshome.info

 

SUFFIT (suffit.org)

Осень 2013
* * * *

Bug-tracker & Project control system. Сайт-трекер. Призван облегчить разработку проектов в командах разработки. Позволяет создавать тикеты (артефакты), брать их в работу и закрывать. Помимо этого позволяет вести версионинг проектов, что существенно облегчает разработку вялотекущих проектов. Сайт является вторым представителем переехавшим на модуль MPMinus. Более подробную информацию можно прочитать на страницах сайта проекта.

http://www.suffit.org

 

Работа №341.7: Раздел сайта "on-line регистрация менеджеров"

Лето 2010
* * *

Здесь я хотел бы привести в качестве примера одну из своих последних работ которая отличается своей кастомизацией от в чем-то похожих систем, написанных с использованием стандартных компонентов, например, системы из библиотеки Google или Yahoo.

Итак. Руководством была поставлена задача:

Создать страницу на сайте менеджеров, на которой могли бы регистрироваться заранее заведенные менеджеры. Под словом «регистрация» понимается:
  • занесение данных загранпаспорта для бронирования билета и оформления визы,
  • занесения контактных данных,
  • выбор группы (автобуса, корпуса отеля),
  • выбор комнаты для проживания в отеле.
Для процесса регистрации важно условие, что заселиться можно в комнату только с однополыми «сожителями». Для процесса управления регистрацией важны условия:
  • количество и качество элементов ввода может легко и быстро изменяться;
  • система внесения новых кандидатов на регистрацию;
  • система изменения констант (количества мест в группе, количество групп, количество VIP групп и количества мест в VIP группе, количество апартаментов, количество свободных мест в номере и VIP номера);
  • гибкая и удобная система управления списком зарегистрировавшихся,
  • система редактирования данных отдельных зарегистрировавшихся;
  • легкая система выгрузки данных в формат EXCEL или другую электронную таблицу;
  • система, позволяющая произвести импортирование данных из базы данных Oracle

Спустя несколько дней получилось сделать все что удовлетворило желаниям заказчика. Вот так оно выглядит:

Верхняя часть страницы
Нижняя часть страницы

Если признаться честно, то работа была трудна и интересна одновременно, потому я и решил ее описать здесь. В качестве технологий были использованы: MySQL, Apache 2.2, Perl 5.8, SSI, XHTML, CSS, YAML, JavaScript. Формат YAML используется как для динамического создания дерева конфигурации, и для хранения данных дополнительных полей пользователя. Пример конфигурационного файла:

---
title: Карибский бриз с Алло Инкогнито
vip:
  fields:
    - case: U
      class: input
      mask: !!perl/regexp '(?-xism:^[A-Za-z]+$)'
      maxlength: 255
      name: familiya
      required: 1
      sample: IVANOV
      style: 'width: 200px;'
      title: 'FAMILIYA (как в загран. паспорте.)'
      type: text
      value: ~
    - case: U
      class: input
      mask: !!perl/regexp '(?-xism:^[A-Za-z]+$)'
      maxlength: 255
      name: imya
      required: 1
      sample: IVAN
      style: 'width: 200px;'
      title: 'IMYA (как в загран. паспорте.)'
      type: text
      value: ~
    - case: l
      class: input
 

Теперь хотелось бы рассмотреть некоторые страницы управления в отдельности и вкратце описать функции которые каждые из них выполняют.

Управление менеджерами

Пройдя несложную процедуру авторизации мы попадаем на страницу «Управление менеджерами»

Страница управления

Страница предназначена главным образом для быстрого поиска менеджера, быстрого определения в какой он группе, в каком номере и кто будет с ним в этом номере проживать. Также, на этой страничке дана возможность очищать заполненные регистрационные данные, удалять его из списка или перейти на страницу изменения его личных данных. Помимо этого, была добавлена возможность, кликая по его фамилии имени отчеству, легко видеть все его введенные данные. Код, описывающий эту страницу, очень короткий (всего около 50 строк) но несмотря на это его нельзя назвать простым, т.к. его компактный внешний вид скрывает функционал, выполняющий сложные манипуляции с данными из БД и YAML файла. Приведу его весь в качестве единственного развернутого примера (в рамках моего описания):

package handler::cabinet;
use strict;
 
sub vform {
    # Данные из сессии
   my %apts = handler::default::getApartmentsAsHash();
 
   my $table_box = $::template->start('table');
   my $n = 0;
   foreach my $k (sort { $apts{$a}{fio} cmp $apts{$b}{fio} }
          keys %apts) {
      if (_filter(
               $apts{$k}{r},
               $apts{$k}{g}
            )
         ) {
         $n++;
         $table_box->loop(
            n   => $n,
            id  => $apts{$k}{id} || 0,
            fio => $apts{$k}{fio} || 'noname',
            r   => $apts{$k}{r} || 0,
            g   => $apts{$k}{g} || 0,
            dt  => $apts{$k}{dt} || ' ',
            v   => handler::default::calcPPR()
			   -($apts{$k}{cnt} || 0),
            class => $n & 1 ? 'light1' : 'light2',
         );
      }
   }
   $table_box->finish;
    1;
}
sub cchck {   1; }
sub mproc { 1; }
sub _filter {
   # Условия взаимодействия с фильтром для данных
   my $r = shift || 0;
   my $g = shift || 0;
   my $ret = 1;
 
   if ($::usr{r}) {
      return 0 if $::usr{r} ne $r
   }
   if ($::usr{g}) {
      return 0 if $::usr{g} ne $g
   }
   return $ret;
}
1;

Данный модуль, как видно, очень короткий по размеру, и на первый взгляд в нем нет ничего сложного. Модуль является частью FrameWork`а, потому любая задача выделена в отдельный пакет состоящего из нескольких конкретных процедур. Процедура vform выполняет функцию отображения списка менеджеров, получаемого процедурой взаимодействия с MySQL: getApartmentsAsHash(). Отображение выполняется зависимым модулем TemplateM Процедура getApartmentsAsHash() содержит в себе SQL код:

sub getApartmentsAsHash {
   # Получение ЗАНЯТЫХ комнат в виде Хэша
   my $table = calcTable();
 
   my $sql = "
       SELECT
         a.id id,
         DATE_FORMAT(a.dt,'%d.%m.%Y %T') dt,
         a.fio fio,
         a.r r,
         a.g g,
         a.x x,
         a.n1 n1,
         a.n2 n2,
         a.n3 n3,
         a.DATA DATA,
         count(*) cnt
      FROM
         $table t,
         $table a
      WHERE 1 = 1
         AND t.r = a.r
      GROUP BY
         t.r,
         a.id
      ORDER BY
         a.r,
         a.fio
   ";
   return $::mysql->tableh("id",$sql);
}

Далее, по коду, идет процедура cchck. Эта процедура необходима для валидации данных, которые приходят со стороны пользователя через интерфейс CGI. Но так как данных для валидации нет, то здесь эта процедура фиктивна, в точности также как и следующая процедура mproc. Процедура mproc выполняет действие, которое могло бы быть выполнено в случае нажатия на кнопку управления, типа «Сохранить», «Добавить» и т.д.

Процедура _filter выполняет отбор строк по заданным критериям, эта процедура проста и не нуждается в комментариях

Что касается того, как выглядит шаблон, позволяющий увидеть все в том виде в каком мы это видим на экране, приведу его содержимое:

<!-- do: field -->
<tr class="table_content">
   <td align="right">
      <!-- val: title -->: 
      <!-- if: required -->
      <font color="#ff0000"><b>*</b></font> 
      <!-- endif: required -->
   </td>
   <td>
   <!-- if: type_text -->
      <input class="!-- val: class --"
         type="!-- val: type --"
         name="!-- val: name --"
         style="!-- val: style --"
         maxlength="!-- val: maxlength --"
         value="!-- val: value --" />
   <!-- endif: type_text -->
   <!-- if: type_select -->
      <select name="!-- val: name --"
         class="!-- val: class --"
         style="!-- val: style --">
      <!-- do: st -->
      <option <!-- val: st_selected -->
         value="!-- val: st_value --">
            <!-- val: st_title -->
      </option>
      <!-- loop: st -->
      </select>
   <!-- endif: type_select -->
   <!-- if: type_textarea -->
      <textarea class="!-- val: class --"
         rows="!-- val: rows --"
         cols="!-- val: cols --"
         name="!-- val: name --"
         style="!-- val: style --">
            <!-- val: textarea -->
      </textarea>
   <!-- endif: type_textarea -->
   <!-- if: sample -->
      <br />
      <span class="small">
         <!-- val: sample -->
      </span>
   <!-- endif: sample -->
   </td>
</tr>
<!-- loop: field -->
 

Добавление менеджеров

Следующей страницей на которой я остановлюсь, это страница где реализована возможность добавления списка менеджеров для возможности их регистрации

Страница добавления менеджеров

Уникальность этой страницы в том, что добавлять менеджеров можно пачкой, т.е. простым копированием (методом «Ctrl+C ... Ctrl+V») из файла EXCEL или форм другой базы данных. Эта возможность достигается парсером написанном с использованием регулярных выражений. Приведу пример:

foreach my $fior (split /\s*\r*\n+\s*/, $::usr{fio}) {
   my @fio = split /\s+/,$fior;
   my ($n1,$n2,$n3) = ($fio[0]
      || '', $fio[1] || '', $fio[2] || '');
   $sql="INSERT INTO $t (fio,n1,n2,n3) VALUES (?,?,?,?)";
   $::mysql->execute($sql,"$n1 $n2 $n3",
      $n1,$n2,$n3)->finish;
}

Перезаселение номеров

Эта страница уникальна тем, что позволяет не заходя на страницу «управление менеджерами» производить перезаселение менеджера из одного занятого номера, в другой, где имеются свободные места

Страница перезаселения номеров

На данном снимке мне не удалось показать правую половину, озаглавленную «КУДА», по причине что снимок был сделан в рабочем режиме и менеджеры к тому моменту заняли все доступные комнаты, но внешне она выглядит в точности также как и левая половина, озаглавленная «ОТКУДА». Для того чтобы сделать все необходимые операции, код получился достаточно большим для размещения тут... потому размещаю только его маленький отрывок:

my $p = $apts[$r] || undef;
my $loc_box = $dst_apartment_box->start('loc');
foreach my $l (1..$ppr) {
   if ($p && $p->[1] && $p->[1][$l-1]) {
      $loc_box->loop(
         id => $p->[1][$l-1]{id},
         fio => $p->[1][$l-1]{fio}
      );
    } else {
        $loc_box->loop( id => 'room'.$r, fio => '' );
    }
}
$loc_box->finish;

Выгрузка

Самая сложная и в тоже время важная страница проекта. Она предоставляет возможность получить суммарную выгрузку всех данных менеджера в виде единой таблицы. Выгрузка выполняется в 2-х вариантах: 1 - в виде HTML для копирования методом «Ctrl+C ... Ctrl+V»; 2 - в виде CSV файла. Выгрузка выполняется всего пару раз - в момент, когда зарегистрировался последний менеджер! Это самый ответственный этап мероприятий регистрации.

Страница выгрузки

Код этой страницы небольшой, каскадный, линейный, но приводить его здесь я не буду, т.к. он ничем необычным не отличается.

Настройки

Еще один немаловажный экран - экран страницы настроек. На этой странице предоставляется возможность явно указать константы, необходимые для работы системы. Дело в том, что проект в компании используется только по определенным датам и с различными условиями. Чтобы автоматизировать процесс запуска, эта страница, а также страница «Очистка таблицы», выполняется в момент Запуска.

Страница настройки

В результате нажатия кнопки «Сохранить данные» выполняется код процедуры mproc, которая в данном примере выглядит так:

sub mproc {
   my $setups = YAML::LoadFile("config.yml");
   my $pfx = $::config->VIP?'vip':'def';
   $setups->{title} = $::usr{title} || '';
   $setups->{name} = $::usr{name} || '';
   foreach (qw/rooms groups ppr ppg/) {
      $setups->{$pfx}->{$_} = $::usr{$_} || 0;
   }
   YAML::DumpFile("config.yml",$setups);
   &::log($::config->dirlog.'/setup.log',
      "LOGIN: ".$::session->param('login'), "|");
   $::usr{info} = "Данные успешно сохронены!";
   my $toencode = $::usr{info};
   $toencode=~s/([^a-zA-Z0-9_.~-])/uc
      sprintf("%%%02x",ord($1))/eg;
   print $::q->redirect(
        -uri=>'?action=setup&info='.$toencode,
        -status => 302,
    );
    return 302;
}

PS: все имена и данные на снимках умышленно изменены
PPS: в документе возможны ошибки, заранее прошу прощения
PPPS: все комментарии жду от вас по электронной почте