Advertisement
  1. Web Design
  2. Yii

Paggawa ng Inyong Panimula: Paunang mga Utos sa Pag-iiskedyul 

Scroll to top
Read Time: 17 min
This post is part of a series called Building Your Startup With PHP.
Building Your Startup: Automatic Time-Zone Detection
Building Your Startup: Requesting Scheduling Changes

() translation by (you can also view the original English article)

Final product imageFinal product imageFinal product image
What You'll Be Creating

Ang tutorial na ito ay bahagi ngserye tungkol sa pagbuo ng iyong startup gamit ang PHP sa Envato Tuts+. Sa seryeng ito, gagabayan ko kayo sa paglulunsad ng isang startup mula sa konsepto sa kasalukuyan gamit ang aking Meeting Planner app bilang isang makatotohanan na halimbawa.  Bawat hakbang sa kahabaan ng proseso, ibibigay ko ang open-source code ng aking Meeting Planner app bilang halimbawa kung saan maaari mong malaman ang pinagmulan. Tatalakayin ko din angmga isyu tungkol sa negosyo kung meron tayong madaanan.

Pagpapalawak ng mga Pagpipilian sa Pagtatakda 

Habang ang unang bahagi ng pagsusuri ng Tagaplano ng Pagpupulong ay nagsisimula, ang pinakamalinaw na puwang sa tampok ay ang kawalan ng kakayahan na baguhin ang pagpupulong pagkatapos na ito ay maitakda na. Ngunit mayroon pang ibang mga tampok na nawawala, katulad ng muling pagpapadala ng imbitasyon sa na nawala sa email, muling pagtatakda ng pagpupulong ng ganap, o kaya ang kawalan ng kakayahan na Makita at mabago ang mga setting ng control na pinili ng tagapag-organisa.  

Kawili-wiling nasimulan kong mapagtanto na ang kakayahan na maiayos ang mga pagpupulong nang madali pagkatapos na ito ay maitakda ay maaaring makabuo o makasire ng tatak ng Tagaplano ng Pagpupulong. Halimbawa, madaming pakikipagkapwang pag-iininyero sa pag-aayos ng katatapos itakdang pagpupulong.  Madalas, kailangan mong itanong sa (mga) kalahok kung ayos lamang na baguhin ang oras o lugar. Maaaring gusto mo lamang magpulong ng mas maaaga ng 15 minuto o kaya sa susunod na araw sa parehong oras at lugar. Ngunit hindi mo maaaring laging gawin ang mga pagbabagong ito ng walang pahintulot.  

Ang pagpapanatiling madaling intindihin at payak gamitin ang site kasama ang lahat ng kakayahan nito ang aking pangunahing direktiba.  Paano ako makakapagdagdag ng pataas na bilang ng mga tampok nang hindi kakalat ang interface ng gagamit o hindi masyadong itatago ang mga ito. Paano ito gagana sa interface ng parehong mobile at desktop?

Sa tutoryal ngayon, tatalakayin ko ang pagpapalawak ng bar ng nabigasyon sa pamamagitan ng paggamit ng Bootstrap at ang mga batayan ng paggawa ng ilan sa mga paunang mga tampok ng pag-iiskedyul sa loob ng Tagaplano ng Pagpupulong. Sa susunod na lingo, irerepaso ko ang paggawa ng mas kumplikadong tampok para sa mga kalahok na hihiling ng (mga) pagbabago at para sa iba na tatanggap o tatanggi sa mga ito. 

Inaasahan ko na susubukan ninyo lahat ng bagong tampok sap ag-iiskedyul sa live na site at ibabahagi ninyo ang inyong mga saloobin at katugunan sa mga komento sa ibaba.  Kung mayroon kayong mga katanungan tungkol sa tutoryal o aplikasyon nito, ako ay sumasagot sa talakayan sa ibaba, at maaari din kayong makipag-ugnayan sa akin sa @reifman sa Twitter. Ako ay laging bukas para sa mga bagong tampok na ideya para sa Meeting Planner at pati na rin sa mga mungkahi para sa mga susunod na episode ng mga serye.

Bilang paalala, ang lahat ng mga code para sa Meeting Planner ay nakasulat sa Yii2 Framework para sa PHP. Kung gusto mong matuto nang iba pa tungkol sa Yii2, tingnan ang aming parallel series Programming Sa Yii2.

