Uw startup opbouwen personen informeren over updates van vergaderingen

Wat je gaat creëren

Deze tutorial maakt deel uit van de Build Your Startup With PHP-serie op Envato Tuts +. In deze serie begeleid ik je door een opstart van concept naar realiteit te starten met behulp van mijn Meeting Planner-app als een realistisch voorbeeld. Elke stap die ik doe, zal ik de Meeting Planner-code vrijgeven als open-source voorbeelden waar je van kunt leren. Ik zal ook opstartgerelateerde zakelijke problemen aanpakken zodra deze zich voordoen.

In deze tweedelige serie zal ik beschrijven hoe we de infrastructuur voor meldingen en de levering ervan hebben gebouwd. Vandaag zal ik me concentreren op het MeetingLog om wijzigingen bij te houden die ons helpen bepalen wanneer updates moeten worden verzonden.

Als u Meeting Planner nog niet hebt uitgeprobeerd, kunt u uw eerste vergadering plannen. Ik neem wel deel aan de opmerkingen hieronder, dus vertel me wat je denkt! Ik ben vooral geïnteresseerd als u nieuwe functies of onderwerpen voor toekomstige zelfstudies wilt voorstellen.

Ter herinnering: alle code voor Meeting Planner is geschreven in het Yii2 Framework voor PHP. Als je meer wilt weten over Yii2, bekijk dan onze parallelle serie Programming With Yii2.

Mijn visie voor meldingen

Dit is wat een vergadermedewerker meestal ziet wanneer ze een uitnodiging ontvangen. Ze delen hun beschikbaarheid voor plaatsen en tijden en kiezen soms de laatste selecties:

Wanneer een deelnemer aan een vergadering reageert op een uitnodiging zoals hierboven, kunnen ze een handvol wijzigingen aanbrengen. Bijvoorbeeld:

  • Deze datum en tijd werken, deze twee niet.
  • Deze plaats werkt, deze niet, laten we ook deze extra overwegen.
  • Ik kies deze plaats en deze keer.
  • Voeg een notitie toe: "Ik ben blij dat we eindelijk samen zijn."

Nadat de wijzigingen zijn aangebracht, moeten we de organisator op de hoogte stellen.

Ons doel is om de planning van vergaderingen te vereenvoudigen en het aantal e-mails te verminderen. Als we een paar minuten wachten nadat de persoon wijzigingen aanbrengt en de wijzigingen samenvoegt tot één update, is dat waarschijnlijk een goed moment om de melding te bezorgen. Maar hoe bouwen we code die dat doet? Hoe houden we bij welke wijzigingen we hebben aangebracht en spellen we dit uit voor de organisator?

Een ander idee dat ik had was om de noodzaak om op submit te klikken weg te nemen als je klaar bent met het aanbrengen van wijzigingen. Ten eerste zou dit enige gebruikersvoorlichting vereisen om hen te verzekeren dat we hun wijzigingen zullen verzenden wanneer ze klaar zijn. Maar we hadden ook een manier nodig om te weten wanneer het goed was om de wijzigingen aan de organisator te bezorgen.

Hoe meldingen werken

De vereisten worden opnieuw geformuleerd en samengevat, hier is hoe meldingen werken: 

Alle acties met betrekking tot vergaderingen worden bewaard in ons MeetingLog-model. Maar we hebben een manier nodig om een ​​tekstueel overzicht van het logboek te maken om met de deelnemers te delen. Mogelijk willen we alleen de wijzigingen weergeven die zijn opgetreden sinds de laatste update. Dus we zullen dat moeten volgen.

Aangezien de persoon wijzigingen in de vergadering aanbrengt, geven we visueel aan dat het niet nodig is om op een niet-bestaande knop voor het indienen of opslaan van wijzigingen te klikken.

We willen controleren wanneer wijzigingen enkele minuten oud zijn en deze samenvoegen tot een enkele update voor de andere deelnemer of organisator.

En tot slot moeten we de e-mailupdate alleen aan de andere deelnemer (s) leveren, niet degene die de wijzigingen heeft doorgevoerd. Of, als beide deelnemers gedurende deze tijd wijzigingen hebben aangebracht, moeten we alle acties van de ander alleen melden.

Het vergaderlogboek samenstellen

