Skip to content

Commit

Permalink
feat: display feed on contact page (monicahq/chandler#52)
Browse files Browse the repository at this point in the history
  • Loading branch information
djaiss authored Mar 19, 2022
1 parent fcde2d6 commit a469f91
Show file tree
Hide file tree
Showing 13 changed files with 223 additions and 3 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -17,3 +17,4 @@ yarn-error.log
.DS_Store
/tests/Features/screenshots/
/tests/Features/videos/
/data.ms
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
<?php

namespace App\Http\Controllers\Vault\Contact\Modules\Feed\ViewHelpers;

use App\Models\User;
use App\Models\Contact;
use App\Models\ContactFeedItem;
use App\Http\Controllers\Vault\Contact\Modules\Note\ViewHelpers\ModuleNotesViewHelper;

class ModuleFeedViewHelper
{
public static function data(Contact $contact, User $user): array
{
$items = ContactFeedItem::where('contact_id', $contact->id)
->orderBy('created_at', 'desc')
->get();

$itemsCollection = $items->map(function ($item) use ($contact, $user) {
if ($item->action == ContactFeedItem::ACTION_NOTE_CREATED) {
$object = ModuleNotesViewHelper::dto($contact, $item->feedable, $user);
}

return [
'id' => $item->id,
'action' => $item->action,
'object' => $object,
];
});

return [
'items' => $itemsCollection,
];
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
use App\Models\TemplatePage;
use Illuminate\Support\Collection;
use Illuminate\Database\Eloquent\Collection as EloquentCollection;
use App\Http\Controllers\Vault\Contact\Modules\Feed\ViewHelpers\ModuleFeedViewHelper;
use App\Http\Controllers\Vault\Contact\Modules\Note\ViewHelpers\ModuleNotesViewHelper;
use App\Http\Controllers\Vault\Contact\Modules\Label\ViewHelpers\ModuleLabelViewHelper;
use App\Http\Controllers\Vault\Contact\Modules\Avatar\ViewHelpers\ModuleAvatarViewHelper;
Expand Down Expand Up @@ -145,7 +146,7 @@ public static function modules(TemplatePage $page, Contact $contact, User $user)
}

if ($module->type == Module::TYPE_FEED) {
$data = ModuleNotesViewHelper::data($contact, $user);
$data = ModuleFeedViewHelper::data($contact, $user);
}

if ($module->type == Module::TYPE_REMINDERS) {
Expand Down
7 changes: 7 additions & 0 deletions app/Models/ContactFeedItem.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,20 @@ class ContactFeedItem extends Model

protected $table = 'contact_feed_items';

/**
* Possible actions.
*/
const ACTION_NOTE_CREATED = 'note_created';
const ACTION_NOTE_UPDATED = 'note_updated';

/**
* The attributes that are mass assignable.
*
* @var array
*/
protected $fillable = [
'contact_id',
'action',
'feedable_id',
'feedable_type',
];
Expand Down
1 change: 1 addition & 0 deletions app/Services/Contact/ManageNote/CreateNote.php
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,7 @@ private function createFeedItem(): void
{
$feedItem = ContactFeedItem::create([
'contact_id' => $this->contact->id,
'action' => ContactFeedItem::ACTION_NOTE_CREATED,
]);
$this->note->feedItem()->save($feedItem);
}
Expand Down
1 change: 1 addition & 0 deletions database/factories/ContactFeedItemFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ public function definition()
{
return [
'contact_id' => Contact::factory(),
'action' => ContactFeedItem::ACTION_NOTE_CREATED,
];
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ public function up()
Schema::create('contact_feed_items', function (Blueprint $table) {
$table->id();
$table->unsignedBigInteger('contact_id');
$table->string('action');
$table->unsignedBigInteger('feedable_id')->nullable();
$table->string('feedable_type')->nullable();
$table->timestamps();
Expand Down
9 changes: 9 additions & 0 deletions resources/js/Pages/Vault/Contact/Show.vue
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,8 @@
<notes v-if="module.type == 'notes'" :data="notes" />

<reminders v-if="module.type == 'reminders'" :data="reminders" />

<feed v-if="module.type == 'feed'" :data="feed" />
</div>
</div>
</div>
Expand All @@ -105,6 +107,7 @@ import Notes from '@/Shared/Modules/Notes';
import ImportantDates from '@/Shared/Modules/ImportantDates';
import Labels from '@/Shared/Modules/Labels';
import Reminders from '@/Shared/Modules/Reminders';
import Feed from '@/Shared/Modules/Feed';
export default {
components: {
Expand All @@ -116,6 +119,7 @@ export default {
ImportantDates,
Labels,
Reminders,
Feed,
},
props: {
Expand All @@ -135,6 +139,7 @@ export default {
contactName: [],
genderPronoun: [],
importantDates: [],
feed: [],
labels: [],
notes: [],
reminders: [],
Expand Down Expand Up @@ -182,6 +187,10 @@ export default {
if (this.data.modules.findIndex((x) => x.type == 'reminders') > -1) {
this.reminders = this.data.modules[this.data.modules.findIndex((x) => x.type == 'reminders')].data;
}
if (this.data.modules.findIndex((x) => x.type == 'feed') > -1) {
this.feed = this.data.modules[this.data.modules.findIndex((x) => x.type == 'feed')].data;
}
}
},
Expand Down
77 changes: 77 additions & 0 deletions resources/js/Pages/Vault/Dashboard/Partials/Feed/Note.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
<style lang="scss" scoped>
.icon-date {
top: -1px;
}
</style>

<template>
<div class="relative border border-gray-300 bg-white sm:rounded-lg">
<span class="absolute rounded border bg-blue-50 px-2 py-0 text-xs text-blue-500" style="top: -10px; left: 10px">
note
</span>

<!-- title, if it exists -->
<div v-if="note.title" class="font-semibol mb-1 border-b border-gray-200 p-3 pt-5 text-xs text-gray-600">
{{ note.title }}
</div>

<div class="p-3">
{{ note.body }}
</div>

<div
class="flex justify-between border-t border-gray-200 px-3 py-1 text-xs text-gray-600 hover:rounded-b hover:bg-slate-50">
<div>
<!-- emotion -->
<div v-if="note.emotion" class="relative mr-3 inline">
{{ note.emotion.name }}
</div>

<!-- date -->
<div class="relative mr-3 inline">
<svg
xmlns="http://www.w3.org/2000/svg"
class="icon-note relative inline h-3 w-3 text-gray-400"
fill="none"
viewBox="0 0 24 24"
stroke="currentColor">
<path
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="M12 8v4l3 3m6-3a9 9 0 11-18 0 9 9 0 0118 0z" />
</svg>
{{ note.written_at }}
</div>

<!-- author -->
<div class="relative mr-3 inline">
<svg
xmlns="http://www.w3.org/2000/svg"
class="icon-note relative inline h-3 w-3 text-gray-400"
fill="none"
viewBox="0 0 24 24"
stroke="currentColor">
<path
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="M5.121 17.804A13.937 13.937 0 0112 16c2.5 0 4.847.655 6.879 1.804M15 10a3 3 0 11-6 0 3 3 0 016 0zm6 2a9 9 0 11-18 0 9 9 0 0118 0z" />
</svg>
{{ note.author }}
</div>
</div>
</div>
</div>
</template>

<script>
export default {
props: {
note: {
type: Array,
default: null,
},
},
};
</script>
41 changes: 41 additions & 0 deletions resources/js/Shared/Modules/Feed.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
<style lang="scss" scoped>
.icon-sidebar {
color: #737e8d;
top: -2px;
}
.icon-note {
top: -1px;
}
</style>

<template>
<div class="mb-4">
<div v-for="item in data.items" :key="item.id" class="mb-6">
<!-- note created -->
<note v-if="item.action == 'note_created'" :note="item.object" />
</div>

<!-- blank state -->
<div v-if="data.items.length == 0">
<p class="p-5 text-center">This person doesn't have any activity yet.</p>
</div>
</div>
</template>

<script>
import Note from '@/Pages/Vault/Dashboard/Partials/Feed/Note';
export default {
components: {
Note,
},
props: {
data: {
type: Object,
default: null,
},
},
};
</script>
4 changes: 2 additions & 2 deletions resources/js/Shared/Modules/Notes.vue
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,7 @@
<div class="relative mr-3 inline">
<svg
xmlns="http://www.w3.org/2000/svg"
class="icon-note relative inline h-4 w-4 text-gray-400"
class="icon-note relative inline h-3 w-3 text-gray-400"
fill="none"
viewBox="0 0 24 24"
stroke="currentColor">
Expand All @@ -161,7 +161,7 @@
<div class="relative mr-3 inline">
<svg
xmlns="http://www.w3.org/2000/svg"
class="icon-note relative inline h-4 w-4 text-gray-400"
class="icon-note relative inline h-3 w-3 text-gray-400"
fill="none"
viewBox="0 0 24 24"
stroke="currentColor">
Expand Down
5 changes: 5 additions & 0 deletions resources/lang/en/feed.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<?php

return [
'update' => 'Update',
];
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
<?php

namespace Tests\Unit\Controllers\Vault\Contact\Modules\Feed\ViewHelpers;

use Tests\TestCase;
use App\Models\Note;
use App\Models\User;
use App\Models\Contact;
use App\Models\ContactFeedItem;
use Illuminate\Foundation\Testing\DatabaseTransactions;
use App\Http\Controllers\Vault\Contact\Modules\Feed\ViewHelpers\ModuleFeedViewHelper;

class ModuleFeedViewHelperTest extends TestCase
{
use DatabaseTransactions;

/** @test */
public function it_gets_the_data_needed_for_the_view(): void
{
$contact = Contact::factory()->create();
$user = User::factory()->create();
$note = Note::factory()->create();
ContactFeedItem::factory()->create([
'contact_id' => $contact->id,
'action' => ContactFeedItem::ACTION_NOTE_CREATED,
'feedable_id' => $note->id,
'feedable_type' => Note::class,
]);

$array = ModuleFeedViewHelper::data($contact, $user);

$this->assertEquals(
1,
count($array)
);

$this->assertArrayHasKey('items', $array);
$this->assertArrayHasKey('id', $array['items']->toArray()[0]);
$this->assertArrayHasKey('action', $array['items']->toArray()[0]);
$this->assertArrayHasKey('object', $array['items']->toArray()[0]);
}
}

0 comments on commit a469f91

Please sign in to comment.