Pagpapalawak sa Bar ng Nabigasyon

Una, tingnan nating kung paano palawakin ang umiiral ng bar ng nabigasyon. Heto ang listahan ng mga tampok na balak kong idagdag:

  • Pagpayag na magbago ang mga lugar, petsa at oras ng pagpupulong pagkatapos na ito ay matapos. 
  • Paghiling ng maliliit ng mga pagbabago sa pagpupulong, katulad ng maaari ba tayong magkita ng mas maaga ng isang oras? O kaya ay sa ibang iminungkahing lugar? 
  • Paglilipat ng iskedyul ng mismong pagpupulong na pareho ang mga kalahok at mga  lugar. 
  • Pag-uulit ng pagpupulong gamit ang mga kalahok, mga lugar, mga araw ng lingo at mga oras ng araw mula sa nakaraang pagpupulong upang mapadali ang pag-iiskedyul ng bagong pagpupulong.
  • Pagpapakita sa mga kalahok ng sunod-sunod na kasaysayan ng lahat ng mga aktibidad sa pagpaplano para sa pagpupulong. 
  • Pagtingin at pag-update sa mga setting para sa pagpupulong.

Katulad ng nakikita niyo, hindi lamang mayroong maraming pagpapaandar na kailangang gawin, ngunit wala rin akong malinaw na sapantaha kung saan ito ilalagay sa interface ng gagamit nang hindi lilikha ng gulo. 

Ang bar ng utos at kailangan ding magbago nang ayon sa kalagayan ng pagpupulong. Ang mga pagpupulong na nasa pagpaplanong bahagi ay may ibang mga pagpipilian sa nakabitin, kumpirmado o nakalipas na tapos ng mga pagpupulong. 

Naunang mga UX na Ideya na Nagdala pabalik sa Bootstrap

Ang unang ideya ko ay magbigay ng maliit na link ng Paunang mga Setting na magpapakita sa nakatagong bar ng utos. Nag-eksperimento dito sa simula, ngunit hindi ito kalugod-lugod tingnan. 

Tapos, nirepaso ko ang dokumentasyon ng Bootstrap at natagpuan ko ang dropdown combo na kahon:

Build Your Startup Advanced Scheduling - Bootstrap Documentation of DropdownBuild Your Startup Advanced Scheduling - Bootstrap Documentation of DropdownBuild Your Startup Advanced Scheduling - Bootstrap Documentation of Dropdown

Nagustuhan ko kung paano ito umandar. Kaya nagpasya ako na ilagay ang karamihan sa mga paunang utos sa nakaayos sa kaliwa na dropdown na button.

Heto ang halimbawa kung ano ang hitsura nito sa pagpaplanong bahagi ng pagpupulong:

Build Your Startup Advanced Scheduling - Meeting Planner Button Dropdown Build Your Startup Advanced Scheduling - Meeting Planner Button Dropdown Build Your Startup Advanced Scheduling - Meeting Planner Button Dropdown

Pansinin na ang bootstap ay nag-aalok ng uri ng mga dropup na menu. Ang bar ng utos na nakalagay sa ilalim ng pahina ay gumagamit ng dropup katulad ng sumusunod: 

1
/* the partial position knows to set the dropclass variable up or down */
2
echo $this->render('_command_bar_past', [
3
    'model'=>$model,
4
    'isPast'=>true,
5
    'dropclass'=>'dropup',
6
    'isOwner' => $isOwner,
7
]);
8
9
/* the resulting view applies the dropclass */
10
<div class="command-bar">
11
  <div class="row">
12
    <div class="col-xs-4">
13
      <div class="<?= $dropclass ?>" >
14
      <button class="btn btn-default dropdown-toggle" type="button" id="dropdownMenu1" data-toggle="dropdown" aria-haspopup="true" aria-expanded="true">
15
      <?= Yii::t('frontend','Options');?>
16
      <span class="caret"></span>
17
      </button>
18
      <ul class="dropdown-menu" aria-labelledby="dropdownMenu1">
19
        <?php