Vanaf het begin wilde ik een compleet overzicht van de acties die werden uitgevoerd bij het plannen van vergaderingen om een ​​aantal redenen. Misschien willen mensen de planningsgeschiedenis zien of terugkeren naar een bepaald moment, maar het is ook nuttig voor foutopsporing. Het bleek ook nodig om te weten wanneer updates over wijzigingen in de vergadering moeten worden bezorgd.

Laten we de structuur achter het MeetingLog-model bekijken. Dit is de migratie die de tabel maakt:

class m141025_220133_create_meeting_log_table breidt Migration uit public function up () $ tableOptions = null; if ($ this-> db-> driverName === 'mysql') $ tableOptions = 'KARAKTER SET utf8 COLLATE utf8_unicode_ci ENGINE = InnoDB';  $ this-> createTable ('% meeting_log', ['id' => Schema :: TYPE_PK, 'meeting_id' => Schema :: TYPE_INTEGER. 'NOT NULL', 'action' => Schema :: TYPE_INTEGER. 'NOT NULL', 'actor_id' => Schema :: TYPE_BIGINT. 'NOT NULL', 'item_id' => Schema :: TYPE_INTEGER. 'NOT NULL', 'extra_id' => Schema :: TYPE_INTEGER. 'NOT NULL ',' created_at '=> Schema :: TYPE_INTEGER.' NOT NULL ',' updated_at '=> Schema :: TYPE_INTEGER.' NOT NULL ',], $ tableOptions); $ this-> addForeignKey ('fk_meeting_log_meeting', '% meeting_log', meeting_id ',' % meeting ',' id ',' CASCADE ',' CASCADE '); $ this-> addForeignKey ('fk_meeting_log_actor', '% meeting_log', 'actor_id', '% user', 'id', 'CASCADE', 'CASCADE'); 

De essentiële elementen die we opnemen zijn:

  • De MEETING_ID vertelt ons welke vergadering we volgen.
  • De actie vertelt ons wat er is gedaan.
  • De actor_id vertelt ons wie de actie heeft uitgevoerd (bijv. gebruikersnaam).
  • De overbelaste item ID kan een tijd vertegenwoordigen, een plaats een notitie.
  • De extra_id is voor het opnemen van andere informatie, afhankelijk van de actie.
  • gemaakt bij vertelt ons wanneer de actie werd uitgevoerd.

Vervolgens heb ik constanten gedefinieerd voor alle acties zoals ACTION_SUGGEST_PLACE of ACTION_ADD_NOTE, enz.

class MeetingLog breidt \ yii \ db \ ActiveRecord const ACTION_CREATE_MEETING = 0; const ACTION_EDIT_MEETING = 3; const ACTION_CANCEL_MEETING = 7; const ACTION_DELETE_MEETING = 8; const ACTION_DECLINE_MEETING = 9; const ACTION_SUGGEST_PLACE = 10; const ACTION_ACCEPT_ALL_PLACES = 11; const ACTION_ACCEPT_PLACE = 12; const ACTION_REJECT_PLACE = 15; const ACTION_SUGGEST_TIME = 20; const ACTION_ACCEPT_ALL_TIMES = 21; const ACTION_ACCEPT_TIME = 22; const ACTION_REJECT_TIME = 25; const ACTION_INVITE_PARTICIPANT = 30; const ACTION_ADD_NOTE = 40; const ACTION_SEND_INVITE = 50; const ACTION_FINALIZE_INVITE = 60; const ACTION_COMPLETE_MEETING = 100; const ACTION_CHOOSE_PLACE = 110; const ACTION_CHOOSE_TIJD = 120; const ACTION_SENT_CONTACT_REQUEST = 150; const TIMELAPSE = 300; // vijf minuten 

De methode voor het toevoegen maakt het gemakkelijk voor functionaliteit overal in de toepassing om activiteiten naar MeetingLog vast te leggen:

// toevoegen aan log openbare statische functie add ($ meeting_id, $ action, $ actor_id = 0, $ item_id = 0, $ extra_id = 0) $ log = new MeetingLog; $ Log> MEETING_ID = $ MEETING_ID; $ log-> actie = $ actie; $ log-> actor_id = $ actor_id; $ log-> item_id = $ item_id; $ log-> extra_id = $ extra_id; $ Log> save (); // stelt het touched_at-veld in voor de Meeting Meeting :: touchLog ($ meeting_id);  

Ik heb ook twee nieuwe velden toegevoegd aan de vergadertafel: logged_at en cleared_at. Wanneer logboekitems worden toegevoegd, werkt de vergadering het logged_at tijdstempel, het moment waarop de vergadering voor het laatst werd gewijzigd:

 openbare statische functie touchLog ($ id) $ mtg = Meeting :: findOne ($ id); $ mtg-> logged_at = time (); $ Mtg-> update ();  

Wanneer iemand bijvoorbeeld een nieuwe MeetingPlace-optie toevoegt, een afterSave evenement voegt toe aan het logboek, en dan natuurlijk Meeting-> logged_at is ook bijgewerkt:

openbare functie afterSave ($ insert, $ changedAttributes) parent :: afterSave ($ insert, $ changedAttributes); if ($ insert) // als MeetingPlace is toegevoegd // voeg MeetingPlaceChoice toe voor eigenaar en deelnemers $ mpc = new MeetingPlaceChoice; $ MPC> addForNewMeetingPlace ($ this-> MEETING_ID, $ this-> suggested_by, $ this-> id); MeetingLog :: toe te voegen ($ this-> MEETING_ID, MeetingLog :: ACTION_SUGGEST_PLACE, $ this-> suggested_by, $ this-> place_id);  

De logged_at de tijd vertelt ons wanneer de laatste verandering plaatsvond. De Meeting-> cleared_at De tijd zal ons vertellen wanneer we de laatste keer updates met deelnemers hebben gedeeld. Dus indien logged_at > cleared_at, we weten dat deelnemers niet volledig zijn bijgewerkt.

Een Engelstalige samenvatting maken

Vervolgens heb ik methoden ontwikkeld om het logboek te vertalen in een Engelstalige geschiedenis van wijzigingen in de vergadering. 

Eerst heb ik gemaakt getMeetingLogCommand () om een ​​tekstuele beschrijving van de actie te krijgen:

openbare functie getMeetingLogCommand () switch ($ this-> actie) case MeetingLog :: ACTION_CREATE_MEETING: $ label = Yii :: t ('frontend', 'create meeting'); breken; case MeetingLog :: ACTION_EDIT_MEETING: $ label = Yii :: t ('frontend', 'bewerk vergadering'); breken; case MeetingLog :: ACTION_CANCEL_MEETING: $ label = Yii :: t ('frontend', 'cancel meeting'); breken; case MeetingLog :: ACTION_DELETE_MEETING: $ label = Yii :: t ('frontend', 'cancel meeting'); breken; case MeetingLog :: ACTION_DELETE_MEETING: $ label = Yii :: t ('frontend', 'deleted meeting'); breken; case MeetingLog :: ACTION_SUGGEST_PLACE: $ label = Yii :: t ('frontend', 'plaats toevoegen'); breken; case MeetingLog :: ACTION_SUGGEST_TIME: $ label = Yii :: t ('frontend', 'add time'); breken; case MeetingLog :: ACTION_ADD_NOTE: $ label = Yii :: t ('frontend', 'note toevoegen'); breken; case MeetingLog :: ACTION_INVITE_PARTICIPANT: $ label = Yii :: t ('frontend', 'Deelnemer uitnodigen'); breken; case MeetingLog :: ACTION_ACCEPT_ALL_PLACES: $ label = Yii :: t ('frontend', 'accept all places'); breken; case MeetingLog :: ACTION_ACCEPT_PLACE: $ label = Yii :: t ('frontend', 'accept place'); breken; case MeetingLog :: ACTION_REJECT_PLACE: $ label = Yii :: t ('frontend', 'reject place'); breken; case MeetingLog :: ACTION_ACCEPT_ALL_TIMES: $ label = Yii :: t ('frontend', 'accept all times'); breken; case MeetingLog :: ACTION_ACCEPT_TIME: $ label = Yii :: t ('frontend', 'accept time'); breken; case MeetingLog :: ACTION_REJECT_TIME: $ label = Yii :: t ('frontend', 'reject time'); breken; case MeetingLog :: ACTION_CHOOSE_PLACE: $ label = Yii :: t ('frontend', 'choose place'); breken; case MeetingLog :: ACTION_CHOOSE_TIME: $ label = Yii :: t ('frontend', 'choose time'); breken; case MeetingLog :: ACTION_SEND_INVITE: $ label = Yii :: t ('frontend', 'Verzenden'); breken; case MeetingLog :: ACTION_FINALIZE_INVITE: $ label = Yii :: t ('frontend', 'Finalize'); breken; case MeetingLog :: ACTION_COMPLETE_MEETING: $ label = Yii :: t ('frontend', 'Complete vergadering'); breken; case MeetingLog :: ACTION_SENT_CONTACT_REQUEST: $ label = Yii :: t ('frontend', 'Verzoek verzenden voor contactinformatie'); standaard: $ label = Yii :: t ('frontend', 'Unknown'); breken;  return $ label; 

Toen heb ik gemaakt getMeetingLogItem (), waarbij contextueel het juiste objectlabel wordt gevonden op basis van de actie die is uitgevoerd. Er zijn hier nog steeds enkele debug-opmerkingen voor mezelf:

openbare functie getMeetingLogItem () $ label = "; switch ($ this-> actie) case MeetingLog :: ACTION_CREATE_MEETING: case MeetingLog :: ACTION_EDIT_MEETING: case MeetingLog :: ACTION_CANCEL_MEETING: case MeetingLog :: ACTION_DECLINE_MEETING: $ label = Yii :: t ('frontend', '-'); break; case MeetingLog :: ACTION_INVITE_PARTICIPANT: $ label = MiscHelpers :: getDisplayName ($ this-> item_id); if (is_null ($ label)) $ label = 'Fout - onbekend gebruiker '; pauze; case MeetingLog :: ACTION_SUGGEST_PLACE: $ label = Plaats :: find () -> where ([' id '=> $ this-> item_id]) -> one (); if (is_null ($ label )) $ label = 'Fout - voorgestelde onbekende plaats'; anders $ label = $ label-> naam; if (is_null ($ label)) $ label = 'Fout - voorgestelde plaats heeft onbekende naam'; pauze; case MeetingLog :: ACTION_ACCEPT_PLACE: case MeetingLog :: ACTION_REJECT_PLACE: $ label = MeetingPlace :: find () -> where (['id' => $ this-> item_id]) -> one (); if (is_null ( $ label)) $ label = 'Fout - accepteer of verwerp onbekende plaats x1'; else if (is_null ($ label-> plaats)) $ label = 'Fout Acc ept of weigert onbekende plaats x2 '; anders $ label = $ label-> plaats-> naam; if (is_null ($ label)) $ label = 'Fout accepteer of verwerp onbekende plaatsnaam x3';  pauze; case MeetingLog :: ACTION_CHOOSE_PLACE: $ label = MeetingPlace :: find () -> where (['id' => $ this-> item_id]) -> one (); if (is_null ($ label)) $ label = 'Fout - kies onbekende plaats x1';  else if (is_null ($ label-> place)) $ label = 'Fout gekozen onbekende plaats x2'; anders $ label = $ label-> plaats-> naam; if (is_null ($ label)) $ label = 'Fout - kies onbekende plaatsnaam x3';  pauze; case MeetingLog :: ACTION_CHOOSE_TIME: case MeetingLog :: ACTION_SUGGEST_TIME: case MeetingLog :: ACTION_ACCEPT_TIME: case MeetingLog :: ACTION_REJECT_TIME: // starttijd ophalen $ mt = MeetingTime :: find () -> where (['id' => $ this-> item_id]) -> één (); if (is_null ($ mt)) $ label = 'Fout bij het voldoen aan de tijd onbekend';  else $ label = Meeting :: friendlyDateFromTimestamp ($ mt-> start);  pauze; case MeetingLog :: ACTION_ADD_NOTE: if ($ this-> item_id == 0) $ label = 'note not logged';  else $ label = MeetingNote :: find () -> where (['id' => $ this-> item_id]) -> one () -> note;  pauze; case MeetingLog :: ACTION_ACCEPT_ALL_PLACES: case MeetingLog :: ACTION_ACCEPT_ALL_TIMES: case MeetingLog :: ACTION_SEND_INVITE: case MeetingLog :: ACTION_FINALIZE_INVITE: case MeetingLog :: ACTION_COMPLETE_MEETING: case MeetingLog :: ACTION_SENT_CONTACT_REQUEST: $ label = Yii :: t ('frontend', '- '); breken; standaard: $ label = Yii :: t ('frontend', 'n / a'); breken;  return $ label; 

Voor het maken, bewerken, annuleren of verwijderen van vergaderingen is bijvoorbeeld geen iteminformatie vereist, terwijl voor acceptietijd een specifieke waarde vereist is item ID overeenkomend met a MeetingTimeChoice datum en tijd.

Visuele aanwijzingen bieden

Wanneer een deelnemer de schuifregelaars voor plaatsen en tijden wijzigt om hun voorkeuren aan te geven, of indien toegestaan, een definitieve keuze maakt, wil ik voor hen aangeven dat hun organisator van de vergadering op de hoogte wordt gesteld wanneer ze klaar zijn. Ik wilde ook dat dit onopvallend zou zijn, b.v. een pop-up melding.

Omdat veel van deze wijzigingen gerelateerd zijn aan AJAX, moest het bericht dichtbij de muisacties worden weergegeven. Wanneer een wijziging wordt ingediend (zoals een nieuwe notitie), kan de melding boven aan de pagina worden weergegeven.

Yii Flash-meldingen zijn geweldig, maar ze verschijnen alleen bovenaan de pagina's. Op dit moment vereist het toevoegen van een notitie bijvoorbeeld een paginavernieuwing. Mensen zien de melding hint bovenaan de pagina nadat ze hun notitie hebben geplaatst:

Dus voor nu, terwijl ons ontwerp in beweging blijft, heb ik zojuist verborgen meldingsflitsen gemaakt boven de gebieden met plaatsen en boven het gebied met tijden. Wanneer mensen wijzigingen aanbrengen, zien ze de melding in de buurt van hun muisactie.

In de toekomst zullen we deze meldingen niet aan ervaren gebruikers laten zien zoals ze al weten.

Dus als iemand een tijd of plaats verandert, bellen we displayNotifier ():

// gebruikers kunnen aangeven of een tijd een optie voor hen is $ ('input [name = "meeting-time-choice"]'). on ('switchChange.bootstrapSwitch', functie (e, s) // set intval doorgeven via AJAX vanuit boolean-status if (s) state = 1; else state = 0; $ .ajax (url: '$ urlPrefix / meeting-time-choice / set', data: id: e.target.id , 'state': state, success: function (data) displayNotifier ('time'); refreshSend (); refreshFinalize (); return true;);); JS; 

Deze code in /frontend/views/meeting/view.php zorgt ervoor dat ze de meldingen niet herhaaldelijk door een sessie zien. Het gebruikt sessievariabelen om bij te houden of een hint al is weergegeven:

$ session = Yii :: $ app-> sessie; if ($ session ['displayHint'] == 'on' || $ model-> status == $ model :: STATUS_PLANNING) $ notifierOkay = 'off'; $ Session-> verwijderen ( 'displayHint');  else $ notifierOkay = 'aan'; ?>  

Wat is het volgende?

Ik heb de visie die ik probeer te creëren beschreven met het plannen van acties tussen deelnemers. In de volgende zelfstudie laat ik u zien hoe we de tijd bijhouden om te weten wanneer en hoe updates moeten worden geleverd. En ik laat u zien hoe we de updates via e-mail bezorgen, zoals hierboven. Ik ga ook laten zien hoe we een tekstueel overzicht maken van de recente wijzigingen die zijn aangebracht.

Terwijl u aan het wachten bent, probeer de functie voor meldingen en plan uw eerste vergadering. Ik zou het ook op prijs stellen als u uw ervaringen hieronder in de opmerkingen deelt en ik ben altijd geïnteresseerd in uw suggesties. Je kunt me ook rechtstreeks op Twitter @reifman bereiken.

Kijk uit voor komende tutorials in de Building Your Startup With PHP-serie. Er komen nog een paar grote functies aan.

Gerelateerde Links

  • Meeting Planner
  • Programmeren met Yii2: Aan de slag
  • De Yii2 Developer Exchange