Вступление
Это руководство является частью серии « Создай свой стартап с помощью PHP» на Envato Tuts +. В этой серии я проведу вас через запуск стартапа от концепции до реальности, используя мое приложение Meeting Planner в качестве примера из реальной жизни. На каждом этапе я буду публиковать код Планировщика собраний в качестве примеров с открытым исходным кодом, из которых вы можете извлечь уроки. Я также буду решать вопросы, связанные с бизнесом по мере их возникновения
Почему разрыв в этой серии?
Вы можете заметить, что между последним эпизодом и этим эпизодом был огромный разрыв во времени. В апреле 2015 года у меня была диагностирована опухоль головного мозга, которая потребовала хирургического вмешательства и облучения . В целом мне невероятно повезло, что я получил такую хорошую помощь, и все прошло довольно хорошо — многие люди не имеют доступа к качественным ресурсам нейрохирургии, которые мне доступны благодаря медицинской страховке на Тихоокеанском северо-западе. С осени прошлого года я снова пишу для Envato Tuts + , но интересно наконец-то вернуть фокус стартапу, и я надеюсь, вам понравится.
Что охватывает этот эпизод?
В этом руководстве мы расскажем о пользовательских функциях, которые необходимы для предоставления различных представлений в зависимости от того, кто просматривает приглашения на собрания. Прежде чем мы начнем рассылать приглашения участникам по электронной почте, нам необходимо подготовить представление с потенциально ограниченными функциями, чтобы поделиться с ними. По сути, мы следим за тем, чтобы представление собрания было именно тем, что необходимо для владельца собрания и участника собрания. Следуйте, чтобы узнать, что нужно.
Весь код для Meeting Planner написан на Yii2 Framework для PHP, который имеет встроенную поддержку I18n. Если вы хотите узнать больше о Yii2, ознакомьтесь с нашей параллельной серией Программирование с Yii2 на Envato Tuts +.
Интересно, что потенциальный инвестор-ангел недавно обратился ко мне с просьбой предоставить ресурсы для ускорения процесса разработки нашего сайта — он видит ценность в концепции. Когда я выберу подходящий путь, чтобы продолжить, я буду держать вас в курсе. Во всяком случае, я надеюсь, что это создает интригующие новые учебные темы по управлению инвестиционным процессом в качестве предпринимателя.
Просто напоминание, я участвую в комментариях ниже. Мне особенно интересно, если у вас есть другие подходы, дополнительные идеи или вы хотите предложить темы для будущих уроков. Вы также можете связаться со мной в Twitter @reifman .
Требования к просмотру собрания
Это довольно увлекательно — в ближайшее время Meeting Planner будет рассылать приглашения приглашенным участникам. Однако для поддержки этого нам необходимо убедиться, что страница просмотра собрания настроена правильно. Если вы создали собрание, у вас есть определенные полномочия, такие как приглашение участников, добавление предлагаемых мест встречи, дат и времени, а также выбор окончательного выбора. В некоторых случаях организатор может предложить некоторые или все эти полномочия участникам.
По сути, мы должны уведомить приложение о том, кто просматривает страницу собрания, а затем настроить внешний вид и доступные команды. Yii делает большую часть этого довольно простым, но в нем много деталей.
Краткая оговорка об опыте пользователя
И позвольте мне сразу сказать, что на пути к минимально жизнеспособному продукту (MVP) потребуется много времени для доработки и доработки пользовательского опыта. Большая часть того, что я сейчас создаю, — это основная функциональность, позволяющая запустить альфа-версию для реального использования. Я знаю, что это выглядит грубым в некоторых местах и не всегда будет казаться таким интуитивным, как вы хотите. Есть также недостатки кодирования, которые необходимо будет оптимизировать в будущем. Пожалуйста, не стесняйтесь оставлять свои мысли и комментарии ниже, и я буду принимать их во внимание для дальнейшей работы.
Текущее представление встречи
Вот взгляд на существующее представление собрания, которое видит создатель (или владелец):
Кнопка « Отправить» отправляет участнику приглашение по электронной почте с текущими открытыми параметрами, чтобы он мог оставить отзыв. Чекбоксы под Вами и Им позволяют зрителю выражать, работают ли для них место (а) и время (и). Флажки Выбрать позволяют зрителю определить конечное место и окончательное время. Кнопка « Завершить» помещает встречу в расписание с выбранными параметрами места и времени.
Конечно, по мере развития продукта мы хотим улучшить взаимодействие с пользователем несколькими способами и значительно его улучшить, но вот несколько функциональных элементов, которые мы хотели бы изменить для участников:
- Кнопка Отправить не понадобится после того, как владелец доставит приглашение.
- Участникам может быть разрешено или не разрешено финализировать варианты встреч.
- Участники не смогут редактировать (значок карандаша) подробный текст встречи.
- Участники не смогут добавлять людей в это время (для нашего MVP).
- Участники могут или не могут добавлять места (значок плюс).
- Участники могут или не могут добавлять даты и время (значок плюс).
- На панелях « Места» и « Даты и время» мы хотим показать выбор текущего зрителя в разделе столбец You и данные другого лица в них .
- На панелях « Места» и « Даты и время» участники могут или не могут выбрать окончательный вариант. место и время.
Все эти варианты должны быть рассмотрены в нашей работе сегодня. Давайте пройдемся по тому, что требуется для создания этих функций.
Выполнение требований
Если вы следуете вместе с кодом, описанные здесь обновления включены в этот выпуск на GitHub .
Кто сейчас зритель
Yii Framework предоставляет текущий user_id
для зрителя здесь:
1
|
$user_id = Yii::$app->user->getId()
|
Модель Meeting имеет свойство $owner_id
и функцию isOwner
чтобы помочь определить, является ли текущий зритель создателем собрания. Если нет, зритель будет иметь меньше контроля над собранием.
Я создал несколько вспомогательных функций в модели Meeting, чтобы сделать это быстрее:
1
2
3
4
5
6
7
8
|
public function setViewer() {
$this->viewer_id = Yii::$app->user->getId();
if ($this->owner_id == $this->viewer_id) {
$this->viewer = Meeting::VIEWER_ORGANIZER;
} else {
$this->viewer = Meeting::VIEWER_PARTICIPANT;
}
}
|
Они настраивают свойства $owner_id
и $viewer
в модели Meeting.
Сборка для настроек собрания
Каждая встреча, которую вы создаете, вероятно, будет иметь разные характеристики. Иногда вы хотите ограничить участников предложением предлагать разные времена и места или уточнять детали. В других случаях вам будет все равно. Когда мы в конечном итоге создадим шаблоны собраний для повторного использования общих типов собраний, например, утренних кофейных бизнес-встреч, в шаблонах, вероятно, также потребуется сохранить такие настройки. Как мы должны это реализовать?
Во-первых, я хотел бы создать набор настроек по умолчанию для пользователей в отношении встреч, которые они создают.
Затем я создам набор MeetingSettings для каждой встречи. Когда собрание создается с нуля, оно наследует настройки по умолчанию от пользователя, который его создает. Редактирование настроек для отдельных встреч можно отложить на потом.
В будущем, когда мы внедрим шаблоны собраний, мы добавим настройки собраний и для шаблонов. Однако это также может быть отложено.
Вот настройки, которые мы хотели бы создать, чтобы начать:
- Разрешить участникам добавлять места.
- Разрешить участникам добавлять даты и время.
- Разрешить участникам выбирать места.
- Разрешить участникам выбирать даты и время.
- Разрешить участникам завершить встречу.
Поскольку мы все возвращаемся в сериал через некоторое время из-за отсутствия моего здоровья, я немного подробнее расскажу о некоторых работах.
Сначала мы создадим миграцию настроек собрания:
1
2
3
4
5
|
$ ./yii migrate/create meeting_setting_table
Yii Migration Tool (based on Yii v2.0.7)
Create new migration ‘/Users/Jeff/Sites/mp/console/migrations/m160401_203412_meeting_setting_table.php’?
New migration created successfully.
|
Это создает файл миграции, нам нужно написать код, который строит таблицу базы данных в соответствии с нашей схемой:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
|
<?php
use yii\db\Schema;
use yii\db\Migration;
class m160401_203412_meeting_setting_table extends Migration
{
public function up()
{
$tableOptions = null;
if ($this->db->driverName === ‘mysql’) {
$tableOptions = ‘CHARACTER SET utf8 COLLATE utf8_unicode_ci ENGINE=InnoDB’;
}
$this->createTable(‘{{%meeting_setting}}’, [
‘id’ => Schema::TYPE_PK,
‘meeting_id’ => Schema::TYPE_INTEGER.’
‘participant_add_place’ => Schema::TYPE_SMALLINT .
‘participant_add_date_time’ => Schema::TYPE_SMALLINT .
‘participant_choose_place’ => Schema::TYPE_SMALLINT .
‘participant_choose_date_time’ => Schema::TYPE_SMALLINT .
‘participant_finalize’ => Schema::TYPE_SMALLINT .
‘created_at’ => Schema::TYPE_INTEGER .
‘updated_at’ => Schema::TYPE_INTEGER .
], $tableOptions);
$this->addForeignKey(‘fk_meeting_setting’, ‘{{%meeting_setting}}’, ‘meeting_id’, ‘{{%meeting}}’, ‘id’, ‘CASCADE’, ‘CASCADE’);
}
public function down()
{
$this->dropForeignKey(‘fk_meeting_setting’, ‘{{%meeting_setting}}’);
$this->dropTable(‘{{%meeting_setting}}’);
}
}
|
По сути, каждое собрание имеет ряд MeetingSettings с логическими свойствами для различных вариантов участников, которые я показал выше.
Затем мы инструктируем Yii перенести вверх и создать таблицу:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
|
$ ./yii migrate/up
Yii Migration Tool (based on Yii v2.0.7)
Total 1 new migration to be applied:
m160401_203412_meeting_setting_table
Apply the above migration?
*** applying m160401_203412_meeting_setting_table
> create table {{%meeting_setting}} … done (time: 0.010s)
> add foreign key fk_meeting_setting: {{%meeting_setting}} (meeting_id) references {{%meeting}} (id) … done (time: 0.011s)
*** applied m160401_203412_meeting_setting_table (time: 0.040s)
1 migration was applied.
Migrated up successfully.
|
Наш внешний ключ создает связь между таблицей Meeting и таблицей MeetingSetting.
Далее мы будем использовать Yii’s Gii для автоматической генерации кода для просмотра и обновления настроек. Для начала я возвращаюсь на http: // localhost: 8888 / mp / index.php / gii / . Начнем с генерации модели:
Затем мы сгенерируем код создания, чтения, обновления, удаления (CRUD):
Поскольку сейчас нам не нужен весь этот код, Gii позволяет нам выбирать только те функции, которые нам нужны: контроллер , представление, _form и update :
Gii показывает вам список файлов, которые он создает с каждым шагом:
Но как насчет пользовательских настроек по умолчанию? По сути, их типичные предпочтения встречи?
Расширение пользовательских настроек
Для этого мы добавим свойства параметров параллельной встречи в таблицу user_setting
. Опять же, мы создадим миграцию:
1
2
3
4
5
|
$ ./yii migrate/create extend_user_setting_table
Yii Migration Tool (based on Yii v2.0.7)
Create new migration ‘/Users/Jeff/Sites/mp/console/migrations/m160401_210852_extend_user_setting_table.php’?
New migration created successfully.
|
Вот столбцы, которые мы должны добавить:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
|
class m160401_210852_extend_user_setting_table extends Migration
{
public function up()
{
$tableOptions = null;
if ($this->db->driverName === ‘mysql’) {
$tableOptions = ‘CHARACTER SET utf8 COLLATE utf8_unicode_ci ENGINE=InnoDB’;
}
$this->addColumn(‘{{%user_setting}}’,’participant_add_place’,Schema::TYPE_SMALLINT.’ NOT NULL’);
$this->addColumn(‘{{%user_setting}}’,’participant_add_date_time’,Schema::TYPE_SMALLINT.’ NOT NULL’);
$this->addColumn(‘{{%user_setting}}’,’participant_choose_place’,Schema::TYPE_SMALLINT.’ NOT NULL’);
$this->addColumn(‘{{%user_setting}}’,’participant_choose_date_time’,Schema::TYPE_SMALLINT.’ NOT NULL’);
$this->addColumn(‘{{%user_setting}}’,’participant_finalize’,Schema::TYPE_SMALLINT.’ NOT NULL’);
}
public function down()
{
$this->dropColumn(‘{{%user_setting}}’,’participant_finalize’);
$this->dropColumn(‘{{%user_setting}}’,’participant_choose_date_time’);
$this->dropColumn(‘{{%user_setting}}’,’participant_choose_place’);
$this->dropColumn(‘{{%user_setting}}’,’participant_add_date_time’);
$this->dropColumn(‘{{%user_setting}}’,’participant_add_place’);
}
}
|
Затем мы запустим миграцию:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
|
$ ./yii migrate/up
Yii Migration Tool (based on Yii v2.0.7)
Total 1 new migration to be applied:
m160401_210852_extend_user_setting_table
Apply the above migration?
*** applying m160401_210852_extend_user_setting_table
> add column participant_add_place smallint NOT NULL to table {{%user_setting}} … done (time: 0.012s)
> add column participant_add_date_time smallint NOT NULL to table {{%user_setting}} … done (time: 0.007s)
> add column participant_choose_place smallint NOT NULL to table {{%user_setting}} … done (time: 0.010s)
> add column participant_choose_date_time smallint NOT NULL to table {{%user_setting}} … done (time: 0.009s)
> add column participant_finalize smallint NOT NULL to table {{%user_setting}} … done (time: 0.009s)
*** applied m160401_210852_extend_user_setting_table (time: 0.061s)
1 migration was applied.
Migrated up successfully.
|
Вместо принудительной перезаписи нашей модели UserSetting.php с помощью Gii, мы будем использовать опцию diff для Gii:
И оттуда мы вручную выберем новые дополнения к файлу и вставим их в:
Функционально мы добавим вкладку настроек собрания на страницу свойств Обновить ваши настройки :
Мы добавим следующий код в /frontend/views/user-setting/_form.php
для поддержки наших новых свойств:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
|
<div class=»col-md-8″>
<!— Nav tabs —>
<ul class=»nav nav-tabs» role=»tablist»>
<li class=»active»><a href=»#general» role=»tab» data-toggle=»tab»><?= Yii::t(‘frontend’,’General Settings’) ?></a></li>
<li><a href=»#preferences» role=»tab» data-toggle=»tab»><?= Yii::t(‘frontend’,’Meeting Preferences’) ?></a></li>
<li><a href=»#photo» role=»tab» data-toggle=»tab»><?= Yii::t(‘frontend’,’Upload Photo’) ?></a></li>
</ul>
<!— Tab panes —>
<div class=»tab-content»>
…
</div>
<div class=»tab-pane vertical-pad» id=»preferences»>
<?= $form->field($model, ‘participant_add_place’)->checkbox([‘uncheck’ => $model::SETTING_NO, ‘checked’ => $model::SETTING_YES]);
<?= $form->field($model, ‘participant_add_date_time’)->checkbox([‘uncheck’ => $model::SETTING_NO, ‘checked’ => $model::SETTING_YES]);
<?= $form->field($model, ‘participant_choose_place’)->checkbox([‘uncheck’ => $model::SETTING_NO, ‘checked’ => $model::SETTING_YES]);
<?= $form->field($model, ‘participant_choose_date_time’)->checkbox([‘uncheck’ => $model::SETTING_NO, ‘checked’ => $model::SETTING_YES]);
<?= $form->field($model, ‘participant_finalize’)->checkbox([‘uncheck’ => $model::SETTING_NO, ‘checked’ => $model::SETTING_YES]);
</div> <!— end of upload meeting-settings tab —>
<div class=»tab-pane vertical-pad» id=»photo»>
…
|
Вот обновленная форма:
Инициализация новых сессий собрания
Всякий раз, когда пользователь создает новое собрание, мы должны загрузить его настройки по умолчанию и скопировать их в настройки отдельного собрания. initializeMeetingSetting вызывается при создании нового собрания для этого:
01
02
03
04
05
06
07
08
09
10
11
12
|
public function initializeMeetingSetting($meeting_id,$owner_id) {
// load meeting creator (owner) user settings to initialize meeting_settings
$user_setting = UserSetting::find()->where([‘user_id’ => $owner_id])->one();
$meeting_setting = new MeetingSetting();
$meeting_setting->meeting_id = $meeting_id;
$meeting_setting->participant_add_place=$user_setting->participant_add_place;
$meeting_setting->participant_add_date_time=$user_setting->participant_add_date_time;
$meeting_setting->participant_choose_place=$user_setting->participant_choose_place;
$meeting_setting->participant_choose_date_time=$user_setting->participant_choose_date_time;
$meeting_setting->participant_finalize=$user_setting->participant_finalize;
$meeting_setting->save();
}
|
Установив настройки собрания, мы готовы перейти к тому, что на самом деле составляет основную часть сегодняшней работы, настроив виды собраний для владельца и участника.
Просмотр представления владельца собрания
Теперь давайте рассмотрим состояние нашего представления собрания на основе создателя или владельца собрания. Вот приглашение на встречу, которое я недавно создал, чтобы пригласить моего друга Роба выпить:
Панель команд
Перед включением функции отправки и завершения необходимо пригласить человека и хотя бы одно место и время. Если есть более одного места и времени, необходимо выбрать один из них для завершения совещания.
Кнопки собрания Отмена (значок X) и Изменить (значок карандаша) также включены для создателей.
люди
Для MVP мы сначала ограничиваем приглашения на собрания только для одного участника. Поэтому, как только человек был приглашен, кнопка « Добавить» (значок «плюс») отключена.
Места и дата и время
Создатель может добавить места и дату и время до максимума нашего сайта (например, семь на одно собрание), и они могут указать их наличие и принятие. И, наконец, когда их несколько, они могут выбрать, какое место и время будут использованы.
Примечания
Создатель всегда может добавить заметки к встрече. Заметки позволяют создателю и участникам общаться друг с другом.
В конечном итоге мы приложим основную часть нашей работы к улучшению функциональности AJAX, чтобы по мере того, как владелец выбирал места и время, кнопки «Отправить» и «Завершить» были правильно включены (или отключены в некоторых случаях).
Вот пример встречи с двумя возможными временами. Кнопка « Завершить» не может быть включена, пока не будет выбран один раз:
После того, как выбор сделан, мы бы хотели включить кнопку « Завершить» через AJAX, чтобы избавить пользователя от обновления страницы.
Просмотр представления участника
Когда мы просматриваем приглашение с точки зрения участника, у нас гораздо меньше начальных возможностей:
Участник может отменить (значок X) свое посещение собрания и указать, приемлемы ли для него места и время, но он не может выбрать окончательное место или завершить собрание. Кроме того, данные в столбцах « Вы» и « Они» теперь переключаются. И панель участника скрыта, так как она не нужна.
Кроме того, скажем, собрание было создано с настройками, которые позволяли участнику выбирать место, дату и время, но не завершали собрание. Это должно выглядеть так:
Так как есть только одно Место, Herkimer Coffee , вам не нужно выбирать селектор. Но там, где есть два возможных времени, теперь вы можете видеть селекторы выбора. Тем не менее, нет кнопки Завершить.
Оказалось, что для поддержки всего этого потребовалось много нового кода для обновления системы, но это начинает проникать в суть продукта — опыт планирования встреч пользователей. Я проведу вас через несколько изменений, которые были необходимы.
Кодирование требований встречи
Реализация настроек встречи
На панелях времени и места встречи нам нужно использовать настройки встречи, чтобы определить, нужно ли показывать селектор выбора. В представлении _panel.php это выглядит так:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
|
<table class=»table»>
<thead>
<tr class=»small-header»>
<td></td>
<td ><?=Yii::t(‘frontend’,’You’) ?></td>
<td ><?=Yii::t(‘frontend’,’Them’) ?></td>
<td >
<?php
if ($timeProvider->count>1 && ($isOwner || $model->meetingSettings->participant_choose_date_time)) echo Yii::t(‘frontend’,’Choose’);
?>
</td>
</tr>
</thead>
<?= ListView::widget([
‘dataProvider’ => $timeProvider,
‘itemOptions’ => [‘class’ => ‘item’],
‘layout’ => ‘{items}’,
‘itemView’ => ‘_list’,
‘viewParams’ => [‘timeCount’=>$timeProvider->count,’isOwner’=>$isOwner,’participant_choose_date_time’=>$model->meetingSettings[‘participant_choose_date_time’]],
]) ?>
</table>
|
Мы проверяем настройки участников и передаем их в качестве параметра в последующее представление _list.php, которое выглядит следующим образом:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
<td style>
<?php
if ($timeCount>1) {
if ($model->status == $model::STATUS_SELECTED) {
$value = $model->id;
} else {
$value = 0;
}
if ($isOwner || $participant_choose_date_time) {
// value has to match for switch to be on
echo SwitchInput::widget([
‘type’ => SwitchInput::RADIO,
‘name’ => ‘time-chooser’,
‘items’ => [
[ ‘value’ => $model->id],
],
‘value’ => $value,
‘pluginOptions’ => [ ‘size’ => ‘mini’,’handleWidth’=>60,’onText’ => ‘<i class=»glyphicon glyphicon-ok»></i>’,’offText’=>'<i class=»glyphicon glyphicon-remove»></i>’],
‘labelOptions’ => [‘style’ => ‘font-size: 12px’],
]);
}
}
?>
</td>
|
Если представление является создателем или участнику разрешено выбрать последний раз, они увидят что-то вроде этого, возможность Выбрать в правом столбце:
Может ли зритель отправить и завершить собрание
Я создал функции canSend()
и canFinalize()
, которые обычно поддерживают код и запросы AJAX для определения активного состояния кнопок отправки и завершения.
Вот canSend()
:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
|
public function canSend($sender_id) {
// check if an invite can be sent
// req: a participant, at least one place, at least one time
if ($this->owner_id == $sender_id
&& count($this->participants)>0
&& count($this->meetingPlaces)>0
&& count($this->meetingTimes)>0
) {
$this->isReadyToSend = true;
} else {
$this->isReadyToSend = false;
}
return $this->isReadyToSend;
}
|
Организатор не может отправить приглашение на собрание, пока не будут указаны участники, места и время.
Вот canFinalize()
:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
|
public function canFinalize($user_id) {
$this->isReadyToFinalize = false;
// check if meeting can be finalized by viewer
// check if overall meeting state can be sent by owner
if (!$this->canSend($this->owner_id)) return false;
$chosenPlace = false;
if (count($this->meetingPlaces)==1) {
$chosenPlace = true;
} else {
foreach ($this->meetingPlaces as $mp) {
if ($mp->status == MeetingPlace::STATUS_SELECTED) {
$chosenPlace = true;
break;
}
}
}
$chosenTime = false;
if (count($this->meetingTimes)==1) {
$chosenTime = true;
} else {
foreach ($this->meetingTimes as $mt) {
if ($mt->status == MeetingTime::STATUS_SELECTED) {
$chosenTime = true;
break;
}
}
}
if ($this->owner_id == $user_id ||
$this->meetingSettings->participant_finalize) {
if ($chosenPlace && $chosenTime) {
$this->isReadyToFinalize = true;
}
}
return $this->isReadyToFinalize;
}
|
Сначала проверяется, может ли собрание быть отправлено, потому что если нет, оно не может быть завершено. Затем он проверяет, выбраны ли место и время. Затем он проверяет, является ли средство просмотра организатором, или настройки собрания позволяют участнику завершить собрание.
По сути, после внесения изменений вы увидите состояние изменений кнопок « Отправить» и « Завершить» :
В view.php собрания я включил JavaScript для поддержки обновлений AJAX для состояния кнопок «Отправить» и «Завершить», когда пользователи изменяют настройки своего собрания. Когда выбор мест и времени сделан, refreshSend()
и refreshFinalize()
, и кнопки соответствующим образом модифицируются:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
|
<?php
if (isset(Yii::$app->params[‘urlPrefix’])) {
$urlPrefix = Yii::$app->params[‘urlPrefix’];
} else {
$urlPrefix =»;
}
$script = <<< JS
function refreshSend() {
$.ajax({
url: ‘$urlPrefix/meeting/cansend’,
data: {id: $model->id, ‘viewer_id’: $viewer},
success: function(data) {
if (data)
$(‘#actionSend’).removeClass(«disabled»);
else
$(‘#actionSend’).addClass(«disabled»);
return true;
}
});
}
function refreshFinalize() {
$.ajax({
url: ‘$urlPrefix/meeting/canfinalize’,
data: {id: $model->id, ‘viewer_id’: $viewer},
success: function(data) {
if (data)
$(‘#actionFinalize’).removeClass(«disabled»);
else
$(‘#actionFinalize’).addClass(«disabled»);
return true;
}
});
}
JS;
$position = \yii\web\View::POS_READY;
$this->registerJs($script, $position);
?>
|
Реверсирование селекторов места и времени
В текущем пользовательском интерфейсе мы показываем выбор места и времени зрителя в крайнем левом или первом столбце. Код должен быть настроен, чтобы изменить это, когда участники просматривают:
Для поддержки отображения разных данных в столбцах «Вы» и «Их» представления собрания для «Времена и места» необходимо обновить файлы _list.php времени собрания и места встречи, чтобы динамически определить, какие данные отображать:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
|
<td style>
<?php
if ($isOwner) {
showTimeOwnerStatus($model,$isOwner);
} else {
showTimeParticipantStatus($model,$isOwner);
}
?>
</td>
<td style>
<?php
if (!$isOwner) {
showTimeOwnerStatus($model,$isOwner);
} else {
showTimeParticipantStatus($model,$isOwner);
}
?>
</td>
|
На данный момент я поместил эти функции в представление _panel.php, которое вызывает _list.php, так как они полагаются на включение виджета SwitchInput в контекст:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
|
<?php
use \kartik\switchinput\SwitchInput;
function showTimeOwnerStatus($model,$isOwner) {
foreach ($model->meetingTimeChoices as $mtc) {
if ($mtc->user_id == $model->meeting->owner_id) {
if ($mtc->status == $mtc::STATUS_YES)
$value = 1;
else
$value =0;
echo SwitchInput::widget([
‘type’ => SwitchInput::CHECKBOX,
‘name’ => ‘meeting-time-choice’,
‘id’=>’mtc-‘.$mtc->id,
‘value’ => $value,
‘disabled’ => !$isOwner,
‘pluginOptions’ => [‘size’ => ‘mini’,’onText’ => ‘<i class=»glyphicon glyphicon-ok»></i>’,’offText’=>'<i class=»glyphicon glyphicon-remove»></i>’,’onColor’ => ‘success’,’offColor’ => ‘danger’,],
]);
}
}
}
function showTimeParticipantStatus($model,$isOwner) {
foreach ($model->meetingTimeChoices as $mtc) {
if (count($model->meeting->participants)==0) break;
if ($mtc->user_id == $model->meeting->participants[0]->participant_id) {
if ($mtc->status == $mtc::STATUS_YES)
$value = 1;
else if ($mtc->status == $mtc::STATUS_NO)
$value =0;
else if ($mtc->status == $mtc::STATUS_UNKNOWN)
$value =-1;
echo SwitchInput::widget([
‘type’ => SwitchInput::CHECKBOX,
‘name’ => ‘meeting-time-choice’,
‘id’=>’mtc-‘.$mtc->id,
‘tristate’=>true,
‘indeterminateValue’=>-1,
‘indeterminateToggle’=>false,
‘disabled’=>$isOwner,
‘value’ => $value,
‘pluginOptions’ => [‘size’ => ‘mini’,’onText’ => ‘<i class=»glyphicon glyphicon-ok»></i>’,’offText’=>'<i class=»glyphicon glyphicon-remove»></i>’,’onColor’ => ‘success’,’offColor’ => ‘danger’,],
]);
}
}
}
?>
|
Предстоящие корректировки
В конечном счете, в этот код необходимо внести множество улучшений. Местами я делаю AJAX-вызовы на сервер два или три раза, когда я могу более эффективно кодировать их в один запрос. В других местах я могу делать больше локально с помощью JavaScript. И пользовательский интерфейс должен будет продолжать улучшаться, и код должен будет измениться, чтобы приспособиться к этому. Но с функциональной точки зрения сегодняшняя работа представляет собой большой общий прогресс в направлении MVP.
Что дальше?
После настройки параметров собрания и просмотра требований для организаторов и участников я готов приступить к отправке первого приглашения. В следующем эпизоде будет рассмотрено отправка приглашения участнику по электронной почте, а также реализация внешнего вида содержимого, функциональных командных ссылок в письме и управление разрешениями для пользователей, которые еще не зарегистрировались. Следите за будущими уроками в нашей серии «Построение стартапа с помощью PHP» — это становится захватывающим!
Пожалуйста, не стесняйтесь добавлять свои вопросы и комментарии ниже; Я обычно участвую в обсуждениях. Вы также можете связаться со мной в Twitter @reifman .