20
          if (!$isPast && ($model->viewer == Meeting::VIEWER_ORGANIZER || $meetingSettings->participant_reopen)) {
21
            ?>
22
            <li><?= Html::a(Yii::t('frontend', 'Make changes'), ['reopen','id'=>$model->id],
23
             ['title'=>Yii::t('frontend','tbd')]); ?></li>

Lumikha din ako ng paunang kita sa mga file na gagawin ayon sa kalagayan ng pagpupulong. Halimbawa sa /frontend/views/meeting/view_confirmed.php, makikita niyo kahit alin sa _command_bar_past.php_command_bar_confirmed.php kasama ang paunang bahagi: 

1
<?php
2
    if ( $model->status >= $model::STATUS_COMPLETED) {
3
      ...
4
      echo $this->render('_command_bar_past', [
5
          'model'=>$model,
6
          'isPast'=>true,
7
          'dropclass'=>'dropdown',
8
          'isOwner' => $isOwner,
9
      ]);
10
    } else {
11
      echo $this->render('_command_bar_confirmed', [
12
          'model'=>$model,
13
          'meetingSettings' => $meetingSettings,
14
          'showRunningLate'=>$showRunningLate,
15
          'isPast'=>$isPast,
16
          'dropclass'=>'dropdown',
17
          'isOwner' => $isOwner,
18
      ]);
19
    }
20
  ?>

Pag-alam ng Access sa mga Utos para sa Iba’t ibang Titingin 

Hindi ko gusto payagan lahat na makita ang lahat ng mg utos. Ang mga taga-organisa ay makakakita ng mas maraming mg autos kaysa sa mga kalahok, ngunit ang mga setting ng pagpupulong ay kadalasang binibigyan din sila ng access. 

Heto ang halimbawa ng pag-alam kung ipapakita ang pagpipilian upang muling mabuksan ang pagpupulong at gumawa ng mga pagbabago dito na parang nasa pagpaplanong bahagi pa din ito:

1
<ul class="dropdown-menu" aria-labelledby="dropdownMenu1">
2
  <?php
3
    if (!$isPast && ($model->viewer == Meeting::VIEWER_ORGANIZER
4
       || $meetingSettings->participant_reopen)) {
5
   ?>
6
      <li><?= Html::a(Yii::t('frontend', 'Make changes'), ['reopen','id'=>$model->id],
7
          ['title'=>Yii::t('frontend','tbd')]); ?></li>
8
        

Ang pagpipilian ay kabilang sa dropdown na menu ng Bootstrap kung ang pagpupulong ay hindi pa lumalampas sa simulang petsa nito at ang titingin ay ang taga-organisa o pinayagan ng taga-organisa ang mga kalahok na gumawa ng mga pagbabago. 

Ngayon, pumunta na tayo sa paggawa ng ilan sa mga pagpapaandar para sa iba’t ibang mga utos na ito. 

Paggawa ng Paunang mga Utos sa Pag-iiskedyul 

Hindi possible na matalakay ang lahat sa bagong gawain na kasama nitong mga tampok sa pag-iiskedyul. Para sa kaiksian, tatalakayin ko lamang ang mga batayan at kahit anong walang kaparehong aspeto ng iba’t-ibang mg autos. 

Bawat Tampok ay Mas Matagal na Ngayon 

Pagkatapos ng pagpapatupad ng mas malalalim na tampok sa seguridad sa loob ng Tagaplano ng Pagpupulong, sinubukan kong umayon sa mas mahigpit na pamantayan sa pagkokodigo habang nagdadagdag ako ng mga bagong tampok. Gumugugol ako ng mas maraming oras sa access ng nagkokontrol, pagsusuri ng modelong access, at pagtatakda ng bilis. 

Gayundin, ang beta na inilabas ay susuporta sa madaming mga kalahok sa pagpupulong, kaya kailangan kong iarkitekto ang code na iyon ang nasa isip habang gumagawa ako. 

Sa kabuuan, lahat ng ginagawa ko ay medyo mas matagal kaysa noong sa mabilis na tularang paraan.

Habang ginagawa ko ang iba’t ibang mga tampok sa pagpupulong na ito, madalas kong maramdaman ang lumaking trabaho na idinagdag ko sa codebase. Mapapansin niyo ang mga tsek na ito sa code sa ibaba.

Mayroon ding atensyon sa tala ng makasaysayang Pagpupulong na gagawin na naming nakikita. Kaya lahat ng aksyon ay madalas nangangailangan ng talaan. At ang mga talaan ay makakatulong sa pagsuporta sa pagtatakda ng bilis. 

Paglikha ng mga Pagbabago sa Pagpupulong 

Isang madaling paraan upang payagan ang mga pagbabago sa pagpupulong na natapos na ay ang payagan lamang ang taga-organisa na muling makapagbukas nito, ibalik ito sa pagpaplanong bahagi. Tapos, maaari nilang idagdag ang petsa, oras at lugar, pumili ng bago, at tapusing mula ang pagpupulong. 

Gusto ko ding magbigay ng kapangyarihan ang taga-organisa sa kanilang mga kalahok upang gawin ito. Nangangailangan ito sa katapusan ng pagbuo ng kakayahan upang makita at maupdate bawat mga setting ng pagpupulong. 

Nagdagdag ako ng mga setting upang payagan ang mga kalahok alinman sa humiling ng mga pagbabago sa taga-organisa o kaya ay gawin ang mga ito ng direkta. 

Kapag ang pagpupulong ay nilikha, ang mga setting ay sinimulan sa nakatakdang mga setting ng gumagamit: 

1
public function initializeMeetingSetting($meeting_id,$owner_id) {
2
  $checkMtgStg = MeetingSetting::find()->where(['meeting_id' => $meeting_id])->one();
3
  if (is_null($checkMtgStg)) {
4
    // load meeting creator (owner) user settings to initialize meeting_settings

5
    UserSetting::initialize($owner_id); // if not initialized

6
    $user_setting = UserSetting::find()->where(['user_id' => $owner_id])->one();
7
    $meeting_setting = new MeetingSetting();
8
    $meeting_setting->meeting_id = $meeting_id;
9
    $meeting_setting->participant_add_place=$user_setting->participant_add_place;
10
    $meeting_setting->participant_add_date_time=$user_setting->participant_add_date_time;
11
    $meeting_setting->participant_choose_place=$user_setting->participant_choose_place;
12
    $meeting_setting->participant_choose_date_time=$user_setting->participant_choose_date_time;
13
    $meeting_setting->participant_finalize=$user_setting->participant_finalize;
14
    $meeting_setting->participant_reopen=$user_setting->participant_reopen;
15
    $meeting_setting->participant_request_change=$user_setting->participant_request_change;
16
    $meeting_setting->save();
17
  }
18
}

Makikita mo ang mga resulta ng bagong tagakontrol at maia-update ang makikita para sa MeetingSettings sa ibaba:

Build Your Startup Advanced Scheduling - Meeting SettingsBuild Your Startup Advanced Scheduling - Meeting SettingsBuild Your Startup Advanced Scheduling - Meeting Settings

At heto/ frontend/controllers/MeetingController.php's actionReopen():

1
public function actionReopen($id) {
2
  $m = $this->findModel($id);
3
  $m->setViewer();
4
  // also check reopen()

5
  if ($m->viewer == Meeting::VIEWER_ORGANIZER || $m->meetingSettings->participant_reopen) {
6
    if ($m->reopen()) {
7
        Yii::$app->getSession()->setFlash('success', Yii::t('frontend','The meeting has now been reopened so you can make changes.'));
8
    } else {
9
        Yii::$app->getSession()->setFlash('error', Yii::t('frontend','Sorry, you are not allowed to reopen a meeting this many times. Try creating a new meeting.'));
10
    }
11
  } else {
12
    Yii::$app->getSession()->setFlash('error', Yii::t('frontend','Sorry, you are not allowed to do this.'));
13
  }
14
  return $this->redirect(['view', 'id' => $id]);
15
}

At heto ang Meeting.php na modelong code upang ilipat ang pagpupulong pabalik sa pagpaplanong bahagi: 

1
public function reopen() {
2
  // when organizer or participant with permission asks to make changes

3
  if (MeetingLog::withinActionLimit($this->id,MeetingLog::ACTION_REOPEN,Yii::$app->user->getId(),7)) {
4
    $this->status = Meeting::STATUS_SENT;
5
    $this->update();
6
    $this->increaseSequence();
7
    MeetingLog::add($this->id,MeetingLog::ACTION_REOPEN,Yii::$app->user->getId());
8
    return true;
9
  } else {
10
    // over limit per meeting

11
    return false;
12
  }
13
}

Ang withinActionLimit ay pagsusuri sa bilang ng pagkakataon na sinubukang buksan ng isang tao ang pagpupulong. Ang IncreaseSequence ay para sa .ics na file—habang nagbabago ang petsa, oras at lugar ng pagpupulong, ang ics na file ay kailangang masabihan. 

Ang larawan sa ibaba ay nagpapakita ng pagpupulong na nakumpirma na mayroong iba’t ibang paunang mga pagpipilian na makikita: 

Build Your Startup Advanced Scheduling - Command bar with fully loaded Dropdown menuBuild Your Startup Advanced Scheduling - Command bar with fully loaded Dropdown menuBuild Your Startup Advanced Scheduling - Command bar with fully loaded Dropdown menu

Kapag pinindot ng gumagamit ang Make Changes sa menu sa itaas, ang kalagayan ng papupulong ay lilipat pabalik sa pagpaplano at maaari silang bumalik upang iupdate ang petsa, orast at lugar: 

Build Your Startup Advanced Scheduling - Reopened Meeting PlanningBuild Your Startup Advanced Scheduling - Reopened Meeting PlanningBuild Your Startup Advanced Scheduling - Reopened Meeting Planning

Paglilipat ng Oras ng Pagpupulong 

Kapag ang mga pangyayari ay nagpangyari upang matanto ng mga kalahok na kailangan nilang magsimula miuli, ang Reschedule na pagpipilian ang mag-uurong sa kasalukuyang pagpupulong at lilikha ng imbitasyon sa bagong pagpaplano. 

Sa kasalukuyan, hinihigpitan ko ang tampok na ito sa mga taga-organisa (hindi sa mga kalahok), ngunit maaari koi tong palawigin sa susunod. Ang Meeting.php::Reschedule() na paraan ay sumusuporta alinman sa taong gumagawa ng aksyon: 

1
    public function reschedule() {
2
      $newOwner = $user_id = Yii::$app->user->getId();
3
      // user can only cancel their own Meeting

4
      if ($this->owner_id == $user_id) {
5
        $addParticipant = false;
6
        $this->cancel($user_id);
7
        MeetingLog::add($this->id,MeetingLog::ACTION_RESCHEDULE,$user_id);
8
      } else {
9
          // if user is participant - needs to reverse

10
          if (!isAttendee($this->id,$user_id)) {
11
            // user isn't owner or participant - error

12
            return false;
13
          } else {
14
            // reverse the owner and participant

15
            $addParticipant = $this->owner_id;
16
          }
17
      }
18
      // create new meeting - as copy of old meeting

19
      $m = new Meeting();
20
      $m->attributes = $this->attributes;
21
      $m->owner_id = $newOwner;
22
      $m->status = Meeting::STATUS_PLANNING;
23
      $m->created_at = time();
24
      $m->updated_at = time();
25
      $m->logged_at = 0;
26
      $m->cleared_at = 0;
27
      $m->sequence_id = 0;
28
      $m->save();
29
      // clone the selected place (not all of them)

30
      $chosenPlace = $this->getChosenPlace($this->id);
31
      if ($chosenPlace!==false) {
32
        $mp = new MeetingPlace;
33
        $mp->suggested_by = $newOwner;
34
        $mp->attributes = $chosenPlace->attributes;
35
        $mp->meeting_id = $m->id;
36
        $mp->created_at = time();
37
        $mp->updated_at = time();
38
        $mp->save();
39
      }
40
      // clone the participants

41
      foreach ($this->participants as $p) {
42
        // skip if reschedule new owner was a participant

43
        if ($p->participant_id==$user_id) {
44
          continue;
45
        }
46
        // note Participant afterSave will create choices for place

47
        $clone_p = new Participant();
48
        $clone_p->attributes = $p->attributes;
49
        $clone_p->email = User::findOne($p->participant_id)->email;
50
        $clone_p->meeting_id = $m->id;
51
        $clone_p->invited_by = $newOwner;
52
        $clone_p->status = Participant::STATUS_DEFAULT;
53
        $clone_p->created_at = time();
54
        $clone_p->updated_at = time();
55
        $clone_p->save();
56
      }
57
      // if participant asked to reschedule - not yet allowed

58
      if ($addParticipant!==false) {
59
        $newP = new Participant();
60
        $newP->meeting_id = $m->id;
61
        $newP->participant_id = $addParticipant;
62
        $newP->invited_by = $user_id;
63
        $newP->status = Participant::STATUS_DEFAULT;
64
        $newP->created_at = time();
65
        $newP->updated_at = time();
66
        $newP->save();
67
      }
68
      return $m->id;
69
    }

Ang mga kalahot at ang napiling lugar ay makokopya sa bagong pagpupulong. 

Pag-uulit ng Pagpupulong 

Isa pang paraan sap ag-iiskedyul ay ang payagan ang mga kalahok na kopyahin ang mga nakaraang pagpupulong. Sa hinaharap, maaari kong hayaan ang tumitingin na magpasya kung sinong mga kalahok, mga lugar at mga oras ang kokopyahin, pero sa ngayon, ang Tagaplano ng Pagpupulong ang lumilikha ng bagong pagpupulong na may parehong mga kalahok at sa parehong lugar—at sa parehong araw ng linggo at oras ng unang araw at dalawang linggo sa hinaharap. 

1
public function repeat() {
2
      // to do - expand repeat meeting to have more options

3
      // e.g. pick same day and time in future week or two

4
      // e.g. duplicate chosenplace or all places

5
      // e.g. duplicate all participants or just some (complicated if participant duplicates)

6
      $newOwner = $user_id = Yii::$app->user->getId();
7
      // if user is participant - needs to reverse

8
      if ($this->owner_id == $user_id) {
9
        $addParticipant = false;
10
      } else {
11
        if (!isAttendee($this->id,$user_id)) {
12
          // user isn't owner or participant - error

13
          return false;
14
        } else {
15
          // reverse the owner and participant

16
          $addParticipant = $this->owner_id;
17
        }
18
      }
19
      // create new meeting - as copy of old meeting

20
      $m = new Meeting();
21
      $m->attributes = $this->attributes;
22
      $m->owner_id = $newOwner;
23
      $m->status = Meeting::STATUS_PLANNING;
24
      $m->created_at = time();
25
      $m->updated_at = time();
26
      $m->logged_at = 0;
27
      $m->cleared_at = 0;
28
      $m->sequence_id = 0;
29
      $m->save();
30
      // get prior meetings selected time and create two future times for the next two weeks

31
      $chosenTime=$this->getChosenTime($this->id);
32
      $mt1 = MeetingTime::createTimePlus($m->id,$m->owner_id,$chosenTime->start,$chosenTime->duration);
33
      $mt2 = MeetingTime::createTimePlus($m->id,$m->owner_id,$mt1->start,$chosenTime->duration);
34
      // clone the selected place (not all of them)

35
      $chosenPlace = $this->getChosenPlace($this->id);
36
      if ($chosenPlace!==false) {
37
        $mp = new MeetingPlace;
38
        $mp->suggested_by = $newOwner;
39
        $mp->attributes = $chosenPlace->attributes;
40
        $mp->meeting_id = $m->id;
41
        $mp->created_at = time();
42
        $mp->updated_at = time();
43
        $mp->save();
44
      }
45
      // clone the participants

46
      foreach ($this->participants as $p) {
47
        // skip if reschedule new owner was a participant

48
        if ($p->participant_id==$user_id) {
49
          continue;
50
        }
51
        // note Participant afterSave will create choices for place

52
        $clone_p = new Participant();
53
        $clone_p->attributes = $p->attributes;
54
        $clone_p->email = User::findOne($p->participant_id)->email;
55
        $clone_p->meeting_id = $m->id;
56
        $clone_p->status = Participant::STATUS_DEFAULT;
57
        $clone_p->created_at = time();
58
        $clone_p->updated_at = time();
59
        $clone_p->save();
60
      }
61
      // if participant asked to repeat

62
      // add the prior owner as a participant

63
      if ($addParticipant!==false) {
64
        $newP = new Participant();
65
        $newP->meeting_id = $m->id;
66
        $newP->participant_id = $addParticipant;
67
        $newP->invited_by = $user_id;
68
        $newP->status = Participant::STATUS_DEFAULT;
69
        $newP->created_at = time();
70
        $newP->updated_at = time();
71
        $newP->save();
72
      }
73
      MeetingLog::add($this->id,MeetingLog::ACTION_REPEAT,$user_id,0);
74
      return $m->id;
75
    }

MeetingTime::createTimePlus() idinagdag sa ibaba ang Oras ng Pagpupulong sa parehong araw ng linggo at oras ng araw, ngunit isang linggo sa hinaharap, kahit na ang orihinal na pagpupulong ay naganap ilang buwan na ang nakalipas. Ang while loop ay kinakailangan para sa mga mas nauna pang mga pagpupulong. 

1
    public static function createTimePlus($meeting_id,$suggested_by,$start,$duration,$timeInFuture = 604800) {
2
      // finds time in multiples of a week or timeInFuture seconds ahead past the present time

3
      $newStart = $start+$timeInFuture;
4
      while ($newStart<time()) {
5
        $newStart+=$timeInFuture;
6
      }
7
      $mt = new MeetingTime();
8
      $mt->meeting_id = $meeting_id;
9
      $mt->start = $newStart;
10
      $mt->duration = $duration;
11
      $mt->end = $mt->start+($mt->duration*3600);
12
      $mt->suggested_by = $suggested_by;
13
      $mt->status = MeetingTime::STATUS_SUGGESTED;
14
      $mt->updated_at = $mt->created_at = time();
15
      $mt->save();
16
      return $mt;
17
    }

Muling Pagpapadala ng mga Imbitasyon 

Gumawa din ako ng muling pagpapadala na tampok kung sakaling ang kalahok ay hindi nakatanggap ng orihinal na imbitasyon o huling kumpirmasyon. 

1
public static function resend($id) {
2
      $sender_id = Yii::$app->user->getId();
3
      // check if within resend limit

4
      $cnt = MeetingLog::find()
5
        ->where(['actor_id'=>$sender_id])
6
        ->andWhere(['meeting_id'=>$id])
7
        ->andWhere(['action'=>MeetingLog::ACTION_RESEND])
8
        ->count();
9
      if ($cnt >= Meeting::RESEND_LIMIT ) {
10
        return false;
11
      } else {
12
        $m = Meeting::findOne($id);
13
        if ($m->status == Meeting::STATUS_SENT) {
14
          $m->send($sender_id,true);
15
          // resend the planning invitation

16
        } else if ($m->status == Meeting::STATUS_CONFIRMED) {
17
          // resend the confirmed invitation

18
          $m->finalize($sender_id,true);
19
        }
20
        MeetingLog::add($id,MeetingLog::ACTION_RESEND,$sender_id,0);
21
        return true;
22
      }
23
    }

Balak kong muling gawin ang papalabas na email na pagpapaandar na gagana nang hindi kasabay at gagawing madali ang muling pagpapadala, ngunit sa kapalaran ang kasalukuyang mga paraan ay gumagana ng maayos sa eksena ng muling pagpapadala nang may kaunting mga pagbabago. 

Kasaysayan ng Pagpupulong 

Sa kabuuan ng serye, gumawa tayo ng tala ng bawat pagbabagong ginawa sa mga pagpupulong. Walang paraan upang makita ng mga dumalo ang kasaysayan ng pagpaplano. Ganito ang hitsura nito: 

Build Your Startup Advanced Scheduling - Viewing the meeting history of eventsBuild Your Startup Advanced Scheduling - Viewing the meeting history of eventsBuild Your Startup Advanced Scheduling - Viewing the meeting history of events

Ang MeetingLogController.php ang nagsusuri na ang tumitingin ay dumalo sa pagpupulong at gumagawa ng datos para sa tala ng pagtingin: 

1
public function actionView($id)
2
    {
3
      if (!Meeting::isAttendee($id,Yii::$app->user->getId())) {
4
        $this->redirect(['site/authfailure']);
5
      }
6
      $timezone = MiscHelpers::fetchUserTimezone(Yii::$app->user->getId());
7
      Yii::$app->timeZone = $timezone;
8
      	$searchModel = new MeetingLogSearch();
9
      $dataProvider = $searchModel->search(['MeetingLogSearch'=>['meeting_id'=>$id]]);
10
      $m= Meeting::findOne($id);
11
      return $this->render('index', [
12
          'searchModel' => $searchModel,
13
          'dataProvider' => $dataProvider,
14
          'meeting_id' => $id,
15
          'subject' => $m->getMeetingHeader('log'),
16
          'timezone' => $timezone,
17
      ]);
18
    }

Tapos ang /frontend/views/meeting-log/index.php ang gumagawa ng mga datos na ipinapakita sa itaas: 

1
<?php Pjax::begin(); ?>
2
<div class="meeting-log-index">
3
    <h1><?php echo  Html::encode($this->title) ?></h1>
4
5
    <?php echo GridView::widget([
6
    'dataProvider' => $dataProvider,
7
    //'filterModel' => $searchModel,

8
    'columns' => [
9
        [
10
          'label'=>'Actor',
11
            'attribute' => 'actor_id',
12
            'format' => 'raw',
13
            'value' => function ($model) {
14
                    return '<div>'.MiscHelpers::getDisplayName($model->actor_id).'</div>';
15
                },
16
        ],
17
        [
18
          'label'=>'Action',
19
            'attribute' => 'action',
20
            'format' => 'raw',
21
            'value' => function ($model) {
22
                  return '<div>'.$model->getMeetingLogCommand().'</div>';
23
                },
24
        ],
25
        [
26
          'label'=>'Item',
27
            'attribute' => 'item_id',
28
            'format' => 'raw',
29
            'value' => function ($model) {
30
                        return '<div>'.$model->getMeetingLogItem().'</div>';
31
                },
32
        ],
33
        [
34
          'label'=>'Created',
35
            'attribute' => 'created_at',
36
            'format' => 'raw',
37
            'value' => function ($model) {
38
                        return '<div>'.Yii::$app->formatter->asDatetime($model->created_at,"hh:ss MMM d").'</div>';
39
                },
40
        ],
41
    ],
42
]);
43
?>
44
<?= Html::a(Yii::t('frontend', 'Return to Meeting'), ['meeting/view', 'id' => $meeting_id],
45
 ['class' => 'btn btn-primary  btn-info',
46
 'title'=>Yii::t('frontend','Return to meeting page'),
47
]); ?>
48
<?php Pjax::end(); ?>

Anong Kasunod? 

Ngayon ay nasa matinding code sprint ako upang makupleto ang paglabas ng beta.  Ang mga diyos ng editorial sa Envato Tuts+ ay sinikap ang kanilang pinakamahusay upang abalahin ako sa pamamagitan ng mga robot na nagkokontrol sa isip at parang OKCupid na mga tunog mula sa kanilang mga daloy ng trabaho na aplikasyon na pinagana ng Ios, ngunit nabigo sila. Ang Tagaplano ng Pagpupulong ay patuloy na umuunlad sa mabilis na lakad.

Ang paglutas ng pakikipagkapwang pag-iininyero at UX para sa mga dadalo ng pagpupulong na hihiling at tutugon sa mas maliliit na pag-aayos sap ag-iiskedyul ay maaaring makabuo o makasira ng tatak ng Tagaplano ng Pagpupulong, at iyan kung ano ang pinakapinagtatrabahuhan ko.

Kung hindi pa kayo, halina iiskedyul na ang inyong unang pagpupulong sa pamamagitan ng Tagaplano ng Pagpupulong. Balak ko din magsulat ng tutoryal tungkol sa pagpopondo sa karamihan ng tao, kaya pakisaalang-alang ang sumusunod na WeFunder na Tagaplano ng Pagpupulong Planner na pahina.  Maaari din kayong lumapit sa akin @reifman. Lagi akong bukas sa mga bagong ideya ng tampok at mga mungkahing paksa para sa mga tutoryal sa hinaharap. 

Manatiling nakatutok para sa lahat ng ito at marami pang darating ng mga tutoryal sa pamamagitan ng pagtingin sa Paggawa ng Inyong Panimula na may PHP na serye.

Related Links

Advertisement
Did you find this post useful?
Want a weekly email summary?
Subscribe below and we’ll send you a weekly email summary of all new Web Design tutorials. Never miss out on learning about the next big thing.
Advertisement
Looking for something to help kick start your next project?
Envato Market has a range of items for sale to help get you started.