diff --git a/app/database/migrations/2015_01_16_083825_CreateTagsTable.php b/app/database/migrations/2015_01_16_083825_CreateTagsTable.php
new file mode 100644
index 00000000..98b053cb
--- /dev/null
+++ b/app/database/migrations/2015_01_16_083825_CreateTagsTable.php
@@ -0,0 +1,35 @@
+increments('id');
+ $table->string('name');
+ $table->string('slug');
+ $table->timestamps();
+
+ $table->unique(['name', 'slug']);
+ });
+ }
+
+ /**
+ * Reverse the migrations.
+ *
+ * @return void
+ */
+ public function down()
+ {
+ Schema::drop('tags');
+ }
+}
diff --git a/app/database/migrations/2015_01_16_084030_CreateComponentTagTable.php b/app/database/migrations/2015_01_16_084030_CreateComponentTagTable.php
new file mode 100644
index 00000000..77a7480e
--- /dev/null
+++ b/app/database/migrations/2015_01_16_084030_CreateComponentTagTable.php
@@ -0,0 +1,35 @@
+increments('id');
+ $table->integer('component_id');
+ $table->integer('tag_id');
+
+ $table->index('component_id');
+ $table->index('tag_id');
+ });
+ }
+
+ /**
+ * Reverse the migrations.
+ *
+ * @return void
+ */
+ public function down()
+ {
+ Schema::drop('component_tag');
+ }
+}
diff --git a/app/database/migrations/2015_01_16_084806_AlterTableComponentsDropTagsColumn.php b/app/database/migrations/2015_01_16_084806_AlterTableComponentsDropTagsColumn.php
new file mode 100644
index 00000000..19a88762
--- /dev/null
+++ b/app/database/migrations/2015_01_16_084806_AlterTableComponentsDropTagsColumn.php
@@ -0,0 +1,32 @@
+dropColumn('tags');
+ });
+ }
+
+ /**
+ * Reverse the migrations.
+ *
+ * @return void
+ */
+ public function down()
+ {
+ Schema::table('components', function (Blueprint $table) {
+ $table->text('tags')->after('link');
+ });
+ }
+}
diff --git a/app/views/dashboard/components/add.blade.php b/app/views/dashboard/components/add.blade.php
index e96a2065..78c48721 100644
--- a/app/views/dashboard/components/add.blade.php
+++ b/app/views/dashboard/components/add.blade.php
@@ -50,7 +50,7 @@
-
+
{{ trans('forms.components.tags-help') }}
diff --git a/app/views/dashboard/components/edit.blade.php b/app/views/dashboard/components/edit.blade.php
index 2bd1de8e..05dcb775 100644
--- a/app/views/dashboard/components/edit.blade.php
+++ b/app/views/dashboard/components/edit.blade.php
@@ -50,7 +50,7 @@
-
+
{{ trans('forms.components.tags-help') }}
diff --git a/src/Http/Controllers/DashComponentController.php b/src/Http/Controllers/DashComponentController.php
index d0c6bf0f..bb70d950 100644
--- a/src/Http/Controllers/DashComponentController.php
+++ b/src/Http/Controllers/DashComponentController.php
@@ -4,6 +4,7 @@ namespace CachetHQ\Cachet\Http\Controllers;
use CachetHQ\Cachet\Models\Component;
use CachetHQ\Cachet\Models\ComponentGroup;
+use CachetHQ\Cachet\Models\Tag;
use GrahamCampbell\Binput\Facades\Binput;
use Illuminate\Routing\Controller;
use Illuminate\Support\Facades\Redirect;
@@ -104,6 +105,7 @@ class DashComponentController extends Controller
public function updateComponentAction(Component $component)
{
$_component = Binput::get('component');
+ $tags = array_pull($_component, 'tags');
$component->update($_component);
if (! $component->isValid()) {
@@ -116,6 +118,19 @@ class DashComponentController extends Controller
->with('errors', $component->getErrors());
}
+ // The component was added successfully, so now let's deal with the tags.
+ $tags = str_replace(', ', ',', $tags); // Clean up.
+ $tags = explode(',', $tags);
+
+ // For every tag, do we need to create it?
+ $componentTags = array_map(function ($taggable) use ($component) {
+ return Tag::firstOrCreate([
+ 'name' => $taggable,
+ ])->id;
+ }, $tags);
+
+ $component->tags()->sync($componentTags);
+
$successMsg = sprintf(
'%s %s',
trans('dashboard.notifications.awesome'),
@@ -148,6 +163,9 @@ class DashComponentController extends Controller
public function createComponentAction()
{
$_component = Binput::get('component');
+ // We deal with tags separately.
+ $tags = array_pull($_component, 'tags');
+
$component = Component::create($_component);
if (! $component->isValid()) {
@@ -160,6 +178,19 @@ class DashComponentController extends Controller
->with('errors', $component->getErrors());
}
+ // The component was added successfully, so now let's deal with the tags.
+ $tags = str_replace(', ', ',', $tags); // Clean up.
+ $tags = explode(',', $tags);
+
+ // For every tag, do we need to create it?
+ $componentTags = array_map(function ($taggable) use ($component) {
+ return Tag::firstOrCreate([
+ 'name' => $taggable,
+ ])->id;
+ }, $tags);
+
+ $component->tags()->sync($componentTags);
+
$successMsg = sprintf(
'%s %s',
trans('dashboard.notifications.awesome'),
diff --git a/src/Models/Component.php b/src/Models/Component.php
index 2af21afa..b9a86256 100644
--- a/src/Models/Component.php
+++ b/src/Models/Component.php
@@ -85,6 +85,16 @@ class Component extends Model implements TransformableInterface
return $this->hasMany('CachetHQ\Cachet\Models\Incident', 'component_id', 'id');
}
+ /**
+ * Components can have many tags.
+ *
+ * @return \Illuminate\Database\Eloquent\Relations\HasMany
+ */
+ public function tags()
+ {
+ return $this->belongsToMany('CachetHQ\Cachet\Models\Tag');
+ }
+
/**
* Finds all components by status.
*
@@ -121,6 +131,20 @@ class Component extends Model implements TransformableInterface
return trans('cachet.components.status.'.$this->status);
}
+ /**
+ * Returns all of the tags on this component.
+ *
+ * @return string
+ */
+ public function getTagsListAttribute()
+ {
+ $tags = $this->tags->map(function ($tag) {
+ return $tag->name;
+ });
+
+ return implode(', ', $tags->toArray());
+ }
+
/**
* Get the transformer instance.
*
diff --git a/src/Models/Tag.php b/src/Models/Tag.php
new file mode 100644
index 00000000..759a6015
--- /dev/null
+++ b/src/Models/Tag.php
@@ -0,0 +1,43 @@
+slug = Str::slug($tag->name);
+ });
+ }
+
+ /**
+ * Tags can have many components.
+ *
+ * @return \Illuminate\Database\Eloquent\Relations\HasMany
+ */
+ public function components()
+ {
+ return $this->belongsToMany('CachetHQ\Cachet\Models\Component');
+ }
+}